xref: /qemu/hw/ppc/e500.c (revision 0d09e41a51aa0752b1ce525ce084f7cd210e461b)
11db09b84Saurel32 /*
2b3305981SScott Wood  * QEMU PowerPC e500-based platforms
31db09b84Saurel32  *
41db09b84Saurel32  * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
51db09b84Saurel32  *
61db09b84Saurel32  * Author: Yu Liu,     <yu.liu@freescale.com>
71db09b84Saurel32  *
81db09b84Saurel32  * This file is derived from hw/ppc440_bamboo.c,
91db09b84Saurel32  * the copyright for that material belongs to the original owners.
101db09b84Saurel32  *
111db09b84Saurel32  * This is free software; you can redistribute it and/or modify
121db09b84Saurel32  * it under the terms of  the GNU General  Public License as published by
131db09b84Saurel32  * the Free Software Foundation;  either version 2 of the  License, or
141db09b84Saurel32  * (at your option) any later version.
151db09b84Saurel32  */
161db09b84Saurel32 
171db09b84Saurel32 #include "config.h"
181db09b84Saurel32 #include "qemu-common.h"
19e6eaabebSScott Wood #include "e500.h"
203eddc1beSBharat Bhushan #include "e500-ccsr.h"
211422e32dSPaolo Bonzini #include "net/net.h"
221de7afc9SPaolo Bonzini #include "qemu/config-file.h"
234a18e7c9SScott Wood #include "hw/hw.h"
24*0d09e41aSPaolo Bonzini #include "hw/char/serial.h"
25a2cb15b0SMichael S. Tsirkin #include "hw/pci/pci.h"
264a18e7c9SScott Wood #include "hw/boards.h"
279c17d615SPaolo Bonzini #include "sysemu/sysemu.h"
289c17d615SPaolo Bonzini #include "sysemu/kvm.h"
291db09b84Saurel32 #include "kvm_ppc.h"
309c17d615SPaolo Bonzini #include "sysemu/device_tree.h"
31*0d09e41aSPaolo Bonzini #include "hw/ppc/openpic.h"
32*0d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h"
334a18e7c9SScott Wood #include "hw/loader.h"
34ca20cf32SBlue Swirl #include "elf.h"
354a18e7c9SScott Wood #include "hw/sysbus.h"
36022c62cbSPaolo Bonzini #include "exec/address-spaces.h"
371de7afc9SPaolo Bonzini #include "qemu/host-utils.h"
38*0d09e41aSPaolo Bonzini #include "hw/pci-host/ppce500.h"
391db09b84Saurel32 
401db09b84Saurel32 #define BINARY_DEVICE_TREE_FILE    "mpc8544ds.dtb"
411db09b84Saurel32 #define UIMAGE_LOAD_BASE           0
429dd5eba1SScott Wood #define DTC_LOAD_PAD               0x1800000
4375bb6589SLiu Yu #define DTC_PAD_MASK               0xFFFFF
44b8dec144SAlexander Graf #define DTB_MAX_SIZE               (8 * 1024 * 1024)
4575bb6589SLiu Yu #define INITRD_LOAD_PAD            0x2000000
4675bb6589SLiu Yu #define INITRD_PAD_MASK            0xFFFFFF
471db09b84Saurel32 
481db09b84Saurel32 #define RAM_SIZES_ALIGN            (64UL << 20)
491db09b84Saurel32 
50b3305981SScott Wood /* TODO: parameterize */
51ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_BASE       0xE0000000ULL
52ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_SIZE       0x00100000ULL
53dffb1dc2SBharat Bhushan #define MPC8544_MPIC_REGS_OFFSET   0x40000ULL
54a911b7a9SAlexander Graf #define MPC8544_MSI_REGS_OFFSET   0x41600ULL
55dffb1dc2SBharat Bhushan #define MPC8544_SERIAL0_REGS_OFFSET 0x4500ULL
56dffb1dc2SBharat Bhushan #define MPC8544_SERIAL1_REGS_OFFSET 0x4600ULL
57dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_OFFSET    0x8000ULL
58dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_BASE      (MPC8544_CCSRBAR_BASE + \
59dffb1dc2SBharat Bhushan                                     MPC8544_PCI_REGS_OFFSET)
60ed2bc496SAlexander Graf #define MPC8544_PCI_REGS_SIZE      0x1000ULL
61ed2bc496SAlexander Graf #define MPC8544_PCI_IO             0xE1000000ULL
62dffb1dc2SBharat Bhushan #define MPC8544_UTIL_OFFSET        0xe0000ULL
63ed2bc496SAlexander Graf #define MPC8544_SPIN_BASE          0xEF000000ULL
641db09b84Saurel32 
653b989d49SAlexander Graf struct boot_info
663b989d49SAlexander Graf {
673b989d49SAlexander Graf     uint32_t dt_base;
68cba2026aSAlexander Graf     uint32_t dt_size;
693b989d49SAlexander Graf     uint32_t entry;
703b989d49SAlexander Graf };
713b989d49SAlexander Graf 
72347dd79dSAlexander Graf static uint32_t *pci_map_create(void *fdt, uint32_t mpic, int first_slot,
73347dd79dSAlexander Graf                                 int nr_slots, int *len)
740dbc0798SAlexander Graf {
75347dd79dSAlexander Graf     int i = 0;
76347dd79dSAlexander Graf     int slot;
77347dd79dSAlexander Graf     int pci_irq;
789e2c1298SAlexander Graf     int host_irq;
79347dd79dSAlexander Graf     int last_slot = first_slot + nr_slots;
80347dd79dSAlexander Graf     uint32_t *pci_map;
810dbc0798SAlexander Graf 
82347dd79dSAlexander Graf     *len = nr_slots * 4 * 7 * sizeof(uint32_t);
83347dd79dSAlexander Graf     pci_map = g_malloc(*len);
84347dd79dSAlexander Graf 
85347dd79dSAlexander Graf     for (slot = first_slot; slot < last_slot; slot++) {
86347dd79dSAlexander Graf         for (pci_irq = 0; pci_irq < 4; pci_irq++) {
87347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(slot << 11);
88347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(0x0);
89347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(0x0);
90347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(pci_irq + 1);
91347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(mpic);
929e2c1298SAlexander Graf             host_irq = ppce500_pci_map_irq_slot(slot, pci_irq);
939e2c1298SAlexander Graf             pci_map[i++] = cpu_to_be32(host_irq + 1);
94347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(0x1);
950dbc0798SAlexander Graf         }
960dbc0798SAlexander Graf     }
970dbc0798SAlexander Graf 
98347dd79dSAlexander Graf     assert((i * sizeof(uint32_t)) == *len);
99347dd79dSAlexander Graf 
100347dd79dSAlexander Graf     return pci_map;
101347dd79dSAlexander Graf }
102347dd79dSAlexander Graf 
103a053a7ceSAlexander Graf static void dt_serial_create(void *fdt, unsigned long long offset,
104a053a7ceSAlexander Graf                              const char *soc, const char *mpic,
105a053a7ceSAlexander Graf                              const char *alias, int idx, bool defcon)
106a053a7ceSAlexander Graf {
107a053a7ceSAlexander Graf     char ser[128];
108a053a7ceSAlexander Graf 
109a053a7ceSAlexander Graf     snprintf(ser, sizeof(ser), "%s/serial@%llx", soc, offset);
110a053a7ceSAlexander Graf     qemu_devtree_add_subnode(fdt, ser);
111a053a7ceSAlexander Graf     qemu_devtree_setprop_string(fdt, ser, "device_type", "serial");
112a053a7ceSAlexander Graf     qemu_devtree_setprop_string(fdt, ser, "compatible", "ns16550");
113a053a7ceSAlexander Graf     qemu_devtree_setprop_cells(fdt, ser, "reg", offset, 0x100);
114a053a7ceSAlexander Graf     qemu_devtree_setprop_cell(fdt, ser, "cell-index", idx);
115a053a7ceSAlexander Graf     qemu_devtree_setprop_cell(fdt, ser, "clock-frequency", 0);
1167e99826cSAlexander Graf     qemu_devtree_setprop_cells(fdt, ser, "interrupts", 42, 2);
117a053a7ceSAlexander Graf     qemu_devtree_setprop_phandle(fdt, ser, "interrupt-parent", mpic);
118a053a7ceSAlexander Graf     qemu_devtree_setprop_string(fdt, "/aliases", alias, ser);
119a053a7ceSAlexander Graf 
120a053a7ceSAlexander Graf     if (defcon) {
121a053a7ceSAlexander Graf         qemu_devtree_setprop_string(fdt, "/chosen", "linux,stdout-path", ser);
122a053a7ceSAlexander Graf     }
123a053a7ceSAlexander Graf }
124a053a7ceSAlexander Graf 
125b3305981SScott Wood static int ppce500_load_device_tree(CPUPPCState *env,
126e6eaabebSScott Wood                                     PPCE500Params *params,
127a8170e5eSAvi Kivity                                     hwaddr addr,
128a8170e5eSAvi Kivity                                     hwaddr initrd_base,
129a8170e5eSAvi Kivity                                     hwaddr initrd_size)
1301db09b84Saurel32 {
131dbf916d8SAurelien Jarno     int ret = -1;
132e6eaabebSScott Wood     uint64_t mem_reg_property[] = { 0, cpu_to_be64(params->ram_size) };
1337ec632b4Spbrook     int fdt_size;
134dbf916d8SAurelien Jarno     void *fdt;
1355de6b46dSAlexander Graf     uint8_t hypercall[16];
136911d6e7aSAlexander Graf     uint32_t clock_freq = 400000000;
137911d6e7aSAlexander Graf     uint32_t tb_freq = 400000000;
138621d05e3SAlexander Graf     int i;
139e6eaabebSScott Wood     const char *toplevel_compat = NULL; /* user override */
140ebb9518aSAlexander Graf     char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus";
1415da96624SAlexander Graf     char soc[128];
14219ac9deaSAlexander Graf     char mpic[128];
14319ac9deaSAlexander Graf     uint32_t mpic_ph;
144a911b7a9SAlexander Graf     uint32_t msi_ph;
145f5038483SAlexander Graf     char gutil[128];
1460dbc0798SAlexander Graf     char pci[128];
147a911b7a9SAlexander Graf     char msi[128];
148347dd79dSAlexander Graf     uint32_t *pci_map = NULL;
149347dd79dSAlexander Graf     int len;
1503627757eSAlexander Graf     uint32_t pci_ranges[14] =
1513627757eSAlexander Graf         {
1523627757eSAlexander Graf             0x2000000, 0x0, 0xc0000000,
1533627757eSAlexander Graf             0x0, 0xc0000000,
1543627757eSAlexander Graf             0x0, 0x20000000,
1553627757eSAlexander Graf 
1563627757eSAlexander Graf             0x1000000, 0x0, 0x0,
1573627757eSAlexander Graf             0x0, 0xe1000000,
1583627757eSAlexander Graf             0x0, 0x10000,
1593627757eSAlexander Graf         };
16025b42708SAlexander Graf     QemuOpts *machine_opts;
161d1b93565SAlexander Graf     const char *dtb_file = NULL;
162d1b93565SAlexander Graf 
163d1b93565SAlexander Graf     machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
164d1b93565SAlexander Graf     if (machine_opts) {
165d1b93565SAlexander Graf         dtb_file = qemu_opt_get(machine_opts, "dtb");
166e6eaabebSScott Wood         toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
167d1b93565SAlexander Graf     }
168d1b93565SAlexander Graf 
169d1b93565SAlexander Graf     if (dtb_file) {
170d1b93565SAlexander Graf         char *filename;
171d1b93565SAlexander Graf         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file);
172d1b93565SAlexander Graf         if (!filename) {
173d1b93565SAlexander Graf             goto out;
174d1b93565SAlexander Graf         }
175d1b93565SAlexander Graf 
176d1b93565SAlexander Graf         fdt = load_device_tree(filename, &fdt_size);
177d1b93565SAlexander Graf         if (!fdt) {
178d1b93565SAlexander Graf             goto out;
179d1b93565SAlexander Graf         }
180d1b93565SAlexander Graf         goto done;
181d1b93565SAlexander Graf     }
1821db09b84Saurel32 
1832636fcb6SAlexander Graf     fdt = create_device_tree(&fdt_size);
1845cea8590SPaul Brook     if (fdt == NULL) {
1855cea8590SPaul Brook         goto out;
1865cea8590SPaul Brook     }
1871db09b84Saurel32 
1881db09b84Saurel32     /* Manipulate device tree in memory. */
1893627757eSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2);
1903627757eSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2);
19151b852b7SAlexander Graf 
192dd0bcfcaSAlexander Graf     qemu_devtree_add_subnode(fdt, "/memory");
193dd0bcfcaSAlexander Graf     qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory");
194dd0bcfcaSAlexander Graf     qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
1951db09b84Saurel32                          sizeof(mem_reg_property));
1961db09b84Saurel32 
197f5231aafSAlexander Graf     qemu_devtree_add_subnode(fdt, "/chosen");
1983b989d49SAlexander Graf     if (initrd_size) {
1991db09b84Saurel32         ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
2001db09b84Saurel32                                         initrd_base);
2013b989d49SAlexander Graf         if (ret < 0) {
2021db09b84Saurel32             fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
2033b989d49SAlexander Graf         }
2041db09b84Saurel32 
2051db09b84Saurel32         ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
2061db09b84Saurel32                                         (initrd_base + initrd_size));
2073b989d49SAlexander Graf         if (ret < 0) {
2081db09b84Saurel32             fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
2093b989d49SAlexander Graf         }
2103b989d49SAlexander Graf     }
2111db09b84Saurel32 
2121db09b84Saurel32     ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
213e6eaabebSScott Wood                                       params->kernel_cmdline);
2141db09b84Saurel32     if (ret < 0)
2151db09b84Saurel32         fprintf(stderr, "couldn't set /chosen/bootargs\n");
2161db09b84Saurel32 
2171db09b84Saurel32     if (kvm_enabled()) {
218911d6e7aSAlexander Graf         /* Read out host's frequencies */
219911d6e7aSAlexander Graf         clock_freq = kvmppc_get_clockfreq();
220911d6e7aSAlexander Graf         tb_freq = kvmppc_get_tbfreq();
2215de6b46dSAlexander Graf 
2225de6b46dSAlexander Graf         /* indicate KVM hypercall interface */
223d50f71a5SAlexander Graf         qemu_devtree_add_subnode(fdt, "/hypervisor");
2245de6b46dSAlexander Graf         qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible",
2255de6b46dSAlexander Graf                                     "linux,kvm");
2265de6b46dSAlexander Graf         kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
2275de6b46dSAlexander Graf         qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",
2285de6b46dSAlexander Graf                              hypercall, sizeof(hypercall));
2291a61a9aeSStuart Yoder         /* if KVM supports the idle hcall, set property indicating this */
2301a61a9aeSStuart Yoder         if (kvmppc_get_hasidle(env)) {
2311a61a9aeSStuart Yoder             qemu_devtree_setprop(fdt, "/hypervisor", "has-idle", NULL, 0);
2321a61a9aeSStuart Yoder         }
2331db09b84Saurel32     }
2341db09b84Saurel32 
235625e665bSAlexander Graf     /* Create CPU nodes */
236625e665bSAlexander Graf     qemu_devtree_add_subnode(fdt, "/cpus");
237625e665bSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/cpus", "#address-cells", 1);
238625e665bSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/cpus", "#size-cells", 0);
239625e665bSAlexander Graf 
2401e3debf0SAlexander Graf     /* We need to generate the cpu nodes in reverse order, so Linux can pick
2411e3debf0SAlexander Graf        the first node as boot node and be happy */
2421e3debf0SAlexander Graf     for (i = smp_cpus - 1; i >= 0; i--) {
243440c8152SAndreas Färber         CPUState *cpu;
244621d05e3SAlexander Graf         char cpu_name[128];
2451d2e5c52SAlexander Graf         uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20);
24610f25a46SAlexander Graf 
247440c8152SAndreas Färber         cpu = qemu_get_cpu(i);
24855e5c285SAndreas Färber         if (cpu == NULL) {
2491e3debf0SAlexander Graf             continue;
2501e3debf0SAlexander Graf         }
251440c8152SAndreas Färber         env = cpu->env_ptr;
2521e3debf0SAlexander Graf 
25355e5c285SAndreas Färber         snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x",
25455e5c285SAndreas Färber                  cpu->cpu_index);
2551e3debf0SAlexander Graf         qemu_devtree_add_subnode(fdt, cpu_name);
2561e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
2571e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
2581e3debf0SAlexander Graf         qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu");
25955e5c285SAndreas Färber         qemu_devtree_setprop_cell(fdt, cpu_name, "reg", cpu->cpu_index);
2601e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size",
2611e3debf0SAlexander Graf                                   env->dcache_line_size);
2621e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size",
2631e3debf0SAlexander Graf                                   env->icache_line_size);
2641e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000);
2651e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000);
2661e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0);
26755e5c285SAndreas Färber         if (cpu->cpu_index) {
2681e3debf0SAlexander Graf             qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled");
2691e3debf0SAlexander Graf             qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table");
2701d2e5c52SAlexander Graf             qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr",
2711d2e5c52SAlexander Graf                                      cpu_release_addr);
2721e3debf0SAlexander Graf         } else {
2731e3debf0SAlexander Graf             qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay");
2741e3debf0SAlexander Graf         }
2751db09b84Saurel32     }
2761db09b84Saurel32 
2770cfc6e8dSAlexander Graf     qemu_devtree_add_subnode(fdt, "/aliases");
2785da96624SAlexander Graf     /* XXX These should go into their respective devices' code */
279ed2bc496SAlexander Graf     snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE);
2805da96624SAlexander Graf     qemu_devtree_add_subnode(fdt, soc);
2815da96624SAlexander Graf     qemu_devtree_setprop_string(fdt, soc, "device_type", "soc");
282ebb9518aSAlexander Graf     qemu_devtree_setprop(fdt, soc, "compatible", compatible_sb,
283ebb9518aSAlexander Graf                          sizeof(compatible_sb));
2845da96624SAlexander Graf     qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1);
2855da96624SAlexander Graf     qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1);
2863627757eSAlexander Graf     qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0,
2873627757eSAlexander Graf                                MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE,
2885da96624SAlexander Graf                                MPC8544_CCSRBAR_SIZE);
2895da96624SAlexander Graf     /* XXX should contain a reasonable value */
2905da96624SAlexander Graf     qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0);
2915da96624SAlexander Graf 
292dffb1dc2SBharat Bhushan     snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET);
29319ac9deaSAlexander Graf     qemu_devtree_add_subnode(fdt, mpic);
29419ac9deaSAlexander Graf     qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic");
295f5fba9d2SScott Wood     qemu_devtree_setprop_string(fdt, mpic, "compatible", "fsl,mpic");
296dffb1dc2SBharat Bhushan     qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET,
297dffb1dc2SBharat Bhushan                                0x40000);
29819ac9deaSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0);
2997e99826cSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2);
30019ac9deaSAlexander Graf     mpic_ph = qemu_devtree_alloc_phandle(fdt);
30119ac9deaSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph);
30219ac9deaSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph);
30319ac9deaSAlexander Graf     qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0);
30419ac9deaSAlexander Graf 
3050cfc6e8dSAlexander Graf     /*
3060cfc6e8dSAlexander Graf      * We have to generate ser1 first, because Linux takes the first
3070cfc6e8dSAlexander Graf      * device it finds in the dt as serial output device. And we generate
3080cfc6e8dSAlexander Graf      * devices in reverse order to the dt.
3090cfc6e8dSAlexander Graf      */
310dffb1dc2SBharat Bhushan     dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET,
311a053a7ceSAlexander Graf                      soc, mpic, "serial1", 1, false);
312dffb1dc2SBharat Bhushan     dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET,
313a053a7ceSAlexander Graf                      soc, mpic, "serial0", 0, true);
3140cfc6e8dSAlexander Graf 
315ed2bc496SAlexander Graf     snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc,
316dffb1dc2SBharat Bhushan              MPC8544_UTIL_OFFSET);
317f5038483SAlexander Graf     qemu_devtree_add_subnode(fdt, gutil);
318f5038483SAlexander Graf     qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts");
319dffb1dc2SBharat Bhushan     qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000);
320f5038483SAlexander Graf     qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0);
321f5038483SAlexander Graf 
322a911b7a9SAlexander Graf     snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET);
323a911b7a9SAlexander Graf     qemu_devtree_add_subnode(fdt, msi);
324a911b7a9SAlexander Graf     qemu_devtree_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi");
325a911b7a9SAlexander Graf     qemu_devtree_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200);
326a911b7a9SAlexander Graf     msi_ph = qemu_devtree_alloc_phandle(fdt);
327a911b7a9SAlexander Graf     qemu_devtree_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100);
328a911b7a9SAlexander Graf     qemu_devtree_setprop_phandle(fdt, msi, "interrupt-parent", mpic);
329a911b7a9SAlexander Graf     qemu_devtree_setprop_cells(fdt, msi, "interrupts",
330a911b7a9SAlexander Graf         0xe0, 0x0,
331a911b7a9SAlexander Graf         0xe1, 0x0,
332a911b7a9SAlexander Graf         0xe2, 0x0,
333a911b7a9SAlexander Graf         0xe3, 0x0,
334a911b7a9SAlexander Graf         0xe4, 0x0,
335a911b7a9SAlexander Graf         0xe5, 0x0,
336a911b7a9SAlexander Graf         0xe6, 0x0,
337a911b7a9SAlexander Graf         0xe7, 0x0);
338a911b7a9SAlexander Graf     qemu_devtree_setprop_cell(fdt, msi, "phandle", msi_ph);
339a911b7a9SAlexander Graf     qemu_devtree_setprop_cell(fdt, msi, "linux,phandle", msi_ph);
340a911b7a9SAlexander Graf 
341ed2bc496SAlexander Graf     snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE);
3420dbc0798SAlexander Graf     qemu_devtree_add_subnode(fdt, pci);
3430dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0);
3440dbc0798SAlexander Graf     qemu_devtree_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci");
3450dbc0798SAlexander Graf     qemu_devtree_setprop_string(fdt, pci, "device_type", "pci");
3460dbc0798SAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0,
3470dbc0798SAlexander Graf                                0x0, 0x7);
348347dd79dSAlexander Graf     pci_map = pci_map_create(fdt, qemu_devtree_get_phandle(fdt, mpic),
349492ec48dSAlexander Graf                              params->pci_first_slot, params->pci_nr_slots,
350492ec48dSAlexander Graf                              &len);
351347dd79dSAlexander Graf     qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, len);
3520dbc0798SAlexander Graf     qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic);
3537e99826cSAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2);
3540dbc0798SAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255);
3553627757eSAlexander Graf     for (i = 0; i < 14; i++) {
3560dbc0798SAlexander Graf         pci_ranges[i] = cpu_to_be32(pci_ranges[i]);
3570dbc0798SAlexander Graf     }
358a911b7a9SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "fsl,msi", msi_ph);
3590dbc0798SAlexander Graf     qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges));
3603627757eSAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32,
3613627757eSAlexander Graf                                MPC8544_PCI_REGS_BASE, 0, 0x1000);
3620dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "clock-frequency", 66666666);
3630dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "#interrupt-cells", 1);
3640dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "#size-cells", 2);
3650dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3);
3660dbc0798SAlexander Graf     qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci);
3670dbc0798SAlexander Graf 
368e6eaabebSScott Wood     params->fixup_devtree(params, fdt);
369e6eaabebSScott Wood 
370e6eaabebSScott Wood     if (toplevel_compat) {
371e6eaabebSScott Wood         qemu_devtree_setprop(fdt, "/", "compatible", toplevel_compat,
372e6eaabebSScott Wood                              strlen(toplevel_compat) + 1);
373e6eaabebSScott Wood     }
374e6eaabebSScott Wood 
375d1b93565SAlexander Graf done:
37671193433SAlexander Graf     qemu_devtree_dumpdtb(fdt, fdt_size);
37704088adbSLiu Yu     ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
378cba2026aSAlexander Graf     if (ret < 0) {
379cba2026aSAlexander Graf         goto out;
380cba2026aSAlexander Graf     }
3817267c094SAnthony Liguori     g_free(fdt);
382cba2026aSAlexander Graf     ret = fdt_size;
3837ec632b4Spbrook 
3841db09b84Saurel32 out:
385347dd79dSAlexander Graf     g_free(pci_map);
3861db09b84Saurel32 
38704088adbSLiu Yu     return ret;
3881db09b84Saurel32 }
3891db09b84Saurel32 
390cba2026aSAlexander Graf /* Create -kernel TLB entries for BookE.  */
391a8170e5eSAvi Kivity static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
392d1e256feSAlexander Graf {
393cba2026aSAlexander Graf     return 63 - clz64(size >> 10);
394d1e256feSAlexander Graf }
395d1e256feSAlexander Graf 
396cba2026aSAlexander Graf static void mmubooke_create_initial_mapping(CPUPPCState *env)
3973b989d49SAlexander Graf {
398cba2026aSAlexander Graf     struct boot_info *bi = env->load_info;
399d1e256feSAlexander Graf     ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0);
400a8170e5eSAvi Kivity     hwaddr size, dt_end;
401cba2026aSAlexander Graf     int ps;
4023b989d49SAlexander Graf 
403cba2026aSAlexander Graf     /* Our initial TLB entry needs to cover everything from 0 to
404cba2026aSAlexander Graf        the device tree top */
405cba2026aSAlexander Graf     dt_end = bi->dt_base + bi->dt_size;
406cba2026aSAlexander Graf     ps = booke206_page_size_to_tlb(dt_end) + 1;
407fb37c302SAlexander Graf     if (ps & 1) {
408fb37c302SAlexander Graf         /* e500v2 can only do even TLB size bits */
409fb37c302SAlexander Graf         ps++;
410fb37c302SAlexander Graf     }
411cba2026aSAlexander Graf     size = (ps << MAS1_TSIZE_SHIFT);
412d1e256feSAlexander Graf     tlb->mas1 = MAS1_VALID | size;
413cba2026aSAlexander Graf     tlb->mas2 = 0;
414cba2026aSAlexander Graf     tlb->mas7_3 = 0;
415d1e256feSAlexander Graf     tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
41693dd5e85SScott Wood 
41793dd5e85SScott Wood     env->tlb_dirty = true;
4183b989d49SAlexander Graf }
4193b989d49SAlexander Graf 
420b3305981SScott Wood static void ppce500_cpu_reset_sec(void *opaque)
4215c145dacSAlexander Graf {
42238f92da6SAndreas Färber     PowerPCCPU *cpu = opaque;
423259186a7SAndreas Färber     CPUState *cs = CPU(cpu);
42438f92da6SAndreas Färber     CPUPPCState *env = &cpu->env;
4255c145dacSAlexander Graf 
426259186a7SAndreas Färber     cpu_reset(cs);
4275c145dacSAlexander Graf 
4285c145dacSAlexander Graf     /* Secondary CPU starts in halted state for now. Needs to change when
4295c145dacSAlexander Graf        implementing non-kernel boot. */
430259186a7SAndreas Färber     cs->halted = 1;
4315c145dacSAlexander Graf     env->exception_index = EXCP_HLT;
4323b989d49SAlexander Graf }
4333b989d49SAlexander Graf 
434b3305981SScott Wood static void ppce500_cpu_reset(void *opaque)
4353b989d49SAlexander Graf {
43638f92da6SAndreas Färber     PowerPCCPU *cpu = opaque;
437259186a7SAndreas Färber     CPUState *cs = CPU(cpu);
43838f92da6SAndreas Färber     CPUPPCState *env = &cpu->env;
4393b989d49SAlexander Graf     struct boot_info *bi = env->load_info;
4403b989d49SAlexander Graf 
441259186a7SAndreas Färber     cpu_reset(cs);
4423b989d49SAlexander Graf 
4433b989d49SAlexander Graf     /* Set initial guest state. */
444259186a7SAndreas Färber     cs->halted = 0;
4453b989d49SAlexander Graf     env->gpr[1] = (16<<20) - 8;
4463b989d49SAlexander Graf     env->gpr[3] = bi->dt_base;
4473b989d49SAlexander Graf     env->nip = bi->entry;
448cba2026aSAlexander Graf     mmubooke_create_initial_mapping(env);
4493b989d49SAlexander Graf }
4503b989d49SAlexander Graf 
451e6eaabebSScott Wood void ppce500_init(PPCE500Params *params)
4521db09b84Saurel32 {
45339186d8aSRichard Henderson     MemoryRegion *address_space_mem = get_system_memory();
4542646c133SAvi Kivity     MemoryRegion *ram = g_new(MemoryRegion, 1);
4551db09b84Saurel32     PCIBus *pci_bus;
456e2684c0bSAndreas Färber     CPUPPCState *env = NULL;
4571db09b84Saurel32     uint64_t elf_entry;
4581db09b84Saurel32     uint64_t elf_lowaddr;
459a8170e5eSAvi Kivity     hwaddr entry=0;
460a8170e5eSAvi Kivity     hwaddr loadaddr=UIMAGE_LOAD_BASE;
4611db09b84Saurel32     target_long kernel_size=0;
46275bb6589SLiu Yu     target_ulong dt_base = 0;
46375bb6589SLiu Yu     target_ulong initrd_base = 0;
4641db09b84Saurel32     target_long initrd_size = 0;
465528e536eSAlexander Graf     target_ulong cur_base = 0;
466d0b72631SAlexander Graf     int i = 0, j, k;
4671db09b84Saurel32     unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
468a915249fSAlexander Graf     qemu_irq **irqs, *mpic;
469be13cc7aSAlexander Graf     DeviceState *dev;
470e2684c0bSAndreas Färber     CPUPPCState *firstenv = NULL;
4713eddc1beSBharat Bhushan     MemoryRegion *ccsr_addr_space;
472dffb1dc2SBharat Bhushan     SysBusDevice *s;
4733eddc1beSBharat Bhushan     PPCE500CCSRState *ccsr;
4741db09b84Saurel32 
475e61c36d5SAlexander Graf     /* Setup CPUs */
476e6eaabebSScott Wood     if (params->cpu_model == NULL) {
477e6eaabebSScott Wood         params->cpu_model = "e500v2_v30";
478ef250db6SAlexander Graf     }
479ef250db6SAlexander Graf 
480a915249fSAlexander Graf     irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
481a915249fSAlexander Graf     irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
482e61c36d5SAlexander Graf     for (i = 0; i < smp_cpus; i++) {
483397b457dSAndreas Färber         PowerPCCPU *cpu;
48455e5c285SAndreas Färber         CPUState *cs;
485e61c36d5SAlexander Graf         qemu_irq *input;
486397b457dSAndreas Färber 
487e6eaabebSScott Wood         cpu = cpu_ppc_init(params->cpu_model);
488397b457dSAndreas Färber         if (cpu == NULL) {
4891db09b84Saurel32             fprintf(stderr, "Unable to initialize CPU!\n");
4901db09b84Saurel32             exit(1);
4911db09b84Saurel32         }
492397b457dSAndreas Färber         env = &cpu->env;
49355e5c285SAndreas Färber         cs = CPU(cpu);
4941db09b84Saurel32 
495e61c36d5SAlexander Graf         if (!firstenv) {
496e61c36d5SAlexander Graf             firstenv = env;
497e61c36d5SAlexander Graf         }
498e61c36d5SAlexander Graf 
499a915249fSAlexander Graf         irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB);
500a915249fSAlexander Graf         input = (qemu_irq *)env->irq_inputs;
501a915249fSAlexander Graf         irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
502a915249fSAlexander Graf         irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
50355e5c285SAndreas Färber         env->spr[SPR_BOOKE_PIR] = cs->cpu_index = i;
50468c2dd70SAlexander Graf         env->mpic_iack = MPC8544_CCSRBAR_BASE +
505bd25922eSScott Wood                          MPC8544_MPIC_REGS_OFFSET + 0xa0;
506e61c36d5SAlexander Graf 
507a34a92b9SAndreas Färber         ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500);
5083b989d49SAlexander Graf 
5093b989d49SAlexander Graf         /* Register reset handler */
5105c145dacSAlexander Graf         if (!i) {
5115c145dacSAlexander Graf             /* Primary CPU */
5125c145dacSAlexander Graf             struct boot_info *boot_info;
513e61c36d5SAlexander Graf             boot_info = g_malloc0(sizeof(struct boot_info));
514b3305981SScott Wood             qemu_register_reset(ppce500_cpu_reset, cpu);
515e61c36d5SAlexander Graf             env->load_info = boot_info;
5165c145dacSAlexander Graf         } else {
5175c145dacSAlexander Graf             /* Secondary CPUs */
518b3305981SScott Wood             qemu_register_reset(ppce500_cpu_reset_sec, cpu);
5195c145dacSAlexander Graf         }
520e61c36d5SAlexander Graf     }
521e61c36d5SAlexander Graf 
522e61c36d5SAlexander Graf     env = firstenv;
5233b989d49SAlexander Graf 
5241db09b84Saurel32     /* Fixup Memory size on a alignment boundary */
5251db09b84Saurel32     ram_size &= ~(RAM_SIZES_ALIGN - 1);
5261db09b84Saurel32 
5271db09b84Saurel32     /* Register Memory */
528c5705a77SAvi Kivity     memory_region_init_ram(ram, "mpc8544ds.ram", ram_size);
529c5705a77SAvi Kivity     vmstate_register_ram_global(ram);
5302646c133SAvi Kivity     memory_region_add_subregion(address_space_mem, 0, ram);
5311db09b84Saurel32 
5323eddc1beSBharat Bhushan     dev = qdev_create(NULL, "e500-ccsr");
5333eddc1beSBharat Bhushan     object_property_add_child(qdev_get_machine(), "e500-ccsr",
5343eddc1beSBharat Bhushan                               OBJECT(dev), NULL);
5353eddc1beSBharat Bhushan     qdev_init_nofail(dev);
5363eddc1beSBharat Bhushan     ccsr = CCSR(dev);
5373eddc1beSBharat Bhushan     ccsr_addr_space = &ccsr->ccsr_space;
5383eddc1beSBharat Bhushan     memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE,
5393eddc1beSBharat Bhushan                                 ccsr_addr_space);
540dffb1dc2SBharat Bhushan 
5411db09b84Saurel32     /* MPIC */
542d0b72631SAlexander Graf     mpic = g_new(qemu_irq, 256);
543d0b72631SAlexander Graf     dev = qdev_create(NULL, "openpic");
544d0b72631SAlexander Graf     qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
545f5fba9d2SScott Wood     qdev_prop_set_uint32(dev, "model", params->mpic_version);
546d0b72631SAlexander Graf     qdev_init_nofail(dev);
5471356b98dSAndreas Färber     s = SYS_BUS_DEVICE(dev);
548a915249fSAlexander Graf 
549d0b72631SAlexander Graf     k = 0;
550d0b72631SAlexander Graf     for (i = 0; i < smp_cpus; i++) {
551d0b72631SAlexander Graf         for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
552d0b72631SAlexander Graf             sysbus_connect_irq(s, k++, irqs[i][j]);
553a915249fSAlexander Graf         }
554d0b72631SAlexander Graf     }
555d0b72631SAlexander Graf 
556d0b72631SAlexander Graf     for (i = 0; i < 256; i++) {
557d0b72631SAlexander Graf         mpic[i] = qdev_get_gpio_in(dev, i);
558d0b72631SAlexander Graf     }
559d0b72631SAlexander Graf 
560d0b72631SAlexander Graf     memory_region_add_subregion(ccsr_addr_space, MPC8544_MPIC_REGS_OFFSET,
561d0b72631SAlexander Graf                                 s->mmio[0].memory);
5621db09b84Saurel32 
5631db09b84Saurel32     /* Serial */
5642d48377aSBlue Swirl     if (serial_hds[0]) {
5653eddc1beSBharat Bhushan         serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET,
566cdbb912aSAlexander Graf                        0, mpic[42], 399193,
5672ff0c7c3SRichard Henderson                        serial_hds[0], DEVICE_BIG_ENDIAN);
5682d48377aSBlue Swirl     }
5691db09b84Saurel32 
5702d48377aSBlue Swirl     if (serial_hds[1]) {
5713eddc1beSBharat Bhushan         serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET,
572cdbb912aSAlexander Graf                        0, mpic[42], 399193,
57359de4f98SBharat Bhushan                        serial_hds[1], DEVICE_BIG_ENDIAN);
5742d48377aSBlue Swirl     }
5751db09b84Saurel32 
576b0fb8423SAlexander Graf     /* General Utility device */
577dffb1dc2SBharat Bhushan     dev = qdev_create(NULL, "mpc8544-guts");
578dffb1dc2SBharat Bhushan     qdev_init_nofail(dev);
579dffb1dc2SBharat Bhushan     s = SYS_BUS_DEVICE(dev);
5803eddc1beSBharat Bhushan     memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET,
581dffb1dc2SBharat Bhushan                                 sysbus_mmio_get_region(s, 0));
582b0fb8423SAlexander Graf 
5831db09b84Saurel32     /* PCI */
584dffb1dc2SBharat Bhushan     dev = qdev_create(NULL, "e500-pcihost");
585492ec48dSAlexander Graf     qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot);
586dffb1dc2SBharat Bhushan     qdev_init_nofail(dev);
587dffb1dc2SBharat Bhushan     s = SYS_BUS_DEVICE(dev);
588dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 0, mpic[pci_irq_nrs[0]]);
589dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 1, mpic[pci_irq_nrs[1]]);
590dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 2, mpic[pci_irq_nrs[2]]);
591dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 3, mpic[pci_irq_nrs[3]]);
5923eddc1beSBharat Bhushan     memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET,
593dffb1dc2SBharat Bhushan                                 sysbus_mmio_get_region(s, 0));
594dffb1dc2SBharat Bhushan 
595d461e3b9SAlexander Graf     pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
5961db09b84Saurel32     if (!pci_bus)
5971db09b84Saurel32         printf("couldn't create PCI controller!\n");
5981db09b84Saurel32 
5991356b98dSAndreas Färber     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, MPC8544_PCI_IO);
6001db09b84Saurel32 
6011db09b84Saurel32     if (pci_bus) {
6021db09b84Saurel32         /* Register network interfaces. */
6031db09b84Saurel32         for (i = 0; i < nb_nics; i++) {
60407caea31SMarkus Armbruster             pci_nic_init_nofail(&nd_table[i], "virtio", NULL);
6051db09b84Saurel32         }
6061db09b84Saurel32     }
6071db09b84Saurel32 
6085c145dacSAlexander Graf     /* Register spinning region */
6095c145dacSAlexander Graf     sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL);
6105c145dacSAlexander Graf 
6111db09b84Saurel32     /* Load kernel. */
612e6eaabebSScott Wood     if (params->kernel_filename) {
613e6eaabebSScott Wood         kernel_size = load_uimage(params->kernel_filename, &entry,
614e6eaabebSScott Wood                                   &loadaddr, NULL);
6151db09b84Saurel32         if (kernel_size < 0) {
616e6eaabebSScott Wood             kernel_size = load_elf(params->kernel_filename, NULL, NULL,
617e6eaabebSScott Wood                                    &elf_entry, &elf_lowaddr, NULL, 1,
618e6eaabebSScott Wood                                    ELF_MACHINE, 0);
6191db09b84Saurel32             entry = elf_entry;
6201db09b84Saurel32             loadaddr = elf_lowaddr;
6211db09b84Saurel32         }
6221db09b84Saurel32         /* XXX try again as binary */
6231db09b84Saurel32         if (kernel_size < 0) {
6241db09b84Saurel32             fprintf(stderr, "qemu: could not load kernel '%s'\n",
625e6eaabebSScott Wood                     params->kernel_filename);
6261db09b84Saurel32             exit(1);
6271db09b84Saurel32         }
628528e536eSAlexander Graf 
629528e536eSAlexander Graf         cur_base = loadaddr + kernel_size;
630b8dec144SAlexander Graf 
631b8dec144SAlexander Graf         /* Reserve space for dtb */
632b8dec144SAlexander Graf         dt_base = (cur_base + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
633b8dec144SAlexander Graf         cur_base += DTB_MAX_SIZE;
6341db09b84Saurel32     }
6351db09b84Saurel32 
6361db09b84Saurel32     /* Load initrd. */
637e6eaabebSScott Wood     if (params->initrd_filename) {
638528e536eSAlexander Graf         initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK;
639e6eaabebSScott Wood         initrd_size = load_image_targphys(params->initrd_filename, initrd_base,
640d7585251Spbrook                                           ram_size - initrd_base);
6411db09b84Saurel32 
6421db09b84Saurel32         if (initrd_size < 0) {
6431db09b84Saurel32             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
644e6eaabebSScott Wood                     params->initrd_filename);
6451db09b84Saurel32             exit(1);
6461db09b84Saurel32         }
647528e536eSAlexander Graf 
648528e536eSAlexander Graf         cur_base = initrd_base + initrd_size;
6491db09b84Saurel32     }
6501db09b84Saurel32 
6511db09b84Saurel32     /* If we're loading a kernel directly, we must load the device tree too. */
652e6eaabebSScott Wood     if (params->kernel_filename) {
6535c145dacSAlexander Graf         struct boot_info *boot_info;
654cba2026aSAlexander Graf         int dt_size;
6555c145dacSAlexander Graf 
656e6eaabebSScott Wood         dt_size = ppce500_load_device_tree(env, params, dt_base, initrd_base,
657e6eaabebSScott Wood                                            initrd_size);
658cba2026aSAlexander Graf         if (dt_size < 0) {
6591db09b84Saurel32             fprintf(stderr, "couldn't load device tree\n");
6601db09b84Saurel32             exit(1);
6611db09b84Saurel32         }
662b8dec144SAlexander Graf         assert(dt_size < DTB_MAX_SIZE);
6631db09b84Saurel32 
664e61c36d5SAlexander Graf         boot_info = env->load_info;
6653b989d49SAlexander Graf         boot_info->entry = entry;
6663b989d49SAlexander Graf         boot_info->dt_base = dt_base;
667cba2026aSAlexander Graf         boot_info->dt_size = dt_size;
6681db09b84Saurel32     }
6691db09b84Saurel32 
6703b989d49SAlexander Graf     if (kvm_enabled()) {
6711db09b84Saurel32         kvmppc_init();
6723b989d49SAlexander Graf     }
6731db09b84Saurel32 }
6743eddc1beSBharat Bhushan 
6753eddc1beSBharat Bhushan static int e500_ccsr_initfn(SysBusDevice *dev)
6763eddc1beSBharat Bhushan {
6773eddc1beSBharat Bhushan     PPCE500CCSRState *ccsr;
6783eddc1beSBharat Bhushan 
6793eddc1beSBharat Bhushan     ccsr = CCSR(dev);
6803eddc1beSBharat Bhushan     memory_region_init(&ccsr->ccsr_space, "e500-ccsr",
6813eddc1beSBharat Bhushan                        MPC8544_CCSRBAR_SIZE);
6823eddc1beSBharat Bhushan     return 0;
6833eddc1beSBharat Bhushan }
6843eddc1beSBharat Bhushan 
6853eddc1beSBharat Bhushan static void e500_ccsr_class_init(ObjectClass *klass, void *data)
6863eddc1beSBharat Bhushan {
6873eddc1beSBharat Bhushan     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
6883eddc1beSBharat Bhushan     k->init = e500_ccsr_initfn;
6893eddc1beSBharat Bhushan }
6903eddc1beSBharat Bhushan 
6913eddc1beSBharat Bhushan static const TypeInfo e500_ccsr_info = {
6923eddc1beSBharat Bhushan     .name          = TYPE_CCSR,
6933eddc1beSBharat Bhushan     .parent        = TYPE_SYS_BUS_DEVICE,
6943eddc1beSBharat Bhushan     .instance_size = sizeof(PPCE500CCSRState),
6953eddc1beSBharat Bhushan     .class_init    = e500_ccsr_class_init,
6963eddc1beSBharat Bhushan };
6973eddc1beSBharat Bhushan 
6983eddc1beSBharat Bhushan static void e500_register_types(void)
6993eddc1beSBharat Bhushan {
7003eddc1beSBharat Bhushan     type_register_static(&e500_ccsr_info);
7013eddc1beSBharat Bhushan }
7023eddc1beSBharat Bhushan 
7033eddc1beSBharat Bhushan type_init(e500_register_types)
704