xref: /qemu/hw/ppc/e500.c (revision 29b358f93a48a415853d11fc9b02f711b5ec8f76)
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"
240d09e41aSPaolo 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"
310d09e41aSPaolo Bonzini #include "hw/ppc/openpic.h"
320d09e41aSPaolo 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"
380d09e41aSPaolo Bonzini #include "hw/pci-host/ppce500.h"
391db09b84Saurel32 
40cefd3cdbSBharat Bhushan #define EPAPR_MAGIC                (0x45504150)
411db09b84Saurel32 #define BINARY_DEVICE_TREE_FILE    "mpc8544ds.dtb"
421db09b84Saurel32 #define UIMAGE_LOAD_BASE           0
439dd5eba1SScott Wood #define DTC_LOAD_PAD               0x1800000
4475bb6589SLiu Yu #define DTC_PAD_MASK               0xFFFFF
45b8dec144SAlexander Graf #define DTB_MAX_SIZE               (8 * 1024 * 1024)
4675bb6589SLiu Yu #define INITRD_LOAD_PAD            0x2000000
4775bb6589SLiu Yu #define INITRD_PAD_MASK            0xFFFFFF
481db09b84Saurel32 
491db09b84Saurel32 #define RAM_SIZES_ALIGN            (64UL << 20)
501db09b84Saurel32 
51b3305981SScott Wood /* TODO: parameterize */
52ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_BASE       0xE0000000ULL
53ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_SIZE       0x00100000ULL
54dffb1dc2SBharat Bhushan #define MPC8544_MPIC_REGS_OFFSET   0x40000ULL
55a911b7a9SAlexander Graf #define MPC8544_MSI_REGS_OFFSET   0x41600ULL
56dffb1dc2SBharat Bhushan #define MPC8544_SERIAL0_REGS_OFFSET 0x4500ULL
57dffb1dc2SBharat Bhushan #define MPC8544_SERIAL1_REGS_OFFSET 0x4600ULL
58dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_OFFSET    0x8000ULL
59dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_BASE      (MPC8544_CCSRBAR_BASE + \
60dffb1dc2SBharat Bhushan                                     MPC8544_PCI_REGS_OFFSET)
61ed2bc496SAlexander Graf #define MPC8544_PCI_REGS_SIZE      0x1000ULL
62ed2bc496SAlexander Graf #define MPC8544_PCI_IO             0xE1000000ULL
63dffb1dc2SBharat Bhushan #define MPC8544_UTIL_OFFSET        0xe0000ULL
64ed2bc496SAlexander Graf #define MPC8544_SPIN_BASE          0xEF000000ULL
651db09b84Saurel32 
663b989d49SAlexander Graf struct boot_info
673b989d49SAlexander Graf {
683b989d49SAlexander Graf     uint32_t dt_base;
69cba2026aSAlexander Graf     uint32_t dt_size;
703b989d49SAlexander Graf     uint32_t entry;
713b989d49SAlexander Graf };
723b989d49SAlexander Graf 
73347dd79dSAlexander Graf static uint32_t *pci_map_create(void *fdt, uint32_t mpic, int first_slot,
74347dd79dSAlexander Graf                                 int nr_slots, int *len)
750dbc0798SAlexander Graf {
76347dd79dSAlexander Graf     int i = 0;
77347dd79dSAlexander Graf     int slot;
78347dd79dSAlexander Graf     int pci_irq;
799e2c1298SAlexander Graf     int host_irq;
80347dd79dSAlexander Graf     int last_slot = first_slot + nr_slots;
81347dd79dSAlexander Graf     uint32_t *pci_map;
820dbc0798SAlexander Graf 
83347dd79dSAlexander Graf     *len = nr_slots * 4 * 7 * sizeof(uint32_t);
84347dd79dSAlexander Graf     pci_map = g_malloc(*len);
85347dd79dSAlexander Graf 
86347dd79dSAlexander Graf     for (slot = first_slot; slot < last_slot; slot++) {
87347dd79dSAlexander Graf         for (pci_irq = 0; pci_irq < 4; pci_irq++) {
88347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(slot << 11);
89347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(0x0);
90347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(0x0);
91347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(pci_irq + 1);
92347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(mpic);
939e2c1298SAlexander Graf             host_irq = ppce500_pci_map_irq_slot(slot, pci_irq);
949e2c1298SAlexander Graf             pci_map[i++] = cpu_to_be32(host_irq + 1);
95347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(0x1);
960dbc0798SAlexander Graf         }
970dbc0798SAlexander Graf     }
980dbc0798SAlexander Graf 
99347dd79dSAlexander Graf     assert((i * sizeof(uint32_t)) == *len);
100347dd79dSAlexander Graf 
101347dd79dSAlexander Graf     return pci_map;
102347dd79dSAlexander Graf }
103347dd79dSAlexander Graf 
104a053a7ceSAlexander Graf static void dt_serial_create(void *fdt, unsigned long long offset,
105a053a7ceSAlexander Graf                              const char *soc, const char *mpic,
106a053a7ceSAlexander Graf                              const char *alias, int idx, bool defcon)
107a053a7ceSAlexander Graf {
108a053a7ceSAlexander Graf     char ser[128];
109a053a7ceSAlexander Graf 
110a053a7ceSAlexander Graf     snprintf(ser, sizeof(ser), "%s/serial@%llx", soc, offset);
111a053a7ceSAlexander Graf     qemu_devtree_add_subnode(fdt, ser);
112a053a7ceSAlexander Graf     qemu_devtree_setprop_string(fdt, ser, "device_type", "serial");
113a053a7ceSAlexander Graf     qemu_devtree_setprop_string(fdt, ser, "compatible", "ns16550");
114a053a7ceSAlexander Graf     qemu_devtree_setprop_cells(fdt, ser, "reg", offset, 0x100);
115a053a7ceSAlexander Graf     qemu_devtree_setprop_cell(fdt, ser, "cell-index", idx);
116a053a7ceSAlexander Graf     qemu_devtree_setprop_cell(fdt, ser, "clock-frequency", 0);
1177e99826cSAlexander Graf     qemu_devtree_setprop_cells(fdt, ser, "interrupts", 42, 2);
118a053a7ceSAlexander Graf     qemu_devtree_setprop_phandle(fdt, ser, "interrupt-parent", mpic);
119a053a7ceSAlexander Graf     qemu_devtree_setprop_string(fdt, "/aliases", alias, ser);
120a053a7ceSAlexander Graf 
121a053a7ceSAlexander Graf     if (defcon) {
122a053a7ceSAlexander Graf         qemu_devtree_setprop_string(fdt, "/chosen", "linux,stdout-path", ser);
123a053a7ceSAlexander Graf     }
124a053a7ceSAlexander Graf }
125a053a7ceSAlexander Graf 
126b3305981SScott Wood static int ppce500_load_device_tree(CPUPPCState *env,
127e6eaabebSScott Wood                                     PPCE500Params *params,
128a8170e5eSAvi Kivity                                     hwaddr addr,
129a8170e5eSAvi Kivity                                     hwaddr initrd_base,
130a8170e5eSAvi Kivity                                     hwaddr initrd_size)
1311db09b84Saurel32 {
132dbf916d8SAurelien Jarno     int ret = -1;
133e6eaabebSScott Wood     uint64_t mem_reg_property[] = { 0, cpu_to_be64(params->ram_size) };
1347ec632b4Spbrook     int fdt_size;
135dbf916d8SAurelien Jarno     void *fdt;
1365de6b46dSAlexander Graf     uint8_t hypercall[16];
137911d6e7aSAlexander Graf     uint32_t clock_freq = 400000000;
138911d6e7aSAlexander Graf     uint32_t tb_freq = 400000000;
139621d05e3SAlexander Graf     int i;
140e6eaabebSScott Wood     const char *toplevel_compat = NULL; /* user override */
141ebb9518aSAlexander Graf     char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus";
1425da96624SAlexander Graf     char soc[128];
14319ac9deaSAlexander Graf     char mpic[128];
14419ac9deaSAlexander Graf     uint32_t mpic_ph;
145a911b7a9SAlexander Graf     uint32_t msi_ph;
146f5038483SAlexander Graf     char gutil[128];
1470dbc0798SAlexander Graf     char pci[128];
148a911b7a9SAlexander Graf     char msi[128];
149347dd79dSAlexander Graf     uint32_t *pci_map = NULL;
150347dd79dSAlexander Graf     int len;
1513627757eSAlexander Graf     uint32_t pci_ranges[14] =
1523627757eSAlexander Graf         {
1533627757eSAlexander Graf             0x2000000, 0x0, 0xc0000000,
1543627757eSAlexander Graf             0x0, 0xc0000000,
1553627757eSAlexander Graf             0x0, 0x20000000,
1563627757eSAlexander Graf 
1573627757eSAlexander Graf             0x1000000, 0x0, 0x0,
1583627757eSAlexander Graf             0x0, 0xe1000000,
1593627757eSAlexander Graf             0x0, 0x10000,
1603627757eSAlexander Graf         };
16125b42708SAlexander Graf     QemuOpts *machine_opts;
162d1b93565SAlexander Graf     const char *dtb_file = NULL;
163d1b93565SAlexander Graf 
164d1b93565SAlexander Graf     machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
165d1b93565SAlexander Graf     if (machine_opts) {
166d1b93565SAlexander Graf         dtb_file = qemu_opt_get(machine_opts, "dtb");
167e6eaabebSScott Wood         toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
168d1b93565SAlexander Graf     }
169d1b93565SAlexander Graf 
170d1b93565SAlexander Graf     if (dtb_file) {
171d1b93565SAlexander Graf         char *filename;
172d1b93565SAlexander Graf         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file);
173d1b93565SAlexander Graf         if (!filename) {
174d1b93565SAlexander Graf             goto out;
175d1b93565SAlexander Graf         }
176d1b93565SAlexander Graf 
177d1b93565SAlexander Graf         fdt = load_device_tree(filename, &fdt_size);
178d1b93565SAlexander Graf         if (!fdt) {
179d1b93565SAlexander Graf             goto out;
180d1b93565SAlexander Graf         }
181d1b93565SAlexander Graf         goto done;
182d1b93565SAlexander Graf     }
1831db09b84Saurel32 
1842636fcb6SAlexander Graf     fdt = create_device_tree(&fdt_size);
1855cea8590SPaul Brook     if (fdt == NULL) {
1865cea8590SPaul Brook         goto out;
1875cea8590SPaul Brook     }
1881db09b84Saurel32 
1891db09b84Saurel32     /* Manipulate device tree in memory. */
1903627757eSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2);
1913627757eSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2);
19251b852b7SAlexander Graf 
193dd0bcfcaSAlexander Graf     qemu_devtree_add_subnode(fdt, "/memory");
194dd0bcfcaSAlexander Graf     qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory");
195dd0bcfcaSAlexander Graf     qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
1961db09b84Saurel32                          sizeof(mem_reg_property));
1971db09b84Saurel32 
198f5231aafSAlexander Graf     qemu_devtree_add_subnode(fdt, "/chosen");
1993b989d49SAlexander Graf     if (initrd_size) {
2001db09b84Saurel32         ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
2011db09b84Saurel32                                         initrd_base);
2023b989d49SAlexander Graf         if (ret < 0) {
2031db09b84Saurel32             fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
2043b989d49SAlexander Graf         }
2051db09b84Saurel32 
2061db09b84Saurel32         ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
2071db09b84Saurel32                                         (initrd_base + initrd_size));
2083b989d49SAlexander Graf         if (ret < 0) {
2091db09b84Saurel32             fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
2103b989d49SAlexander Graf         }
2113b989d49SAlexander Graf     }
2121db09b84Saurel32 
2131db09b84Saurel32     ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
214e6eaabebSScott Wood                                       params->kernel_cmdline);
2151db09b84Saurel32     if (ret < 0)
2161db09b84Saurel32         fprintf(stderr, "couldn't set /chosen/bootargs\n");
2171db09b84Saurel32 
2181db09b84Saurel32     if (kvm_enabled()) {
219911d6e7aSAlexander Graf         /* Read out host's frequencies */
220911d6e7aSAlexander Graf         clock_freq = kvmppc_get_clockfreq();
221911d6e7aSAlexander Graf         tb_freq = kvmppc_get_tbfreq();
2225de6b46dSAlexander Graf 
2235de6b46dSAlexander Graf         /* indicate KVM hypercall interface */
224d50f71a5SAlexander Graf         qemu_devtree_add_subnode(fdt, "/hypervisor");
2255de6b46dSAlexander Graf         qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible",
2265de6b46dSAlexander Graf                                     "linux,kvm");
2275de6b46dSAlexander Graf         kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
2285de6b46dSAlexander Graf         qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",
2295de6b46dSAlexander Graf                              hypercall, sizeof(hypercall));
2301a61a9aeSStuart Yoder         /* if KVM supports the idle hcall, set property indicating this */
2311a61a9aeSStuart Yoder         if (kvmppc_get_hasidle(env)) {
2321a61a9aeSStuart Yoder             qemu_devtree_setprop(fdt, "/hypervisor", "has-idle", NULL, 0);
2331a61a9aeSStuart Yoder         }
2341db09b84Saurel32     }
2351db09b84Saurel32 
236625e665bSAlexander Graf     /* Create CPU nodes */
237625e665bSAlexander Graf     qemu_devtree_add_subnode(fdt, "/cpus");
238625e665bSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/cpus", "#address-cells", 1);
239625e665bSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/cpus", "#size-cells", 0);
240625e665bSAlexander Graf 
2411e3debf0SAlexander Graf     /* We need to generate the cpu nodes in reverse order, so Linux can pick
2421e3debf0SAlexander Graf        the first node as boot node and be happy */
2431e3debf0SAlexander Graf     for (i = smp_cpus - 1; i >= 0; i--) {
244440c8152SAndreas Färber         CPUState *cpu;
245621d05e3SAlexander Graf         char cpu_name[128];
2461d2e5c52SAlexander Graf         uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20);
24710f25a46SAlexander Graf 
248440c8152SAndreas Färber         cpu = qemu_get_cpu(i);
24955e5c285SAndreas Färber         if (cpu == NULL) {
2501e3debf0SAlexander Graf             continue;
2511e3debf0SAlexander Graf         }
252440c8152SAndreas Färber         env = cpu->env_ptr;
2531e3debf0SAlexander Graf 
25455e5c285SAndreas Färber         snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x",
25555e5c285SAndreas Färber                  cpu->cpu_index);
2561e3debf0SAlexander Graf         qemu_devtree_add_subnode(fdt, cpu_name);
2571e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
2581e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
2591e3debf0SAlexander Graf         qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu");
26055e5c285SAndreas Färber         qemu_devtree_setprop_cell(fdt, cpu_name, "reg", cpu->cpu_index);
2611e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size",
2621e3debf0SAlexander Graf                                   env->dcache_line_size);
2631e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size",
2641e3debf0SAlexander Graf                                   env->icache_line_size);
2651e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000);
2661e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000);
2671e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0);
26855e5c285SAndreas Färber         if (cpu->cpu_index) {
2691e3debf0SAlexander Graf             qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled");
2701e3debf0SAlexander Graf             qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table");
2711d2e5c52SAlexander Graf             qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr",
2721d2e5c52SAlexander Graf                                      cpu_release_addr);
2731e3debf0SAlexander Graf         } else {
2741e3debf0SAlexander Graf             qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay");
2751e3debf0SAlexander Graf         }
2761db09b84Saurel32     }
2771db09b84Saurel32 
2780cfc6e8dSAlexander Graf     qemu_devtree_add_subnode(fdt, "/aliases");
2795da96624SAlexander Graf     /* XXX These should go into their respective devices' code */
280ed2bc496SAlexander Graf     snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE);
2815da96624SAlexander Graf     qemu_devtree_add_subnode(fdt, soc);
2825da96624SAlexander Graf     qemu_devtree_setprop_string(fdt, soc, "device_type", "soc");
283ebb9518aSAlexander Graf     qemu_devtree_setprop(fdt, soc, "compatible", compatible_sb,
284ebb9518aSAlexander Graf                          sizeof(compatible_sb));
2855da96624SAlexander Graf     qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1);
2865da96624SAlexander Graf     qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1);
2873627757eSAlexander Graf     qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0,
2883627757eSAlexander Graf                                MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE,
2895da96624SAlexander Graf                                MPC8544_CCSRBAR_SIZE);
2905da96624SAlexander Graf     /* XXX should contain a reasonable value */
2915da96624SAlexander Graf     qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0);
2925da96624SAlexander Graf 
293dffb1dc2SBharat Bhushan     snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET);
29419ac9deaSAlexander Graf     qemu_devtree_add_subnode(fdt, mpic);
29519ac9deaSAlexander Graf     qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic");
296f5fba9d2SScott Wood     qemu_devtree_setprop_string(fdt, mpic, "compatible", "fsl,mpic");
297dffb1dc2SBharat Bhushan     qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET,
298dffb1dc2SBharat Bhushan                                0x40000);
29919ac9deaSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0);
3007e99826cSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2);
30119ac9deaSAlexander Graf     mpic_ph = qemu_devtree_alloc_phandle(fdt);
30219ac9deaSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph);
30319ac9deaSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph);
30419ac9deaSAlexander Graf     qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0);
30519ac9deaSAlexander Graf 
3060cfc6e8dSAlexander Graf     /*
3070cfc6e8dSAlexander Graf      * We have to generate ser1 first, because Linux takes the first
3080cfc6e8dSAlexander Graf      * device it finds in the dt as serial output device. And we generate
3090cfc6e8dSAlexander Graf      * devices in reverse order to the dt.
3100cfc6e8dSAlexander Graf      */
311dffb1dc2SBharat Bhushan     dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET,
312a053a7ceSAlexander Graf                      soc, mpic, "serial1", 1, false);
313dffb1dc2SBharat Bhushan     dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET,
314a053a7ceSAlexander Graf                      soc, mpic, "serial0", 0, true);
3150cfc6e8dSAlexander Graf 
316ed2bc496SAlexander Graf     snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc,
317dffb1dc2SBharat Bhushan              MPC8544_UTIL_OFFSET);
318f5038483SAlexander Graf     qemu_devtree_add_subnode(fdt, gutil);
319f5038483SAlexander Graf     qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts");
320dffb1dc2SBharat Bhushan     qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000);
321f5038483SAlexander Graf     qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0);
322f5038483SAlexander Graf 
323a911b7a9SAlexander Graf     snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET);
324a911b7a9SAlexander Graf     qemu_devtree_add_subnode(fdt, msi);
325a911b7a9SAlexander Graf     qemu_devtree_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi");
326a911b7a9SAlexander Graf     qemu_devtree_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200);
327a911b7a9SAlexander Graf     msi_ph = qemu_devtree_alloc_phandle(fdt);
328a911b7a9SAlexander Graf     qemu_devtree_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100);
329a911b7a9SAlexander Graf     qemu_devtree_setprop_phandle(fdt, msi, "interrupt-parent", mpic);
330a911b7a9SAlexander Graf     qemu_devtree_setprop_cells(fdt, msi, "interrupts",
331a911b7a9SAlexander Graf         0xe0, 0x0,
332a911b7a9SAlexander Graf         0xe1, 0x0,
333a911b7a9SAlexander Graf         0xe2, 0x0,
334a911b7a9SAlexander Graf         0xe3, 0x0,
335a911b7a9SAlexander Graf         0xe4, 0x0,
336a911b7a9SAlexander Graf         0xe5, 0x0,
337a911b7a9SAlexander Graf         0xe6, 0x0,
338a911b7a9SAlexander Graf         0xe7, 0x0);
339a911b7a9SAlexander Graf     qemu_devtree_setprop_cell(fdt, msi, "phandle", msi_ph);
340a911b7a9SAlexander Graf     qemu_devtree_setprop_cell(fdt, msi, "linux,phandle", msi_ph);
341a911b7a9SAlexander Graf 
342ed2bc496SAlexander Graf     snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE);
3430dbc0798SAlexander Graf     qemu_devtree_add_subnode(fdt, pci);
3440dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0);
3450dbc0798SAlexander Graf     qemu_devtree_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci");
3460dbc0798SAlexander Graf     qemu_devtree_setprop_string(fdt, pci, "device_type", "pci");
3470dbc0798SAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0,
3480dbc0798SAlexander Graf                                0x0, 0x7);
349347dd79dSAlexander Graf     pci_map = pci_map_create(fdt, qemu_devtree_get_phandle(fdt, mpic),
350492ec48dSAlexander Graf                              params->pci_first_slot, params->pci_nr_slots,
351492ec48dSAlexander Graf                              &len);
352347dd79dSAlexander Graf     qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, len);
3530dbc0798SAlexander Graf     qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic);
3547e99826cSAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2);
3550dbc0798SAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255);
3563627757eSAlexander Graf     for (i = 0; i < 14; i++) {
3570dbc0798SAlexander Graf         pci_ranges[i] = cpu_to_be32(pci_ranges[i]);
3580dbc0798SAlexander Graf     }
359a911b7a9SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "fsl,msi", msi_ph);
3600dbc0798SAlexander Graf     qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges));
3613627757eSAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32,
3623627757eSAlexander Graf                                MPC8544_PCI_REGS_BASE, 0, 0x1000);
3630dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "clock-frequency", 66666666);
3640dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "#interrupt-cells", 1);
3650dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "#size-cells", 2);
3660dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3);
3670dbc0798SAlexander Graf     qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci);
3680dbc0798SAlexander Graf 
369e6eaabebSScott Wood     params->fixup_devtree(params, fdt);
370e6eaabebSScott Wood 
371e6eaabebSScott Wood     if (toplevel_compat) {
372e6eaabebSScott Wood         qemu_devtree_setprop(fdt, "/", "compatible", toplevel_compat,
373e6eaabebSScott Wood                              strlen(toplevel_compat) + 1);
374e6eaabebSScott Wood     }
375e6eaabebSScott Wood 
376d1b93565SAlexander Graf done:
37771193433SAlexander Graf     qemu_devtree_dumpdtb(fdt, fdt_size);
37804088adbSLiu Yu     ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
379cba2026aSAlexander Graf     if (ret < 0) {
380cba2026aSAlexander Graf         goto out;
381cba2026aSAlexander Graf     }
3827267c094SAnthony Liguori     g_free(fdt);
383cba2026aSAlexander Graf     ret = fdt_size;
3847ec632b4Spbrook 
3851db09b84Saurel32 out:
386347dd79dSAlexander Graf     g_free(pci_map);
3871db09b84Saurel32 
38804088adbSLiu Yu     return ret;
3891db09b84Saurel32 }
3901db09b84Saurel32 
391cba2026aSAlexander Graf /* Create -kernel TLB entries for BookE.  */
392a8170e5eSAvi Kivity static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
393d1e256feSAlexander Graf {
394cba2026aSAlexander Graf     return 63 - clz64(size >> 10);
395d1e256feSAlexander Graf }
396d1e256feSAlexander Graf 
397cefd3cdbSBharat Bhushan static int booke206_initial_map_tsize(CPUPPCState *env)
3983b989d49SAlexander Graf {
399cba2026aSAlexander Graf     struct boot_info *bi = env->load_info;
400cefd3cdbSBharat Bhushan     hwaddr 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     }
411cefd3cdbSBharat Bhushan     return ps;
412cefd3cdbSBharat Bhushan }
413cefd3cdbSBharat Bhushan 
414cefd3cdbSBharat Bhushan static uint64_t mmubooke_initial_mapsize(CPUPPCState *env)
415cefd3cdbSBharat Bhushan {
416cefd3cdbSBharat Bhushan     int tsize;
417cefd3cdbSBharat Bhushan 
418cefd3cdbSBharat Bhushan     tsize = booke206_initial_map_tsize(env);
419cefd3cdbSBharat Bhushan     return (1ULL << 10 << tsize);
420cefd3cdbSBharat Bhushan }
421cefd3cdbSBharat Bhushan 
422cefd3cdbSBharat Bhushan static void mmubooke_create_initial_mapping(CPUPPCState *env)
423cefd3cdbSBharat Bhushan {
424cefd3cdbSBharat Bhushan     ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0);
425cefd3cdbSBharat Bhushan     hwaddr size;
426cefd3cdbSBharat Bhushan     int ps;
427cefd3cdbSBharat Bhushan 
428cefd3cdbSBharat Bhushan     ps = booke206_initial_map_tsize(env);
429cba2026aSAlexander Graf     size = (ps << MAS1_TSIZE_SHIFT);
430d1e256feSAlexander Graf     tlb->mas1 = MAS1_VALID | size;
431cba2026aSAlexander Graf     tlb->mas2 = 0;
432cba2026aSAlexander Graf     tlb->mas7_3 = 0;
433d1e256feSAlexander Graf     tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
43493dd5e85SScott Wood 
43593dd5e85SScott Wood     env->tlb_dirty = true;
4363b989d49SAlexander Graf }
4373b989d49SAlexander Graf 
438b3305981SScott Wood static void ppce500_cpu_reset_sec(void *opaque)
4395c145dacSAlexander Graf {
44038f92da6SAndreas Färber     PowerPCCPU *cpu = opaque;
441259186a7SAndreas Färber     CPUState *cs = CPU(cpu);
44238f92da6SAndreas Färber     CPUPPCState *env = &cpu->env;
4435c145dacSAlexander Graf 
444259186a7SAndreas Färber     cpu_reset(cs);
4455c145dacSAlexander Graf 
4465c145dacSAlexander Graf     /* Secondary CPU starts in halted state for now. Needs to change when
4475c145dacSAlexander Graf        implementing non-kernel boot. */
448259186a7SAndreas Färber     cs->halted = 1;
4495c145dacSAlexander Graf     env->exception_index = EXCP_HLT;
4503b989d49SAlexander Graf }
4513b989d49SAlexander Graf 
452b3305981SScott Wood static void ppce500_cpu_reset(void *opaque)
4533b989d49SAlexander Graf {
45438f92da6SAndreas Färber     PowerPCCPU *cpu = opaque;
455259186a7SAndreas Färber     CPUState *cs = CPU(cpu);
45638f92da6SAndreas Färber     CPUPPCState *env = &cpu->env;
4573b989d49SAlexander Graf     struct boot_info *bi = env->load_info;
4583b989d49SAlexander Graf 
459259186a7SAndreas Färber     cpu_reset(cs);
4603b989d49SAlexander Graf 
4613b989d49SAlexander Graf     /* Set initial guest state. */
462259186a7SAndreas Färber     cs->halted = 0;
4633b989d49SAlexander Graf     env->gpr[1] = (16<<20) - 8;
4643b989d49SAlexander Graf     env->gpr[3] = bi->dt_base;
465cefd3cdbSBharat Bhushan     env->gpr[4] = 0;
466cefd3cdbSBharat Bhushan     env->gpr[5] = 0;
467cefd3cdbSBharat Bhushan     env->gpr[6] = EPAPR_MAGIC;
468cefd3cdbSBharat Bhushan     env->gpr[7] = mmubooke_initial_mapsize(env);
469cefd3cdbSBharat Bhushan     env->gpr[8] = 0;
470cefd3cdbSBharat Bhushan     env->gpr[9] = 0;
4713b989d49SAlexander Graf     env->nip = bi->entry;
472cba2026aSAlexander Graf     mmubooke_create_initial_mapping(env);
4733b989d49SAlexander Graf }
4743b989d49SAlexander Graf 
475d85937e6SScott Wood static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params,
47682fc73b6SScott Wood                                            qemu_irq **irqs)
47782fc73b6SScott Wood {
47882fc73b6SScott Wood     DeviceState *dev;
47982fc73b6SScott Wood     SysBusDevice *s;
48082fc73b6SScott Wood     int i, j, k;
48182fc73b6SScott Wood 
482e1766344SAndreas Färber     dev = qdev_create(NULL, TYPE_OPENPIC);
48382fc73b6SScott Wood     qdev_prop_set_uint32(dev, "model", params->mpic_version);
484d85937e6SScott Wood     qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
485d85937e6SScott Wood 
48682fc73b6SScott Wood     qdev_init_nofail(dev);
48782fc73b6SScott Wood     s = SYS_BUS_DEVICE(dev);
48882fc73b6SScott Wood 
48982fc73b6SScott Wood     k = 0;
49082fc73b6SScott Wood     for (i = 0; i < smp_cpus; i++) {
49182fc73b6SScott Wood         for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
49282fc73b6SScott Wood             sysbus_connect_irq(s, k++, irqs[i][j]);
49382fc73b6SScott Wood         }
49482fc73b6SScott Wood     }
49582fc73b6SScott Wood 
496d85937e6SScott Wood     return dev;
497d85937e6SScott Wood }
498d85937e6SScott Wood 
499d85937e6SScott Wood static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params,
500d85937e6SScott Wood                                           qemu_irq **irqs)
501d85937e6SScott Wood {
502d85937e6SScott Wood     DeviceState *dev;
503d85937e6SScott Wood     CPUPPCState *env;
504d85937e6SScott Wood     CPUState *cs;
505d85937e6SScott Wood     int r;
506d85937e6SScott Wood 
507dd49c038SAndreas Färber     dev = qdev_create(NULL, TYPE_KVM_OPENPIC);
508d85937e6SScott Wood     qdev_prop_set_uint32(dev, "model", params->mpic_version);
509d85937e6SScott Wood 
510d85937e6SScott Wood     r = qdev_init(dev);
511d85937e6SScott Wood     if (r) {
512d85937e6SScott Wood         return NULL;
513d85937e6SScott Wood     }
514d85937e6SScott Wood 
515d85937e6SScott Wood     for (env = first_cpu; env != NULL; env = env->next_cpu) {
516d85937e6SScott Wood         cs = ENV_GET_CPU(env);
517d85937e6SScott Wood 
518d85937e6SScott Wood         if (kvm_openpic_connect_vcpu(dev, cs)) {
519d85937e6SScott Wood             fprintf(stderr, "%s: failed to connect vcpu to irqchip\n",
520d85937e6SScott Wood                     __func__);
521d85937e6SScott Wood             abort();
522d85937e6SScott Wood         }
523d85937e6SScott Wood     }
524d85937e6SScott Wood 
525d85937e6SScott Wood     return dev;
526d85937e6SScott Wood }
527d85937e6SScott Wood 
528d85937e6SScott Wood static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr,
529d85937e6SScott Wood                                    qemu_irq **irqs)
530d85937e6SScott Wood {
531d85937e6SScott Wood     QemuOptsList *list;
532d85937e6SScott Wood     qemu_irq *mpic;
533d85937e6SScott Wood     DeviceState *dev = NULL;
534d85937e6SScott Wood     SysBusDevice *s;
535d85937e6SScott Wood     int i;
536d85937e6SScott Wood 
537d85937e6SScott Wood     mpic = g_new(qemu_irq, 256);
538d85937e6SScott Wood 
539d85937e6SScott Wood     if (kvm_enabled()) {
540d85937e6SScott Wood         bool irqchip_allowed = true, irqchip_required = false;
541d85937e6SScott Wood 
542d85937e6SScott Wood         list = qemu_find_opts("machine");
543d85937e6SScott Wood         if (!QTAILQ_EMPTY(&list->head)) {
544d85937e6SScott Wood             irqchip_allowed = qemu_opt_get_bool(QTAILQ_FIRST(&list->head),
545d85937e6SScott Wood                                                 "kernel_irqchip", true);
546d85937e6SScott Wood             irqchip_required = qemu_opt_get_bool(QTAILQ_FIRST(&list->head),
547d85937e6SScott Wood                                                  "kernel_irqchip", false);
548d85937e6SScott Wood         }
549d85937e6SScott Wood 
550d85937e6SScott Wood         if (irqchip_allowed) {
551d85937e6SScott Wood             dev = ppce500_init_mpic_kvm(params, irqs);
552d85937e6SScott Wood         }
553d85937e6SScott Wood 
554d85937e6SScott Wood         if (irqchip_required && !dev) {
555d85937e6SScott Wood             fprintf(stderr, "%s: irqchip requested but unavailable\n",
556d85937e6SScott Wood                     __func__);
557d85937e6SScott Wood             abort();
558d85937e6SScott Wood         }
559d85937e6SScott Wood     }
560d85937e6SScott Wood 
561d85937e6SScott Wood     if (!dev) {
562d85937e6SScott Wood         dev = ppce500_init_mpic_qemu(params, irqs);
563d85937e6SScott Wood     }
564d85937e6SScott Wood 
56582fc73b6SScott Wood     for (i = 0; i < 256; i++) {
56682fc73b6SScott Wood         mpic[i] = qdev_get_gpio_in(dev, i);
56782fc73b6SScott Wood     }
56882fc73b6SScott Wood 
569d85937e6SScott Wood     s = SYS_BUS_DEVICE(dev);
57082fc73b6SScott Wood     memory_region_add_subregion(ccsr, MPC8544_MPIC_REGS_OFFSET,
57182fc73b6SScott Wood                                 s->mmio[0].memory);
57282fc73b6SScott Wood 
57382fc73b6SScott Wood     return mpic;
57482fc73b6SScott Wood }
57582fc73b6SScott Wood 
576e6eaabebSScott Wood void ppce500_init(PPCE500Params *params)
5771db09b84Saurel32 {
57839186d8aSRichard Henderson     MemoryRegion *address_space_mem = get_system_memory();
5792646c133SAvi Kivity     MemoryRegion *ram = g_new(MemoryRegion, 1);
5801db09b84Saurel32     PCIBus *pci_bus;
581e2684c0bSAndreas Färber     CPUPPCState *env = NULL;
5821db09b84Saurel32     uint64_t elf_entry;
5831db09b84Saurel32     uint64_t elf_lowaddr;
584a8170e5eSAvi Kivity     hwaddr entry=0;
585a8170e5eSAvi Kivity     hwaddr loadaddr=UIMAGE_LOAD_BASE;
5861db09b84Saurel32     target_long kernel_size=0;
58775bb6589SLiu Yu     target_ulong dt_base = 0;
58875bb6589SLiu Yu     target_ulong initrd_base = 0;
5891db09b84Saurel32     target_long initrd_size = 0;
590528e536eSAlexander Graf     target_ulong cur_base = 0;
59182fc73b6SScott Wood     int i;
5921db09b84Saurel32     unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
593a915249fSAlexander Graf     qemu_irq **irqs, *mpic;
594be13cc7aSAlexander Graf     DeviceState *dev;
595e2684c0bSAndreas Färber     CPUPPCState *firstenv = NULL;
5963eddc1beSBharat Bhushan     MemoryRegion *ccsr_addr_space;
597dffb1dc2SBharat Bhushan     SysBusDevice *s;
5983eddc1beSBharat Bhushan     PPCE500CCSRState *ccsr;
5991db09b84Saurel32 
600e61c36d5SAlexander Graf     /* Setup CPUs */
601e6eaabebSScott Wood     if (params->cpu_model == NULL) {
602e6eaabebSScott Wood         params->cpu_model = "e500v2_v30";
603ef250db6SAlexander Graf     }
604ef250db6SAlexander Graf 
605a915249fSAlexander Graf     irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
606a915249fSAlexander Graf     irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
607e61c36d5SAlexander Graf     for (i = 0; i < smp_cpus; i++) {
608397b457dSAndreas Färber         PowerPCCPU *cpu;
60955e5c285SAndreas Färber         CPUState *cs;
610e61c36d5SAlexander Graf         qemu_irq *input;
611397b457dSAndreas Färber 
612e6eaabebSScott Wood         cpu = cpu_ppc_init(params->cpu_model);
613397b457dSAndreas Färber         if (cpu == NULL) {
6141db09b84Saurel32             fprintf(stderr, "Unable to initialize CPU!\n");
6151db09b84Saurel32             exit(1);
6161db09b84Saurel32         }
617397b457dSAndreas Färber         env = &cpu->env;
61855e5c285SAndreas Färber         cs = CPU(cpu);
6191db09b84Saurel32 
620e61c36d5SAlexander Graf         if (!firstenv) {
621e61c36d5SAlexander Graf             firstenv = env;
622e61c36d5SAlexander Graf         }
623e61c36d5SAlexander Graf 
624a915249fSAlexander Graf         irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB);
625a915249fSAlexander Graf         input = (qemu_irq *)env->irq_inputs;
626a915249fSAlexander Graf         irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
627a915249fSAlexander Graf         irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
62855e5c285SAndreas Färber         env->spr[SPR_BOOKE_PIR] = cs->cpu_index = i;
62968c2dd70SAlexander Graf         env->mpic_iack = MPC8544_CCSRBAR_BASE +
630bd25922eSScott Wood                          MPC8544_MPIC_REGS_OFFSET + 0xa0;
631e61c36d5SAlexander Graf 
632a34a92b9SAndreas Färber         ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500);
6333b989d49SAlexander Graf 
6343b989d49SAlexander Graf         /* Register reset handler */
6355c145dacSAlexander Graf         if (!i) {
6365c145dacSAlexander Graf             /* Primary CPU */
6375c145dacSAlexander Graf             struct boot_info *boot_info;
638e61c36d5SAlexander Graf             boot_info = g_malloc0(sizeof(struct boot_info));
639b3305981SScott Wood             qemu_register_reset(ppce500_cpu_reset, cpu);
640e61c36d5SAlexander Graf             env->load_info = boot_info;
6415c145dacSAlexander Graf         } else {
6425c145dacSAlexander Graf             /* Secondary CPUs */
643b3305981SScott Wood             qemu_register_reset(ppce500_cpu_reset_sec, cpu);
6445c145dacSAlexander Graf         }
645e61c36d5SAlexander Graf     }
646e61c36d5SAlexander Graf 
647e61c36d5SAlexander Graf     env = firstenv;
6483b989d49SAlexander Graf 
6491db09b84Saurel32     /* Fixup Memory size on a alignment boundary */
6501db09b84Saurel32     ram_size &= ~(RAM_SIZES_ALIGN - 1);
65143d03f29STiejun Chen     params->ram_size = ram_size;
6521db09b84Saurel32 
6531db09b84Saurel32     /* Register Memory */
654c5705a77SAvi Kivity     memory_region_init_ram(ram, "mpc8544ds.ram", ram_size);
655c5705a77SAvi Kivity     vmstate_register_ram_global(ram);
6562646c133SAvi Kivity     memory_region_add_subregion(address_space_mem, 0, ram);
6571db09b84Saurel32 
6583eddc1beSBharat Bhushan     dev = qdev_create(NULL, "e500-ccsr");
6593eddc1beSBharat Bhushan     object_property_add_child(qdev_get_machine(), "e500-ccsr",
6603eddc1beSBharat Bhushan                               OBJECT(dev), NULL);
6613eddc1beSBharat Bhushan     qdev_init_nofail(dev);
6623eddc1beSBharat Bhushan     ccsr = CCSR(dev);
6633eddc1beSBharat Bhushan     ccsr_addr_space = &ccsr->ccsr_space;
6643eddc1beSBharat Bhushan     memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE,
6653eddc1beSBharat Bhushan                                 ccsr_addr_space);
666dffb1dc2SBharat Bhushan 
66782fc73b6SScott Wood     mpic = ppce500_init_mpic(params, ccsr_addr_space, irqs);
6681db09b84Saurel32 
6691db09b84Saurel32     /* Serial */
6702d48377aSBlue Swirl     if (serial_hds[0]) {
6713eddc1beSBharat Bhushan         serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET,
672cdbb912aSAlexander Graf                        0, mpic[42], 399193,
6732ff0c7c3SRichard Henderson                        serial_hds[0], DEVICE_BIG_ENDIAN);
6742d48377aSBlue Swirl     }
6751db09b84Saurel32 
6762d48377aSBlue Swirl     if (serial_hds[1]) {
6773eddc1beSBharat Bhushan         serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET,
678cdbb912aSAlexander Graf                        0, mpic[42], 399193,
67959de4f98SBharat Bhushan                        serial_hds[1], DEVICE_BIG_ENDIAN);
6802d48377aSBlue Swirl     }
6811db09b84Saurel32 
682b0fb8423SAlexander Graf     /* General Utility device */
683dffb1dc2SBharat Bhushan     dev = qdev_create(NULL, "mpc8544-guts");
684dffb1dc2SBharat Bhushan     qdev_init_nofail(dev);
685dffb1dc2SBharat Bhushan     s = SYS_BUS_DEVICE(dev);
6863eddc1beSBharat Bhushan     memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET,
687dffb1dc2SBharat Bhushan                                 sysbus_mmio_get_region(s, 0));
688b0fb8423SAlexander Graf 
6891db09b84Saurel32     /* PCI */
690dffb1dc2SBharat Bhushan     dev = qdev_create(NULL, "e500-pcihost");
691492ec48dSAlexander Graf     qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot);
692dffb1dc2SBharat Bhushan     qdev_init_nofail(dev);
693dffb1dc2SBharat Bhushan     s = SYS_BUS_DEVICE(dev);
694dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 0, mpic[pci_irq_nrs[0]]);
695dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 1, mpic[pci_irq_nrs[1]]);
696dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 2, mpic[pci_irq_nrs[2]]);
697dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 3, mpic[pci_irq_nrs[3]]);
6983eddc1beSBharat Bhushan     memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET,
699dffb1dc2SBharat Bhushan                                 sysbus_mmio_get_region(s, 0));
700dffb1dc2SBharat Bhushan 
701d461e3b9SAlexander Graf     pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
7021db09b84Saurel32     if (!pci_bus)
7031db09b84Saurel32         printf("couldn't create PCI controller!\n");
7041db09b84Saurel32 
7051356b98dSAndreas Färber     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, MPC8544_PCI_IO);
7061db09b84Saurel32 
7071db09b84Saurel32     if (pci_bus) {
7081db09b84Saurel32         /* Register network interfaces. */
7091db09b84Saurel32         for (i = 0; i < nb_nics; i++) {
710*29b358f9SDavid Gibson             pci_nic_init_nofail(&nd_table[i], pci_bus, "virtio", NULL);
7111db09b84Saurel32         }
7121db09b84Saurel32     }
7131db09b84Saurel32 
7145c145dacSAlexander Graf     /* Register spinning region */
7155c145dacSAlexander Graf     sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL);
7165c145dacSAlexander Graf 
7171db09b84Saurel32     /* Load kernel. */
718e6eaabebSScott Wood     if (params->kernel_filename) {
719e6eaabebSScott Wood         kernel_size = load_uimage(params->kernel_filename, &entry,
720e6eaabebSScott Wood                                   &loadaddr, NULL);
7211db09b84Saurel32         if (kernel_size < 0) {
722e6eaabebSScott Wood             kernel_size = load_elf(params->kernel_filename, NULL, NULL,
723e6eaabebSScott Wood                                    &elf_entry, &elf_lowaddr, NULL, 1,
724e6eaabebSScott Wood                                    ELF_MACHINE, 0);
7251db09b84Saurel32             entry = elf_entry;
7261db09b84Saurel32             loadaddr = elf_lowaddr;
7271db09b84Saurel32         }
7281db09b84Saurel32         /* XXX try again as binary */
7291db09b84Saurel32         if (kernel_size < 0) {
7301db09b84Saurel32             fprintf(stderr, "qemu: could not load kernel '%s'\n",
731e6eaabebSScott Wood                     params->kernel_filename);
7321db09b84Saurel32             exit(1);
7331db09b84Saurel32         }
734528e536eSAlexander Graf 
735528e536eSAlexander Graf         cur_base = loadaddr + kernel_size;
736b8dec144SAlexander Graf 
737b8dec144SAlexander Graf         /* Reserve space for dtb */
738b8dec144SAlexander Graf         dt_base = (cur_base + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
739b8dec144SAlexander Graf         cur_base += DTB_MAX_SIZE;
7401db09b84Saurel32     }
7411db09b84Saurel32 
7421db09b84Saurel32     /* Load initrd. */
743e6eaabebSScott Wood     if (params->initrd_filename) {
744528e536eSAlexander Graf         initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK;
745e6eaabebSScott Wood         initrd_size = load_image_targphys(params->initrd_filename, initrd_base,
746d7585251Spbrook                                           ram_size - initrd_base);
7471db09b84Saurel32 
7481db09b84Saurel32         if (initrd_size < 0) {
7491db09b84Saurel32             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
750e6eaabebSScott Wood                     params->initrd_filename);
7511db09b84Saurel32             exit(1);
7521db09b84Saurel32         }
753528e536eSAlexander Graf 
754528e536eSAlexander Graf         cur_base = initrd_base + initrd_size;
7551db09b84Saurel32     }
7561db09b84Saurel32 
7571db09b84Saurel32     /* If we're loading a kernel directly, we must load the device tree too. */
758e6eaabebSScott Wood     if (params->kernel_filename) {
7595c145dacSAlexander Graf         struct boot_info *boot_info;
760cba2026aSAlexander Graf         int dt_size;
7615c145dacSAlexander Graf 
762e6eaabebSScott Wood         dt_size = ppce500_load_device_tree(env, params, dt_base, initrd_base,
763e6eaabebSScott Wood                                            initrd_size);
764cba2026aSAlexander Graf         if (dt_size < 0) {
7651db09b84Saurel32             fprintf(stderr, "couldn't load device tree\n");
7661db09b84Saurel32             exit(1);
7671db09b84Saurel32         }
768b8dec144SAlexander Graf         assert(dt_size < DTB_MAX_SIZE);
7691db09b84Saurel32 
770e61c36d5SAlexander Graf         boot_info = env->load_info;
7713b989d49SAlexander Graf         boot_info->entry = entry;
7723b989d49SAlexander Graf         boot_info->dt_base = dt_base;
773cba2026aSAlexander Graf         boot_info->dt_size = dt_size;
7741db09b84Saurel32     }
7751db09b84Saurel32 
7763b989d49SAlexander Graf     if (kvm_enabled()) {
7771db09b84Saurel32         kvmppc_init();
7783b989d49SAlexander Graf     }
7791db09b84Saurel32 }
7803eddc1beSBharat Bhushan 
7813eddc1beSBharat Bhushan static int e500_ccsr_initfn(SysBusDevice *dev)
7823eddc1beSBharat Bhushan {
7833eddc1beSBharat Bhushan     PPCE500CCSRState *ccsr;
7843eddc1beSBharat Bhushan 
7853eddc1beSBharat Bhushan     ccsr = CCSR(dev);
7863eddc1beSBharat Bhushan     memory_region_init(&ccsr->ccsr_space, "e500-ccsr",
7873eddc1beSBharat Bhushan                        MPC8544_CCSRBAR_SIZE);
7883eddc1beSBharat Bhushan     return 0;
7893eddc1beSBharat Bhushan }
7903eddc1beSBharat Bhushan 
7913eddc1beSBharat Bhushan static void e500_ccsr_class_init(ObjectClass *klass, void *data)
7923eddc1beSBharat Bhushan {
7933eddc1beSBharat Bhushan     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
7943eddc1beSBharat Bhushan     k->init = e500_ccsr_initfn;
7953eddc1beSBharat Bhushan }
7963eddc1beSBharat Bhushan 
7973eddc1beSBharat Bhushan static const TypeInfo e500_ccsr_info = {
7983eddc1beSBharat Bhushan     .name          = TYPE_CCSR,
7993eddc1beSBharat Bhushan     .parent        = TYPE_SYS_BUS_DEVICE,
8003eddc1beSBharat Bhushan     .instance_size = sizeof(PPCE500CCSRState),
8013eddc1beSBharat Bhushan     .class_init    = e500_ccsr_class_init,
8023eddc1beSBharat Bhushan };
8033eddc1beSBharat Bhushan 
8043eddc1beSBharat Bhushan static void e500_register_types(void)
8053eddc1beSBharat Bhushan {
8063eddc1beSBharat Bhushan     type_register_static(&e500_ccsr_info);
8073eddc1beSBharat Bhushan }
8083eddc1beSBharat Bhushan 
8093eddc1beSBharat Bhushan type_init(e500_register_types)
810