xref: /openbmc/qemu/hw/i386/pc_piix.c (revision 6f2e2730)
1 /*
2  * QEMU PC System Emulator
3  *
4  * Copyright (c) 2003-2004 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 #include <glib.h>
26 
27 #include "hw/hw.h"
28 #include "hw/loader.h"
29 #include "hw/i386/pc.h"
30 #include "hw/i386/apic.h"
31 #include "hw/i386/smbios.h"
32 #include "hw/pci/pci.h"
33 #include "hw/pci/pci_ids.h"
34 #include "hw/usb.h"
35 #include "net/net.h"
36 #include "hw/boards.h"
37 #include "hw/ide.h"
38 #include "sysemu/kvm.h"
39 #include "hw/kvm/clock.h"
40 #include "sysemu/sysemu.h"
41 #include "hw/sysbus.h"
42 #include "hw/cpu/icc_bus.h"
43 #include "sysemu/arch_init.h"
44 #include "sysemu/blockdev.h"
45 #include "hw/i2c/smbus.h"
46 #include "hw/xen/xen.h"
47 #include "exec/memory.h"
48 #include "exec/address-spaces.h"
49 #include "hw/acpi/acpi.h"
50 #include "cpu.h"
51 #ifdef CONFIG_XEN
52 #  include <xen/hvm/hvm_info_table.h>
53 #endif
54 
55 #define MAX_IDE_BUS 2
56 
57 static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
58 static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
59 static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
60 
61 static bool has_pci_info;
62 static bool has_acpi_build = true;
63 static bool smbios_defaults = true;
64 static bool smbios_legacy_mode;
65 /* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
66  * host addresses aligned at 1Gbyte boundaries.  This way we can use 1GByte
67  * pages in the host.
68  */
69 static bool gigabyte_align = true;
70 static bool has_reserved_memory = true;
71 
72 /* PC hardware initialisation */
73 static void pc_init1(MachineState *machine,
74                      int pci_enabled,
75                      int kvmclock_enabled)
76 {
77     PCMachineState *pc_machine = PC_MACHINE(machine);
78     MemoryRegion *system_memory = get_system_memory();
79     MemoryRegion *system_io = get_system_io();
80     int i;
81     ram_addr_t below_4g_mem_size, above_4g_mem_size;
82     PCIBus *pci_bus;
83     ISABus *isa_bus;
84     PCII440FXState *i440fx_state;
85     int piix3_devfn = -1;
86     qemu_irq *cpu_irq;
87     qemu_irq *gsi;
88     qemu_irq *i8259;
89     qemu_irq *smi_irq;
90     GSIState *gsi_state;
91     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
92     BusState *idebus[MAX_IDE_BUS];
93     ISADevice *rtc_state;
94     ISADevice *floppy;
95     MemoryRegion *ram_memory;
96     MemoryRegion *pci_memory;
97     MemoryRegion *rom_memory;
98     DeviceState *icc_bridge;
99     FWCfgState *fw_cfg = NULL;
100     PcGuestInfo *guest_info;
101 
102     if (xen_enabled() && xen_hvm_init(&ram_memory) != 0) {
103         fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
104         exit(1);
105     }
106 
107     icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
108     object_property_add_child(qdev_get_machine(), "icc-bridge",
109                               OBJECT(icc_bridge), NULL);
110 
111     pc_cpus_init(machine->cpu_model, icc_bridge);
112 
113     if (kvm_enabled() && kvmclock_enabled) {
114         kvmclock_create();
115     }
116 
117     /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory).
118      * If it doesn't, we need to split it in chunks below and above 4G.
119      * In any case, try to make sure that guest addresses aligned at
120      * 1G boundaries get mapped to host addresses aligned at 1G boundaries.
121      * For old machine types, use whatever split we used historically to avoid
122      * breaking migration.
123      */
124     if (machine->ram_size >= 0xe0000000) {
125         ram_addr_t lowmem = gigabyte_align ? 0xc0000000 : 0xe0000000;
126         above_4g_mem_size = machine->ram_size - lowmem;
127         below_4g_mem_size = lowmem;
128     } else {
129         above_4g_mem_size = 0;
130         below_4g_mem_size = machine->ram_size;
131     }
132 
133     if (pci_enabled) {
134         pci_memory = g_new(MemoryRegion, 1);
135         memory_region_init(pci_memory, NULL, "pci", UINT64_MAX);
136         rom_memory = pci_memory;
137     } else {
138         pci_memory = NULL;
139         rom_memory = system_memory;
140     }
141 
142     guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
143 
144     guest_info->has_acpi_build = has_acpi_build;
145 
146     guest_info->has_pci_info = has_pci_info;
147     guest_info->isapc_ram_fw = !pci_enabled;
148     guest_info->has_reserved_memory = has_reserved_memory;
149 
150     if (smbios_defaults) {
151         MachineClass *mc = MACHINE_GET_CLASS(machine);
152         /* These values are guest ABI, do not change */
153         smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
154                             mc->name, smbios_legacy_mode);
155     }
156 
157     /* allocate ram and load rom/bios */
158     if (!xen_enabled()) {
159         fw_cfg = pc_memory_init(machine, system_memory,
160                                 below_4g_mem_size, above_4g_mem_size,
161                                 rom_memory, &ram_memory, guest_info);
162     }
163 
164     gsi_state = g_malloc0(sizeof(*gsi_state));
165     if (kvm_irqchip_in_kernel()) {
166         kvm_pc_setup_irq_routing(pci_enabled);
167         gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
168                                  GSI_NUM_PINS);
169     } else {
170         gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
171     }
172 
173     if (pci_enabled) {
174         pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
175                               system_memory, system_io, machine->ram_size,
176                               below_4g_mem_size,
177                               above_4g_mem_size,
178                               pci_memory, ram_memory);
179     } else {
180         pci_bus = NULL;
181         i440fx_state = NULL;
182         isa_bus = isa_bus_new(NULL, system_io);
183         no_hpet = 1;
184     }
185     isa_bus_irqs(isa_bus, gsi);
186 
187     if (kvm_irqchip_in_kernel()) {
188         i8259 = kvm_i8259_init(isa_bus);
189     } else if (xen_enabled()) {
190         i8259 = xen_interrupt_controller_init();
191     } else {
192         cpu_irq = pc_allocate_cpu_irq();
193         i8259 = i8259_init(isa_bus, cpu_irq[0]);
194     }
195 
196     for (i = 0; i < ISA_NUM_IRQS; i++) {
197         gsi_state->i8259_irq[i] = i8259[i];
198     }
199     if (pci_enabled) {
200         ioapic_init_gsi(gsi_state, "i440fx");
201     }
202     qdev_init_nofail(icc_bridge);
203 
204     pc_register_ferr_irq(gsi[13]);
205 
206     pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
207 
208     /* init basic PC hardware */
209     pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled(),
210         0x4);
211 
212     pc_nic_init(isa_bus, pci_bus);
213 
214     ide_drive_get(hd, MAX_IDE_BUS);
215     if (pci_enabled) {
216         PCIDevice *dev;
217         if (xen_enabled()) {
218             dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
219         } else {
220             dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
221         }
222         idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
223         idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
224     } else {
225         for(i = 0; i < MAX_IDE_BUS; i++) {
226             ISADevice *dev;
227             char busname[] = "ide.0";
228             dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
229                                ide_irq[i],
230                                hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
231             /*
232              * The ide bus name is ide.0 for the first bus and ide.1 for the
233              * second one.
234              */
235             busname[4] = '0' + i;
236             idebus[i] = qdev_get_child_bus(DEVICE(dev), busname);
237         }
238     }
239 
240     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, machine->boot_order,
241                  floppy, idebus[0], idebus[1], rtc_state);
242 
243     if (pci_enabled && usb_enabled(false)) {
244         pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
245     }
246 
247     if (pci_enabled && acpi_enabled) {
248         DeviceState *piix4_pm;
249         I2CBus *smbus;
250 
251         smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
252         /* TODO: Populate SPD eeprom data.  */
253         smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
254                               gsi[9], *smi_irq,
255                               kvm_enabled(), fw_cfg, &piix4_pm);
256         smbus_eeprom_init(smbus, 8, NULL, 0);
257 
258         object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
259                                  TYPE_HOTPLUG_HANDLER,
260                                  (Object **)&pc_machine->acpi_dev,
261                                  object_property_allow_set_link,
262                                  OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
263         object_property_set_link(OBJECT(machine), OBJECT(piix4_pm),
264                                  PC_MACHINE_ACPI_DEVICE_PROP, &error_abort);
265     }
266 
267     if (pci_enabled) {
268         pc_pci_device_init(pci_bus);
269     }
270 }
271 
272 static void pc_init_pci(MachineState *machine)
273 {
274     pc_init1(machine, 1, 1);
275 }
276 
277 static void pc_compat_2_0(MachineState *machine)
278 {
279     smbios_legacy_mode = true;
280     has_reserved_memory = false;
281 }
282 
283 static void pc_compat_1_7(MachineState *machine)
284 {
285     pc_compat_2_0(machine);
286     smbios_defaults = false;
287     gigabyte_align = false;
288     option_rom_has_mr = true;
289     x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC);
290 }
291 
292 static void pc_compat_1_6(MachineState *machine)
293 {
294     pc_compat_1_7(machine);
295     has_pci_info = false;
296     rom_file_has_mr = false;
297     has_acpi_build = false;
298 }
299 
300 static void pc_compat_1_5(MachineState *machine)
301 {
302     pc_compat_1_6(machine);
303 }
304 
305 static void pc_compat_1_4(MachineState *machine)
306 {
307     pc_compat_1_5(machine);
308     x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
309     x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
310 }
311 
312 static void pc_compat_1_3(MachineState *machine)
313 {
314     pc_compat_1_4(machine);
315     enable_compat_apic_id_mode();
316 }
317 
318 /* PC compat function for pc-0.14 to pc-1.2 */
319 static void pc_compat_1_2(MachineState *machine)
320 {
321     pc_compat_1_3(machine);
322     x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
323 }
324 
325 static void pc_init_pci_2_0(MachineState *machine)
326 {
327     pc_compat_2_0(machine);
328     pc_init_pci(machine);
329 }
330 
331 static void pc_init_pci_1_7(MachineState *machine)
332 {
333     pc_compat_1_7(machine);
334     pc_init_pci(machine);
335 }
336 
337 static void pc_init_pci_1_6(MachineState *machine)
338 {
339     pc_compat_1_6(machine);
340     pc_init_pci(machine);
341 }
342 
343 static void pc_init_pci_1_5(MachineState *machine)
344 {
345     pc_compat_1_5(machine);
346     pc_init_pci(machine);
347 }
348 
349 static void pc_init_pci_1_4(MachineState *machine)
350 {
351     pc_compat_1_4(machine);
352     pc_init_pci(machine);
353 }
354 
355 static void pc_init_pci_1_3(MachineState *machine)
356 {
357     pc_compat_1_3(machine);
358     pc_init_pci(machine);
359 }
360 
361 /* PC machine init function for pc-0.14 to pc-1.2 */
362 static void pc_init_pci_1_2(MachineState *machine)
363 {
364     pc_compat_1_2(machine);
365     pc_init_pci(machine);
366 }
367 
368 /* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */
369 static void pc_init_pci_no_kvmclock(MachineState *machine)
370 {
371     has_pci_info = false;
372     has_acpi_build = false;
373     smbios_defaults = false;
374     x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
375     enable_compat_apic_id_mode();
376     pc_init1(machine, 1, 0);
377 }
378 
379 static void pc_init_isa(MachineState *machine)
380 {
381     has_pci_info = false;
382     has_acpi_build = false;
383     smbios_defaults = false;
384     if (!machine->cpu_model) {
385         machine->cpu_model = "486";
386     }
387     x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
388     enable_compat_apic_id_mode();
389     pc_init1(machine, 0, 1);
390 }
391 
392 #ifdef CONFIG_XEN
393 static void pc_xen_hvm_init(MachineState *machine)
394 {
395     PCIBus *bus;
396 
397     pc_init_pci(machine);
398 
399     bus = pci_find_primary_bus();
400     if (bus != NULL) {
401         pci_create_simple(bus, -1, "xen-platform");
402     }
403 }
404 #endif
405 
406 #define PC_I440FX_MACHINE_OPTIONS \
407     PC_DEFAULT_MACHINE_OPTIONS, \
408     .desc = "Standard PC (i440FX + PIIX, 1996)", \
409     .hot_add_cpu = pc_hot_add_cpu
410 
411 #define PC_I440FX_2_1_MACHINE_OPTIONS                           \
412     PC_I440FX_MACHINE_OPTIONS,                                  \
413     .default_machine_opts = "firmware=bios-256k.bin"
414 
415 static QEMUMachine pc_i440fx_machine_v2_1 = {
416     PC_I440FX_2_1_MACHINE_OPTIONS,
417     .name = "pc-i440fx-2.1",
418     .alias = "pc",
419     .init = pc_init_pci,
420     .is_default = 1,
421 };
422 
423 #define PC_I440FX_2_0_MACHINE_OPTIONS PC_I440FX_2_1_MACHINE_OPTIONS
424 
425 static QEMUMachine pc_i440fx_machine_v2_0 = {
426     PC_I440FX_2_0_MACHINE_OPTIONS,
427     .name = "pc-i440fx-2.0",
428     .init = pc_init_pci_2_0,
429     .compat_props = (GlobalProperty[]) {
430         PC_COMPAT_2_0,
431         { /* end of list */ }
432     },
433 };
434 
435 #define PC_I440FX_1_7_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
436 
437 static QEMUMachine pc_i440fx_machine_v1_7 = {
438     PC_I440FX_1_7_MACHINE_OPTIONS,
439     .name = "pc-i440fx-1.7",
440     .init = pc_init_pci_1_7,
441     .compat_props = (GlobalProperty[]) {
442         PC_COMPAT_1_7,
443         { /* end of list */ }
444     },
445 };
446 
447 #define PC_I440FX_1_6_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
448 
449 static QEMUMachine pc_i440fx_machine_v1_6 = {
450     PC_I440FX_1_6_MACHINE_OPTIONS,
451     .name = "pc-i440fx-1.6",
452     .init = pc_init_pci_1_6,
453     .compat_props = (GlobalProperty[]) {
454         PC_COMPAT_1_6,
455         { /* end of list */ }
456     },
457 };
458 
459 static QEMUMachine pc_i440fx_machine_v1_5 = {
460     PC_I440FX_1_6_MACHINE_OPTIONS,
461     .name = "pc-i440fx-1.5",
462     .init = pc_init_pci_1_5,
463     .compat_props = (GlobalProperty[]) {
464         PC_COMPAT_1_5,
465         { /* end of list */ }
466     },
467 };
468 
469 #define PC_I440FX_1_4_MACHINE_OPTIONS \
470     PC_I440FX_1_6_MACHINE_OPTIONS, \
471     .hot_add_cpu = NULL
472 
473 static QEMUMachine pc_i440fx_machine_v1_4 = {
474     PC_I440FX_1_4_MACHINE_OPTIONS,
475     .name = "pc-i440fx-1.4",
476     .init = pc_init_pci_1_4,
477     .compat_props = (GlobalProperty[]) {
478         PC_COMPAT_1_4,
479         { /* end of list */ }
480     },
481 };
482 
483 #define PC_COMPAT_1_3 \
484 	PC_COMPAT_1_4, \
485         {\
486             .driver   = "usb-tablet",\
487             .property = "usb_version",\
488             .value    = stringify(1),\
489         },{\
490             .driver   = "virtio-net-pci",\
491             .property = "ctrl_mac_addr",\
492             .value    = "off",      \
493         },{ \
494             .driver   = "virtio-net-pci", \
495             .property = "mq", \
496             .value    = "off", \
497         }, {\
498             .driver   = "e1000",\
499             .property = "autonegotiation",\
500             .value    = "off",\
501         }
502 
503 static QEMUMachine pc_machine_v1_3 = {
504     PC_I440FX_1_4_MACHINE_OPTIONS,
505     .name = "pc-1.3",
506     .init = pc_init_pci_1_3,
507     .compat_props = (GlobalProperty[]) {
508         PC_COMPAT_1_3,
509         { /* end of list */ }
510     },
511 };
512 
513 #define PC_COMPAT_1_2 \
514         PC_COMPAT_1_3,\
515         {\
516             .driver   = "nec-usb-xhci",\
517             .property = "msi",\
518             .value    = "off",\
519         },{\
520             .driver   = "nec-usb-xhci",\
521             .property = "msix",\
522             .value    = "off",\
523         },{\
524             .driver   = "ivshmem",\
525             .property = "use64",\
526             .value    = "0",\
527         },{\
528             .driver   = "qxl",\
529             .property = "revision",\
530             .value    = stringify(3),\
531         },{\
532             .driver   = "qxl-vga",\
533             .property = "revision",\
534             .value    = stringify(3),\
535         },{\
536             .driver   = "VGA",\
537             .property = "mmio",\
538             .value    = "off",\
539         }
540 
541 #define PC_I440FX_1_2_MACHINE_OPTIONS \
542     PC_I440FX_1_4_MACHINE_OPTIONS, \
543     .init = pc_init_pci_1_2
544 
545 static QEMUMachine pc_machine_v1_2 = {
546     PC_I440FX_1_2_MACHINE_OPTIONS,
547     .name = "pc-1.2",
548     .compat_props = (GlobalProperty[]) {
549         PC_COMPAT_1_2,
550         { /* end of list */ }
551     },
552 };
553 
554 #define PC_COMPAT_1_1 \
555         PC_COMPAT_1_2,\
556         {\
557             .driver   = "virtio-scsi-pci",\
558             .property = "hotplug",\
559             .value    = "off",\
560         },{\
561             .driver   = "virtio-scsi-pci",\
562             .property = "param_change",\
563             .value    = "off",\
564         },{\
565             .driver   = "VGA",\
566             .property = "vgamem_mb",\
567             .value    = stringify(8),\
568         },{\
569             .driver   = "vmware-svga",\
570             .property = "vgamem_mb",\
571             .value    = stringify(8),\
572         },{\
573             .driver   = "qxl-vga",\
574             .property = "vgamem_mb",\
575             .value    = stringify(8),\
576         },{\
577             .driver   = "qxl",\
578             .property = "vgamem_mb",\
579             .value    = stringify(8),\
580         },{\
581             .driver   = "virtio-blk-pci",\
582             .property = "config-wce",\
583             .value    = "off",\
584         }
585 
586 static QEMUMachine pc_machine_v1_1 = {
587     PC_I440FX_1_2_MACHINE_OPTIONS,
588     .name = "pc-1.1",
589     .compat_props = (GlobalProperty[]) {
590         PC_COMPAT_1_1,
591         { /* end of list */ }
592     },
593 };
594 
595 #define PC_COMPAT_1_0 \
596         PC_COMPAT_1_1,\
597         {\
598             .driver   = TYPE_ISA_FDC,\
599             .property = "check_media_rate",\
600             .value    = "off",\
601         }, {\
602             .driver   = "virtio-balloon-pci",\
603             .property = "class",\
604             .value    = stringify(PCI_CLASS_MEMORY_RAM),\
605         },{\
606             .driver   = "apic",\
607             .property = "vapic",\
608             .value    = "off",\
609         },{\
610             .driver   = TYPE_USB_DEVICE,\
611             .property = "full-path",\
612             .value    = "no",\
613         }
614 
615 static QEMUMachine pc_machine_v1_0 = {
616     PC_I440FX_1_2_MACHINE_OPTIONS,
617     .name = "pc-1.0",
618     .compat_props = (GlobalProperty[]) {
619         PC_COMPAT_1_0,
620         { /* end of list */ }
621     },
622     .hw_version = "1.0",
623 };
624 
625 #define PC_COMPAT_0_15 \
626         PC_COMPAT_1_0
627 
628 static QEMUMachine pc_machine_v0_15 = {
629     PC_I440FX_1_2_MACHINE_OPTIONS,
630     .name = "pc-0.15",
631     .compat_props = (GlobalProperty[]) {
632         PC_COMPAT_0_15,
633         { /* end of list */ }
634     },
635     .hw_version = "0.15",
636 };
637 
638 #define PC_COMPAT_0_14 \
639         PC_COMPAT_0_15,\
640         {\
641             .driver   = "virtio-blk-pci",\
642             .property = "event_idx",\
643             .value    = "off",\
644         },{\
645             .driver   = "virtio-serial-pci",\
646             .property = "event_idx",\
647             .value    = "off",\
648         },{\
649             .driver   = "virtio-net-pci",\
650             .property = "event_idx",\
651             .value    = "off",\
652         },{\
653             .driver   = "virtio-balloon-pci",\
654             .property = "event_idx",\
655             .value    = "off",\
656         }
657 
658 static QEMUMachine pc_machine_v0_14 = {
659     PC_I440FX_1_2_MACHINE_OPTIONS,
660     .name = "pc-0.14",
661     .compat_props = (GlobalProperty[]) {
662         PC_COMPAT_0_14,
663         {
664             .driver   = "qxl",
665             .property = "revision",
666             .value    = stringify(2),
667         },{
668             .driver   = "qxl-vga",
669             .property = "revision",
670             .value    = stringify(2),
671         },
672         { /* end of list */ }
673     },
674     .hw_version = "0.14",
675 };
676 
677 #define PC_COMPAT_0_13 \
678         PC_COMPAT_0_14,\
679         {\
680             .driver   = TYPE_PCI_DEVICE,\
681             .property = "command_serr_enable",\
682             .value    = "off",\
683         },{\
684             .driver   = "AC97",\
685             .property = "use_broken_id",\
686             .value    = stringify(1),\
687         }
688 
689 #define PC_I440FX_0_13_MACHINE_OPTIONS \
690     PC_I440FX_1_2_MACHINE_OPTIONS, \
691     .init = pc_init_pci_no_kvmclock
692 
693 static QEMUMachine pc_machine_v0_13 = {
694     PC_I440FX_0_13_MACHINE_OPTIONS,
695     .name = "pc-0.13",
696     .compat_props = (GlobalProperty[]) {
697         PC_COMPAT_0_13,
698         {
699             .driver   = "virtio-9p-pci",
700             .property = "vectors",
701             .value    = stringify(0),
702         },{
703             .driver   = "VGA",
704             .property = "rombar",
705             .value    = stringify(0),
706         },{
707             .driver   = "vmware-svga",
708             .property = "rombar",
709             .value    = stringify(0),
710         },
711         { /* end of list */ }
712     },
713     .hw_version = "0.13",
714 };
715 
716 #define PC_COMPAT_0_12 \
717         PC_COMPAT_0_13,\
718         {\
719             .driver   = "virtio-serial-pci",\
720             .property = "max_ports",\
721             .value    = stringify(1),\
722         },{\
723             .driver   = "virtio-serial-pci",\
724             .property = "vectors",\
725             .value    = stringify(0),\
726         },{\
727             .driver   = "usb-mouse",\
728             .property = "serial",\
729             .value    = "1",\
730         },{\
731             .driver   = "usb-tablet",\
732             .property = "serial",\
733             .value    = "1",\
734         },{\
735             .driver   = "usb-kbd",\
736             .property = "serial",\
737             .value    = "1",\
738         }
739 
740 static QEMUMachine pc_machine_v0_12 = {
741     PC_I440FX_0_13_MACHINE_OPTIONS,
742     .name = "pc-0.12",
743     .compat_props = (GlobalProperty[]) {
744         PC_COMPAT_0_12,
745         {
746             .driver   = "VGA",
747             .property = "rombar",
748             .value    = stringify(0),
749         },{
750             .driver   = "vmware-svga",
751             .property = "rombar",
752             .value    = stringify(0),
753         },
754         { /* end of list */ }
755     },
756     .hw_version = "0.12",
757 };
758 
759 #define PC_COMPAT_0_11 \
760         PC_COMPAT_0_12,\
761         {\
762             .driver   = "virtio-blk-pci",\
763             .property = "vectors",\
764             .value    = stringify(0),\
765         },{\
766             .driver   = TYPE_PCI_DEVICE,\
767             .property = "rombar",\
768             .value    = stringify(0),\
769         }
770 
771 static QEMUMachine pc_machine_v0_11 = {
772     PC_I440FX_0_13_MACHINE_OPTIONS,
773     .name = "pc-0.11",
774     .compat_props = (GlobalProperty[]) {
775         PC_COMPAT_0_11,
776         {
777             .driver   = "ide-drive",
778             .property = "ver",
779             .value    = "0.11",
780         },{
781             .driver   = "scsi-disk",
782             .property = "ver",
783             .value    = "0.11",
784         },
785         { /* end of list */ }
786     },
787     .hw_version = "0.11",
788 };
789 
790 static QEMUMachine pc_machine_v0_10 = {
791     PC_I440FX_0_13_MACHINE_OPTIONS,
792     .name = "pc-0.10",
793     .compat_props = (GlobalProperty[]) {
794         PC_COMPAT_0_11,
795         {
796             .driver   = "virtio-blk-pci",
797             .property = "class",
798             .value    = stringify(PCI_CLASS_STORAGE_OTHER),
799         },{
800             .driver   = "virtio-serial-pci",
801             .property = "class",
802             .value    = stringify(PCI_CLASS_DISPLAY_OTHER),
803         },{
804             .driver   = "virtio-net-pci",
805             .property = "vectors",
806             .value    = stringify(0),
807         },{
808             .driver   = "ide-drive",
809             .property = "ver",
810             .value    = "0.10",
811         },{
812             .driver   = "scsi-disk",
813             .property = "ver",
814             .value    = "0.10",
815         },
816         { /* end of list */ }
817     },
818     .hw_version = "0.10",
819 };
820 
821 static QEMUMachine isapc_machine = {
822     PC_COMMON_MACHINE_OPTIONS,
823     .name = "isapc",
824     .desc = "ISA-only PC",
825     .init = pc_init_isa,
826     .max_cpus = 1,
827     .compat_props = (GlobalProperty[]) {
828         { /* end of list */ }
829     },
830 };
831 
832 #ifdef CONFIG_XEN
833 static QEMUMachine xenfv_machine = {
834     PC_COMMON_MACHINE_OPTIONS,
835     .name = "xenfv",
836     .desc = "Xen Fully-virtualized PC",
837     .init = pc_xen_hvm_init,
838     .max_cpus = HVM_MAX_VCPUS,
839     .default_machine_opts = "accel=xen",
840     .hot_add_cpu = pc_hot_add_cpu,
841     .compat_props = (GlobalProperty[]) {
842         /* xenfv has no fwcfg and so does not load acpi from QEMU.
843          * as such new acpi features don't work.
844          */
845         {
846             .driver   = "PIIX4_PM",
847             .property = "acpi-pci-hotplug-with-bridge-support",
848             .value    = "off",
849         },
850         { /* end of list */ }
851     },
852 };
853 #endif
854 
855 static void pc_machine_init(void)
856 {
857     qemu_register_pc_machine(&pc_i440fx_machine_v2_1);
858     qemu_register_pc_machine(&pc_i440fx_machine_v2_0);
859     qemu_register_pc_machine(&pc_i440fx_machine_v1_7);
860     qemu_register_pc_machine(&pc_i440fx_machine_v1_6);
861     qemu_register_pc_machine(&pc_i440fx_machine_v1_5);
862     qemu_register_pc_machine(&pc_i440fx_machine_v1_4);
863     qemu_register_pc_machine(&pc_machine_v1_3);
864     qemu_register_pc_machine(&pc_machine_v1_2);
865     qemu_register_pc_machine(&pc_machine_v1_1);
866     qemu_register_pc_machine(&pc_machine_v1_0);
867     qemu_register_pc_machine(&pc_machine_v0_15);
868     qemu_register_pc_machine(&pc_machine_v0_14);
869     qemu_register_pc_machine(&pc_machine_v0_13);
870     qemu_register_pc_machine(&pc_machine_v0_12);
871     qemu_register_pc_machine(&pc_machine_v0_11);
872     qemu_register_pc_machine(&pc_machine_v0_10);
873     qemu_register_pc_machine(&isapc_machine);
874 #ifdef CONFIG_XEN
875     qemu_register_pc_machine(&xenfv_machine);
876 #endif
877 }
878 
879 machine_init(pc_machine_init);
880