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 "qemu/osdep.h"
26 #include CONFIG_DEVICES
27
28 #include "qemu/units.h"
29 #include "hw/char/parallel-isa.h"
30 #include "hw/dma/i8257.h"
31 #include "hw/loader.h"
32 #include "hw/i386/x86.h"
33 #include "hw/i386/pc.h"
34 #include "hw/i386/apic.h"
35 #include "hw/pci-host/i440fx.h"
36 #include "hw/rtc/mc146818rtc.h"
37 #include "hw/southbridge/piix.h"
38 #include "hw/display/ramfb.h"
39 #include "hw/pci/pci.h"
40 #include "hw/pci/pci_ids.h"
41 #include "hw/usb.h"
42 #include "net/net.h"
43 #include "hw/ide/isa.h"
44 #include "hw/ide/pci.h"
45 #include "hw/irq.h"
46 #include "system/kvm.h"
47 #include "hw/i386/kvm/clock.h"
48 #include "hw/sysbus.h"
49 #include "hw/i2c/smbus_eeprom.h"
50 #include "system/memory.h"
51 #include "hw/acpi/acpi.h"
52 #include "hw/vfio/types.h"
53 #include "qapi/error.h"
54 #include "qemu/error-report.h"
55 #include "system/xen.h"
56 #ifdef CONFIG_XEN
57 #include <xen/hvm/hvm_info_table.h>
58 #include "hw/xen/xen_pt.h"
59 #include "hw/xen/xen_igd.h"
60 #endif
61 #include "hw/xen/xen-x86.h"
62 #include "hw/xen/xen.h"
63 #include "migration/global_state.h"
64 #include "migration/misc.h"
65 #include "system/runstate.h"
66 #include "system/numa.h"
67 #include "hw/hyperv/vmbus-bridge.h"
68 #include "hw/mem/nvdimm.h"
69 #include "hw/uefi/var-service-api.h"
70 #include "hw/i386/acpi-build.h"
71 #include "target/i386/cpu.h"
72
73 #define XEN_IOAPIC_NUM_PIRQS 128ULL
74
75 #ifdef CONFIG_IDE_ISA
76 static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
77 static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
78 static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
79 #endif
80
81 static GlobalProperty pc_piix_compat_defaults[] = {
82 { TYPE_RAMFB_DEVICE, "use-legacy-x86-rom", "true" },
83 { TYPE_VFIO_PCI_NOHOTPLUG, "use-legacy-x86-rom", "true" },
84 };
85 static const size_t pc_piix_compat_defaults_len =
86 G_N_ELEMENTS(pc_piix_compat_defaults);
87
88 /*
89 * Return the global irq number corresponding to a given device irq
90 * pin. We could also use the bus number to have a more precise mapping.
91 */
pc_pci_slot_get_pirq(PCIDevice * pci_dev,int pci_intx)92 static int pc_pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx)
93 {
94 int slot_addend;
95 slot_addend = PCI_SLOT(pci_dev->devfn) - 1;
96 return (pci_intx + slot_addend) & 3;
97 }
98
piix_intx_routing_notifier_xen(PCIDevice * dev)99 static void piix_intx_routing_notifier_xen(PCIDevice *dev)
100 {
101 int i;
102
103 /* Scan for updates to PCI link routes. */
104 for (i = 0; i < PIIX_NUM_PIRQS; i++) {
105 const PCIINTxRoute route = pci_device_route_intx_to_irq(dev, i);
106 const uint8_t v = route.mode == PCI_INTX_ENABLED ? route.irq : 0;
107 xen_set_pci_link_route(i, v);
108 }
109 }
110
111 /* PC hardware initialisation */
pc_init1(MachineState * machine,const char * pci_type)112 static void pc_init1(MachineState *machine, const char *pci_type)
113 {
114 PCMachineState *pcms = PC_MACHINE(machine);
115 PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
116 X86MachineState *x86ms = X86_MACHINE(machine);
117 MemoryRegion *system_memory = get_system_memory();
118 MemoryRegion *system_io = get_system_io();
119 Object *phb = NULL;
120 ISABus *isa_bus;
121 Object *piix4_pm = NULL;
122 qemu_irq smi_irq;
123 GSIState *gsi_state;
124 MemoryRegion *ram_memory;
125 MemoryRegion *pci_memory = NULL;
126 MemoryRegion *rom_memory = system_memory;
127 ram_addr_t lowmem;
128 uint64_t hole64_size = 0;
129
130 /*
131 * Calculate ram split, for memory below and above 4G. It's a bit
132 * complicated for backward compatibility reasons ...
133 *
134 * - Traditional split is 3.5G (lowmem = 0xe0000000). This is the
135 * default value for max_ram_below_4g now.
136 *
137 * - Then, to gigabyte align the memory, we move the split to 3G
138 * (lowmem = 0xc0000000). But only in case we have to split in
139 * the first place, i.e. ram_size is larger than (traditional)
140 * lowmem. And for new machine types (gigabyte_align = true)
141 * only, for live migration compatibility reasons.
142 *
143 * - Next the max-ram-below-4g option was added, which allowed to
144 * reduce lowmem to a smaller value, to allow a larger PCI I/O
145 * window below 4G. qemu doesn't enforce gigabyte alignment here,
146 * but prints a warning.
147 *
148 * - Finally max-ram-below-4g got updated to also allow raising lowmem,
149 * so legacy non-PAE guests can get as much memory as possible in
150 * the 32bit address space below 4G.
151 *
152 * - Note that Xen has its own ram setup code in xen_ram_init(),
153 * called via xen_hvm_init_pc().
154 *
155 * Examples:
156 * qemu -M pc-1.7 -m 4G (old default) -> 3584M low, 512M high
157 * qemu -M pc -m 4G (new default) -> 3072M low, 1024M high
158 * qemu -M pc,max-ram-below-4g=2G -m 4G -> 2048M low, 2048M high
159 * qemu -M pc,max-ram-below-4g=4G -m 3968M -> 3968M low (=4G-128M)
160 */
161 if (xen_enabled()) {
162 xen_hvm_init_pc(pcms, &ram_memory);
163 } else {
164 ram_memory = machine->ram;
165 if (!pcms->max_ram_below_4g) {
166 pcms->max_ram_below_4g = 0xe0000000; /* default: 3.5G */
167 }
168 lowmem = pcms->max_ram_below_4g;
169 if (machine->ram_size >= pcms->max_ram_below_4g) {
170 if (pcmc->gigabyte_align) {
171 if (lowmem > 0xc0000000) {
172 lowmem = 0xc0000000;
173 }
174 if (lowmem & (1 * GiB - 1)) {
175 warn_report("Large machine and max_ram_below_4g "
176 "(%" PRIu64 ") not a multiple of 1G; "
177 "possible bad performance.",
178 pcms->max_ram_below_4g);
179 }
180 }
181 }
182
183 if (machine->ram_size >= lowmem) {
184 x86ms->above_4g_mem_size = machine->ram_size - lowmem;
185 x86ms->below_4g_mem_size = lowmem;
186 } else {
187 x86ms->above_4g_mem_size = 0;
188 x86ms->below_4g_mem_size = machine->ram_size;
189 }
190 }
191
192 pc_machine_init_sgx_epc(pcms);
193 x86_cpus_init(x86ms, pcmc->default_cpu_version);
194
195 if (kvm_enabled()) {
196 kvmclock_create(pcmc->kvmclock_create_always);
197 }
198
199 if (pcmc->pci_enabled) {
200 pci_memory = g_new(MemoryRegion, 1);
201 memory_region_init(pci_memory, NULL, "pci", UINT64_MAX);
202 rom_memory = pci_memory;
203
204 phb = OBJECT(qdev_new(TYPE_I440FX_PCI_HOST_BRIDGE));
205 object_property_add_child(OBJECT(machine), "i440fx", phb);
206 object_property_set_link(phb, PCI_HOST_PROP_RAM_MEM,
207 OBJECT(ram_memory), &error_fatal);
208 object_property_set_link(phb, PCI_HOST_PROP_PCI_MEM,
209 OBJECT(pci_memory), &error_fatal);
210 object_property_set_link(phb, PCI_HOST_PROP_SYSTEM_MEM,
211 OBJECT(system_memory), &error_fatal);
212 object_property_set_link(phb, PCI_HOST_PROP_IO_MEM,
213 OBJECT(system_io), &error_fatal);
214 object_property_set_uint(phb, PCI_HOST_BELOW_4G_MEM_SIZE,
215 x86ms->below_4g_mem_size, &error_fatal);
216 object_property_set_uint(phb, PCI_HOST_ABOVE_4G_MEM_SIZE,
217 x86ms->above_4g_mem_size, &error_fatal);
218 object_property_set_str(phb, I440FX_HOST_PROP_PCI_TYPE, pci_type,
219 &error_fatal);
220 sysbus_realize_and_unref(SYS_BUS_DEVICE(phb), &error_fatal);
221
222 pcms->pcibus = PCI_BUS(qdev_get_child_bus(DEVICE(phb), "pci.0"));
223 pci_bus_map_irqs(pcms->pcibus,
224 xen_enabled() ? xen_pci_slot_get_pirq
225 : pc_pci_slot_get_pirq);
226
227 hole64_size = object_property_get_uint(phb,
228 PCI_HOST_PROP_PCI_HOLE64_SIZE,
229 &error_abort);
230 }
231
232 /* allocate ram and load rom/bios */
233 if (!xen_enabled()) {
234 pc_memory_init(pcms, system_memory, rom_memory, hole64_size);
235 } else {
236 assert(machine->ram_size == x86ms->below_4g_mem_size +
237 x86ms->above_4g_mem_size);
238
239 pc_system_flash_cleanup_unused(pcms);
240 if (machine->kernel_filename != NULL) {
241 /* For xen HVM direct kernel boot, load linux here */
242 xen_load_linux(pcms);
243 }
244 }
245
246 gsi_state = pc_gsi_create(&x86ms->gsi, pcmc->pci_enabled);
247
248 if (pcmc->pci_enabled) {
249 PCIDevice *pci_dev;
250 DeviceState *dev;
251 size_t i;
252
253 pci_dev = pci_new_multifunction(-1, pcms->south_bridge);
254 object_property_set_bool(OBJECT(pci_dev), "has-usb",
255 machine_usb(machine), &error_abort);
256 object_property_set_bool(OBJECT(pci_dev), "has-acpi",
257 x86_machine_is_acpi_enabled(x86ms),
258 &error_abort);
259 object_property_set_bool(OBJECT(pci_dev), "has-pic", false,
260 &error_abort);
261 object_property_set_bool(OBJECT(pci_dev), "has-pit", false,
262 &error_abort);
263 qdev_prop_set_uint32(DEVICE(pci_dev), "smb_io_base", 0xb100);
264 object_property_set_bool(OBJECT(pci_dev), "smm-enabled",
265 x86_machine_is_smm_enabled(x86ms),
266 &error_abort);
267 dev = DEVICE(pci_dev);
268 for (i = 0; i < ISA_NUM_IRQS; i++) {
269 qdev_connect_gpio_out_named(dev, "isa-irqs", i, x86ms->gsi[i]);
270 }
271 pci_realize_and_unref(pci_dev, pcms->pcibus, &error_fatal);
272
273 if (xen_enabled()) {
274 pci_device_set_intx_routing_notifier(
275 pci_dev, piix_intx_routing_notifier_xen);
276
277 /*
278 * Xen supports additional interrupt routes from the PCI devices to
279 * the IOAPIC: the four pins of each PCI device on the bus are also
280 * connected to the IOAPIC directly.
281 * These additional routes can be discovered through ACPI.
282 */
283 pci_bus_irqs(pcms->pcibus, xen_intx_set_irq, pci_dev,
284 XEN_IOAPIC_NUM_PIRQS);
285 }
286
287 isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(pci_dev), "isa.0"));
288 x86ms->rtc = ISA_DEVICE(object_resolve_path_component(OBJECT(pci_dev),
289 "rtc"));
290 piix4_pm = object_resolve_path_component(OBJECT(pci_dev), "pm");
291 dev = DEVICE(object_resolve_path_component(OBJECT(pci_dev), "ide"));
292 pci_ide_create_devs(PCI_DEVICE(dev));
293 pcms->idebus[0] = qdev_get_child_bus(dev, "ide.0");
294 pcms->idebus[1] = qdev_get_child_bus(dev, "ide.1");
295 } else {
296 uint32_t irq;
297
298 isa_bus = isa_bus_new(NULL, system_memory, system_io,
299 &error_abort);
300 isa_bus_register_input_irqs(isa_bus, x86ms->gsi);
301
302 x86ms->rtc = isa_new(TYPE_MC146818_RTC);
303 qdev_prop_set_int32(DEVICE(x86ms->rtc), "base_year", 2000);
304 isa_realize_and_unref(x86ms->rtc, isa_bus, &error_fatal);
305 irq = object_property_get_uint(OBJECT(x86ms->rtc), "irq",
306 &error_fatal);
307 isa_connect_gpio_out(ISA_DEVICE(x86ms->rtc), 0, irq);
308
309 i8257_dma_init(OBJECT(machine), isa_bus, 0);
310 pcms->hpet_enabled = false;
311 }
312
313 if (x86ms->pic == ON_OFF_AUTO_ON || x86ms->pic == ON_OFF_AUTO_AUTO) {
314 pc_i8259_create(isa_bus, gsi_state->i8259_irq);
315 }
316
317 if (phb) {
318 ioapic_init_gsi(gsi_state, phb);
319 }
320
321 if (tcg_enabled()) {
322 x86_register_ferr_irq(x86ms->gsi[13]);
323 }
324
325 pc_vga_init(isa_bus, pcmc->pci_enabled ? pcms->pcibus : NULL);
326
327 /* init basic PC hardware */
328 pc_basic_device_init(pcms, isa_bus, x86ms->gsi, x86ms->rtc,
329 !MACHINE_CLASS(pcmc)->no_floppy, 0x4);
330
331 pc_nic_init(pcmc, isa_bus, pcms->pcibus);
332
333 #ifdef CONFIG_IDE_ISA
334 if (!pcmc->pci_enabled) {
335 DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
336 int i;
337
338 ide_drive_get(hd, ARRAY_SIZE(hd));
339 for (i = 0; i < MAX_IDE_BUS; i++) {
340 ISADevice *dev;
341 char busname[] = "ide.0";
342 dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
343 ide_irq[i],
344 hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
345 /*
346 * The ide bus name is ide.0 for the first bus and ide.1 for the
347 * second one.
348 */
349 busname[4] = '0' + i;
350 pcms->idebus[i] = qdev_get_child_bus(DEVICE(dev), busname);
351 }
352 }
353 #endif
354
355 if (piix4_pm) {
356 smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0);
357
358 qdev_connect_gpio_out_named(DEVICE(piix4_pm), "smi-irq", 0, smi_irq);
359 pcms->smbus = I2C_BUS(qdev_get_child_bus(DEVICE(piix4_pm), "i2c"));
360 /* TODO: Populate SPD eeprom data. */
361 smbus_eeprom_init(pcms->smbus, 8, NULL, 0);
362
363 object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
364 TYPE_HOTPLUG_HANDLER,
365 (Object **)&x86ms->acpi_dev,
366 object_property_allow_set_link,
367 OBJ_PROP_LINK_STRONG);
368 object_property_set_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
369 piix4_pm, &error_abort);
370 }
371
372 if (machine->nvdimms_state->is_enabled) {
373 nvdimm_init_acpi_state(machine->nvdimms_state, system_io,
374 x86_nvdimm_acpi_dsmio,
375 x86ms->fw_cfg, OBJECT(pcms));
376 }
377
378 #if defined(CONFIG_IGVM)
379 /* Apply guest state from IGVM if supplied */
380 if (x86ms->igvm) {
381 if (IGVM_CFG_GET_CLASS(x86ms->igvm)
382 ->process(x86ms->igvm, machine->cgs, false, &error_fatal) < 0) {
383 g_assert_not_reached();
384 }
385 }
386 #endif
387 }
388
389 typedef enum PCSouthBridgeOption {
390 PC_SOUTH_BRIDGE_OPTION_PIIX3,
391 PC_SOUTH_BRIDGE_OPTION_PIIX4,
392 PC_SOUTH_BRIDGE_OPTION_MAX,
393 } PCSouthBridgeOption;
394
395 static const QEnumLookup PCSouthBridgeOption_lookup = {
396 .array = (const char *const[]) {
397 [PC_SOUTH_BRIDGE_OPTION_PIIX3] = TYPE_PIIX3_DEVICE,
398 [PC_SOUTH_BRIDGE_OPTION_PIIX4] = TYPE_PIIX4_PCI_DEVICE,
399 },
400 .size = PC_SOUTH_BRIDGE_OPTION_MAX
401 };
402
pc_get_south_bridge(Object * obj,Error ** errp)403 static int pc_get_south_bridge(Object *obj, Error **errp)
404 {
405 PCMachineState *pcms = PC_MACHINE(obj);
406 int i;
407
408 for (i = 0; i < PCSouthBridgeOption_lookup.size; i++) {
409 if (g_strcmp0(PCSouthBridgeOption_lookup.array[i],
410 pcms->south_bridge) == 0) {
411 return i;
412 }
413 }
414
415 error_setg(errp, "Invalid south bridge value set");
416 return 0;
417 }
418
pc_set_south_bridge(Object * obj,int value,Error ** errp)419 static void pc_set_south_bridge(Object *obj, int value, Error **errp)
420 {
421 PCMachineState *pcms = PC_MACHINE(obj);
422
423 if (value < 0) {
424 error_setg(errp, "Value can't be negative");
425 return;
426 }
427
428 if (value >= PCSouthBridgeOption_lookup.size) {
429 error_setg(errp, "Value too big");
430 return;
431 }
432
433 pcms->south_bridge = PCSouthBridgeOption_lookup.array[value];
434 }
435
436 #ifdef CONFIG_ISAPC
pc_init_isa(MachineState * machine)437 static void pc_init_isa(MachineState *machine)
438 {
439 pc_init1(machine, NULL);
440 }
441 #endif
442
443 #ifdef CONFIG_XEN
pc_xen_hvm_init_pci(MachineState * machine)444 static void pc_xen_hvm_init_pci(MachineState *machine)
445 {
446 const char *pci_type = xen_igd_gfx_pt_enabled() ?
447 TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE : TYPE_I440FX_PCI_DEVICE;
448
449 pc_init1(machine, pci_type);
450 }
451
pc_xen_hvm_init(MachineState * machine)452 static void pc_xen_hvm_init(MachineState *machine)
453 {
454 PCMachineState *pcms = PC_MACHINE(machine);
455
456 if (!xen_enabled()) {
457 error_report("xenfv machine requires the xen accelerator");
458 exit(1);
459 }
460
461 pc_xen_hvm_init_pci(machine);
462 xen_igd_reserve_slot(pcms->pcibus);
463 pci_create_simple(pcms->pcibus, -1, "xen-platform");
464 }
465 #endif
466
pc_i440fx_init(MachineState * machine)467 static void pc_i440fx_init(MachineState *machine)
468 {
469 pc_init1(machine, TYPE_I440FX_PCI_DEVICE);
470 }
471
472 #define DEFINE_I440FX_MACHINE(major, minor) \
473 DEFINE_PC_VER_MACHINE(pc_i440fx, "pc-i440fx", pc_i440fx_init, false, NULL, major, minor);
474
475 #define DEFINE_I440FX_MACHINE_AS_LATEST(major, minor) \
476 DEFINE_PC_VER_MACHINE(pc_i440fx, "pc-i440fx", pc_i440fx_init, true, "pc", major, minor);
477
pc_i440fx_machine_options(MachineClass * m)478 static void pc_i440fx_machine_options(MachineClass *m)
479 {
480 PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
481 ObjectClass *oc = OBJECT_CLASS(m);
482 pcmc->default_south_bridge = TYPE_PIIX3_DEVICE;
483 pcmc->pci_root_uid = 0;
484 pcmc->default_cpu_version = 1;
485
486 m->family = "pc_piix";
487 m->desc = "Standard PC (i440FX + PIIX, 1996)";
488 m->default_machine_opts = "firmware=bios-256k.bin";
489 m->default_display = "std";
490 m->default_nic = "e1000";
491 m->no_floppy = !module_object_class_by_name(TYPE_ISA_FDC);
492 m->no_parallel = !module_object_class_by_name(TYPE_ISA_PARALLEL);
493 machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE);
494 machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE);
495 machine_class_allow_dynamic_sysbus_dev(m, TYPE_UEFI_VARS_X64);
496
497 object_class_property_add_enum(oc, "x-south-bridge", "PCSouthBridgeOption",
498 &PCSouthBridgeOption_lookup,
499 pc_get_south_bridge,
500 pc_set_south_bridge);
501 object_class_property_set_description(oc, "x-south-bridge",
502 "Use a different south bridge than PIIX3");
503 compat_props_add(m->compat_props,
504 pc_piix_compat_defaults, pc_piix_compat_defaults_len);
505 }
506
pc_i440fx_machine_10_1_options(MachineClass * m)507 static void pc_i440fx_machine_10_1_options(MachineClass *m)
508 {
509 pc_i440fx_machine_options(m);
510 }
511
512 DEFINE_I440FX_MACHINE_AS_LATEST(10, 1);
513
pc_i440fx_machine_10_0_options(MachineClass * m)514 static void pc_i440fx_machine_10_0_options(MachineClass *m)
515 {
516 pc_i440fx_machine_10_1_options(m);
517 compat_props_add(m->compat_props, hw_compat_10_0, hw_compat_10_0_len);
518 compat_props_add(m->compat_props, pc_compat_10_0, pc_compat_10_0_len);
519 }
520
521 DEFINE_I440FX_MACHINE(10, 0);
522
pc_i440fx_machine_9_2_options(MachineClass * m)523 static void pc_i440fx_machine_9_2_options(MachineClass *m)
524 {
525 pc_i440fx_machine_10_0_options(m);
526 compat_props_add(m->compat_props, hw_compat_9_2, hw_compat_9_2_len);
527 compat_props_add(m->compat_props, pc_compat_9_2, pc_compat_9_2_len);
528 }
529
530 DEFINE_I440FX_MACHINE(9, 2);
531
pc_i440fx_machine_9_1_options(MachineClass * m)532 static void pc_i440fx_machine_9_1_options(MachineClass *m)
533 {
534 pc_i440fx_machine_9_2_options(m);
535 compat_props_add(m->compat_props, hw_compat_9_1, hw_compat_9_1_len);
536 compat_props_add(m->compat_props, pc_compat_9_1, pc_compat_9_1_len);
537 }
538
539 DEFINE_I440FX_MACHINE(9, 1);
540
pc_i440fx_machine_9_0_options(MachineClass * m)541 static void pc_i440fx_machine_9_0_options(MachineClass *m)
542 {
543 PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
544
545 pc_i440fx_machine_9_1_options(m);
546 m->smbios_memory_device_size = 16 * GiB;
547
548 compat_props_add(m->compat_props, hw_compat_9_0, hw_compat_9_0_len);
549 compat_props_add(m->compat_props, pc_compat_9_0, pc_compat_9_0_len);
550 pcmc->isa_bios_alias = false;
551 }
552
553 DEFINE_I440FX_MACHINE(9, 0);
554
pc_i440fx_machine_8_2_options(MachineClass * m)555 static void pc_i440fx_machine_8_2_options(MachineClass *m)
556 {
557 PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
558
559 pc_i440fx_machine_9_0_options(m);
560
561 compat_props_add(m->compat_props, hw_compat_8_2, hw_compat_8_2_len);
562 compat_props_add(m->compat_props, pc_compat_8_2, pc_compat_8_2_len);
563 /* For pc-i44fx-8.2 and 8.1, use SMBIOS 3.X by default */
564 pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_64;
565 }
566
567 DEFINE_I440FX_MACHINE(8, 2);
568
pc_i440fx_machine_8_1_options(MachineClass * m)569 static void pc_i440fx_machine_8_1_options(MachineClass *m)
570 {
571 PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
572
573 pc_i440fx_machine_8_2_options(m);
574 pcmc->broken_32bit_mem_addr_check = true;
575
576 compat_props_add(m->compat_props, hw_compat_8_1, hw_compat_8_1_len);
577 compat_props_add(m->compat_props, pc_compat_8_1, pc_compat_8_1_len);
578 }
579
580 DEFINE_I440FX_MACHINE(8, 1);
581
pc_i440fx_machine_8_0_options(MachineClass * m)582 static void pc_i440fx_machine_8_0_options(MachineClass *m)
583 {
584 PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
585
586 pc_i440fx_machine_8_1_options(m);
587 compat_props_add(m->compat_props, hw_compat_8_0, hw_compat_8_0_len);
588 compat_props_add(m->compat_props, pc_compat_8_0, pc_compat_8_0_len);
589
590 /* For pc-i44fx-8.0 and older, use SMBIOS 2.8 by default */
591 pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_32;
592 }
593
594 DEFINE_I440FX_MACHINE(8, 0);
595
pc_i440fx_machine_7_2_options(MachineClass * m)596 static void pc_i440fx_machine_7_2_options(MachineClass *m)
597 {
598 pc_i440fx_machine_8_0_options(m);
599 compat_props_add(m->compat_props, hw_compat_7_2, hw_compat_7_2_len);
600 compat_props_add(m->compat_props, pc_compat_7_2, pc_compat_7_2_len);
601 }
602
603 DEFINE_I440FX_MACHINE(7, 2)
604
pc_i440fx_machine_7_1_options(MachineClass * m)605 static void pc_i440fx_machine_7_1_options(MachineClass *m)
606 {
607 pc_i440fx_machine_7_2_options(m);
608 compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len);
609 compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len);
610 }
611
612 DEFINE_I440FX_MACHINE(7, 1);
613
pc_i440fx_machine_7_0_options(MachineClass * m)614 static void pc_i440fx_machine_7_0_options(MachineClass *m)
615 {
616 PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
617 pc_i440fx_machine_7_1_options(m);
618 pcmc->enforce_amd_1tb_hole = false;
619 compat_props_add(m->compat_props, hw_compat_7_0, hw_compat_7_0_len);
620 compat_props_add(m->compat_props, pc_compat_7_0, pc_compat_7_0_len);
621 }
622
623 DEFINE_I440FX_MACHINE(7, 0);
624
pc_i440fx_machine_6_2_options(MachineClass * m)625 static void pc_i440fx_machine_6_2_options(MachineClass *m)
626 {
627 pc_i440fx_machine_7_0_options(m);
628 compat_props_add(m->compat_props, hw_compat_6_2, hw_compat_6_2_len);
629 compat_props_add(m->compat_props, pc_compat_6_2, pc_compat_6_2_len);
630 }
631
632 DEFINE_I440FX_MACHINE(6, 2);
633
pc_i440fx_machine_6_1_options(MachineClass * m)634 static void pc_i440fx_machine_6_1_options(MachineClass *m)
635 {
636 pc_i440fx_machine_6_2_options(m);
637 compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len);
638 compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len);
639 m->smp_props.prefer_sockets = true;
640 }
641
642 DEFINE_I440FX_MACHINE(6, 1);
643
pc_i440fx_machine_6_0_options(MachineClass * m)644 static void pc_i440fx_machine_6_0_options(MachineClass *m)
645 {
646 pc_i440fx_machine_6_1_options(m);
647 compat_props_add(m->compat_props, hw_compat_6_0, hw_compat_6_0_len);
648 compat_props_add(m->compat_props, pc_compat_6_0, pc_compat_6_0_len);
649 }
650
651 DEFINE_I440FX_MACHINE(6, 0);
652
pc_i440fx_machine_5_2_options(MachineClass * m)653 static void pc_i440fx_machine_5_2_options(MachineClass *m)
654 {
655 pc_i440fx_machine_6_0_options(m);
656 compat_props_add(m->compat_props, hw_compat_5_2, hw_compat_5_2_len);
657 compat_props_add(m->compat_props, pc_compat_5_2, pc_compat_5_2_len);
658 }
659
660 DEFINE_I440FX_MACHINE(5, 2);
661
pc_i440fx_machine_5_1_options(MachineClass * m)662 static void pc_i440fx_machine_5_1_options(MachineClass *m)
663 {
664 PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
665
666 pc_i440fx_machine_5_2_options(m);
667 compat_props_add(m->compat_props, hw_compat_5_1, hw_compat_5_1_len);
668 compat_props_add(m->compat_props, pc_compat_5_1, pc_compat_5_1_len);
669 pcmc->kvmclock_create_always = false;
670 pcmc->pci_root_uid = 1;
671 }
672
673 DEFINE_I440FX_MACHINE(5, 1);
674
pc_i440fx_machine_5_0_options(MachineClass * m)675 static void pc_i440fx_machine_5_0_options(MachineClass *m)
676 {
677 pc_i440fx_machine_5_1_options(m);
678 m->numa_mem_supported = true;
679 compat_props_add(m->compat_props, hw_compat_5_0, hw_compat_5_0_len);
680 compat_props_add(m->compat_props, pc_compat_5_0, pc_compat_5_0_len);
681 m->auto_enable_numa_with_memdev = false;
682 }
683
684 DEFINE_I440FX_MACHINE(5, 0);
685
pc_i440fx_machine_4_2_options(MachineClass * m)686 static void pc_i440fx_machine_4_2_options(MachineClass *m)
687 {
688 pc_i440fx_machine_5_0_options(m);
689 compat_props_add(m->compat_props, hw_compat_4_2, hw_compat_4_2_len);
690 compat_props_add(m->compat_props, pc_compat_4_2, pc_compat_4_2_len);
691 }
692
693 DEFINE_I440FX_MACHINE(4, 2);
694
pc_i440fx_machine_4_1_options(MachineClass * m)695 static void pc_i440fx_machine_4_1_options(MachineClass *m)
696 {
697 pc_i440fx_machine_4_2_options(m);
698 compat_props_add(m->compat_props, hw_compat_4_1, hw_compat_4_1_len);
699 compat_props_add(m->compat_props, pc_compat_4_1, pc_compat_4_1_len);
700 }
701
702 DEFINE_I440FX_MACHINE(4, 1);
703
pc_i440fx_machine_4_0_options(MachineClass * m)704 static void pc_i440fx_machine_4_0_options(MachineClass *m)
705 {
706 PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
707 pc_i440fx_machine_4_1_options(m);
708 pcmc->default_cpu_version = CPU_VERSION_LEGACY;
709 compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len);
710 compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
711 }
712
713 DEFINE_I440FX_MACHINE(4, 0);
714
pc_i440fx_machine_3_1_options(MachineClass * m)715 static void pc_i440fx_machine_3_1_options(MachineClass *m)
716 {
717 PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
718
719 pc_i440fx_machine_4_0_options(m);
720 m->smbus_no_migration_support = true;
721 pcmc->pvh_enabled = false;
722 compat_props_add(m->compat_props, hw_compat_3_1, hw_compat_3_1_len);
723 compat_props_add(m->compat_props, pc_compat_3_1, pc_compat_3_1_len);
724 }
725
726 DEFINE_I440FX_MACHINE(3, 1);
727
pc_i440fx_machine_3_0_options(MachineClass * m)728 static void pc_i440fx_machine_3_0_options(MachineClass *m)
729 {
730 pc_i440fx_machine_3_1_options(m);
731 compat_props_add(m->compat_props, hw_compat_3_0, hw_compat_3_0_len);
732 compat_props_add(m->compat_props, pc_compat_3_0, pc_compat_3_0_len);
733 }
734
735 DEFINE_I440FX_MACHINE(3, 0);
736
pc_i440fx_machine_2_12_options(MachineClass * m)737 static void pc_i440fx_machine_2_12_options(MachineClass *m)
738 {
739 pc_i440fx_machine_3_0_options(m);
740 compat_props_add(m->compat_props, hw_compat_2_12, hw_compat_2_12_len);
741 compat_props_add(m->compat_props, pc_compat_2_12, pc_compat_2_12_len);
742 }
743
744 DEFINE_I440FX_MACHINE(2, 12);
745
pc_i440fx_machine_2_11_options(MachineClass * m)746 static void pc_i440fx_machine_2_11_options(MachineClass *m)
747 {
748 pc_i440fx_machine_2_12_options(m);
749 compat_props_add(m->compat_props, hw_compat_2_11, hw_compat_2_11_len);
750 compat_props_add(m->compat_props, pc_compat_2_11, pc_compat_2_11_len);
751 }
752
753 DEFINE_I440FX_MACHINE(2, 11);
754
pc_i440fx_machine_2_10_options(MachineClass * m)755 static void pc_i440fx_machine_2_10_options(MachineClass *m)
756 {
757 pc_i440fx_machine_2_11_options(m);
758 compat_props_add(m->compat_props, hw_compat_2_10, hw_compat_2_10_len);
759 compat_props_add(m->compat_props, pc_compat_2_10, pc_compat_2_10_len);
760 m->auto_enable_numa_with_memhp = false;
761 }
762
763 DEFINE_I440FX_MACHINE(2, 10);
764
pc_i440fx_machine_2_9_options(MachineClass * m)765 static void pc_i440fx_machine_2_9_options(MachineClass *m)
766 {
767 pc_i440fx_machine_2_10_options(m);
768 compat_props_add(m->compat_props, hw_compat_2_9, hw_compat_2_9_len);
769 compat_props_add(m->compat_props, pc_compat_2_9, pc_compat_2_9_len);
770 }
771
772 DEFINE_I440FX_MACHINE(2, 9);
773
pc_i440fx_machine_2_8_options(MachineClass * m)774 static void pc_i440fx_machine_2_8_options(MachineClass *m)
775 {
776 pc_i440fx_machine_2_9_options(m);
777 compat_props_add(m->compat_props, hw_compat_2_8, hw_compat_2_8_len);
778 compat_props_add(m->compat_props, pc_compat_2_8, pc_compat_2_8_len);
779 }
780
781 DEFINE_I440FX_MACHINE(2, 8);
782
pc_i440fx_machine_2_7_options(MachineClass * m)783 static void pc_i440fx_machine_2_7_options(MachineClass *m)
784 {
785 pc_i440fx_machine_2_8_options(m);
786 compat_props_add(m->compat_props, hw_compat_2_7, hw_compat_2_7_len);
787 compat_props_add(m->compat_props, pc_compat_2_7, pc_compat_2_7_len);
788 }
789
790 DEFINE_I440FX_MACHINE(2, 7);
791
pc_i440fx_machine_2_6_options(MachineClass * m)792 static void pc_i440fx_machine_2_6_options(MachineClass *m)
793 {
794 X86MachineClass *x86mc = X86_MACHINE_CLASS(m);
795 PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
796
797 pc_i440fx_machine_2_7_options(m);
798 pcmc->legacy_cpu_hotplug = true;
799 x86mc->fwcfg_dma_enabled = false;
800 compat_props_add(m->compat_props, hw_compat_2_6, hw_compat_2_6_len);
801 compat_props_add(m->compat_props, pc_compat_2_6, pc_compat_2_6_len);
802 }
803
804 DEFINE_I440FX_MACHINE(2, 6);
805
806 #ifdef CONFIG_ISAPC
isapc_machine_options(MachineClass * m)807 static void isapc_machine_options(MachineClass *m)
808 {
809 PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
810 m->desc = "ISA-only PC";
811 m->max_cpus = 1;
812 m->option_rom_has_mr = true;
813 m->rom_file_has_mr = false;
814 pcmc->pci_enabled = false;
815 pcmc->has_acpi_build = false;
816 pcmc->smbios_defaults = false;
817 pcmc->gigabyte_align = false;
818 pcmc->smbios_legacy_mode = true;
819 pcmc->has_reserved_memory = false;
820 m->default_nic = "ne2k_isa";
821 m->default_cpu_type = X86_CPU_TYPE_NAME("486");
822 m->no_floppy = !module_object_class_by_name(TYPE_ISA_FDC);
823 m->no_parallel = !module_object_class_by_name(TYPE_ISA_PARALLEL);
824 }
825
826 DEFINE_PC_MACHINE(isapc, "isapc", pc_init_isa,
827 isapc_machine_options);
828 #endif
829
830 #ifdef CONFIG_XEN
xenfv_machine_4_2_options(MachineClass * m)831 static void xenfv_machine_4_2_options(MachineClass *m)
832 {
833 pc_i440fx_machine_4_2_options(m);
834 m->desc = "Xen Fully-virtualized PC";
835 m->max_cpus = HVM_MAX_VCPUS;
836 m->default_machine_opts = "accel=xen,suppress-vmdesc=on";
837 }
838
839 DEFINE_PC_MACHINE(xenfv_4_2, "xenfv-4.2", pc_xen_hvm_init,
840 xenfv_machine_4_2_options);
841
xenfv_machine_3_1_options(MachineClass * m)842 static void xenfv_machine_3_1_options(MachineClass *m)
843 {
844 pc_i440fx_machine_3_1_options(m);
845 m->desc = "Xen Fully-virtualized PC";
846 m->alias = "xenfv";
847 m->max_cpus = HVM_MAX_VCPUS;
848 m->default_machine_opts = "accel=xen,suppress-vmdesc=on";
849 }
850
851 DEFINE_PC_MACHINE(xenfv, "xenfv-3.1", pc_xen_hvm_init,
852 xenfv_machine_3_1_options);
853 #endif
854