xref: /qemu/hw/ppc/e500.c (revision 28290f37e20cda27574f15be9e9499493e3d0fe8)
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 
126*28290f37SAlexander Graf static int ppce500_load_device_tree(QEMUMachineInitArgs *args,
127e6eaabebSScott Wood                                     PPCE500Params *params,
128a8170e5eSAvi Kivity                                     hwaddr addr,
129a8170e5eSAvi Kivity                                     hwaddr initrd_base,
130*28290f37SAlexander Graf                                     hwaddr initrd_size,
131*28290f37SAlexander Graf                                     bool dry_run)
1321db09b84Saurel32 {
133*28290f37SAlexander Graf     CPUPPCState *env = first_cpu->env_ptr;
134dbf916d8SAurelien Jarno     int ret = -1;
13592238367SMarkus Armbruster     uint64_t mem_reg_property[] = { 0, cpu_to_be64(args->ram_size) };
1367ec632b4Spbrook     int fdt_size;
137dbf916d8SAurelien Jarno     void *fdt;
1385de6b46dSAlexander Graf     uint8_t hypercall[16];
139911d6e7aSAlexander Graf     uint32_t clock_freq = 400000000;
140911d6e7aSAlexander Graf     uint32_t tb_freq = 400000000;
141621d05e3SAlexander Graf     int i;
142ebb9518aSAlexander Graf     char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus";
1435da96624SAlexander Graf     char soc[128];
14419ac9deaSAlexander Graf     char mpic[128];
14519ac9deaSAlexander Graf     uint32_t mpic_ph;
146a911b7a9SAlexander Graf     uint32_t msi_ph;
147f5038483SAlexander Graf     char gutil[128];
1480dbc0798SAlexander Graf     char pci[128];
149a911b7a9SAlexander Graf     char msi[128];
150347dd79dSAlexander Graf     uint32_t *pci_map = NULL;
151347dd79dSAlexander Graf     int len;
1523627757eSAlexander Graf     uint32_t pci_ranges[14] =
1533627757eSAlexander Graf         {
1543627757eSAlexander Graf             0x2000000, 0x0, 0xc0000000,
1553627757eSAlexander Graf             0x0, 0xc0000000,
1563627757eSAlexander Graf             0x0, 0x20000000,
1573627757eSAlexander Graf 
1583627757eSAlexander Graf             0x1000000, 0x0, 0x0,
1593627757eSAlexander Graf             0x0, 0xe1000000,
1603627757eSAlexander Graf             0x0, 0x10000,
1613627757eSAlexander Graf         };
1622ff3de68SMarkus Armbruster     QemuOpts *machine_opts = qemu_get_machine_opts();
1632ff3de68SMarkus Armbruster     const char *dtb_file = qemu_opt_get(machine_opts, "dtb");
1642ff3de68SMarkus Armbruster     const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
165d1b93565SAlexander Graf 
166d1b93565SAlexander Graf     if (dtb_file) {
167d1b93565SAlexander Graf         char *filename;
168d1b93565SAlexander Graf         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file);
169d1b93565SAlexander Graf         if (!filename) {
170d1b93565SAlexander Graf             goto out;
171d1b93565SAlexander Graf         }
172d1b93565SAlexander Graf 
173d1b93565SAlexander Graf         fdt = load_device_tree(filename, &fdt_size);
174d1b93565SAlexander Graf         if (!fdt) {
175d1b93565SAlexander Graf             goto out;
176d1b93565SAlexander Graf         }
177d1b93565SAlexander Graf         goto done;
178d1b93565SAlexander Graf     }
1791db09b84Saurel32 
1802636fcb6SAlexander Graf     fdt = create_device_tree(&fdt_size);
1815cea8590SPaul Brook     if (fdt == NULL) {
1825cea8590SPaul Brook         goto out;
1835cea8590SPaul Brook     }
1841db09b84Saurel32 
1851db09b84Saurel32     /* Manipulate device tree in memory. */
1863627757eSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2);
1873627757eSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2);
18851b852b7SAlexander Graf 
189dd0bcfcaSAlexander Graf     qemu_devtree_add_subnode(fdt, "/memory");
190dd0bcfcaSAlexander Graf     qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory");
191dd0bcfcaSAlexander Graf     qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
1921db09b84Saurel32                          sizeof(mem_reg_property));
1931db09b84Saurel32 
194f5231aafSAlexander Graf     qemu_devtree_add_subnode(fdt, "/chosen");
1953b989d49SAlexander Graf     if (initrd_size) {
1961db09b84Saurel32         ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
1971db09b84Saurel32                                         initrd_base);
1983b989d49SAlexander Graf         if (ret < 0) {
1991db09b84Saurel32             fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
2003b989d49SAlexander Graf         }
2011db09b84Saurel32 
2021db09b84Saurel32         ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
2031db09b84Saurel32                                         (initrd_base + initrd_size));
2043b989d49SAlexander Graf         if (ret < 0) {
2051db09b84Saurel32             fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
2063b989d49SAlexander Graf         }
2073b989d49SAlexander Graf     }
2081db09b84Saurel32 
2091db09b84Saurel32     ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
21092238367SMarkus Armbruster                                       args->kernel_cmdline);
2111db09b84Saurel32     if (ret < 0)
2121db09b84Saurel32         fprintf(stderr, "couldn't set /chosen/bootargs\n");
2131db09b84Saurel32 
2141db09b84Saurel32     if (kvm_enabled()) {
215911d6e7aSAlexander Graf         /* Read out host's frequencies */
216911d6e7aSAlexander Graf         clock_freq = kvmppc_get_clockfreq();
217911d6e7aSAlexander Graf         tb_freq = kvmppc_get_tbfreq();
2185de6b46dSAlexander Graf 
2195de6b46dSAlexander Graf         /* indicate KVM hypercall interface */
220d50f71a5SAlexander Graf         qemu_devtree_add_subnode(fdt, "/hypervisor");
2215de6b46dSAlexander Graf         qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible",
2225de6b46dSAlexander Graf                                     "linux,kvm");
2235de6b46dSAlexander Graf         kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
2245de6b46dSAlexander Graf         qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",
2255de6b46dSAlexander Graf                              hypercall, sizeof(hypercall));
2261a61a9aeSStuart Yoder         /* if KVM supports the idle hcall, set property indicating this */
2271a61a9aeSStuart Yoder         if (kvmppc_get_hasidle(env)) {
2281a61a9aeSStuart Yoder             qemu_devtree_setprop(fdt, "/hypervisor", "has-idle", NULL, 0);
2291a61a9aeSStuart Yoder         }
2301db09b84Saurel32     }
2311db09b84Saurel32 
232625e665bSAlexander Graf     /* Create CPU nodes */
233625e665bSAlexander Graf     qemu_devtree_add_subnode(fdt, "/cpus");
234625e665bSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/cpus", "#address-cells", 1);
235625e665bSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/cpus", "#size-cells", 0);
236625e665bSAlexander Graf 
2371e3debf0SAlexander Graf     /* We need to generate the cpu nodes in reverse order, so Linux can pick
2381e3debf0SAlexander Graf        the first node as boot node and be happy */
2391e3debf0SAlexander Graf     for (i = smp_cpus - 1; i >= 0; i--) {
240440c8152SAndreas Färber         CPUState *cpu;
241621d05e3SAlexander Graf         char cpu_name[128];
2421d2e5c52SAlexander Graf         uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20);
24310f25a46SAlexander Graf 
244440c8152SAndreas Färber         cpu = qemu_get_cpu(i);
24555e5c285SAndreas Färber         if (cpu == NULL) {
2461e3debf0SAlexander Graf             continue;
2471e3debf0SAlexander Graf         }
248440c8152SAndreas Färber         env = cpu->env_ptr;
2491e3debf0SAlexander Graf 
25055e5c285SAndreas Färber         snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x",
25155e5c285SAndreas Färber                  cpu->cpu_index);
2521e3debf0SAlexander Graf         qemu_devtree_add_subnode(fdt, cpu_name);
2531e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
2541e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
2551e3debf0SAlexander Graf         qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu");
25655e5c285SAndreas Färber         qemu_devtree_setprop_cell(fdt, cpu_name, "reg", cpu->cpu_index);
2571e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size",
2581e3debf0SAlexander Graf                                   env->dcache_line_size);
2591e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size",
2601e3debf0SAlexander Graf                                   env->icache_line_size);
2611e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000);
2621e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000);
2631e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0);
26455e5c285SAndreas Färber         if (cpu->cpu_index) {
2651e3debf0SAlexander Graf             qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled");
2661e3debf0SAlexander Graf             qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table");
2671d2e5c52SAlexander Graf             qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr",
2681d2e5c52SAlexander Graf                                      cpu_release_addr);
2691e3debf0SAlexander Graf         } else {
2701e3debf0SAlexander Graf             qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay");
2711e3debf0SAlexander Graf         }
2721db09b84Saurel32     }
2731db09b84Saurel32 
2740cfc6e8dSAlexander Graf     qemu_devtree_add_subnode(fdt, "/aliases");
2755da96624SAlexander Graf     /* XXX These should go into their respective devices' code */
276ed2bc496SAlexander Graf     snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE);
2775da96624SAlexander Graf     qemu_devtree_add_subnode(fdt, soc);
2785da96624SAlexander Graf     qemu_devtree_setprop_string(fdt, soc, "device_type", "soc");
279ebb9518aSAlexander Graf     qemu_devtree_setprop(fdt, soc, "compatible", compatible_sb,
280ebb9518aSAlexander Graf                          sizeof(compatible_sb));
2815da96624SAlexander Graf     qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1);
2825da96624SAlexander Graf     qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1);
2833627757eSAlexander Graf     qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0,
2843627757eSAlexander Graf                                MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE,
2855da96624SAlexander Graf                                MPC8544_CCSRBAR_SIZE);
2865da96624SAlexander Graf     /* XXX should contain a reasonable value */
2875da96624SAlexander Graf     qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0);
2885da96624SAlexander Graf 
289dffb1dc2SBharat Bhushan     snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET);
29019ac9deaSAlexander Graf     qemu_devtree_add_subnode(fdt, mpic);
29119ac9deaSAlexander Graf     qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic");
292f5fba9d2SScott Wood     qemu_devtree_setprop_string(fdt, mpic, "compatible", "fsl,mpic");
293dffb1dc2SBharat Bhushan     qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET,
294dffb1dc2SBharat Bhushan                                0x40000);
29519ac9deaSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0);
2967e99826cSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2);
29719ac9deaSAlexander Graf     mpic_ph = qemu_devtree_alloc_phandle(fdt);
29819ac9deaSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph);
29919ac9deaSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph);
30019ac9deaSAlexander Graf     qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0);
30119ac9deaSAlexander Graf 
3020cfc6e8dSAlexander Graf     /*
3030cfc6e8dSAlexander Graf      * We have to generate ser1 first, because Linux takes the first
3040cfc6e8dSAlexander Graf      * device it finds in the dt as serial output device. And we generate
3050cfc6e8dSAlexander Graf      * devices in reverse order to the dt.
3060cfc6e8dSAlexander Graf      */
307dffb1dc2SBharat Bhushan     dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET,
308a053a7ceSAlexander Graf                      soc, mpic, "serial1", 1, false);
309dffb1dc2SBharat Bhushan     dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET,
310a053a7ceSAlexander Graf                      soc, mpic, "serial0", 0, true);
3110cfc6e8dSAlexander Graf 
312ed2bc496SAlexander Graf     snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc,
313dffb1dc2SBharat Bhushan              MPC8544_UTIL_OFFSET);
314f5038483SAlexander Graf     qemu_devtree_add_subnode(fdt, gutil);
315f5038483SAlexander Graf     qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts");
316dffb1dc2SBharat Bhushan     qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000);
317f5038483SAlexander Graf     qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0);
318f5038483SAlexander Graf 
319a911b7a9SAlexander Graf     snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET);
320a911b7a9SAlexander Graf     qemu_devtree_add_subnode(fdt, msi);
321a911b7a9SAlexander Graf     qemu_devtree_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi");
322a911b7a9SAlexander Graf     qemu_devtree_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200);
323a911b7a9SAlexander Graf     msi_ph = qemu_devtree_alloc_phandle(fdt);
324a911b7a9SAlexander Graf     qemu_devtree_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100);
325a911b7a9SAlexander Graf     qemu_devtree_setprop_phandle(fdt, msi, "interrupt-parent", mpic);
326a911b7a9SAlexander Graf     qemu_devtree_setprop_cells(fdt, msi, "interrupts",
327a911b7a9SAlexander Graf         0xe0, 0x0,
328a911b7a9SAlexander Graf         0xe1, 0x0,
329a911b7a9SAlexander Graf         0xe2, 0x0,
330a911b7a9SAlexander Graf         0xe3, 0x0,
331a911b7a9SAlexander Graf         0xe4, 0x0,
332a911b7a9SAlexander Graf         0xe5, 0x0,
333a911b7a9SAlexander Graf         0xe6, 0x0,
334a911b7a9SAlexander Graf         0xe7, 0x0);
335a911b7a9SAlexander Graf     qemu_devtree_setprop_cell(fdt, msi, "phandle", msi_ph);
336a911b7a9SAlexander Graf     qemu_devtree_setprop_cell(fdt, msi, "linux,phandle", msi_ph);
337a911b7a9SAlexander Graf 
338ed2bc496SAlexander Graf     snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE);
3390dbc0798SAlexander Graf     qemu_devtree_add_subnode(fdt, pci);
3400dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0);
3410dbc0798SAlexander Graf     qemu_devtree_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci");
3420dbc0798SAlexander Graf     qemu_devtree_setprop_string(fdt, pci, "device_type", "pci");
3430dbc0798SAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0,
3440dbc0798SAlexander Graf                                0x0, 0x7);
345347dd79dSAlexander Graf     pci_map = pci_map_create(fdt, qemu_devtree_get_phandle(fdt, mpic),
346492ec48dSAlexander Graf                              params->pci_first_slot, params->pci_nr_slots,
347492ec48dSAlexander Graf                              &len);
348347dd79dSAlexander Graf     qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, len);
3490dbc0798SAlexander Graf     qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic);
3507e99826cSAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2);
3510dbc0798SAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255);
3523627757eSAlexander Graf     for (i = 0; i < 14; i++) {
3530dbc0798SAlexander Graf         pci_ranges[i] = cpu_to_be32(pci_ranges[i]);
3540dbc0798SAlexander Graf     }
355a911b7a9SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "fsl,msi", msi_ph);
3560dbc0798SAlexander Graf     qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges));
3573627757eSAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32,
3583627757eSAlexander Graf                                MPC8544_PCI_REGS_BASE, 0, 0x1000);
3590dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "clock-frequency", 66666666);
3600dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "#interrupt-cells", 1);
3610dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "#size-cells", 2);
3620dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3);
3630dbc0798SAlexander Graf     qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci);
3640dbc0798SAlexander Graf 
365e6eaabebSScott Wood     params->fixup_devtree(params, fdt);
366e6eaabebSScott Wood 
367e6eaabebSScott Wood     if (toplevel_compat) {
368e6eaabebSScott Wood         qemu_devtree_setprop(fdt, "/", "compatible", toplevel_compat,
369e6eaabebSScott Wood                              strlen(toplevel_compat) + 1);
370e6eaabebSScott Wood     }
371e6eaabebSScott Wood 
372d1b93565SAlexander Graf done:
373*28290f37SAlexander Graf     if (!dry_run) {
37471193433SAlexander Graf         qemu_devtree_dumpdtb(fdt, fdt_size);
375*28290f37SAlexander Graf         cpu_physical_memory_write(addr, fdt, fdt_size);
376cba2026aSAlexander Graf     }
377cba2026aSAlexander Graf     ret = fdt_size;
3787ec632b4Spbrook 
3791db09b84Saurel32 out:
380347dd79dSAlexander Graf     g_free(pci_map);
3811db09b84Saurel32 
38204088adbSLiu Yu     return ret;
3831db09b84Saurel32 }
3841db09b84Saurel32 
385*28290f37SAlexander Graf typedef struct DeviceTreeParams {
386*28290f37SAlexander Graf     QEMUMachineInitArgs args;
387*28290f37SAlexander Graf     PPCE500Params params;
388*28290f37SAlexander Graf     hwaddr addr;
389*28290f37SAlexander Graf     hwaddr initrd_base;
390*28290f37SAlexander Graf     hwaddr initrd_size;
391*28290f37SAlexander Graf } DeviceTreeParams;
392*28290f37SAlexander Graf 
393*28290f37SAlexander Graf static void ppce500_reset_device_tree(void *opaque)
394*28290f37SAlexander Graf {
395*28290f37SAlexander Graf     DeviceTreeParams *p = opaque;
396*28290f37SAlexander Graf     ppce500_load_device_tree(&p->args, &p->params, p->addr, p->initrd_base,
397*28290f37SAlexander Graf                              p->initrd_size, false);
398*28290f37SAlexander Graf }
399*28290f37SAlexander Graf 
400*28290f37SAlexander Graf static int ppce500_prep_device_tree(QEMUMachineInitArgs *args,
401*28290f37SAlexander Graf                                     PPCE500Params *params,
402*28290f37SAlexander Graf                                     hwaddr addr,
403*28290f37SAlexander Graf                                     hwaddr initrd_base,
404*28290f37SAlexander Graf                                     hwaddr initrd_size)
405*28290f37SAlexander Graf {
406*28290f37SAlexander Graf     DeviceTreeParams *p = g_new(DeviceTreeParams, 1);
407*28290f37SAlexander Graf     p->args = *args;
408*28290f37SAlexander Graf     p->params = *params;
409*28290f37SAlexander Graf     p->addr = addr;
410*28290f37SAlexander Graf     p->initrd_base = initrd_base;
411*28290f37SAlexander Graf     p->initrd_size = initrd_size;
412*28290f37SAlexander Graf 
413*28290f37SAlexander Graf     qemu_register_reset(ppce500_reset_device_tree, p);
414*28290f37SAlexander Graf 
415*28290f37SAlexander Graf     /* Issue the device tree loader once, so that we get the size of the blob */
416*28290f37SAlexander Graf     return ppce500_load_device_tree(args, params, addr, initrd_base,
417*28290f37SAlexander Graf                                     initrd_size, true);
418*28290f37SAlexander Graf }
419*28290f37SAlexander Graf 
420cba2026aSAlexander Graf /* Create -kernel TLB entries for BookE.  */
421a8170e5eSAvi Kivity static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
422d1e256feSAlexander Graf {
423cba2026aSAlexander Graf     return 63 - clz64(size >> 10);
424d1e256feSAlexander Graf }
425d1e256feSAlexander Graf 
426cefd3cdbSBharat Bhushan static int booke206_initial_map_tsize(CPUPPCState *env)
4273b989d49SAlexander Graf {
428cba2026aSAlexander Graf     struct boot_info *bi = env->load_info;
429cefd3cdbSBharat Bhushan     hwaddr dt_end;
430cba2026aSAlexander Graf     int ps;
4313b989d49SAlexander Graf 
432cba2026aSAlexander Graf     /* Our initial TLB entry needs to cover everything from 0 to
433cba2026aSAlexander Graf        the device tree top */
434cba2026aSAlexander Graf     dt_end = bi->dt_base + bi->dt_size;
435cba2026aSAlexander Graf     ps = booke206_page_size_to_tlb(dt_end) + 1;
436fb37c302SAlexander Graf     if (ps & 1) {
437fb37c302SAlexander Graf         /* e500v2 can only do even TLB size bits */
438fb37c302SAlexander Graf         ps++;
439fb37c302SAlexander Graf     }
440cefd3cdbSBharat Bhushan     return ps;
441cefd3cdbSBharat Bhushan }
442cefd3cdbSBharat Bhushan 
443cefd3cdbSBharat Bhushan static uint64_t mmubooke_initial_mapsize(CPUPPCState *env)
444cefd3cdbSBharat Bhushan {
445cefd3cdbSBharat Bhushan     int tsize;
446cefd3cdbSBharat Bhushan 
447cefd3cdbSBharat Bhushan     tsize = booke206_initial_map_tsize(env);
448cefd3cdbSBharat Bhushan     return (1ULL << 10 << tsize);
449cefd3cdbSBharat Bhushan }
450cefd3cdbSBharat Bhushan 
451cefd3cdbSBharat Bhushan static void mmubooke_create_initial_mapping(CPUPPCState *env)
452cefd3cdbSBharat Bhushan {
453cefd3cdbSBharat Bhushan     ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0);
454cefd3cdbSBharat Bhushan     hwaddr size;
455cefd3cdbSBharat Bhushan     int ps;
456cefd3cdbSBharat Bhushan 
457cefd3cdbSBharat Bhushan     ps = booke206_initial_map_tsize(env);
458cba2026aSAlexander Graf     size = (ps << MAS1_TSIZE_SHIFT);
459d1e256feSAlexander Graf     tlb->mas1 = MAS1_VALID | size;
460cba2026aSAlexander Graf     tlb->mas2 = 0;
461cba2026aSAlexander Graf     tlb->mas7_3 = 0;
462d1e256feSAlexander Graf     tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
46393dd5e85SScott Wood 
46493dd5e85SScott Wood     env->tlb_dirty = true;
4653b989d49SAlexander Graf }
4663b989d49SAlexander Graf 
467b3305981SScott Wood static void ppce500_cpu_reset_sec(void *opaque)
4685c145dacSAlexander Graf {
46938f92da6SAndreas Färber     PowerPCCPU *cpu = opaque;
470259186a7SAndreas Färber     CPUState *cs = CPU(cpu);
47138f92da6SAndreas Färber     CPUPPCState *env = &cpu->env;
4725c145dacSAlexander Graf 
473259186a7SAndreas Färber     cpu_reset(cs);
4745c145dacSAlexander Graf 
4755c145dacSAlexander Graf     /* Secondary CPU starts in halted state for now. Needs to change when
4765c145dacSAlexander Graf        implementing non-kernel boot. */
477259186a7SAndreas Färber     cs->halted = 1;
4785c145dacSAlexander Graf     env->exception_index = EXCP_HLT;
4793b989d49SAlexander Graf }
4803b989d49SAlexander Graf 
481b3305981SScott Wood static void ppce500_cpu_reset(void *opaque)
4823b989d49SAlexander Graf {
48338f92da6SAndreas Färber     PowerPCCPU *cpu = opaque;
484259186a7SAndreas Färber     CPUState *cs = CPU(cpu);
48538f92da6SAndreas Färber     CPUPPCState *env = &cpu->env;
4863b989d49SAlexander Graf     struct boot_info *bi = env->load_info;
4873b989d49SAlexander Graf 
488259186a7SAndreas Färber     cpu_reset(cs);
4893b989d49SAlexander Graf 
4903b989d49SAlexander Graf     /* Set initial guest state. */
491259186a7SAndreas Färber     cs->halted = 0;
4923b989d49SAlexander Graf     env->gpr[1] = (16<<20) - 8;
4933b989d49SAlexander Graf     env->gpr[3] = bi->dt_base;
494cefd3cdbSBharat Bhushan     env->gpr[4] = 0;
495cefd3cdbSBharat Bhushan     env->gpr[5] = 0;
496cefd3cdbSBharat Bhushan     env->gpr[6] = EPAPR_MAGIC;
497cefd3cdbSBharat Bhushan     env->gpr[7] = mmubooke_initial_mapsize(env);
498cefd3cdbSBharat Bhushan     env->gpr[8] = 0;
499cefd3cdbSBharat Bhushan     env->gpr[9] = 0;
5003b989d49SAlexander Graf     env->nip = bi->entry;
501cba2026aSAlexander Graf     mmubooke_create_initial_mapping(env);
5023b989d49SAlexander Graf }
5033b989d49SAlexander Graf 
504d85937e6SScott Wood static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params,
50582fc73b6SScott Wood                                            qemu_irq **irqs)
50682fc73b6SScott Wood {
50782fc73b6SScott Wood     DeviceState *dev;
50882fc73b6SScott Wood     SysBusDevice *s;
50982fc73b6SScott Wood     int i, j, k;
51082fc73b6SScott Wood 
511e1766344SAndreas Färber     dev = qdev_create(NULL, TYPE_OPENPIC);
51282fc73b6SScott Wood     qdev_prop_set_uint32(dev, "model", params->mpic_version);
513d85937e6SScott Wood     qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
514d85937e6SScott Wood 
51582fc73b6SScott Wood     qdev_init_nofail(dev);
51682fc73b6SScott Wood     s = SYS_BUS_DEVICE(dev);
51782fc73b6SScott Wood 
51882fc73b6SScott Wood     k = 0;
51982fc73b6SScott Wood     for (i = 0; i < smp_cpus; i++) {
52082fc73b6SScott Wood         for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
52182fc73b6SScott Wood             sysbus_connect_irq(s, k++, irqs[i][j]);
52282fc73b6SScott Wood         }
52382fc73b6SScott Wood     }
52482fc73b6SScott Wood 
525d85937e6SScott Wood     return dev;
526d85937e6SScott Wood }
527d85937e6SScott Wood 
528d85937e6SScott Wood static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params,
529d85937e6SScott Wood                                           qemu_irq **irqs)
530d85937e6SScott Wood {
531d85937e6SScott Wood     DeviceState *dev;
532d85937e6SScott Wood     CPUState *cs;
533d85937e6SScott Wood     int r;
534d85937e6SScott Wood 
535dd49c038SAndreas Färber     dev = qdev_create(NULL, TYPE_KVM_OPENPIC);
536d85937e6SScott Wood     qdev_prop_set_uint32(dev, "model", params->mpic_version);
537d85937e6SScott Wood 
538d85937e6SScott Wood     r = qdev_init(dev);
539d85937e6SScott Wood     if (r) {
540d85937e6SScott Wood         return NULL;
541d85937e6SScott Wood     }
542d85937e6SScott Wood 
543182735efSAndreas Färber     for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
544d85937e6SScott Wood         if (kvm_openpic_connect_vcpu(dev, cs)) {
545d85937e6SScott Wood             fprintf(stderr, "%s: failed to connect vcpu to irqchip\n",
546d85937e6SScott Wood                     __func__);
547d85937e6SScott Wood             abort();
548d85937e6SScott Wood         }
549d85937e6SScott Wood     }
550d85937e6SScott Wood 
551d85937e6SScott Wood     return dev;
552d85937e6SScott Wood }
553d85937e6SScott Wood 
554d85937e6SScott Wood static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr,
555d85937e6SScott Wood                                    qemu_irq **irqs)
556d85937e6SScott Wood {
557d85937e6SScott Wood     qemu_irq *mpic;
558d85937e6SScott Wood     DeviceState *dev = NULL;
559d85937e6SScott Wood     SysBusDevice *s;
560d85937e6SScott Wood     int i;
561d85937e6SScott Wood 
562d85937e6SScott Wood     mpic = g_new(qemu_irq, 256);
563d85937e6SScott Wood 
564d85937e6SScott Wood     if (kvm_enabled()) {
56536ad0e94SMarkus Armbruster         QemuOpts *machine_opts = qemu_get_machine_opts();
56636ad0e94SMarkus Armbruster         bool irqchip_allowed = qemu_opt_get_bool(machine_opts,
567d85937e6SScott Wood                                                 "kernel_irqchip", true);
56836ad0e94SMarkus Armbruster         bool irqchip_required = qemu_opt_get_bool(machine_opts,
569d85937e6SScott Wood                                                   "kernel_irqchip", false);
570d85937e6SScott Wood 
571d85937e6SScott Wood         if (irqchip_allowed) {
572d85937e6SScott Wood             dev = ppce500_init_mpic_kvm(params, irqs);
573d85937e6SScott Wood         }
574d85937e6SScott Wood 
575d85937e6SScott Wood         if (irqchip_required && !dev) {
576d85937e6SScott Wood             fprintf(stderr, "%s: irqchip requested but unavailable\n",
577d85937e6SScott Wood                     __func__);
578d85937e6SScott Wood             abort();
579d85937e6SScott Wood         }
580d85937e6SScott Wood     }
581d85937e6SScott Wood 
582d85937e6SScott Wood     if (!dev) {
583d85937e6SScott Wood         dev = ppce500_init_mpic_qemu(params, irqs);
584d85937e6SScott Wood     }
585d85937e6SScott Wood 
58682fc73b6SScott Wood     for (i = 0; i < 256; i++) {
58782fc73b6SScott Wood         mpic[i] = qdev_get_gpio_in(dev, i);
58882fc73b6SScott Wood     }
58982fc73b6SScott Wood 
590d85937e6SScott Wood     s = SYS_BUS_DEVICE(dev);
59182fc73b6SScott Wood     memory_region_add_subregion(ccsr, MPC8544_MPIC_REGS_OFFSET,
59282fc73b6SScott Wood                                 s->mmio[0].memory);
59382fc73b6SScott Wood 
59482fc73b6SScott Wood     return mpic;
59582fc73b6SScott Wood }
59682fc73b6SScott Wood 
59792238367SMarkus Armbruster void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params)
5981db09b84Saurel32 {
59939186d8aSRichard Henderson     MemoryRegion *address_space_mem = get_system_memory();
6002646c133SAvi Kivity     MemoryRegion *ram = g_new(MemoryRegion, 1);
6011db09b84Saurel32     PCIBus *pci_bus;
602e2684c0bSAndreas Färber     CPUPPCState *env = NULL;
6031db09b84Saurel32     uint64_t elf_entry;
6041db09b84Saurel32     uint64_t elf_lowaddr;
605a8170e5eSAvi Kivity     hwaddr entry=0;
606a8170e5eSAvi Kivity     hwaddr loadaddr=UIMAGE_LOAD_BASE;
6071db09b84Saurel32     target_long kernel_size=0;
60875bb6589SLiu Yu     target_ulong dt_base = 0;
60975bb6589SLiu Yu     target_ulong initrd_base = 0;
6101db09b84Saurel32     target_long initrd_size = 0;
611528e536eSAlexander Graf     target_ulong cur_base = 0;
61282fc73b6SScott Wood     int i;
6131db09b84Saurel32     unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
614a915249fSAlexander Graf     qemu_irq **irqs, *mpic;
615be13cc7aSAlexander Graf     DeviceState *dev;
616e2684c0bSAndreas Färber     CPUPPCState *firstenv = NULL;
6173eddc1beSBharat Bhushan     MemoryRegion *ccsr_addr_space;
618dffb1dc2SBharat Bhushan     SysBusDevice *s;
6193eddc1beSBharat Bhushan     PPCE500CCSRState *ccsr;
6201db09b84Saurel32 
621e61c36d5SAlexander Graf     /* Setup CPUs */
62292238367SMarkus Armbruster     if (args->cpu_model == NULL) {
62392238367SMarkus Armbruster         args->cpu_model = "e500v2_v30";
624ef250db6SAlexander Graf     }
625ef250db6SAlexander Graf 
626a915249fSAlexander Graf     irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
627a915249fSAlexander Graf     irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
628e61c36d5SAlexander Graf     for (i = 0; i < smp_cpus; i++) {
629397b457dSAndreas Färber         PowerPCCPU *cpu;
63055e5c285SAndreas Färber         CPUState *cs;
631e61c36d5SAlexander Graf         qemu_irq *input;
632397b457dSAndreas Färber 
63392238367SMarkus Armbruster         cpu = cpu_ppc_init(args->cpu_model);
634397b457dSAndreas Färber         if (cpu == NULL) {
6351db09b84Saurel32             fprintf(stderr, "Unable to initialize CPU!\n");
6361db09b84Saurel32             exit(1);
6371db09b84Saurel32         }
638397b457dSAndreas Färber         env = &cpu->env;
63955e5c285SAndreas Färber         cs = CPU(cpu);
6401db09b84Saurel32 
641e61c36d5SAlexander Graf         if (!firstenv) {
642e61c36d5SAlexander Graf             firstenv = env;
643e61c36d5SAlexander Graf         }
644e61c36d5SAlexander Graf 
645a915249fSAlexander Graf         irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB);
646a915249fSAlexander Graf         input = (qemu_irq *)env->irq_inputs;
647a915249fSAlexander Graf         irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
648a915249fSAlexander Graf         irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
64955e5c285SAndreas Färber         env->spr[SPR_BOOKE_PIR] = cs->cpu_index = i;
65068c2dd70SAlexander Graf         env->mpic_iack = MPC8544_CCSRBAR_BASE +
651bd25922eSScott Wood                          MPC8544_MPIC_REGS_OFFSET + 0xa0;
652e61c36d5SAlexander Graf 
653a34a92b9SAndreas Färber         ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500);
6543b989d49SAlexander Graf 
6553b989d49SAlexander Graf         /* Register reset handler */
6565c145dacSAlexander Graf         if (!i) {
6575c145dacSAlexander Graf             /* Primary CPU */
6585c145dacSAlexander Graf             struct boot_info *boot_info;
659e61c36d5SAlexander Graf             boot_info = g_malloc0(sizeof(struct boot_info));
660b3305981SScott Wood             qemu_register_reset(ppce500_cpu_reset, cpu);
661e61c36d5SAlexander Graf             env->load_info = boot_info;
6625c145dacSAlexander Graf         } else {
6635c145dacSAlexander Graf             /* Secondary CPUs */
664b3305981SScott Wood             qemu_register_reset(ppce500_cpu_reset_sec, cpu);
6655c145dacSAlexander Graf         }
666e61c36d5SAlexander Graf     }
667e61c36d5SAlexander Graf 
668e61c36d5SAlexander Graf     env = firstenv;
6693b989d49SAlexander Graf 
6701db09b84Saurel32     /* Fixup Memory size on a alignment boundary */
6711db09b84Saurel32     ram_size &= ~(RAM_SIZES_ALIGN - 1);
67292238367SMarkus Armbruster     args->ram_size = ram_size;
6731db09b84Saurel32 
6741db09b84Saurel32     /* Register Memory */
6752c9b15caSPaolo Bonzini     memory_region_init_ram(ram, NULL, "mpc8544ds.ram", ram_size);
676c5705a77SAvi Kivity     vmstate_register_ram_global(ram);
6772646c133SAvi Kivity     memory_region_add_subregion(address_space_mem, 0, ram);
6781db09b84Saurel32 
6793eddc1beSBharat Bhushan     dev = qdev_create(NULL, "e500-ccsr");
6803eddc1beSBharat Bhushan     object_property_add_child(qdev_get_machine(), "e500-ccsr",
6813eddc1beSBharat Bhushan                               OBJECT(dev), NULL);
6823eddc1beSBharat Bhushan     qdev_init_nofail(dev);
6833eddc1beSBharat Bhushan     ccsr = CCSR(dev);
6843eddc1beSBharat Bhushan     ccsr_addr_space = &ccsr->ccsr_space;
6853eddc1beSBharat Bhushan     memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE,
6863eddc1beSBharat Bhushan                                 ccsr_addr_space);
687dffb1dc2SBharat Bhushan 
68882fc73b6SScott Wood     mpic = ppce500_init_mpic(params, ccsr_addr_space, irqs);
6891db09b84Saurel32 
6901db09b84Saurel32     /* Serial */
6912d48377aSBlue Swirl     if (serial_hds[0]) {
6923eddc1beSBharat Bhushan         serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET,
693cdbb912aSAlexander Graf                        0, mpic[42], 399193,
6942ff0c7c3SRichard Henderson                        serial_hds[0], DEVICE_BIG_ENDIAN);
6952d48377aSBlue Swirl     }
6961db09b84Saurel32 
6972d48377aSBlue Swirl     if (serial_hds[1]) {
6983eddc1beSBharat Bhushan         serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET,
699cdbb912aSAlexander Graf                        0, mpic[42], 399193,
70059de4f98SBharat Bhushan                        serial_hds[1], DEVICE_BIG_ENDIAN);
7012d48377aSBlue Swirl     }
7021db09b84Saurel32 
703b0fb8423SAlexander Graf     /* General Utility device */
704dffb1dc2SBharat Bhushan     dev = qdev_create(NULL, "mpc8544-guts");
705dffb1dc2SBharat Bhushan     qdev_init_nofail(dev);
706dffb1dc2SBharat Bhushan     s = SYS_BUS_DEVICE(dev);
7073eddc1beSBharat Bhushan     memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET,
708dffb1dc2SBharat Bhushan                                 sysbus_mmio_get_region(s, 0));
709b0fb8423SAlexander Graf 
7101db09b84Saurel32     /* PCI */
711dffb1dc2SBharat Bhushan     dev = qdev_create(NULL, "e500-pcihost");
712492ec48dSAlexander Graf     qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot);
713dffb1dc2SBharat Bhushan     qdev_init_nofail(dev);
714dffb1dc2SBharat Bhushan     s = SYS_BUS_DEVICE(dev);
715dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 0, mpic[pci_irq_nrs[0]]);
716dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 1, mpic[pci_irq_nrs[1]]);
717dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 2, mpic[pci_irq_nrs[2]]);
718dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 3, mpic[pci_irq_nrs[3]]);
7193eddc1beSBharat Bhushan     memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET,
720dffb1dc2SBharat Bhushan                                 sysbus_mmio_get_region(s, 0));
721dffb1dc2SBharat Bhushan 
722d461e3b9SAlexander Graf     pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
7231db09b84Saurel32     if (!pci_bus)
7241db09b84Saurel32         printf("couldn't create PCI controller!\n");
7251db09b84Saurel32 
7261356b98dSAndreas Färber     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, MPC8544_PCI_IO);
7271db09b84Saurel32 
7281db09b84Saurel32     if (pci_bus) {
7291db09b84Saurel32         /* Register network interfaces. */
7301db09b84Saurel32         for (i = 0; i < nb_nics; i++) {
73129b358f9SDavid Gibson             pci_nic_init_nofail(&nd_table[i], pci_bus, "virtio", NULL);
7321db09b84Saurel32         }
7331db09b84Saurel32     }
7341db09b84Saurel32 
7355c145dacSAlexander Graf     /* Register spinning region */
7365c145dacSAlexander Graf     sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL);
7375c145dacSAlexander Graf 
7381db09b84Saurel32     /* Load kernel. */
73992238367SMarkus Armbruster     if (args->kernel_filename) {
74092238367SMarkus Armbruster         kernel_size = load_uimage(args->kernel_filename, &entry,
741e6eaabebSScott Wood                                   &loadaddr, NULL);
7421db09b84Saurel32         if (kernel_size < 0) {
74392238367SMarkus Armbruster             kernel_size = load_elf(args->kernel_filename, NULL, NULL,
744e6eaabebSScott Wood                                    &elf_entry, &elf_lowaddr, NULL, 1,
745e6eaabebSScott Wood                                    ELF_MACHINE, 0);
7461db09b84Saurel32             entry = elf_entry;
7471db09b84Saurel32             loadaddr = elf_lowaddr;
7481db09b84Saurel32         }
7491db09b84Saurel32         /* XXX try again as binary */
7501db09b84Saurel32         if (kernel_size < 0) {
7511db09b84Saurel32             fprintf(stderr, "qemu: could not load kernel '%s'\n",
75292238367SMarkus Armbruster                     args->kernel_filename);
7531db09b84Saurel32             exit(1);
7541db09b84Saurel32         }
755528e536eSAlexander Graf 
756528e536eSAlexander Graf         cur_base = loadaddr + kernel_size;
757b8dec144SAlexander Graf 
758b8dec144SAlexander Graf         /* Reserve space for dtb */
759b8dec144SAlexander Graf         dt_base = (cur_base + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
760b8dec144SAlexander Graf         cur_base += DTB_MAX_SIZE;
7611db09b84Saurel32     }
7621db09b84Saurel32 
7631db09b84Saurel32     /* Load initrd. */
76492238367SMarkus Armbruster     if (args->initrd_filename) {
765528e536eSAlexander Graf         initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK;
76692238367SMarkus Armbruster         initrd_size = load_image_targphys(args->initrd_filename, initrd_base,
767d7585251Spbrook                                           ram_size - initrd_base);
7681db09b84Saurel32 
7691db09b84Saurel32         if (initrd_size < 0) {
7701db09b84Saurel32             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
77192238367SMarkus Armbruster                     args->initrd_filename);
7721db09b84Saurel32             exit(1);
7731db09b84Saurel32         }
774528e536eSAlexander Graf 
775528e536eSAlexander Graf         cur_base = initrd_base + initrd_size;
7761db09b84Saurel32     }
7771db09b84Saurel32 
7781db09b84Saurel32     /* If we're loading a kernel directly, we must load the device tree too. */
77992238367SMarkus Armbruster     if (args->kernel_filename) {
7805c145dacSAlexander Graf         struct boot_info *boot_info;
781cba2026aSAlexander Graf         int dt_size;
7825c145dacSAlexander Graf 
783*28290f37SAlexander Graf         dt_size = ppce500_prep_device_tree(args, params, dt_base,
78492238367SMarkus Armbruster                                            initrd_base, initrd_size);
785cba2026aSAlexander Graf         if (dt_size < 0) {
7861db09b84Saurel32             fprintf(stderr, "couldn't load device tree\n");
7871db09b84Saurel32             exit(1);
7881db09b84Saurel32         }
789b8dec144SAlexander Graf         assert(dt_size < DTB_MAX_SIZE);
7901db09b84Saurel32 
791e61c36d5SAlexander Graf         boot_info = env->load_info;
7923b989d49SAlexander Graf         boot_info->entry = entry;
7933b989d49SAlexander Graf         boot_info->dt_base = dt_base;
794cba2026aSAlexander Graf         boot_info->dt_size = dt_size;
7951db09b84Saurel32     }
7961db09b84Saurel32 
7973b989d49SAlexander Graf     if (kvm_enabled()) {
7981db09b84Saurel32         kvmppc_init();
7993b989d49SAlexander Graf     }
8001db09b84Saurel32 }
8013eddc1beSBharat Bhushan 
8023eddc1beSBharat Bhushan static int e500_ccsr_initfn(SysBusDevice *dev)
8033eddc1beSBharat Bhushan {
8043eddc1beSBharat Bhushan     PPCE500CCSRState *ccsr;
8053eddc1beSBharat Bhushan 
8063eddc1beSBharat Bhushan     ccsr = CCSR(dev);
80740c5dce9SPaolo Bonzini     memory_region_init(&ccsr->ccsr_space, OBJECT(ccsr), "e500-ccsr",
8083eddc1beSBharat Bhushan                        MPC8544_CCSRBAR_SIZE);
8093eddc1beSBharat Bhushan     return 0;
8103eddc1beSBharat Bhushan }
8113eddc1beSBharat Bhushan 
8123eddc1beSBharat Bhushan static void e500_ccsr_class_init(ObjectClass *klass, void *data)
8133eddc1beSBharat Bhushan {
8143eddc1beSBharat Bhushan     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
8153eddc1beSBharat Bhushan     k->init = e500_ccsr_initfn;
8163eddc1beSBharat Bhushan }
8173eddc1beSBharat Bhushan 
8183eddc1beSBharat Bhushan static const TypeInfo e500_ccsr_info = {
8193eddc1beSBharat Bhushan     .name          = TYPE_CCSR,
8203eddc1beSBharat Bhushan     .parent        = TYPE_SYS_BUS_DEVICE,
8213eddc1beSBharat Bhushan     .instance_size = sizeof(PPCE500CCSRState),
8223eddc1beSBharat Bhushan     .class_init    = e500_ccsr_class_init,
8233eddc1beSBharat Bhushan };
8243eddc1beSBharat Bhushan 
8253eddc1beSBharat Bhushan static void e500_register_types(void)
8263eddc1beSBharat Bhushan {
8273eddc1beSBharat Bhushan     type_register_static(&e500_ccsr_info);
8283eddc1beSBharat Bhushan }
8293eddc1beSBharat Bhushan 
8303eddc1beSBharat Bhushan type_init(e500_register_types)
831