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