]> git.proxmox.com Git - mirror_qemu.git/blame - hw/spapr.c
ppc: Alter CPU state to mask out TCG unimplemented instructions as appropriate
[mirror_qemu.git] / hw / spapr.c
CommitLineData
9fdf0c29
DG
1/*
2 * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
3 *
4 * Copyright (c) 2004-2007 Fabrice Bellard
5 * Copyright (c) 2007 Jocelyn Mayer
6 * Copyright (c) 2010 David Gibson, IBM Corporation.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 *
26 */
27#include "sysemu.h"
9fdf0c29
DG
28#include "hw.h"
29#include "elf.h"
8d90ad90 30#include "net.h"
6e270446 31#include "blockdev.h"
e97c3636
DG
32#include "cpus.h"
33#include "kvm.h"
34#include "kvm_ppc.h"
9fdf0c29
DG
35
36#include "hw/boards.h"
37#include "hw/ppc.h"
38#include "hw/loader.h"
39
40#include "hw/spapr.h"
4040ab72 41#include "hw/spapr_vio.h"
b5cec4c5 42#include "hw/xics.h"
9fdf0c29 43
f61b4bed
AG
44#include "kvm.h"
45#include "kvm_ppc.h"
46
890c2b77
AK
47#include "exec-memory.h"
48
9fdf0c29
DG
49#include <libfdt.h>
50
51#define KERNEL_LOAD_ADDR 0x00000000
52#define INITRD_LOAD_ADDR 0x02800000
53#define FDT_MAX_SIZE 0x10000
39ac8455 54#define RTAS_MAX_SIZE 0x10000
a9f8ad8f
DG
55#define FW_MAX_SIZE 0x400000
56#define FW_FILE_NAME "slof.bin"
57
58#define MIN_RAM_SLOF 512UL
9fdf0c29
DG
59
60#define TIMEBASE_FREQ 512000000ULL
61
41019fec 62#define MAX_CPUS 256
b5cec4c5 63#define XICS_IRQS 1024
9fdf0c29 64
0c103f8e
DG
65#define PHANDLE_XICP 0x00001111
66
9fdf0c29
DG
67sPAPREnvironment *spapr;
68
e6c866d4
DG
69qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num)
70{
71 uint32_t irq;
72 qemu_irq qirq;
73
74 if (hint) {
75 irq = hint;
76 /* FIXME: we should probably check for collisions somehow */
77 } else {
78 irq = spapr->next_irq++;
79 }
80
81 qirq = xics_find_qirq(spapr->icp, irq);
82 if (!qirq) {
83 return NULL;
84 }
85
86 if (irq_num) {
87 *irq_num = irq;
88 }
89
90 return qirq;
91}
92
a3467baa 93static void *spapr_create_fdt_skel(const char *cpu_model,
354ac20a 94 target_phys_addr_t rma_size,
a3467baa
DG
95 target_phys_addr_t initrd_base,
96 target_phys_addr_t initrd_size,
97 const char *boot_device,
98 const char *kernel_cmdline,
99 long hash_shift)
9fdf0c29
DG
100{
101 void *fdt;
c7a5c0c9 102 CPUState *env;
354ac20a
DG
103 uint64_t mem_reg_property_rma[] = { 0, cpu_to_be64(rma_size) };
104 uint64_t mem_reg_property_nonrma[] = { cpu_to_be64(rma_size),
105 cpu_to_be64(ram_size - rma_size) };
9fdf0c29
DG
106 uint32_t start_prop = cpu_to_be32(initrd_base);
107 uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
f43e3525 108 uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
ee86dfee 109 char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
a3d0abae 110 "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk";
b5cec4c5 111 uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
9fdf0c29
DG
112 int i;
113 char *modelname;
e97c3636 114 int smt = kvmppc_smt_threads();
9fdf0c29
DG
115
116#define _FDT(exp) \
117 do { \
118 int ret = (exp); \
119 if (ret < 0) { \
120 fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \
121 #exp, fdt_strerror(ret)); \
122 exit(1); \
123 } \
124 } while (0)
125
7267c094 126 fdt = g_malloc0(FDT_MAX_SIZE);
9fdf0c29
DG
127 _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
128
129 _FDT((fdt_finish_reservemap(fdt)));
130
131 /* Root node */
132 _FDT((fdt_begin_node(fdt, "")));
133 _FDT((fdt_property_string(fdt, "device_type", "chrp")));
5d73dd66 134 _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
9fdf0c29
DG
135
136 _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
137 _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
138
139 /* /chosen */
140 _FDT((fdt_begin_node(fdt, "chosen")));
141
142 _FDT((fdt_property_string(fdt, "bootargs", kernel_cmdline)));
143 _FDT((fdt_property(fdt, "linux,initrd-start",
144 &start_prop, sizeof(start_prop))));
145 _FDT((fdt_property(fdt, "linux,initrd-end",
146 &end_prop, sizeof(end_prop))));
a9f8ad8f 147 _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device)));
9fdf0c29
DG
148
149 _FDT((fdt_end_node(fdt)));
150
354ac20a 151 /* memory node(s) */
9fdf0c29
DG
152 _FDT((fdt_begin_node(fdt, "memory@0")));
153
154 _FDT((fdt_property_string(fdt, "device_type", "memory")));
354ac20a
DG
155 _FDT((fdt_property(fdt, "reg", mem_reg_property_rma,
156 sizeof(mem_reg_property_rma))));
9fdf0c29
DG
157 _FDT((fdt_end_node(fdt)));
158
354ac20a
DG
159 if (ram_size > rma_size) {
160 char mem_name[32];
161
162 sprintf(mem_name, "memory@%" PRIx64, (uint64_t)rma_size);
163 _FDT((fdt_begin_node(fdt, mem_name)));
164 _FDT((fdt_property_string(fdt, "device_type", "memory")));
165 _FDT((fdt_property(fdt, "reg", mem_reg_property_nonrma,
166 sizeof(mem_reg_property_nonrma))));
167 _FDT((fdt_end_node(fdt)));
168 }
169
9fdf0c29
DG
170 /* cpus */
171 _FDT((fdt_begin_node(fdt, "cpus")));
172
173 _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
174 _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
175
7267c094 176 modelname = g_strdup(cpu_model);
9fdf0c29
DG
177
178 for (i = 0; i < strlen(modelname); i++) {
179 modelname[i] = toupper(modelname[i]);
180 }
181
c7a5c0c9
DG
182 for (env = first_cpu; env != NULL; env = env->next_cpu) {
183 int index = env->cpu_index;
e97c3636
DG
184 uint32_t servers_prop[smp_threads];
185 uint32_t gservers_prop[smp_threads * 2];
9fdf0c29
DG
186 char *nodename;
187 uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
188 0xffffffff, 0xffffffff};
0a8b2938
AG
189 uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ;
190 uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
9fdf0c29 191
e97c3636
DG
192 if ((index % smt) != 0) {
193 continue;
194 }
195
c7a5c0c9 196 if (asprintf(&nodename, "%s@%x", modelname, index) < 0) {
9fdf0c29
DG
197 fprintf(stderr, "Allocation failure\n");
198 exit(1);
199 }
200
201 _FDT((fdt_begin_node(fdt, nodename)));
202
203 free(nodename);
204
c7a5c0c9 205 _FDT((fdt_property_cell(fdt, "reg", index)));
9fdf0c29
DG
206 _FDT((fdt_property_string(fdt, "device_type", "cpu")));
207
208 _FDT((fdt_property_cell(fdt, "cpu-version", env->spr[SPR_PVR])));
209 _FDT((fdt_property_cell(fdt, "dcache-block-size",
210 env->dcache_line_size)));
211 _FDT((fdt_property_cell(fdt, "icache-block-size",
212 env->icache_line_size)));
0a8b2938
AG
213 _FDT((fdt_property_cell(fdt, "timebase-frequency", tbfreq)));
214 _FDT((fdt_property_cell(fdt, "clock-frequency", cpufreq)));
9fdf0c29 215 _FDT((fdt_property_cell(fdt, "ibm,slb-size", env->slb_nr)));
f43e3525
DG
216 _FDT((fdt_property(fdt, "ibm,pft-size",
217 pft_size_prop, sizeof(pft_size_prop))));
9fdf0c29
DG
218 _FDT((fdt_property_string(fdt, "status", "okay")));
219 _FDT((fdt_property(fdt, "64-bit", NULL, 0)));
e97c3636
DG
220
221 /* Build interrupt servers and gservers properties */
222 for (i = 0; i < smp_threads; i++) {
223 servers_prop[i] = cpu_to_be32(index + i);
224 /* Hack, direct the group queues back to cpu 0 */
225 gservers_prop[i*2] = cpu_to_be32(index + i);
226 gservers_prop[i*2 + 1] = 0;
227 }
228 _FDT((fdt_property(fdt, "ibm,ppc-interrupt-server#s",
229 servers_prop, sizeof(servers_prop))));
b5cec4c5 230 _FDT((fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
e97c3636 231 gservers_prop, sizeof(gservers_prop))));
9fdf0c29 232
c7a5c0c9 233 if (env->mmu_model & POWERPC_MMU_1TSEG) {
9fdf0c29
DG
234 _FDT((fdt_property(fdt, "ibm,processor-segment-sizes",
235 segs, sizeof(segs))));
236 }
237
6659394f
DG
238 /* Advertise VMX/VSX (vector extensions) if available
239 * 0 / no property == no vector extensions
240 * 1 == VMX / Altivec available
241 * 2 == VSX available */
a7342588
DG
242 if (env->insns_flags & PPC_ALTIVEC) {
243 uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
244
6659394f
DG
245 _FDT((fdt_property_cell(fdt, "ibm,vmx", vmx)));
246 }
247
248 /* Advertise DFP (Decimal Floating Point) if available
249 * 0 / no property == no DFP
250 * 1 == DFP available */
a7342588
DG
251 if (env->insns_flags2 & PPC2_DFP) {
252 _FDT((fdt_property_cell(fdt, "ibm,dfp", 1)));
6659394f
DG
253 }
254
9fdf0c29
DG
255 _FDT((fdt_end_node(fdt)));
256 }
257
7267c094 258 g_free(modelname);
9fdf0c29
DG
259
260 _FDT((fdt_end_node(fdt)));
261
f43e3525
DG
262 /* RTAS */
263 _FDT((fdt_begin_node(fdt, "rtas")));
264
265 _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas_prop,
266 sizeof(hypertas_prop))));
267
268 _FDT((fdt_end_node(fdt)));
269
b5cec4c5 270 /* interrupt controller */
9dfef5aa 271 _FDT((fdt_begin_node(fdt, "interrupt-controller")));
b5cec4c5
DG
272
273 _FDT((fdt_property_string(fdt, "device_type",
274 "PowerPC-External-Interrupt-Presentation")));
275 _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
b5cec4c5
DG
276 _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
277 _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
278 interrupt_server_ranges_prop,
279 sizeof(interrupt_server_ranges_prop))));
0c103f8e
DG
280 _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
281 _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
282 _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
b5cec4c5
DG
283
284 _FDT((fdt_end_node(fdt)));
285
4040ab72
DG
286 /* vdevice */
287 _FDT((fdt_begin_node(fdt, "vdevice")));
288
289 _FDT((fdt_property_string(fdt, "device_type", "vdevice")));
290 _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
291 _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
292 _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
b5cec4c5
DG
293 _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));
294 _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
4040ab72
DG
295
296 _FDT((fdt_end_node(fdt)));
297
9fdf0c29
DG
298 _FDT((fdt_end_node(fdt))); /* close root node */
299 _FDT((fdt_finish(fdt)));
300
a3467baa
DG
301 return fdt;
302}
303
304static void spapr_finalize_fdt(sPAPREnvironment *spapr,
305 target_phys_addr_t fdt_addr,
306 target_phys_addr_t rtas_addr,
307 target_phys_addr_t rtas_size)
308{
309 int ret;
310 void *fdt;
311
7267c094 312 fdt = g_malloc(FDT_MAX_SIZE);
a3467baa
DG
313
314 /* open out the base tree into a temp buffer for the final tweaks */
315 _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE)));
4040ab72
DG
316
317 ret = spapr_populate_vdevice(spapr->vio_bus, fdt);
318 if (ret < 0) {
319 fprintf(stderr, "couldn't setup vio devices in fdt\n");
320 exit(1);
321 }
322
39ac8455
DG
323 /* RTAS */
324 ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size);
325 if (ret < 0) {
326 fprintf(stderr, "Couldn't set up RTAS device tree properties\n");
327 }
328
4040ab72
DG
329 _FDT((fdt_pack(fdt)));
330
a3467baa 331 cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
9fdf0c29 332
7267c094 333 g_free(fdt);
9fdf0c29
DG
334}
335
336static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
337{
338 return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
339}
340
341static void emulate_spapr_hypercall(CPUState *env)
342{
343 env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]);
344}
345
a3467baa
DG
346static void spapr_reset(void *opaque)
347{
348 sPAPREnvironment *spapr = (sPAPREnvironment *)opaque;
349
350 fprintf(stderr, "sPAPR reset\n");
351
352 /* flush out the hash table */
353 memset(spapr->htab, 0, spapr->htab_size);
354
355 /* Load the fdt */
356 spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr,
357 spapr->rtas_size);
358
359 /* Set up the entry state */
360 first_cpu->gpr[3] = spapr->fdt_addr;
361 first_cpu->gpr[5] = 0;
362 first_cpu->halted = 0;
363 first_cpu->nip = spapr->entry_point;
364
365}
366
9fdf0c29
DG
367/* pSeries LPAR / sPAPR hardware init */
368static void ppc_spapr_init(ram_addr_t ram_size,
369 const char *boot_device,
370 const char *kernel_filename,
371 const char *kernel_cmdline,
372 const char *initrd_filename,
373 const char *cpu_model)
374{
c7a5c0c9 375 CPUState *env;
9fdf0c29 376 int i;
890c2b77
AK
377 MemoryRegion *sysmem = get_system_memory();
378 MemoryRegion *ram = g_new(MemoryRegion, 1);
354ac20a 379 target_phys_addr_t rma_alloc_size, rma_size;
a3467baa
DG
380 uint32_t initrd_base;
381 long kernel_size, initrd_size, fw_size;
f43e3525 382 long pteg_shift = 17;
39ac8455 383 char *filename;
9fdf0c29 384
7267c094 385 spapr = g_malloc(sizeof(*spapr));
9fdf0c29
DG
386 cpu_ppc_hypercall = emulate_spapr_hypercall;
387
354ac20a
DG
388 /* Allocate RMA if necessary */
389 rma_alloc_size = kvmppc_alloc_rma("ppc_spapr.rma", sysmem);
390
391 if (rma_alloc_size == -1) {
392 hw_error("qemu: Unable to create RMA\n");
393 exit(1);
394 }
395 if (rma_alloc_size && (rma_alloc_size < ram_size)) {
396 rma_size = rma_alloc_size;
397 } else {
398 rma_size = ram_size;
399 }
400
401 /* We place the device tree just below either the top of the RMA,
402 * or just below 2GB, whichever is lowere, so that it can be
403 * processed with 32-bit real mode code if necessary */
404 spapr->fdt_addr = MIN(rma_size, 0x80000000) - FDT_MAX_SIZE;
a3467baa 405 spapr->rtas_addr = spapr->fdt_addr - RTAS_MAX_SIZE;
9fdf0c29
DG
406
407 /* init CPUs */
408 if (cpu_model == NULL) {
6b7a2cf6 409 cpu_model = kvm_enabled() ? "host" : "POWER7";
9fdf0c29
DG
410 }
411 for (i = 0; i < smp_cpus; i++) {
c7a5c0c9 412 env = cpu_init(cpu_model);
9fdf0c29
DG
413
414 if (!env) {
415 fprintf(stderr, "Unable to find PowerPC CPU definition\n");
416 exit(1);
417 }
418 /* Set time-base frequency to 512 MHz */
419 cpu_ppc_tb_init(env, TIMEBASE_FREQ);
420 qemu_register_reset((QEMUResetHandler *)&cpu_reset, env);
421
422 env->hreset_vector = 0x60;
423 env->hreset_excp_prefix = 0;
c7a5c0c9 424 env->gpr[3] = env->cpu_index;
9fdf0c29
DG
425 }
426
427 /* allocate RAM */
f73a2575 428 spapr->ram_limit = ram_size;
354ac20a
DG
429 if (spapr->ram_limit > rma_alloc_size) {
430 ram_addr_t nonrma_base = rma_alloc_size;
431 ram_addr_t nonrma_size = spapr->ram_limit - rma_alloc_size;
432
433 memory_region_init_ram(ram, NULL, "ppc_spapr.ram", nonrma_size);
434 memory_region_add_subregion(sysmem, nonrma_base, ram);
435 }
9fdf0c29 436
f43e3525
DG
437 /* allocate hash page table. For now we always make this 16mb,
438 * later we should probably make it scale to the size of guest
439 * RAM */
a3467baa 440 spapr->htab_size = 1ULL << (pteg_shift + 7);
f61b4bed 441 spapr->htab = qemu_memalign(spapr->htab_size, spapr->htab_size);
f43e3525 442
c7a5c0c9 443 for (env = first_cpu; env != NULL; env = env->next_cpu) {
a3467baa 444 env->external_htab = spapr->htab;
c7a5c0c9 445 env->htab_base = -1;
a3467baa 446 env->htab_mask = spapr->htab_size - 1;
f61b4bed
AG
447
448 /* Tell KVM that we're in PAPR mode */
449 env->spr[SPR_SDR1] = (unsigned long)spapr->htab |
450 ((pteg_shift + 7) - 18);
451 env->spr[SPR_HIOR] = 0;
452
453 if (kvm_enabled()) {
454 kvmppc_set_papr(env);
455 }
f43e3525
DG
456 }
457
39ac8455 458 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
a3467baa
DG
459 spapr->rtas_size = load_image_targphys(filename, spapr->rtas_addr,
460 ram_size - spapr->rtas_addr);
461 if (spapr->rtas_size < 0) {
39ac8455
DG
462 hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
463 exit(1);
464 }
7267c094 465 g_free(filename);
39ac8455 466
b5cec4c5 467 /* Set up Interrupt Controller */
c7a5c0c9 468 spapr->icp = xics_system_init(XICS_IRQS);
e6c866d4 469 spapr->next_irq = 16;
b5cec4c5
DG
470
471 /* Set up VIO bus */
4040ab72
DG
472 spapr->vio_bus = spapr_vio_bus_init();
473
277f9acf 474 for (i = 0; i < MAX_SERIAL_PORTS; i++) {
4040ab72 475 if (serial_hds[i]) {
b4a78527 476 spapr_vty_create(spapr->vio_bus, SPAPR_VTY_BASE_ADDRESS + i,
277f9acf 477 serial_hds[i]);
4040ab72
DG
478 }
479 }
9fdf0c29 480
277f9acf 481 for (i = 0; i < nb_nics; i++) {
8d90ad90
DG
482 NICInfo *nd = &nd_table[i];
483
484 if (!nd->model) {
7267c094 485 nd->model = g_strdup("ibmveth");
8d90ad90
DG
486 }
487
488 if (strcmp(nd->model, "ibmveth") == 0) {
277f9acf 489 spapr_vlan_create(spapr->vio_bus, 0x1000 + i, nd);
8d90ad90
DG
490 } else {
491 fprintf(stderr, "pSeries (sPAPR) platform does not support "
492 "NIC model '%s' (only ibmveth is supported)\n",
493 nd->model);
494 exit(1);
495 }
496 }
497
6e270446 498 for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) {
277f9acf 499 spapr_vscsi_create(spapr->vio_bus, 0x2000 + i);
6e270446
BH
500 }
501
9fdf0c29
DG
502 if (kernel_filename) {
503 uint64_t lowaddr = 0;
504
9fdf0c29
DG
505 kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
506 NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
507 if (kernel_size < 0) {
a3467baa
DG
508 kernel_size = load_image_targphys(kernel_filename,
509 KERNEL_LOAD_ADDR,
510 ram_size - KERNEL_LOAD_ADDR);
9fdf0c29
DG
511 }
512 if (kernel_size < 0) {
513 fprintf(stderr, "qemu: could not load kernel '%s'\n",
514 kernel_filename);
515 exit(1);
516 }
517
518 /* load initrd */
519 if (initrd_filename) {
520 initrd_base = INITRD_LOAD_ADDR;
521 initrd_size = load_image_targphys(initrd_filename, initrd_base,
522 ram_size - initrd_base);
523 if (initrd_size < 0) {
524 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
525 initrd_filename);
526 exit(1);
527 }
528 } else {
529 initrd_base = 0;
530 initrd_size = 0;
531 }
a3467baa
DG
532
533 spapr->entry_point = KERNEL_LOAD_ADDR;
9fdf0c29 534 } else {
a9f8ad8f
DG
535 if (ram_size < (MIN_RAM_SLOF << 20)) {
536 fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
537 "%ldM guest RAM\n", MIN_RAM_SLOF);
538 exit(1);
539 }
68722054 540 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME);
a9f8ad8f
DG
541 fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
542 if (fw_size < 0) {
543 hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
544 exit(1);
545 }
7267c094 546 g_free(filename);
a3467baa 547 spapr->entry_point = 0x100;
a9f8ad8f
DG
548 initrd_base = 0;
549 initrd_size = 0;
550
551 /* SLOF will startup the secondary CPUs using RTAS,
552 rather than expecting a kexec() style entry */
c7a5c0c9
DG
553 for (env = first_cpu; env != NULL; env = env->next_cpu) {
554 env->halted = 1;
a9f8ad8f 555 }
9fdf0c29
DG
556 }
557
558 /* Prepare the device tree */
354ac20a 559 spapr->fdt_skel = spapr_create_fdt_skel(cpu_model, rma_size,
a3467baa
DG
560 initrd_base, initrd_size,
561 boot_device, kernel_cmdline,
562 pteg_shift + 7);
563 assert(spapr->fdt_skel != NULL);
9fdf0c29 564
a3467baa 565 qemu_register_reset(spapr_reset, spapr);
9fdf0c29
DG
566}
567
568static QEMUMachine spapr_machine = {
569 .name = "pseries",
570 .desc = "pSeries Logical Partition (PAPR compliant)",
571 .init = ppc_spapr_init,
572 .max_cpus = MAX_CPUS,
573 .no_vga = 1,
574 .no_parallel = 1,
6e270446 575 .use_scsi = 1,
9fdf0c29
DG
576};
577
578static void spapr_machine_init(void)
579{
580 qemu_register_machine(&spapr_machine);
581}
582
583machine_init(spapr_machine_init);