]> git.proxmox.com Git - mirror_qemu.git/blame - hw/ppc/e500.c
Rename target_phys_addr_t to hwaddr
[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
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,
a8170e5e
AK
111 hwaddr addr,
112 hwaddr initrd_base,
113 hwaddr 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. */
a8170e5e 349static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
d1e256fe 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);
a8170e5e 358 hwaddr size, dt_end;
cba2026a
AG
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;
fb37c302
AG
365 if (ps & 1) {
366 /* e500v2 can only do even TLB size bits */
367 ps++;
368 }
cba2026a 369 size = (ps << MAS1_TSIZE_SHIFT);
d1e256fe 370 tlb->mas1 = MAS1_VALID | size;
cba2026a
AG
371 tlb->mas2 = 0;
372 tlb->mas7_3 = 0;
d1e256fe 373 tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
93dd5e85
SW
374
375 env->tlb_dirty = true;
3b989d49
AG
376}
377
b3305981 378static void ppce500_cpu_reset_sec(void *opaque)
5c145dac 379{
38f92da6
AF
380 PowerPCCPU *cpu = opaque;
381 CPUPPCState *env = &cpu->env;
5c145dac 382
38f92da6 383 cpu_reset(CPU(cpu));
5c145dac
AG
384
385 /* Secondary CPU starts in halted state for now. Needs to change when
386 implementing non-kernel boot. */
387 env->halted = 1;
388 env->exception_index = EXCP_HLT;
3b989d49
AG
389}
390
b3305981 391static void ppce500_cpu_reset(void *opaque)
3b989d49 392{
38f92da6
AF
393 PowerPCCPU *cpu = opaque;
394 CPUPPCState *env = &cpu->env;
3b989d49
AG
395 struct boot_info *bi = env->load_info;
396
38f92da6 397 cpu_reset(CPU(cpu));
3b989d49
AG
398
399 /* Set initial guest state. */
5c145dac 400 env->halted = 0;
3b989d49
AG
401 env->gpr[1] = (16<<20) - 8;
402 env->gpr[3] = bi->dt_base;
403 env->nip = bi->entry;
cba2026a 404 mmubooke_create_initial_mapping(env);
3b989d49
AG
405}
406
e6eaabeb 407void ppce500_init(PPCE500Params *params)
1db09b84 408{
39186d8a 409 MemoryRegion *address_space_mem = get_system_memory();
2646c133 410 MemoryRegion *ram = g_new(MemoryRegion, 1);
1db09b84 411 PCIBus *pci_bus;
e2684c0b 412 CPUPPCState *env = NULL;
1db09b84
AJ
413 uint64_t elf_entry;
414 uint64_t elf_lowaddr;
a8170e5e
AK
415 hwaddr entry=0;
416 hwaddr loadaddr=UIMAGE_LOAD_BASE;
1db09b84 417 target_long kernel_size=0;
75bb6589
LY
418 target_ulong dt_base = 0;
419 target_ulong initrd_base = 0;
1db09b84 420 target_long initrd_size=0;
1db09b84
AJ
421 int i=0;
422 unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
a915249f 423 qemu_irq **irqs, *mpic;
be13cc7a 424 DeviceState *dev;
e2684c0b 425 CPUPPCState *firstenv = NULL;
1db09b84 426
e61c36d5 427 /* Setup CPUs */
e6eaabeb
SW
428 if (params->cpu_model == NULL) {
429 params->cpu_model = "e500v2_v30";
ef250db6
AG
430 }
431
a915249f
AG
432 irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
433 irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
e61c36d5 434 for (i = 0; i < smp_cpus; i++) {
397b457d 435 PowerPCCPU *cpu;
e61c36d5 436 qemu_irq *input;
397b457d 437
e6eaabeb 438 cpu = cpu_ppc_init(params->cpu_model);
397b457d 439 if (cpu == NULL) {
e61c36d5
AG
440 fprintf(stderr, "Unable to initialize CPU!\n");
441 exit(1);
442 }
397b457d 443 env = &cpu->env;
1db09b84 444
e61c36d5
AG
445 if (!firstenv) {
446 firstenv = env;
447 }
1db09b84 448
a915249f
AG
449 irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB);
450 input = (qemu_irq *)env->irq_inputs;
451 irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
452 irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
e61c36d5 453 env->spr[SPR_BOOKE_PIR] = env->cpu_index = i;
2a7a47fc 454 env->mpic_cpu_base = MPC8544_MPIC_REGS_BASE + 0x20000;
3b989d49 455
ddd1055b 456 ppc_booke_timers_init(env, 400000000, PPC_TIMER_E500);
e61c36d5
AG
457
458 /* Register reset handler */
5c145dac
AG
459 if (!i) {
460 /* Primary CPU */
461 struct boot_info *boot_info;
462 boot_info = g_malloc0(sizeof(struct boot_info));
b3305981 463 qemu_register_reset(ppce500_cpu_reset, cpu);
5c145dac
AG
464 env->load_info = boot_info;
465 } else {
466 /* Secondary CPUs */
b3305981 467 qemu_register_reset(ppce500_cpu_reset_sec, cpu);
5c145dac 468 }
e61c36d5 469 }
3b989d49 470
e61c36d5 471 env = firstenv;
3b989d49 472
1db09b84
AJ
473 /* Fixup Memory size on a alignment boundary */
474 ram_size &= ~(RAM_SIZES_ALIGN - 1);
475
476 /* Register Memory */
c5705a77
AK
477 memory_region_init_ram(ram, "mpc8544ds.ram", ram_size);
478 vmstate_register_ram_global(ram);
2646c133 479 memory_region_add_subregion(address_space_mem, 0, ram);
1db09b84
AJ
480
481 /* MPIC */
df2921d3
AK
482 mpic = mpic_init(address_space_mem, MPC8544_MPIC_REGS_BASE,
483 smp_cpus, irqs, NULL);
a915249f
AG
484
485 if (!mpic) {
486 cpu_abort(env, "MPIC failed to initialize\n");
487 }
1db09b84
AJ
488
489 /* Serial */
2d48377a 490 if (serial_hds[0]) {
39186d8a 491 serial_mm_init(address_space_mem, MPC8544_SERIAL0_REGS_BASE,
49a2942d 492 0, mpic[12+26], 399193,
2ff0c7c3 493 serial_hds[0], DEVICE_BIG_ENDIAN);
2d48377a 494 }
1db09b84 495
2d48377a 496 if (serial_hds[1]) {
39186d8a 497 serial_mm_init(address_space_mem, MPC8544_SERIAL1_REGS_BASE,
49a2942d 498 0, mpic[12+26], 399193,
2ff0c7c3 499 serial_hds[0], DEVICE_BIG_ENDIAN);
2d48377a 500 }
1db09b84 501
b0fb8423
AG
502 /* General Utility device */
503 sysbus_create_simple("mpc8544-guts", MPC8544_UTIL_BASE, NULL);
504
1db09b84 505 /* PCI */
be13cc7a
AG
506 dev = sysbus_create_varargs("e500-pcihost", MPC8544_PCI_REGS_BASE,
507 mpic[pci_irq_nrs[0]], mpic[pci_irq_nrs[1]],
508 mpic[pci_irq_nrs[2]], mpic[pci_irq_nrs[3]],
509 NULL);
d461e3b9 510 pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
1db09b84
AJ
511 if (!pci_bus)
512 printf("couldn't create PCI controller!\n");
513
968d683c 514 isa_mmio_init(MPC8544_PCI_IO, MPC8544_PCI_IOLEN);
1db09b84
AJ
515
516 if (pci_bus) {
1db09b84
AJ
517 /* Register network interfaces. */
518 for (i = 0; i < nb_nics; i++) {
07caea31 519 pci_nic_init_nofail(&nd_table[i], "virtio", NULL);
1db09b84
AJ
520 }
521 }
522
5c145dac
AG
523 /* Register spinning region */
524 sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL);
525
1db09b84 526 /* Load kernel. */
e6eaabeb
SW
527 if (params->kernel_filename) {
528 kernel_size = load_uimage(params->kernel_filename, &entry,
529 &loadaddr, NULL);
1db09b84 530 if (kernel_size < 0) {
e6eaabeb
SW
531 kernel_size = load_elf(params->kernel_filename, NULL, NULL,
532 &elf_entry, &elf_lowaddr, NULL, 1,
533 ELF_MACHINE, 0);
1db09b84
AJ
534 entry = elf_entry;
535 loadaddr = elf_lowaddr;
536 }
537 /* XXX try again as binary */
538 if (kernel_size < 0) {
539 fprintf(stderr, "qemu: could not load kernel '%s'\n",
e6eaabeb 540 params->kernel_filename);
1db09b84
AJ
541 exit(1);
542 }
543 }
544
545 /* Load initrd. */
e6eaabeb 546 if (params->initrd_filename) {
7e7ec2d2
SW
547 initrd_base = (loadaddr + kernel_size + INITRD_LOAD_PAD) &
548 ~INITRD_PAD_MASK;
e6eaabeb 549 initrd_size = load_image_targphys(params->initrd_filename, initrd_base,
d7585251 550 ram_size - initrd_base);
1db09b84
AJ
551
552 if (initrd_size < 0) {
553 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
e6eaabeb 554 params->initrd_filename);
1db09b84
AJ
555 exit(1);
556 }
557 }
558
559 /* If we're loading a kernel directly, we must load the device tree too. */
e6eaabeb 560 if (params->kernel_filename) {
5c145dac 561 struct boot_info *boot_info;
cba2026a 562 int dt_size;
5c145dac 563
cba2026a 564 dt_base = (loadaddr + kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
e6eaabeb
SW
565 dt_size = ppce500_load_device_tree(env, params, dt_base, initrd_base,
566 initrd_size);
cba2026a 567 if (dt_size < 0) {
1db09b84
AJ
568 fprintf(stderr, "couldn't load device tree\n");
569 exit(1);
570 }
571
e61c36d5 572 boot_info = env->load_info;
3b989d49
AG
573 boot_info->entry = entry;
574 boot_info->dt_base = dt_base;
cba2026a 575 boot_info->dt_size = dt_size;
1db09b84
AJ
576 }
577
3b989d49 578 if (kvm_enabled()) {
1db09b84 579 kvmppc_init();
3b989d49 580 }
1db09b84 581}