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