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