diff options
Diffstat (limited to 'hw/i386/pc_piix.c')
-rw-r--r-- | hw/i386/pc_piix.c | 304 |
1 files changed, 112 insertions, 192 deletions
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 0dce512..7e78b6d 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -27,20 +27,16 @@ #include "qemu/units.h" #include "hw/char/parallel-isa.h" -#include "hw/dma/i8257.h" -#include "hw/loader.h" #include "hw/i386/x86.h" #include "hw/i386/pc.h" #include "hw/i386/apic.h" #include "hw/pci-host/i440fx.h" -#include "hw/rtc/mc146818rtc.h" #include "hw/southbridge/piix.h" #include "hw/display/ramfb.h" #include "hw/pci/pci.h" #include "hw/pci/pci_ids.h" #include "hw/usb.h" #include "net/net.h" -#include "hw/ide/isa.h" #include "hw/ide/pci.h" #include "hw/irq.h" #include "system/kvm.h" @@ -49,6 +45,7 @@ #include "hw/i2c/smbus_eeprom.h" #include "system/memory.h" #include "hw/acpi/acpi.h" +#include "hw/vfio/types.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "system/xen.h" @@ -71,11 +68,12 @@ #define XEN_IOAPIC_NUM_PIRQS 128ULL -#ifdef CONFIG_IDE_ISA -static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 }; -static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 }; -static const int ide_irq[MAX_IDE_BUS] = { 14, 15 }; -#endif +static GlobalProperty pc_piix_compat_defaults[] = { + { TYPE_RAMFB_DEVICE, "use-legacy-x86-rom", "true" }, + { TYPE_VFIO_PCI_NOHOTPLUG, "use-legacy-x86-rom", "true" }, +}; +static const size_t pc_piix_compat_defaults_len = + G_N_ELEMENTS(pc_piix_compat_defaults); /* * Return the global irq number corresponding to a given device irq @@ -115,9 +113,13 @@ static void pc_init1(MachineState *machine, const char *pci_type) GSIState *gsi_state; MemoryRegion *ram_memory; MemoryRegion *pci_memory = NULL; - MemoryRegion *rom_memory = system_memory; ram_addr_t lowmem; uint64_t hole64_size = 0; + PCIDevice *pci_dev; + DeviceState *dev; + size_t i; + + assert(pcmc->pci_enabled); /* * Calculate ram split, for memory below and above 4G. It's a bit @@ -188,42 +190,39 @@ static void pc_init1(MachineState *machine, const char *pci_type) kvmclock_create(pcmc->kvmclock_create_always); } - if (pcmc->pci_enabled) { - pci_memory = g_new(MemoryRegion, 1); - memory_region_init(pci_memory, NULL, "pci", UINT64_MAX); - rom_memory = pci_memory; - - phb = OBJECT(qdev_new(TYPE_I440FX_PCI_HOST_BRIDGE)); - object_property_add_child(OBJECT(machine), "i440fx", phb); - object_property_set_link(phb, PCI_HOST_PROP_RAM_MEM, - OBJECT(ram_memory), &error_fatal); - object_property_set_link(phb, PCI_HOST_PROP_PCI_MEM, - OBJECT(pci_memory), &error_fatal); - object_property_set_link(phb, PCI_HOST_PROP_SYSTEM_MEM, - OBJECT(system_memory), &error_fatal); - object_property_set_link(phb, PCI_HOST_PROP_IO_MEM, - OBJECT(system_io), &error_fatal); - object_property_set_uint(phb, PCI_HOST_BELOW_4G_MEM_SIZE, - x86ms->below_4g_mem_size, &error_fatal); - object_property_set_uint(phb, PCI_HOST_ABOVE_4G_MEM_SIZE, - x86ms->above_4g_mem_size, &error_fatal); - object_property_set_str(phb, I440FX_HOST_PROP_PCI_TYPE, pci_type, - &error_fatal); - sysbus_realize_and_unref(SYS_BUS_DEVICE(phb), &error_fatal); - - pcms->pcibus = PCI_BUS(qdev_get_child_bus(DEVICE(phb), "pci.0")); - pci_bus_map_irqs(pcms->pcibus, - xen_enabled() ? xen_pci_slot_get_pirq - : pc_pci_slot_get_pirq); - - hole64_size = object_property_get_uint(phb, - PCI_HOST_PROP_PCI_HOLE64_SIZE, - &error_abort); - } + pci_memory = g_new(MemoryRegion, 1); + memory_region_init(pci_memory, NULL, "pci", UINT64_MAX); + + phb = OBJECT(qdev_new(TYPE_I440FX_PCI_HOST_BRIDGE)); + object_property_add_child(OBJECT(machine), "i440fx", phb); + object_property_set_link(phb, PCI_HOST_PROP_RAM_MEM, + OBJECT(ram_memory), &error_fatal); + object_property_set_link(phb, PCI_HOST_PROP_PCI_MEM, + OBJECT(pci_memory), &error_fatal); + object_property_set_link(phb, PCI_HOST_PROP_SYSTEM_MEM, + OBJECT(system_memory), &error_fatal); + object_property_set_link(phb, PCI_HOST_PROP_IO_MEM, + OBJECT(system_io), &error_fatal); + object_property_set_uint(phb, PCI_HOST_BELOW_4G_MEM_SIZE, + x86ms->below_4g_mem_size, &error_fatal); + object_property_set_uint(phb, PCI_HOST_ABOVE_4G_MEM_SIZE, + x86ms->above_4g_mem_size, &error_fatal); + object_property_set_str(phb, I440FX_HOST_PROP_PCI_TYPE, pci_type, + &error_fatal); + sysbus_realize_and_unref(SYS_BUS_DEVICE(phb), &error_fatal); + + pcms->pcibus = PCI_BUS(qdev_get_child_bus(DEVICE(phb), "pci.0")); + pci_bus_map_irqs(pcms->pcibus, + xen_enabled() ? xen_pci_slot_get_pirq + : pc_pci_slot_get_pirq); + + hole64_size = object_property_get_uint(phb, + PCI_HOST_PROP_PCI_HOLE64_SIZE, + &error_abort); /* allocate ram and load rom/bios */ if (!xen_enabled()) { - pc_memory_init(pcms, system_memory, rom_memory, hole64_size); + pc_memory_init(pcms, system_memory, pci_memory, hole64_size); } else { assert(machine->ram_size == x86ms->below_4g_mem_size + x86ms->above_4g_mem_size); @@ -235,67 +234,51 @@ static void pc_init1(MachineState *machine, const char *pci_type) } } - gsi_state = pc_gsi_create(&x86ms->gsi, pcmc->pci_enabled); - - if (pcmc->pci_enabled) { - PCIDevice *pci_dev; - DeviceState *dev; - size_t i; - - pci_dev = pci_new_multifunction(-1, pcms->south_bridge); - object_property_set_bool(OBJECT(pci_dev), "has-usb", - machine_usb(machine), &error_abort); - object_property_set_bool(OBJECT(pci_dev), "has-acpi", - x86_machine_is_acpi_enabled(x86ms), - &error_abort); - object_property_set_bool(OBJECT(pci_dev), "has-pic", false, - &error_abort); - object_property_set_bool(OBJECT(pci_dev), "has-pit", false, - &error_abort); - qdev_prop_set_uint32(DEVICE(pci_dev), "smb_io_base", 0xb100); - object_property_set_bool(OBJECT(pci_dev), "smm-enabled", - x86_machine_is_smm_enabled(x86ms), - &error_abort); - dev = DEVICE(pci_dev); - for (i = 0; i < ISA_NUM_IRQS; i++) { - qdev_connect_gpio_out_named(dev, "isa-irqs", i, x86ms->gsi[i]); - } - pci_realize_and_unref(pci_dev, pcms->pcibus, &error_fatal); - - if (xen_enabled()) { - pci_device_set_intx_routing_notifier( - pci_dev, piix_intx_routing_notifier_xen); - - /* - * Xen supports additional interrupt routes from the PCI devices to - * the IOAPIC: the four pins of each PCI device on the bus are also - * connected to the IOAPIC directly. - * These additional routes can be discovered through ACPI. - */ - pci_bus_irqs(pcms->pcibus, xen_intx_set_irq, pci_dev, - XEN_IOAPIC_NUM_PIRQS); - } + gsi_state = pc_gsi_create(&x86ms->gsi, true); + + pci_dev = pci_new_multifunction(-1, pcms->south_bridge); + object_property_set_bool(OBJECT(pci_dev), "has-usb", + machine_usb(machine), &error_abort); + object_property_set_bool(OBJECT(pci_dev), "has-acpi", + x86_machine_is_acpi_enabled(x86ms), + &error_abort); + object_property_set_bool(OBJECT(pci_dev), "has-pic", false, + &error_abort); + object_property_set_bool(OBJECT(pci_dev), "has-pit", false, + &error_abort); + qdev_prop_set_uint32(DEVICE(pci_dev), "smb_io_base", 0xb100); + object_property_set_bool(OBJECT(pci_dev), "smm-enabled", + x86_machine_is_smm_enabled(x86ms), + &error_abort); + dev = DEVICE(pci_dev); + for (i = 0; i < ISA_NUM_IRQS; i++) { + qdev_connect_gpio_out_named(dev, "isa-irqs", i, x86ms->gsi[i]); + } + pci_realize_and_unref(pci_dev, pcms->pcibus, &error_fatal); - isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(pci_dev), "isa.0")); - x86ms->rtc = ISA_DEVICE(object_resolve_path_component(OBJECT(pci_dev), - "rtc")); - piix4_pm = object_resolve_path_component(OBJECT(pci_dev), "pm"); - dev = DEVICE(object_resolve_path_component(OBJECT(pci_dev), "ide")); - pci_ide_create_devs(PCI_DEVICE(dev)); - pcms->idebus[0] = qdev_get_child_bus(dev, "ide.0"); - pcms->idebus[1] = qdev_get_child_bus(dev, "ide.1"); - } else { - isa_bus = isa_bus_new(NULL, system_memory, system_io, - &error_abort); - isa_bus_register_input_irqs(isa_bus, x86ms->gsi); + if (xen_enabled()) { + pci_device_set_intx_routing_notifier( + pci_dev, piix_intx_routing_notifier_xen); + + /* + * Xen supports additional interrupt routes from the PCI devices to + * the IOAPIC: the four pins of each PCI device on the bus are also + * connected to the IOAPIC directly. + * These additional routes can be discovered through ACPI. + */ + pci_bus_irqs(pcms->pcibus, xen_intx_set_irq, pci_dev, + XEN_IOAPIC_NUM_PIRQS); + } - x86ms->rtc = isa_new(TYPE_MC146818_RTC); - qdev_prop_set_int32(DEVICE(x86ms->rtc), "base_year", 2000); - isa_realize_and_unref(x86ms->rtc, isa_bus, &error_fatal); + isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(pci_dev), "isa.0")); + x86ms->rtc = ISA_DEVICE(object_resolve_path_component(OBJECT(pci_dev), + "rtc")); + piix4_pm = object_resolve_path_component(OBJECT(pci_dev), "pm"); + dev = DEVICE(object_resolve_path_component(OBJECT(pci_dev), "ide")); + pci_ide_create_devs(PCI_DEVICE(dev)); + pcms->idebus[0] = qdev_get_child_bus(dev, "ide.0"); + pcms->idebus[1] = qdev_get_child_bus(dev, "ide.1"); - i8257_dma_init(OBJECT(machine), isa_bus, 0); - pcms->hpet_enabled = false; - } if (x86ms->pic == ON_OFF_AUTO_ON || x86ms->pic == ON_OFF_AUTO_AUTO) { pc_i8259_create(isa_bus, gsi_state->i8259_irq); @@ -309,7 +292,7 @@ static void pc_init1(MachineState *machine, const char *pci_type) x86_register_ferr_irq(x86ms->gsi[13]); } - pc_vga_init(isa_bus, pcmc->pci_enabled ? pcms->pcibus : NULL); + pc_vga_init(isa_bus, pcms->pcibus); /* init basic PC hardware */ pc_basic_device_init(pcms, isa_bus, x86ms->gsi, x86ms->rtc, @@ -317,28 +300,6 @@ static void pc_init1(MachineState *machine, const char *pci_type) pc_nic_init(pcmc, isa_bus, pcms->pcibus); -#ifdef CONFIG_IDE_ISA - if (!pcmc->pci_enabled) { - DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; - int i; - - ide_drive_get(hd, ARRAY_SIZE(hd)); - for (i = 0; i < MAX_IDE_BUS; i++) { - ISADevice *dev; - char busname[] = "ide.0"; - dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], - ide_irq[i], - hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]); - /* - * The ide bus name is ide.0 for the first bus and ide.1 for the - * second one. - */ - busname[4] = '0' + i; - pcms->idebus[i] = qdev_get_child_bus(DEVICE(dev), busname); - } - } -#endif - if (piix4_pm) { smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0); @@ -361,6 +322,16 @@ static void pc_init1(MachineState *machine, const char *pci_type) x86_nvdimm_acpi_dsmio, x86ms->fw_cfg, OBJECT(pcms)); } + +#if defined(CONFIG_IGVM) + /* Apply guest state from IGVM if supplied */ + if (x86ms->igvm) { + if (IGVM_CFG_GET_CLASS(x86ms->igvm) + ->process(x86ms->igvm, machine->cgs, false, &error_fatal) < 0) { + g_assert_not_reached(); + } + } +#endif } typedef enum PCSouthBridgeOption { @@ -410,22 +381,7 @@ static void pc_set_south_bridge(Object *obj, int value, Error **errp) pcms->south_bridge = PCSouthBridgeOption_lookup.array[value]; } -#ifdef CONFIG_ISAPC -static void pc_init_isa(MachineState *machine) -{ - pc_init1(machine, NULL); -} -#endif - #ifdef CONFIG_XEN -static void pc_xen_hvm_init_pci(MachineState *machine) -{ - const char *pci_type = xen_igd_gfx_pt_enabled() ? - TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE : TYPE_I440FX_PCI_DEVICE; - - pc_init1(machine, pci_type); -} - static void pc_xen_hvm_init(MachineState *machine) { PCMachineState *pcms = PC_MACHINE(machine); @@ -435,7 +391,10 @@ static void pc_xen_hvm_init(MachineState *machine) exit(1); } - pc_xen_hvm_init_pci(machine); + pc_init1(machine, xen_igd_gfx_pt_enabled() + ? TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE + : TYPE_I440FX_PCI_DEVICE); + xen_igd_reserve_slot(pcms->pcibus); pci_create_simple(pcms->pcibus, -1, "xen-platform"); } @@ -477,14 +436,25 @@ static void pc_i440fx_machine_options(MachineClass *m) pc_set_south_bridge); object_class_property_set_description(oc, "x-south-bridge", "Use a different south bridge than PIIX3"); + compat_props_add(m->compat_props, + pc_piix_compat_defaults, pc_piix_compat_defaults_len); } -static void pc_i440fx_machine_10_1_options(MachineClass *m) +static void pc_i440fx_machine_10_2_options(MachineClass *m) { pc_i440fx_machine_options(m); } -DEFINE_I440FX_MACHINE_AS_LATEST(10, 1); +DEFINE_I440FX_MACHINE_AS_LATEST(10, 2); + +static void pc_i440fx_machine_10_1_options(MachineClass *m) +{ + pc_i440fx_machine_10_2_options(m); + compat_props_add(m->compat_props, hw_compat_10_1, hw_compat_10_1_len); + compat_props_add(m->compat_props, pc_compat_10_1, pc_compat_10_1_len); +} + +DEFINE_I440FX_MACHINE(10, 1); static void pc_i440fx_machine_10_0_options(MachineClass *m) { @@ -778,56 +748,6 @@ static void pc_i440fx_machine_2_6_options(MachineClass *m) DEFINE_I440FX_MACHINE(2, 6); -static void pc_i440fx_machine_2_5_options(MachineClass *m) -{ - X86MachineClass *x86mc = X86_MACHINE_CLASS(m); - - pc_i440fx_machine_2_6_options(m); - x86mc->save_tsc_khz = false; - m->legacy_fw_cfg_order = 1; - compat_props_add(m->compat_props, hw_compat_2_5, hw_compat_2_5_len); - compat_props_add(m->compat_props, pc_compat_2_5, pc_compat_2_5_len); -} - -DEFINE_I440FX_MACHINE(2, 5); - -static void pc_i440fx_machine_2_4_options(MachineClass *m) -{ - PCMachineClass *pcmc = PC_MACHINE_CLASS(m); - - pc_i440fx_machine_2_5_options(m); - m->hw_version = "2.4.0"; - pcmc->broken_reserved_end = true; - compat_props_add(m->compat_props, hw_compat_2_4, hw_compat_2_4_len); - compat_props_add(m->compat_props, pc_compat_2_4, pc_compat_2_4_len); -} - -DEFINE_I440FX_MACHINE(2, 4); - -#ifdef CONFIG_ISAPC -static void isapc_machine_options(MachineClass *m) -{ - PCMachineClass *pcmc = PC_MACHINE_CLASS(m); - m->desc = "ISA-only PC"; - m->max_cpus = 1; - m->option_rom_has_mr = true; - m->rom_file_has_mr = false; - pcmc->pci_enabled = false; - pcmc->has_acpi_build = false; - pcmc->smbios_defaults = false; - pcmc->gigabyte_align = false; - pcmc->smbios_legacy_mode = true; - pcmc->has_reserved_memory = false; - m->default_nic = "ne2k_isa"; - m->default_cpu_type = X86_CPU_TYPE_NAME("486"); - m->no_floppy = !module_object_class_by_name(TYPE_ISA_FDC); - m->no_parallel = !module_object_class_by_name(TYPE_ISA_PARALLEL); -} - -DEFINE_PC_MACHINE(isapc, "isapc", pc_init_isa, - isapc_machine_options); -#endif - #ifdef CONFIG_XEN static void xenfv_machine_4_2_options(MachineClass *m) { |