]> git.proxmox.com Git - mirror_qemu.git/blame - hw/ppc/e500.c
ppc/pseries: Reset VPA registration on CPU reset
[mirror_qemu.git] / hw / ppc / e500.c
CommitLineData
1db09b84 1/*
b3305981 2 * QEMU PowerPC e500-based platforms
1db09b84
AJ
3 *
4 * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
5 *
6 * Author: Yu Liu, <yu.liu@freescale.com>
7 *
8 * This file is derived from hw/ppc440_bamboo.c,
9 * the copyright for that material belongs to the original owners.
10 *
11 * This is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
1db09b84
AJ
17#include "config.h"
18#include "qemu-common.h"
e6eaabeb 19#include "e500.h"
1db09b84 20#include "net.h"
4a18e7c9
SW
21#include "hw/hw.h"
22#include "hw/pc.h"
23#include "hw/pci.h"
24#include "hw/boards.h"
1db09b84
AJ
25#include "sysemu.h"
26#include "kvm.h"
27#include "kvm_ppc.h"
28#include "device_tree.h"
4a18e7c9
SW
29#include "hw/openpic.h"
30#include "hw/ppc.h"
31#include "hw/loader.h"
ca20cf32 32#include "elf.h"
4a18e7c9 33#include "hw/sysbus.h"
39186d8a 34#include "exec-memory.h"
cba2026a 35#include "host-utils.h"
1db09b84
AJ
36
37#define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb"
38#define UIMAGE_LOAD_BASE 0
9dd5eba1 39#define DTC_LOAD_PAD 0x1800000
75bb6589
LY
40#define DTC_PAD_MASK 0xFFFFF
41#define INITRD_LOAD_PAD 0x2000000
42#define INITRD_PAD_MASK 0xFFFFFF
1db09b84
AJ
43
44#define RAM_SIZES_ALIGN (64UL << 20)
45
b3305981 46/* TODO: parameterize */
ed2bc496
AG
47#define MPC8544_CCSRBAR_BASE 0xE0000000ULL
48#define MPC8544_CCSRBAR_SIZE 0x00100000ULL
49#define MPC8544_MPIC_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x40000ULL)
50#define MPC8544_SERIAL0_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4500ULL)
51#define MPC8544_SERIAL1_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4600ULL)
52#define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x8000ULL)
53#define MPC8544_PCI_REGS_SIZE 0x1000ULL
54#define MPC8544_PCI_IO 0xE1000000ULL
55#define MPC8544_PCI_IOLEN 0x10000ULL
56#define MPC8544_UTIL_BASE (MPC8544_CCSRBAR_BASE + 0xe0000ULL)
57#define MPC8544_SPIN_BASE 0xEF000000ULL
1db09b84 58
3b989d49
AG
59struct boot_info
60{
61 uint32_t dt_base;
cba2026a 62 uint32_t dt_size;
3b989d49
AG
63 uint32_t entry;
64};
65
0dbc0798
AG
66static void pci_map_create(void *fdt, uint32_t *pci_map, uint32_t mpic)
67{
68 int i;
69 const uint32_t tmp[] = {
70 /* IDSEL 0x11 J17 Slot 1 */
7e99826c
AG
71 0x8800, 0x0, 0x0, 0x1, mpic, 0x2, 0x1,
72 0x8800, 0x0, 0x0, 0x2, mpic, 0x3, 0x1,
73 0x8800, 0x0, 0x0, 0x3, mpic, 0x4, 0x1,
74 0x8800, 0x0, 0x0, 0x4, mpic, 0x1, 0x1,
0dbc0798
AG
75
76 /* IDSEL 0x12 J16 Slot 2 */
7e99826c
AG
77 0x9000, 0x0, 0x0, 0x1, mpic, 0x3, 0x1,
78 0x9000, 0x0, 0x0, 0x2, mpic, 0x4, 0x1,
79 0x9000, 0x0, 0x0, 0x3, mpic, 0x2, 0x1,
80 0x9000, 0x0, 0x0, 0x4, mpic, 0x1, 0x1,
0dbc0798 81 };
7e99826c 82 for (i = 0; i < (7 * 8); i++) {
0dbc0798
AG
83 pci_map[i] = cpu_to_be32(tmp[i]);
84 }
85}
86
a053a7ce
AG
87static void dt_serial_create(void *fdt, unsigned long long offset,
88 const char *soc, const char *mpic,
89 const char *alias, int idx, bool defcon)
90{
91 char ser[128];
92
93 snprintf(ser, sizeof(ser), "%s/serial@%llx", soc, offset);
94 qemu_devtree_add_subnode(fdt, ser);
95 qemu_devtree_setprop_string(fdt, ser, "device_type", "serial");
96 qemu_devtree_setprop_string(fdt, ser, "compatible", "ns16550");
97 qemu_devtree_setprop_cells(fdt, ser, "reg", offset, 0x100);
98 qemu_devtree_setprop_cell(fdt, ser, "cell-index", idx);
99 qemu_devtree_setprop_cell(fdt, ser, "clock-frequency", 0);
7e99826c 100 qemu_devtree_setprop_cells(fdt, ser, "interrupts", 42, 2);
a053a7ce
AG
101 qemu_devtree_setprop_phandle(fdt, ser, "interrupt-parent", mpic);
102 qemu_devtree_setprop_string(fdt, "/aliases", alias, ser);
103
104 if (defcon) {
105 qemu_devtree_setprop_string(fdt, "/chosen", "linux,stdout-path", ser);
106 }
107}
108
b3305981 109static int ppce500_load_device_tree(CPUPPCState *env,
e6eaabeb 110 PPCE500Params *params,
5de6b46d 111 target_phys_addr_t addr,
5de6b46d 112 target_phys_addr_t initrd_base,
e6eaabeb 113 target_phys_addr_t initrd_size)
1db09b84 114{
dbf916d8 115 int ret = -1;
e6eaabeb 116 uint64_t mem_reg_property[] = { 0, cpu_to_be64(params->ram_size) };
7ec632b4 117 int fdt_size;
dbf916d8 118 void *fdt;
5de6b46d 119 uint8_t hypercall[16];
911d6e7a
AG
120 uint32_t clock_freq = 400000000;
121 uint32_t tb_freq = 400000000;
621d05e3 122 int i;
e6eaabeb 123 const char *toplevel_compat = NULL; /* user override */
ebb9518a 124 char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus";
5da96624 125 char soc[128];
19ac9dea
AG
126 char mpic[128];
127 uint32_t mpic_ph;
f5038483 128 char gutil[128];
0dbc0798 129 char pci[128];
7e99826c 130 uint32_t pci_map[7 * 8];
3627757e
AG
131 uint32_t pci_ranges[14] =
132 {
133 0x2000000, 0x0, 0xc0000000,
134 0x0, 0xc0000000,
135 0x0, 0x20000000,
136
137 0x1000000, 0x0, 0x0,
138 0x0, 0xe1000000,
139 0x0, 0x10000,
140 };
25b42708 141 QemuOpts *machine_opts;
d1b93565
AG
142 const char *dtb_file = NULL;
143
144 machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
145 if (machine_opts) {
d1b93565 146 dtb_file = qemu_opt_get(machine_opts, "dtb");
e6eaabeb 147 toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
d1b93565
AG
148 }
149
150 if (dtb_file) {
151 char *filename;
152 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file);
153 if (!filename) {
154 goto out;
155 }
156
157 fdt = load_device_tree(filename, &fdt_size);
158 if (!fdt) {
159 goto out;
160 }
161 goto done;
162 }
1db09b84 163
2636fcb6 164 fdt = create_device_tree(&fdt_size);
5cea8590
PB
165 if (fdt == NULL) {
166 goto out;
167 }
1db09b84
AJ
168
169 /* Manipulate device tree in memory. */
3627757e
AG
170 qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2);
171 qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2);
51b852b7 172
dd0bcfca
AG
173 qemu_devtree_add_subnode(fdt, "/memory");
174 qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory");
175 qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
176 sizeof(mem_reg_property));
1db09b84 177
f5231aaf 178 qemu_devtree_add_subnode(fdt, "/chosen");
3b989d49
AG
179 if (initrd_size) {
180 ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
181 initrd_base);
182 if (ret < 0) {
183 fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
184 }
1db09b84 185
3b989d49
AG
186 ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
187 (initrd_base + initrd_size));
188 if (ret < 0) {
189 fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
190 }
191 }
1db09b84
AJ
192
193 ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
e6eaabeb 194 params->kernel_cmdline);
1db09b84
AJ
195 if (ret < 0)
196 fprintf(stderr, "couldn't set /chosen/bootargs\n");
197
198 if (kvm_enabled()) {
911d6e7a
AG
199 /* Read out host's frequencies */
200 clock_freq = kvmppc_get_clockfreq();
201 tb_freq = kvmppc_get_tbfreq();
5de6b46d
AG
202
203 /* indicate KVM hypercall interface */
d50f71a5 204 qemu_devtree_add_subnode(fdt, "/hypervisor");
5de6b46d
AG
205 qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible",
206 "linux,kvm");
207 kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
208 qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",
209 hypercall, sizeof(hypercall));
1db09b84 210 }
3b989d49 211
625e665b
AG
212 /* Create CPU nodes */
213 qemu_devtree_add_subnode(fdt, "/cpus");
214 qemu_devtree_setprop_cell(fdt, "/cpus", "#address-cells", 1);
215 qemu_devtree_setprop_cell(fdt, "/cpus", "#size-cells", 0);
216
1e3debf0
AG
217 /* We need to generate the cpu nodes in reverse order, so Linux can pick
218 the first node as boot node and be happy */
219 for (i = smp_cpus - 1; i >= 0; i--) {
621d05e3 220 char cpu_name[128];
1d2e5c52 221 uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20);
10f25a46 222
1e3debf0
AG
223 for (env = first_cpu; env != NULL; env = env->next_cpu) {
224 if (env->cpu_index == i) {
225 break;
226 }
227 }
228
229 if (!env) {
230 continue;
231 }
232
233 snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", env->cpu_index);
234 qemu_devtree_add_subnode(fdt, cpu_name);
621d05e3
AG
235 qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
236 qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
1e3debf0
AG
237 qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu");
238 qemu_devtree_setprop_cell(fdt, cpu_name, "reg", env->cpu_index);
239 qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size",
240 env->dcache_line_size);
241 qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size",
242 env->icache_line_size);
243 qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000);
244 qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000);
245 qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0);
246 if (env->cpu_index) {
247 qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled");
248 qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table");
1d2e5c52
AG
249 qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr",
250 cpu_release_addr);
1e3debf0
AG
251 } else {
252 qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay");
253 }
1db09b84
AJ
254 }
255
0cfc6e8d 256 qemu_devtree_add_subnode(fdt, "/aliases");
5da96624 257 /* XXX These should go into their respective devices' code */
ed2bc496 258 snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE);
5da96624
AG
259 qemu_devtree_add_subnode(fdt, soc);
260 qemu_devtree_setprop_string(fdt, soc, "device_type", "soc");
ebb9518a
AG
261 qemu_devtree_setprop(fdt, soc, "compatible", compatible_sb,
262 sizeof(compatible_sb));
5da96624
AG
263 qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1);
264 qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1);
3627757e
AG
265 qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0,
266 MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE,
5da96624 267 MPC8544_CCSRBAR_SIZE);
5da96624
AG
268 /* XXX should contain a reasonable value */
269 qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0);
270
ed2bc496 271 snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc,
19ac9dea
AG
272 MPC8544_MPIC_REGS_BASE - MPC8544_CCSRBAR_BASE);
273 qemu_devtree_add_subnode(fdt, mpic);
274 qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic");
7e99826c 275 qemu_devtree_setprop_string(fdt, mpic, "compatible", "chrp,open-pic");
19ac9dea
AG
276 qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_BASE -
277 MPC8544_CCSRBAR_BASE, 0x40000);
278 qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0);
7e99826c 279 qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2);
19ac9dea
AG
280 mpic_ph = qemu_devtree_alloc_phandle(fdt);
281 qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph);
282 qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph);
283 qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0);
284
0cfc6e8d
AG
285 /*
286 * We have to generate ser1 first, because Linux takes the first
287 * device it finds in the dt as serial output device. And we generate
288 * devices in reverse order to the dt.
289 */
a053a7ce
AG
290 dt_serial_create(fdt, MPC8544_SERIAL1_REGS_BASE - MPC8544_CCSRBAR_BASE,
291 soc, mpic, "serial1", 1, false);
292 dt_serial_create(fdt, MPC8544_SERIAL0_REGS_BASE - MPC8544_CCSRBAR_BASE,
293 soc, mpic, "serial0", 0, true);
0cfc6e8d 294
ed2bc496 295 snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc,
f5038483
AG
296 MPC8544_UTIL_BASE - MPC8544_CCSRBAR_BASE);
297 qemu_devtree_add_subnode(fdt, gutil);
298 qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts");
299 qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_BASE -
300 MPC8544_CCSRBAR_BASE, 0x1000);
301 qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0);
302
ed2bc496 303 snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE);
0dbc0798
AG
304 qemu_devtree_add_subnode(fdt, pci);
305 qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0);
306 qemu_devtree_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci");
307 qemu_devtree_setprop_string(fdt, pci, "device_type", "pci");
308 qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0,
309 0x0, 0x7);
310 pci_map_create(fdt, pci_map, qemu_devtree_get_phandle(fdt, mpic));
311 qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, sizeof(pci_map));
312 qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic);
7e99826c 313 qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2);
0dbc0798 314 qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255);
3627757e 315 for (i = 0; i < 14; i++) {
0dbc0798
AG
316 pci_ranges[i] = cpu_to_be32(pci_ranges[i]);
317 }
318 qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges));
3627757e
AG
319 qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32,
320 MPC8544_PCI_REGS_BASE, 0, 0x1000);
0dbc0798
AG
321 qemu_devtree_setprop_cell(fdt, pci, "clock-frequency", 66666666);
322 qemu_devtree_setprop_cell(fdt, pci, "#interrupt-cells", 1);
323 qemu_devtree_setprop_cell(fdt, pci, "#size-cells", 2);
324 qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3);
325 qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci);
326
e6eaabeb
SW
327 params->fixup_devtree(params, fdt);
328
329 if (toplevel_compat) {
330 qemu_devtree_setprop(fdt, "/", "compatible", toplevel_compat,
331 strlen(toplevel_compat) + 1);
332 }
333
d1b93565 334done:
71193433 335 qemu_devtree_dumpdtb(fdt, fdt_size);
04088adb 336 ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
cba2026a
AG
337 if (ret < 0) {
338 goto out;
339 }
7267c094 340 g_free(fdt);
cba2026a 341 ret = fdt_size;
7ec632b4 342
1db09b84 343out:
1db09b84 344
04088adb 345 return ret;
1db09b84
AJ
346}
347
cba2026a 348/* Create -kernel TLB entries for BookE. */
d1e256fe
AG
349static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size)
350{
cba2026a 351 return 63 - clz64(size >> 10);
d1e256fe
AG
352}
353
cba2026a 354static void mmubooke_create_initial_mapping(CPUPPCState *env)
3b989d49 355{
cba2026a 356 struct boot_info *bi = env->load_info;
d1e256fe 357 ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0);
cba2026a
AG
358 target_phys_addr_t size, dt_end;
359 int ps;
360
361 /* Our initial TLB entry needs to cover everything from 0 to
362 the device tree top */
363 dt_end = bi->dt_base + bi->dt_size;
364 ps = booke206_page_size_to_tlb(dt_end) + 1;
365 size = (ps << MAS1_TSIZE_SHIFT);
d1e256fe 366 tlb->mas1 = MAS1_VALID | size;
cba2026a
AG
367 tlb->mas2 = 0;
368 tlb->mas7_3 = 0;
d1e256fe 369 tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
93dd5e85
SW
370
371 env->tlb_dirty = true;
3b989d49
AG
372}
373
b3305981 374static void ppce500_cpu_reset_sec(void *opaque)
5c145dac 375{
38f92da6
AF
376 PowerPCCPU *cpu = opaque;
377 CPUPPCState *env = &cpu->env;
5c145dac 378
38f92da6 379 cpu_reset(CPU(cpu));
5c145dac
AG
380
381 /* Secondary CPU starts in halted state for now. Needs to change when
382 implementing non-kernel boot. */
383 env->halted = 1;
384 env->exception_index = EXCP_HLT;
3b989d49
AG
385}
386
b3305981 387static void ppce500_cpu_reset(void *opaque)
3b989d49 388{
38f92da6
AF
389 PowerPCCPU *cpu = opaque;
390 CPUPPCState *env = &cpu->env;
3b989d49
AG
391 struct boot_info *bi = env->load_info;
392
38f92da6 393 cpu_reset(CPU(cpu));
3b989d49
AG
394
395 /* Set initial guest state. */
5c145dac 396 env->halted = 0;
3b989d49
AG
397 env->gpr[1] = (16<<20) - 8;
398 env->gpr[3] = bi->dt_base;
399 env->nip = bi->entry;
cba2026a 400 mmubooke_create_initial_mapping(env);
3b989d49
AG
401}
402
e6eaabeb 403void ppce500_init(PPCE500Params *params)
1db09b84 404{
39186d8a 405 MemoryRegion *address_space_mem = get_system_memory();
2646c133 406 MemoryRegion *ram = g_new(MemoryRegion, 1);
1db09b84 407 PCIBus *pci_bus;
e2684c0b 408 CPUPPCState *env = NULL;
1db09b84
AJ
409 uint64_t elf_entry;
410 uint64_t elf_lowaddr;
c227f099
AL
411 target_phys_addr_t entry=0;
412 target_phys_addr_t loadaddr=UIMAGE_LOAD_BASE;
1db09b84 413 target_long kernel_size=0;
75bb6589
LY
414 target_ulong dt_base = 0;
415 target_ulong initrd_base = 0;
1db09b84 416 target_long initrd_size=0;
1db09b84
AJ
417 int i=0;
418 unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
a915249f 419 qemu_irq **irqs, *mpic;
be13cc7a 420 DeviceState *dev;
e2684c0b 421 CPUPPCState *firstenv = NULL;
1db09b84 422
e61c36d5 423 /* Setup CPUs */
e6eaabeb
SW
424 if (params->cpu_model == NULL) {
425 params->cpu_model = "e500v2_v30";
ef250db6
AG
426 }
427
a915249f
AG
428 irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
429 irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
e61c36d5 430 for (i = 0; i < smp_cpus; i++) {
397b457d 431 PowerPCCPU *cpu;
e61c36d5 432 qemu_irq *input;
397b457d 433
e6eaabeb 434 cpu = cpu_ppc_init(params->cpu_model);
397b457d 435 if (cpu == NULL) {
e61c36d5
AG
436 fprintf(stderr, "Unable to initialize CPU!\n");
437 exit(1);
438 }
397b457d 439 env = &cpu->env;
1db09b84 440
e61c36d5
AG
441 if (!firstenv) {
442 firstenv = env;
443 }
1db09b84 444
a915249f
AG
445 irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB);
446 input = (qemu_irq *)env->irq_inputs;
447 irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
448 irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
e61c36d5 449 env->spr[SPR_BOOKE_PIR] = env->cpu_index = i;
2a7a47fc 450 env->mpic_cpu_base = MPC8544_MPIC_REGS_BASE + 0x20000;
3b989d49 451
ddd1055b 452 ppc_booke_timers_init(env, 400000000, PPC_TIMER_E500);
e61c36d5
AG
453
454 /* Register reset handler */
5c145dac
AG
455 if (!i) {
456 /* Primary CPU */
457 struct boot_info *boot_info;
458 boot_info = g_malloc0(sizeof(struct boot_info));
b3305981 459 qemu_register_reset(ppce500_cpu_reset, cpu);
5c145dac
AG
460 env->load_info = boot_info;
461 } else {
462 /* Secondary CPUs */
b3305981 463 qemu_register_reset(ppce500_cpu_reset_sec, cpu);
5c145dac 464 }
e61c36d5 465 }
3b989d49 466
e61c36d5 467 env = firstenv;
3b989d49 468
1db09b84
AJ
469 /* Fixup Memory size on a alignment boundary */
470 ram_size &= ~(RAM_SIZES_ALIGN - 1);
471
472 /* Register Memory */
c5705a77
AK
473 memory_region_init_ram(ram, "mpc8544ds.ram", ram_size);
474 vmstate_register_ram_global(ram);
2646c133 475 memory_region_add_subregion(address_space_mem, 0, ram);
1db09b84
AJ
476
477 /* MPIC */
df2921d3
AK
478 mpic = mpic_init(address_space_mem, MPC8544_MPIC_REGS_BASE,
479 smp_cpus, irqs, NULL);
a915249f
AG
480
481 if (!mpic) {
482 cpu_abort(env, "MPIC failed to initialize\n");
483 }
1db09b84
AJ
484
485 /* Serial */
2d48377a 486 if (serial_hds[0]) {
39186d8a 487 serial_mm_init(address_space_mem, MPC8544_SERIAL0_REGS_BASE,
49a2942d 488 0, mpic[12+26], 399193,
2ff0c7c3 489 serial_hds[0], DEVICE_BIG_ENDIAN);
2d48377a 490 }
1db09b84 491
2d48377a 492 if (serial_hds[1]) {
39186d8a 493 serial_mm_init(address_space_mem, MPC8544_SERIAL1_REGS_BASE,
49a2942d 494 0, mpic[12+26], 399193,
2ff0c7c3 495 serial_hds[0], DEVICE_BIG_ENDIAN);
2d48377a 496 }
1db09b84 497
b0fb8423
AG
498 /* General Utility device */
499 sysbus_create_simple("mpc8544-guts", MPC8544_UTIL_BASE, NULL);
500
1db09b84 501 /* PCI */
be13cc7a
AG
502 dev = sysbus_create_varargs("e500-pcihost", MPC8544_PCI_REGS_BASE,
503 mpic[pci_irq_nrs[0]], mpic[pci_irq_nrs[1]],
504 mpic[pci_irq_nrs[2]], mpic[pci_irq_nrs[3]],
505 NULL);
d461e3b9 506 pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
1db09b84
AJ
507 if (!pci_bus)
508 printf("couldn't create PCI controller!\n");
509
968d683c 510 isa_mmio_init(MPC8544_PCI_IO, MPC8544_PCI_IOLEN);
1db09b84
AJ
511
512 if (pci_bus) {
1db09b84
AJ
513 /* Register network interfaces. */
514 for (i = 0; i < nb_nics; i++) {
07caea31 515 pci_nic_init_nofail(&nd_table[i], "virtio", NULL);
1db09b84
AJ
516 }
517 }
518
5c145dac
AG
519 /* Register spinning region */
520 sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL);
521
1db09b84 522 /* Load kernel. */
e6eaabeb
SW
523 if (params->kernel_filename) {
524 kernel_size = load_uimage(params->kernel_filename, &entry,
525 &loadaddr, NULL);
1db09b84 526 if (kernel_size < 0) {
e6eaabeb
SW
527 kernel_size = load_elf(params->kernel_filename, NULL, NULL,
528 &elf_entry, &elf_lowaddr, NULL, 1,
529 ELF_MACHINE, 0);
1db09b84
AJ
530 entry = elf_entry;
531 loadaddr = elf_lowaddr;
532 }
533 /* XXX try again as binary */
534 if (kernel_size < 0) {
535 fprintf(stderr, "qemu: could not load kernel '%s'\n",
e6eaabeb 536 params->kernel_filename);
1db09b84
AJ
537 exit(1);
538 }
539 }
540
541 /* Load initrd. */
e6eaabeb 542 if (params->initrd_filename) {
7e7ec2d2
SW
543 initrd_base = (loadaddr + kernel_size + INITRD_LOAD_PAD) &
544 ~INITRD_PAD_MASK;
e6eaabeb 545 initrd_size = load_image_targphys(params->initrd_filename, initrd_base,
d7585251 546 ram_size - initrd_base);
1db09b84
AJ
547
548 if (initrd_size < 0) {
549 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
e6eaabeb 550 params->initrd_filename);
1db09b84
AJ
551 exit(1);
552 }
553 }
554
555 /* If we're loading a kernel directly, we must load the device tree too. */
e6eaabeb 556 if (params->kernel_filename) {
5c145dac 557 struct boot_info *boot_info;
cba2026a 558 int dt_size;
5c145dac 559
cba2026a 560 dt_base = (loadaddr + kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
e6eaabeb
SW
561 dt_size = ppce500_load_device_tree(env, params, dt_base, initrd_base,
562 initrd_size);
cba2026a 563 if (dt_size < 0) {
1db09b84
AJ
564 fprintf(stderr, "couldn't load device tree\n");
565 exit(1);
566 }
567
e61c36d5 568 boot_info = env->load_info;
3b989d49
AG
569 boot_info->entry = entry;
570 boot_info->dt_base = dt_base;
cba2026a 571 boot_info->dt_size = dt_size;
1db09b84
AJ
572 }
573
3b989d49 574 if (kvm_enabled()) {
1db09b84 575 kvmppc_init();
3b989d49 576 }
1db09b84 577}