diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2019-12-20 11:20:25 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2019-12-20 11:20:25 +0000 |
commit | 48008198270e3ebcc9394401d676c54ed5ac139c (patch) | |
tree | 5dd154ecc44a6c49bcd3d6276336422e14790fe1 /hw | |
parent | 31b2bd89b915d527ff907e8f3c151585e0c45d4f (diff) | |
parent | e2328a11bda7a4d087200c524333adafb8beb7d7 (diff) | |
download | qemu-48008198270e3ebcc9394401d676c54ed5ac139c.zip |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* More uses of RCU_READ_LOCK_GUARD (Dave, myself)
* QOM doc improvments (Greg)
* Cleanups from the Meson conversion (Marc-André)
* Support for multiple -accel options (myself)
* Many x86 machine cleanup (Philippe, myself)
* tests/migration-test cleanup (Juan)
* PC machine removal and next round of deprecation (Thomas)
* kernel-doc integration (Peter, myself)
# gpg: Signature made Wed 18 Dec 2019 01:35:02 GMT
# gpg: using RSA key BFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini/tags/for-upstream: (87 commits)
vga: cleanup mapping of VRAM for non-PCI VGA
hw/display: Remove "rombar" hack from vga-pci and vmware_vga
hw/pci: Remove the "command_serr_enable" property
hw/audio: Remove the "use_broken_id" hack from the AC97 device
hw/i386: Remove the deprecated machines 0.12 up to 0.15
hw/pci-host: Add Kconfig entry to select the IGD Passthrough Host Bridge
hw/pci-host/i440fx: Extract the IGD passthrough host bridge device
hw/pci-host/i440fx: Use definitions instead of magic values
hw/pci-host/i440fx: Use size_t to iterate over ARRAY_SIZE()
hw/pci-host/i440fx: Extract PCII440FXState to "hw/pci-host/i440fx.h"
hw/pci-host/i440fx: Correct the header description
Fix some comment spelling errors.
target/i386: remove unused pci-assign codes
WHPX: refactor load library
migration: check length directly to make sure the range is aligned
memory: include MemoryListener documentation and some missing function parameters
docs: add memory API reference
memory.h: Silence kernel-doc complaints
docs: Create bitops.rst as example of kernel-docs
bitops.h: Silence kernel-doc complaints
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
59 files changed, 603 insertions, 732 deletions
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs index 655a9c1973..99253057e1 100644 --- a/hw/acpi/Makefile.objs +++ b/hw/acpi/Makefile.objs @@ -8,6 +8,7 @@ common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o common-obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device.o common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o +common-obj-$(call lnot,$(CONFIG_PC)) += acpi-x86-stub.o common-obj-y += acpi_interface.o common-obj-y += bios-linker-loader.o @@ -20,4 +21,4 @@ common-obj-$(call lnot,$(CONFIG_IPMI)) += ipmi-stub.o else common-obj-y += acpi-stub.o endif -common-obj-$(CONFIG_ALL) += acpi-stub.o ipmi-stub.o +common-obj-$(CONFIG_ALL) += acpi-stub.o acpi-x86-stub.o ipmi-stub.o diff --git a/hw/acpi/acpi-x86-stub.c b/hw/acpi/acpi-x86-stub.c new file mode 100644 index 0000000000..f88d6a090b --- /dev/null +++ b/hw/acpi/acpi-x86-stub.c @@ -0,0 +1,7 @@ +#include "qemu/osdep.h" +#include "hw/i386/pc.h" + +void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, + const CPUArchIdList *apic_ids, GArray *entry) +{ +} diff --git a/hw/alpha/alpha_sys.h b/hw/alpha/alpha_sys.h index 4e127a6de8..95033d7f0b 100644 --- a/hw/alpha/alpha_sys.h +++ b/hw/alpha/alpha_sys.h @@ -7,7 +7,8 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_host.h" #include "hw/ide.h" -#include "hw/i386/pc.h" +#include "hw/boards.h" +#include "hw/intc/i8259.h" PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, AlphaCPU *[4], diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c index 51b3cf7a61..f2026fda6d 100644 --- a/hw/alpha/dp264.c +++ b/hw/alpha/dp264.c @@ -19,6 +19,7 @@ #include "hw/timer/i8254.h" #include "hw/isa/superio.h" #include "hw/dma/i8257.h" +#include "net/net.h" #include "qemu/cutils.h" #define MAX_IDE_BUS 2 diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index a136b97f68..78cda88333 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -161,7 +161,6 @@ typedef struct AC97BusMasterRegs { typedef struct AC97LinkState { PCIDevice dev; QEMUSoundCard card; - uint32_t use_broken_id; uint32_t glob_cnt; uint32_t glob_sta; uint32_t cas; @@ -1373,13 +1372,6 @@ static void ac97_realize(PCIDevice *dev, Error **errp) c[PCI_BASE_ADDRESS_0 + 6] = 0x00; c[PCI_BASE_ADDRESS_0 + 7] = 0x00; - if (s->use_broken_id) { - c[PCI_SUBSYSTEM_VENDOR_ID] = 0x86; - c[PCI_SUBSYSTEM_VENDOR_ID + 1] = 0x80; - c[PCI_SUBSYSTEM_ID] = 0x00; - c[PCI_SUBSYSTEM_ID + 1] = 0x00; - } - c[PCI_INTERRUPT_LINE] = 0x00; /* intr_ln interrupt line rw */ c[PCI_INTERRUPT_PIN] = 0x01; /* intr_pn interrupt pin ro */ @@ -1411,7 +1403,6 @@ static int ac97_init (PCIBus *bus) static Property ac97_properties[] = { DEFINE_AUDIO_PROPERTIES(AC97LinkState, card), - DEFINE_PROP_UINT32 ("use_broken_id", AC97LinkState, use_broken_id, 0), DEFINE_PROP_END_OF_LIST (), }; diff --git a/hw/core/machine.c b/hw/core/machine.c index 023548b4f3..56137e9bf0 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -178,86 +178,6 @@ GlobalProperty hw_compat_2_1[] = { }; const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1); -static char *machine_get_accel(Object *obj, Error **errp) -{ - MachineState *ms = MACHINE(obj); - - return g_strdup(ms->accel); -} - -static void machine_set_accel(Object *obj, const char *value, Error **errp) -{ - MachineState *ms = MACHINE(obj); - - g_free(ms->accel); - ms->accel = g_strdup(value); -} - -static void machine_set_kernel_irqchip(Object *obj, Visitor *v, - const char *name, void *opaque, - Error **errp) -{ - Error *err = NULL; - MachineState *ms = MACHINE(obj); - OnOffSplit mode; - - visit_type_OnOffSplit(v, name, &mode, &err); - if (err) { - error_propagate(errp, err); - return; - } else { - switch (mode) { - case ON_OFF_SPLIT_ON: - ms->kernel_irqchip_allowed = true; - ms->kernel_irqchip_required = true; - ms->kernel_irqchip_split = false; - break; - case ON_OFF_SPLIT_OFF: - ms->kernel_irqchip_allowed = false; - ms->kernel_irqchip_required = false; - ms->kernel_irqchip_split = false; - break; - case ON_OFF_SPLIT_SPLIT: - ms->kernel_irqchip_allowed = true; - ms->kernel_irqchip_required = true; - ms->kernel_irqchip_split = true; - break; - default: - /* The value was checked in visit_type_OnOffSplit() above. If - * we get here, then something is wrong in QEMU. - */ - abort(); - } - } -} - -static void machine_get_kvm_shadow_mem(Object *obj, Visitor *v, - const char *name, void *opaque, - Error **errp) -{ - MachineState *ms = MACHINE(obj); - int64_t value = ms->kvm_shadow_mem; - - visit_type_int(v, name, &value, errp); -} - -static void machine_set_kvm_shadow_mem(Object *obj, Visitor *v, - const char *name, void *opaque, - Error **errp) -{ - MachineState *ms = MACHINE(obj); - Error *error = NULL; - int64_t value; - - visit_type_int(v, name, &value, &error); - if (error) { - error_propagate(errp, error); - return; - } - - ms->kvm_shadow_mem = value; -} - static char *machine_get_kernel(Object *obj, Error **errp) { MachineState *ms = MACHINE(obj); @@ -432,20 +352,6 @@ static void machine_set_graphics(Object *obj, bool value, Error **errp) ms->enable_graphics = value; } -static bool machine_get_igd_gfx_passthru(Object *obj, Error **errp) -{ - MachineState *ms = MACHINE(obj); - - return ms->igd_gfx_passthru; -} - -static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error **errp) -{ - MachineState *ms = MACHINE(obj); - - ms->igd_gfx_passthru = value; -} - static char *machine_get_firmware(Object *obj, Error **errp) { MachineState *ms = MACHINE(obj); @@ -813,23 +719,6 @@ static void machine_class_init(ObjectClass *oc, void *data) mc->numa_mem_align_shift = 23; mc->numa_auto_assign_ram = numa_default_auto_assign_ram; - object_class_property_add_str(oc, "accel", - machine_get_accel, machine_set_accel, &error_abort); - object_class_property_set_description(oc, "accel", - "Accelerator list", &error_abort); - - object_class_property_add(oc, "kernel-irqchip", "on|off|split", - NULL, machine_set_kernel_irqchip, - NULL, NULL, &error_abort); - object_class_property_set_description(oc, "kernel-irqchip", - "Configure KVM in-kernel irqchip", &error_abort); - - object_class_property_add(oc, "kvm-shadow-mem", "int", - machine_get_kvm_shadow_mem, machine_set_kvm_shadow_mem, - NULL, NULL, &error_abort); - object_class_property_set_description(oc, "kvm-shadow-mem", - "KVM shadow MMU size", &error_abort); - object_class_property_add_str(oc, "kernel", machine_get_kernel, machine_set_kernel, &error_abort); object_class_property_set_description(oc, "kernel", @@ -887,12 +776,6 @@ static void machine_class_init(ObjectClass *oc, void *data) object_class_property_set_description(oc, "graphics", "Set on/off to enable/disable graphics emulation", &error_abort); - object_class_property_add_bool(oc, "igd-passthru", - machine_get_igd_gfx_passthru, machine_set_igd_gfx_passthru, - &error_abort); - object_class_property_set_description(oc, "igd-passthru", - "Set on/off to enable/disable igd passthrou", &error_abort); - object_class_property_add_str(oc, "firmware", machine_get_firmware, machine_set_firmware, &error_abort); @@ -935,9 +818,6 @@ static void machine_initfn(Object *obj) MachineState *ms = MACHINE(obj); MachineClass *mc = MACHINE_GET_CLASS(obj); - ms->kernel_irqchip_allowed = true; - ms->kernel_irqchip_split = mc->default_kernel_irqchip_split; - ms->kvm_shadow_mem = -1; ms->dump_guest_core = true; ms->mem_merge = true; ms->enable_graphics = true; @@ -976,7 +856,6 @@ static void machine_finalize(Object *obj) { MachineState *ms = MACHINE(obj); - g_free(ms->accel); g_free(ms->kernel_filename); g_free(ms->initrd_filename); g_free(ms->kernel_cmdline); @@ -994,26 +873,6 @@ bool machine_usb(MachineState *machine) return machine->usb; } -bool machine_kernel_irqchip_allowed(MachineState *machine) -{ - return machine->kernel_irqchip_allowed; -} - -bool machine_kernel_irqchip_required(MachineState *machine) -{ - return machine->kernel_irqchip_required; -} - -bool machine_kernel_irqchip_split(MachineState *machine) -{ - return machine->kernel_irqchip_split; -} - -int machine_kvm_shadow_mem(MachineState *machine) -{ - return machine->kvm_shadow_mem; -} - int machine_phandle_start(MachineState *machine) { return machine->phandle_start; diff --git a/hw/display/vga-isa-mm.c b/hw/display/vga-isa-mm.c index e9c43e5530..7321b7a06d 100644 --- a/hw/display/vga-isa-mm.c +++ b/hw/display/vga-isa-mm.c @@ -106,6 +106,9 @@ int isa_vga_mm_init(hwaddr vram_base, s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s); - vga_init_vbe(&s->vga, NULL, address_space); + memory_region_add_subregion(address_space, + VBE_DISPI_LFB_PHYSICAL_ADDRESS, + &s->vga.vram); + return 0; } diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c index 873e5e9706..08a2730db5 100644 --- a/hw/display/vga-isa.c +++ b/hw/display/vga-isa.c @@ -76,7 +76,9 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp) memory_region_set_coalescing(vga_io_memory); s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s); - vga_init_vbe(s, OBJECT(dev), isa_address_space(isadev)); + memory_region_add_subregion(isa_address_space(isadev), + VBE_DISPI_LFB_PHYSICAL_ADDRESS, + &s->vram); /* ROM BIOS */ rom_add_vga(VGABIOS_FILENAME); } diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c index a27b88122d..cfe095713e 100644 --- a/hw/display/vga-pci.c +++ b/hw/display/vga-pci.c @@ -264,11 +264,6 @@ static void pci_std_vga_realize(PCIDevice *dev, Error **errp) pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); } - - if (!dev->rom_bar) { - /* compatibility with pc-0.13 and older */ - vga_init_vbe(s, OBJECT(dev), pci_address_space(dev)); - } } static void pci_std_vga_init(Object *obj) diff --git a/hw/display/vga.c b/hw/display/vga.c index 82ebe53610..061fd9ab8f 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -2301,17 +2301,3 @@ void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space, portio_list_add(&s->vbe_port_list, address_space_io, 0x1ce); } } - -void vga_init_vbe(VGACommonState *s, Object *obj, MemoryRegion *system_memory) -{ - /* With pc-0.12 and below we map both the PCI BAR and the fixed VBE region, - * so use an alias to avoid double-mapping the same region. - */ - memory_region_init_alias(&s->vram_vbe, obj, "vram.vbe", - &s->vram, 0, memory_region_size(&s->vram)); - /* XXX: use optimized standard vga accesses */ - memory_region_add_subregion(system_memory, - VBE_DISPI_LFB_PHYSICAL_ADDRESS, - &s->vram_vbe); - s->vbe_mapped = 1; -} diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h index 55c418eab5..847e784ca6 100644 --- a/hw/display/vga_int.h +++ b/hw/display/vga_int.h @@ -60,7 +60,6 @@ typedef struct VGACommonState { MemoryRegion *legacy_address_space; uint8_t *vram_ptr; MemoryRegion vram; - MemoryRegion vram_vbe; uint32_t vram_size; uint32_t vram_size_mb; /* property */ uint32_t vbe_size; @@ -106,7 +105,6 @@ typedef struct VGACommonState { uint32_t vbe_start_addr; uint32_t vbe_line_offset; uint32_t vbe_bank_mask; - int vbe_mapped; /* display refresh support */ QemuConsole *con; uint32_t font_offsets[2]; @@ -178,7 +176,6 @@ void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2); int vga_ioport_invalid(VGACommonState *s, uint32_t addr); -void vga_init_vbe(VGACommonState *s, Object *obj, MemoryRegion *address_space); uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr); void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val); void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val); diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index 23dc8910cc..ead754eccf 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -1312,11 +1312,6 @@ static void pci_vmsvga_realize(PCIDevice *dev, Error **errp) &s->chip.vga.vram); pci_register_bar(dev, 2, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->chip.fifo_ram); - - if (!dev->rom_bar) { - /* compatibility with pc-0.13 and older */ - vga_init_vbe(&s->chip.vga, OBJECT(dev), pci_address_space(dev)); - } } static Property vga_vmware_properties[] = { diff --git a/hw/hppa/hppa_sys.h b/hw/hppa/hppa_sys.h index 43d25d21fc..4e5019695e 100644 --- a/hw/hppa/hppa_sys.h +++ b/hw/hppa/hppa_sys.h @@ -6,7 +6,8 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_host.h" #include "hw/ide.h" -#include "hw/i386/pc.h" +#include "hw/boards.h" +#include "hw/intc/i8259.h" #include "hppa_hardware.h" diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index b30aba6d54..5d0de26140 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -19,6 +19,7 @@ #include "hppa_sys.h" #include "qemu/units.h" #include "qapi/error.h" +#include "net/net.h" #include "qemu/log.h" #define MAX_IDE_BUS 2 diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c index 6ebf31c310..da8ce82725 100644 --- a/hw/hyperv/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -546,14 +546,14 @@ uint16_t hyperv_hcall_post_message(uint64_t param, bool fast) } ret = HV_STATUS_INVALID_CONNECTION_ID; - rcu_read_lock(); - QLIST_FOREACH_RCU(mh, &msg_handlers, link) { - if (mh->conn_id == (msg->connection_id & HV_CONNECTION_ID_MASK)) { - ret = mh->handler(msg, mh->data); - break; + WITH_RCU_READ_LOCK_GUARD() { + QLIST_FOREACH_RCU(mh, &msg_handlers, link) { + if (mh->conn_id == (msg->connection_id & HV_CONNECTION_ID_MASK)) { + ret = mh->handler(msg, mh->data); + break; + } } } - rcu_read_unlock(); unmap: cpu_physical_memory_unmap(msg, len, 0, 0); @@ -619,7 +619,6 @@ int hyperv_set_event_flag_handler(uint32_t conn_id, EventNotifier *notifier) uint16_t hyperv_hcall_signal_event(uint64_t param, bool fast) { - uint16_t ret; EventFlagHandler *handler; if (unlikely(!fast)) { @@ -645,15 +644,12 @@ uint16_t hyperv_hcall_signal_event(uint64_t param, bool fast) return HV_STATUS_INVALID_HYPERCALL_INPUT; } - ret = HV_STATUS_INVALID_CONNECTION_ID; - rcu_read_lock(); + RCU_READ_LOCK_GUARD(); QLIST_FOREACH_RCU(handler, &event_flag_handlers, link) { if (handler->conn_id == param) { event_notifier_set(handler->notifier); - ret = 0; - break; + return 0; } } - rcu_read_unlock(); - return ret; + return HV_STATUS_INVALID_CONNECTION_ID; } diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig index 5a494342ea..91cf5843b4 100644 --- a/hw/i386/Kconfig +++ b/hw/i386/Kconfig @@ -103,11 +103,17 @@ config MICROVM select MC146818RTC select VIRTIO_MMIO +config X86_IOMMU + bool + depends on PC + config VTD bool + select X86_IOMMU config AMD_IOMMU bool + select X86_IOMMU config VMPORT bool diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 0d195b5210..8ce1b26533 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -1,17 +1,19 @@ obj-$(CONFIG_KVM) += kvm/ obj-y += e820_memory_layout.o multiboot.o obj-y += x86.o -obj-y += pc.o +obj-$(CONFIG_PC) += pc.o pc_sysfw.o obj-$(CONFIG_I440FX) += pc_piix.o obj-$(CONFIG_Q35) += pc_q35.o obj-$(CONFIG_MICROVM) += microvm.o -obj-y += fw_cfg.o pc_sysfw.o -obj-y += x86-iommu.o +obj-y += fw_cfg.o +obj-$(CONFIG_X86_IOMMU) += x86-iommu.o +obj-$(call lnot,$(CONFIG_X86_IOMMU)) += x86-iommu-stub.o obj-$(CONFIG_VTD) += intel_iommu.o obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o obj-$(CONFIG_XEN) += ../xenpv/ xen/ obj-$(CONFIG_VMPORT) += vmport.o obj-$(CONFIG_VMMOUSE) += vmmouse.o +obj-$(CONFIG_PC) += port92.o obj-y += kvmvapic.o -obj-y += acpi-build.o +obj-$(CONFIG_PC) += acpi-build.o diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 12ff55fcfb..7b8da62d41 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -53,6 +53,7 @@ /* Supported chipsets: */ #include "hw/southbridge/piix.h" #include "hw/acpi/pcihp.h" +#include "hw/i386/fw_cfg.h" #include "hw/i386/ich9.h" #include "hw/pci/pci_bus.h" #include "hw/pci-host/q35.h" diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c index 39b6bc6052..da60ada594 100644 --- a/hw/i386/fw_cfg.c +++ b/hw/i386/fw_cfg.c @@ -16,12 +16,14 @@ #include "sysemu/numa.h" #include "hw/acpi/acpi.h" #include "hw/firmware/smbios.h" -#include "hw/i386/pc.h" #include "hw/i386/fw_cfg.h" #include "hw/timer/hpet.h" #include "hw/nvram/fw_cfg.h" #include "e820_memory_layout.h" #include "kvm_i386.h" +#include "config-devices.h" + +struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX}; const char *fw_cfg_arch_key_name(uint16_t key) { @@ -46,6 +48,7 @@ const char *fw_cfg_arch_key_name(uint16_t key) void fw_cfg_build_smbios(MachineState *ms, FWCfgState *fw_cfg) { +#ifdef CONFIG_SMBIOS uint8_t *smbios_tables, *smbios_anchor; size_t smbios_tables_len, smbios_anchor_len; struct smbios_phys_mem_area *mem_array; @@ -83,6 +86,7 @@ void fw_cfg_build_smbios(MachineState *ms, FWCfgState *fw_cfg) fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-anchor", smbios_anchor, smbios_anchor_len); } +#endif } FWCfgState *fw_cfg_arch_create(MachineState *ms, @@ -114,8 +118,10 @@ FWCfgState *fw_cfg_arch_create(MachineState *ms, */ fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, apic_id_limit); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); +#ifdef CONFIG_ACPI fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, acpi_tables, acpi_tables_len); +#endif fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override()); fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE, diff --git a/hw/i386/fw_cfg.h b/hw/i386/fw_cfg.h index e0856a3769..9e74278779 100644 --- a/hw/i386/fw_cfg.h +++ b/hw/i386/fw_cfg.h @@ -12,6 +12,8 @@ #include "hw/boards.h" #include "hw/nvram/fw_cfg.h" +#define FW_CFG_IO_BASE 0x510 + #define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0) #define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1) #define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2) diff --git a/hw/i386/kvm/Makefile.objs b/hw/i386/kvm/Makefile.objs index 4224ed900e..0c8d5f2dee 100644 --- a/hw/i386/kvm/Makefile.objs +++ b/hw/i386/kvm/Makefile.objs @@ -1 +1,5 @@ -obj-y += clock.o apic.o i8259.o ioapic.o i8254.o +obj-y += clock.o +obj-$(CONFIG_APIC) += apic.o +obj-$(CONFIG_IOAPIC) += ioapic.o +obj-$(CONFIG_I8254) += i8254.o +obj-$(CONFIG_I8259) += i8259.o diff --git a/hw/i386/kvm/i8259.c b/hw/i386/kvm/i8259.c index d0c1b1deac..e404fdcdac 100644 --- a/hw/i386/kvm/i8259.c +++ b/hw/i386/kvm/i8259.c @@ -12,6 +12,7 @@ #include "qemu/osdep.h" #include "hw/isa/i8259_internal.h" +#include "hw/intc/i8259.h" #include "qemu/module.h" #include "hw/i386/apic_internal.h" #include "hw/irq.h" diff --git a/hw/i386/kvm/ioapic.c b/hw/i386/kvm/ioapic.c index f94729c565..973e2b2af1 100644 --- a/hw/i386/kvm/ioapic.c +++ b/hw/i386/kvm/ioapic.c @@ -12,7 +12,7 @@ #include "qemu/osdep.h" #include "monitor/monitor.h" -#include "hw/i386/pc.h" +#include "hw/i386/x86.h" #include "hw/irq.h" #include "hw/qdev-properties.h" #include "hw/i386/ioapic_internal.h" @@ -48,18 +48,6 @@ void kvm_pc_setup_irq_routing(bool pci_enabled) } } -void kvm_pc_gsi_handler(void *opaque, int n, int level) -{ - GSIState *s = opaque; - - if (n < ISA_NUM_IRQS) { - /* Kernel will forward to both PIC and IOAPIC */ - qemu_set_irq(s->i8259_irq[n], level); - } else { - qemu_set_irq(s->ioapic_irq[n], level); - } -} - typedef struct KVMIOAPICState KVMIOAPICState; struct KVMIOAPICState { diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index def37e60f7..827ce29e58 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -32,8 +32,8 @@ #include "hw/kvm/clock.h" #include "hw/i386/microvm.h" #include "hw/i386/x86.h" -#include "hw/i386/pc.h" #include "target/i386/cpu.h" +#include "hw/intc/i8259.h" #include "hw/timer/i8254.h" #include "hw/rtc/mc146818rtc.h" #include "hw/char/serial.h" @@ -132,7 +132,7 @@ static void microvm_devices_init(MicrovmMachineState *mms) if (mms->pic == ON_OFF_AUTO_ON || mms->pic == ON_OFF_AUTO_AUTO) { qemu_irq *i8259; - i8259 = i8259_init(isa_bus, pc_allocate_cpu_irq()); + i8259 = i8259_init(isa_bus, x86_allocate_cpu_irq()); for (i = 0; i < ISA_NUM_IRQS; i++) { gsi_state->i8259_irq[i] = i8259[i]; } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 58867f987d..42014b06de 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -44,6 +44,7 @@ #include "migration/vmstate.h" #include "multiboot.h" #include "hw/rtc/mc146818rtc.h" +#include "hw/intc/i8259.h" #include "hw/dma/i8257.h" #include "hw/timer/i8254.h" #include "hw/input/i8042.h" @@ -90,18 +91,7 @@ #include "config-devices.h" #include "e820_memory_layout.h" #include "fw_cfg.h" - -/* debug PC/ISA interrupts */ -//#define DEBUG_IRQ - -#ifdef DEBUG_IRQ -#define DPRINTF(fmt, ...) \ - do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) -#endif - -struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX}; +#include "trace.h" GlobalProperty pc_compat_4_2[] = {}; const size_t pc_compat_4_2_len = G_N_ELEMENTS(pc_compat_4_2); @@ -347,17 +337,6 @@ GlobalProperty pc_compat_1_4[] = { }; const size_t pc_compat_1_4_len = G_N_ELEMENTS(pc_compat_1_4); -void gsi_handler(void *opaque, int n, int level) -{ - GSIState *s = opaque; - - DPRINTF("pc: %s GSI %d\n", level ? "raising" : "lowering", n); - if (n < ISA_NUM_IRQS) { - qemu_set_irq(s->i8259_irq[n], level); - } - qemu_set_irq(s->ioapic_irq[n], level); -} - GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled) { GSIState *s; @@ -365,10 +344,8 @@ GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled) s = g_new0(GSIState, 1); if (kvm_ioapic_in_kernel()) { kvm_pc_setup_irq_routing(pci_enabled); - *irqs = qemu_allocate_irqs(kvm_pc_gsi_handler, s, GSI_NUM_PINS); - } else { - *irqs = qemu_allocate_irqs(gsi_handler, s, GSI_NUM_PINS); } + *irqs = qemu_allocate_irqs(gsi_handler, s, GSI_NUM_PINS); return s; } @@ -397,55 +374,6 @@ static uint64_t ioportF0_read(void *opaque, hwaddr addr, unsigned size) return 0xffffffffffffffffULL; } -/* TSC handling */ -uint64_t cpu_get_tsc(CPUX86State *env) -{ - return cpu_get_ticks(); -} - -/* IRQ handling */ -int cpu_get_pic_interrupt(CPUX86State *env) -{ - X86CPU *cpu = env_archcpu(env); - int intno; - - if (!kvm_irqchip_in_kernel()) { - intno = apic_get_interrupt(cpu->apic_state); - if (intno >= 0) { - return intno; - } - /* read the irq from the PIC */ - if (!apic_accept_pic_intr(cpu->apic_state)) { - return -1; - } - } - - intno = pic_read_irq(isa_pic); - return intno; -} - -static void pic_irq_request(void *opaque, int irq, int level) -{ - CPUState *cs = first_cpu; - X86CPU *cpu = X86_CPU(cs); - - DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq); - if (cpu->apic_state && !kvm_irqchip_in_kernel()) { - CPU_FOREACH(cs) { - cpu = X86_CPU(cs); - if (apic_accept_pic_intr(cpu->apic_state)) { - apic_deliver_pic_intr(cpu->apic_state, level); - } - } - } else { - if (level) { - cpu_interrupt(cs, CPU_INTERRUPT_HARD); - } else { - cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); - } - } -} - /* PC cmos mappings */ #define REG_EQUIPMENT_BYTE 0x14 @@ -745,124 +673,6 @@ void pc_cmos_init(PCMachineState *pcms, qemu_register_reset(pc_cmos_init_late, &arg); } -#define TYPE_PORT92 "port92" -#define PORT92(obj) OBJECT_CHECK(Port92State, (obj), TYPE_PORT92) - -/* port 92 stuff: could be split off */ -typedef struct Port92State { - ISADevice parent_obj; - - MemoryRegion io; - uint8_t outport; - qemu_irq a20_out; -} Port92State; - -static void port92_write(void *opaque, hwaddr addr, uint64_t val, - unsigned size) -{ - Port92State *s = opaque; - int oldval = s->outport; - - DPRINTF("port92: write 0x%02" PRIx64 "\n", val); - s->outport = val; - qemu_set_irq(s->a20_out, (val >> 1) & 1); - if ((val & 1) && !(oldval & 1)) { - qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); - } -} - -static uint64_t port92_read(void *opaque, hwaddr addr, - unsigned size) -{ - Port92State *s = opaque; - uint32_t ret; - - ret = s->outport; - DPRINTF("port92: read 0x%02x\n", ret); - return ret; -} - -static void port92_init(ISADevice *dev, qemu_irq a20_out) -{ - qdev_connect_gpio_out_named(DEVICE(dev), PORT92_A20_LINE, 0, a20_out); -} - -static const VMStateDescription vmstate_port92_isa = { - .name = "port92", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT8(outport, Port92State), - VMSTATE_END_OF_LIST() - } -}; - -static void port92_reset(DeviceState *d) -{ - Port92State *s = PORT92(d); - - s->outport &= ~1; -} - -static const MemoryRegionOps port92_ops = { - .read = port92_read, - .write = port92_write, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static void port92_initfn(Object *obj) -{ - Port92State *s = PORT92(obj); - - memory_region_init_io(&s->io, OBJECT(s), &port92_ops, s, "port92", 1); - - s->outport = 0; - - qdev_init_gpio_out_named(DEVICE(obj), &s->a20_out, PORT92_A20_LINE, 1); -} - -static void port92_realizefn(DeviceState *dev, Error **errp) -{ - ISADevice *isadev = ISA_DEVICE(dev); - Port92State *s = PORT92(dev); - - isa_register_ioport(isadev, &s->io, 0x92); -} - -static void port92_class_initfn(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = port92_realizefn; - dc->reset = port92_reset; - dc->vmsd = &vmstate_port92_isa; - /* - * Reason: unlike ordinary ISA devices, this one needs additional - * wiring: its A20 output line needs to be wired up by - * port92_init(). - */ - dc->user_creatable = false; -} - -static const TypeInfo port92_info = { - .name = TYPE_PORT92, - .parent = TYPE_ISA_DEVICE, - .instance_size = sizeof(Port92State), - .instance_init = port92_initfn, - .class_init = port92_class_initfn, -}; - -static void port92_register_types(void) -{ - type_register_static(&port92_info); -} - -type_init(port92_register_types) - static void handle_a20_line_change(void *opaque, int irq, int level) { X86CPU *cpu = opaque; @@ -889,16 +699,6 @@ void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd) nb_ne2k++; } -DeviceState *cpu_get_current_apic(void) -{ - if (current_cpu) { - X86CPU *cpu = X86_CPU(current_cpu); - return cpu->apic_state; - } else { - return NULL; - } -} - void pc_acpi_smi_interrupt(void *opaque, int irq, int level) { X86CPU *cpu = opaque; @@ -1294,11 +1094,6 @@ uint64_t pc_pci_hole64_start(void) return ROUND_UP(hole64_start, 1 * GiB); } -qemu_irq pc_allocate_cpu_irq(void) -{ - return qemu_allocate_irq(pic_irq_request, NULL, 0); -} - DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus) { DeviceState *dev = NULL; @@ -1365,11 +1160,12 @@ static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl, bool no_vmport) qdev_prop_set_ptr(dev, "ps2_mouse", i8042); qdev_init_nofail(dev); } - port92 = isa_create_simple(isa_bus, "port92"); + port92 = isa_create_simple(isa_bus, TYPE_PORT92); a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2); i8042_setup_a20_line(i8042, a20_line[0]); - port92_init(port92, a20_line[1]); + qdev_connect_gpio_out_named(DEVICE(port92), + PORT92_A20_LINE, 0, a20_line[1]); g_free(a20_line); } @@ -1475,7 +1271,7 @@ void pc_i8259_create(ISABus *isa_bus, qemu_irq *i8259_irqs) } else if (xen_enabled()) { i8259 = xen_interrupt_controller_init(); } else { - i8259 = i8259_init(isa_bus, pc_allocate_cpu_irq()); + i8259 = i8259_init(isa_bus, x86_allocate_cpu_irq()); } for (size_t i = 0; i < ISA_NUM_IRQS; i++) { @@ -1485,30 +1281,6 @@ void pc_i8259_create(ISABus *isa_bus, qemu_irq *i8259_irqs) g_free(i8259); } -void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name) -{ - DeviceState *dev; - SysBusDevice *d; - unsigned int i; - - if (kvm_ioapic_in_kernel()) { - dev = qdev_create(NULL, TYPE_KVM_IOAPIC); - } else { - dev = qdev_create(NULL, TYPE_IOAPIC); - } - if (parent_name) { - object_property_add_child(object_resolve_path(parent_name, NULL), - "ioapic", OBJECT(dev), NULL); - } - qdev_init_nofail(dev); - d = SYS_BUS_DEVICE(dev); - sysbus_mmio_map(d, 0, IO_APIC_DEFAULT_ADDRESS); - - for (i = 0; i < IOAPIC_NUM_PINS; i++) { - gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i); - } -} - static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -2032,48 +1804,6 @@ static void pc_machine_set_vmport(Object *obj, Visitor *v, const char *name, visit_type_OnOffAuto(v, name, &pcms->vmport, errp); } -bool pc_machine_is_smm_enabled(PCMachineState *pcms) -{ - bool smm_available = false; - - if (pcms->smm == ON_OFF_AUTO_OFF) { - return false; - } - - if (tcg_enabled() || qtest_enabled()) { - smm_available = true; - } else if (kvm_enabled()) { - smm_available = kvm_has_smm(); - } - - if (smm_available) { - return true; - } - - if (pcms->smm == ON_OFF_AUTO_ON) { - error_report("System Management Mode not supported by this hypervisor."); - exit(1); - } - return false; -} - -static void pc_machine_get_smm(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - PCMachineState *pcms = PC_MACHINE(obj); - OnOffAuto smm = pcms->smm; - - visit_type_OnOffAuto(v, name, &smm, errp); -} - -static void pc_machine_set_smm(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - PCMachineState *pcms = PC_MACHINE(obj); - - visit_type_OnOffAuto(v, name, &pcms->smm, errp); -} - static bool pc_machine_get_smbus(Object *obj, Error **errp) { PCMachineState *pcms = PC_MACHINE(obj); @@ -2120,7 +1850,6 @@ static void pc_machine_initfn(Object *obj) { PCMachineState *pcms = PC_MACHINE(obj); - pcms->smm = ON_OFF_AUTO_AUTO; #ifdef CONFIG_VMPORT pcms->vmport = ON_OFF_AUTO_AUTO; #else @@ -2227,12 +1956,6 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) pc_machine_get_device_memory_region_size, NULL, NULL, NULL, &error_abort); - object_class_property_add(oc, PC_MACHINE_SMM, "OnOffAuto", - pc_machine_get_smm, pc_machine_set_smm, - NULL, NULL, &error_abort); - object_class_property_set_description(oc, PC_MACHINE_SMM, - "Enable SMM (pc & q35)", &error_abort); - object_class_property_add(oc, PC_MACHINE_VMPORT, "OnOffAuto", pc_machine_get_vmport, pc_machine_set_vmport, NULL, NULL, &error_abort); diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index ffb30c32ce..721c7aa64e 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -281,7 +281,7 @@ else { /* TODO: Populate SPD eeprom data. */ pcms->smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, x86ms->gsi[9], smi_irq, - pc_machine_is_smm_enabled(pcms), + x86_machine_is_smm_enabled(x86ms), &piix4_pm); smbus_eeprom_init(pcms->smbus, 8, NULL, 0); @@ -309,9 +309,9 @@ else { static void pc_compat_2_3_fn(MachineState *machine) { - PCMachineState *pcms = PC_MACHINE(machine); + X86MachineState *x86ms = X86_MACHINE(machine); if (kvm_enabled()) { - pcms->smm = ON_OFF_AUTO_OFF; + x86ms->smm = ON_OFF_AUTO_OFF; } } @@ -357,19 +357,13 @@ static void pc_compat_1_3(MachineState *machine) pc_compat_1_4_fn(machine); } -/* PC compat function for pc-0.14 to pc-1.2 */ +/* PC compat function for pc-1.0 to pc-1.2 */ static void pc_compat_1_2(MachineState *machine) { pc_compat_1_3(machine); x86_cpu_change_kvm_default("kvm-pv-eoi", NULL); } -/* PC compat function for pc-0.12 and pc-0.13 */ -static void pc_compat_0_13(MachineState *machine) -{ - pc_compat_1_2(machine); -} - static void pc_init_isa(MachineState *machine) { pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, TYPE_I440FX_PCI_DEVICE); @@ -745,6 +739,7 @@ static void pc_i440fx_1_3_machine_options(MachineClass *m) pc_i440fx_1_4_machine_options(m); m->hw_version = "1.3.0"; + m->deprecation_reason = "use a newer machine type instead"; x86mc->compat_apic_id_mode = true; compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat)); } @@ -813,82 +808,6 @@ DEFINE_I440FX_MACHINE(v1_0, "pc-1.0", pc_compat_1_2, pc_i440fx_1_0_machine_options); -static void pc_i440fx_0_15_machine_options(MachineClass *m) -{ - static GlobalProperty compat[] = { - PC_CPU_MODEL_IDS("0.15") - }; - - pc_i440fx_1_0_machine_options(m); - m->hw_version = "0.15"; - m->deprecation_reason = "use a newer machine type instead"; - compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat)); -} - -DEFINE_I440FX_MACHINE(v0_15, "pc-0.15", pc_compat_1_2, - pc_i440fx_0_15_machine_options); - - -static void pc_i440fx_0_14_machine_options(MachineClass *m) -{ - static GlobalProperty compat[] = { - PC_CPU_MODEL_IDS("0.14") - { "virtio-blk-pci", "event_idx", "off" }, - { "virtio-serial-pci", "event_idx", "off" }, - { "virtio-net-pci", "event_idx", "off" }, - { "virtio-balloon-pci", "event_idx", "off" }, - { "qxl", "revision", "2" }, - { "qxl-vga", "revision", "2" }, - }; - - pc_i440fx_0_15_machine_options(m); - m->hw_version = "0.14"; - compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat)); -} - -DEFINE_I440FX_MACHINE(v0_14, "pc-0.14", pc_compat_1_2, - pc_i440fx_0_14_machine_options); - -static void pc_i440fx_0_13_machine_options(MachineClass *m) -{ - PCMachineClass *pcmc = PC_MACHINE_CLASS(m); - static GlobalProperty compat[] = { - PC_CPU_MODEL_IDS("0.13") - { TYPE_PCI_DEVICE, "command_serr_enable", "off" }, - { "AC97", "use_broken_id", "1" }, - { "virtio-9p-pci", "vectors", "0" }, - { "VGA", "rombar", "0" }, - { "vmware-svga", "rombar", "0" }, - }; - - pc_i440fx_0_14_machine_options(m); - m->hw_version = "0.13"; - compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat)); - pcmc->kvmclock_enabled = false; -} - -DEFINE_I440FX_MACHINE(v0_13, "pc-0.13", pc_compat_0_13, - pc_i440fx_0_13_machine_options); - -static void pc_i440fx_0_12_machine_options(MachineClass *m) -{ - static GlobalProperty compat[] = { - PC_CPU_MODEL_IDS("0.12") - { "virtio-serial-pci", "max_ports", "1" }, - { "virtio-serial-pci", "vectors", "0" }, - { "usb-mouse", "serial", "1" }, - { "usb-tablet", "serial", "1" }, - { "usb-kbd", "serial", "1" }, - }; - - pc_i440fx_0_13_machine_options(m); - m->hw_version = "0.12"; - compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat)); -} - -DEFINE_I440FX_MACHINE(v0_12, "pc-0.12", pc_compat_0_13, - pc_i440fx_0_12_machine_options); - typedef struct { uint16_t gpu_device_id; uint16_t pch_device_id; diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 7398d7baa2..52f45735e4 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -276,7 +276,7 @@ static void pc_q35_init(MachineState *machine) 0xff0104); /* connect pm stuff to lpc */ - ich9_lpc_pm_init(lpc, pc_machine_is_smm_enabled(pcms)); + ich9_lpc_pm_init(lpc, x86_machine_is_smm_enabled(x86ms)); if (pcms->sata_enabled) { /* ahci and SATA device, for q35 1 ahci controller is built-in */ diff --git a/hw/i386/port92.c b/hw/i386/port92.c new file mode 100644 index 0000000000..19866c44ef --- /dev/null +++ b/hw/i386/port92.c @@ -0,0 +1,126 @@ +/* + * QEMU I/O port 0x92 (System Control Port A, to handle Fast Gate A20) + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * SPDX-License-Identifier: MIT + */ + +#include "qemu/osdep.h" +#include "sysemu/runstate.h" +#include "migration/vmstate.h" +#include "hw/irq.h" +#include "hw/i386/pc.h" +#include "trace.h" + +#define PORT92(obj) OBJECT_CHECK(Port92State, (obj), TYPE_PORT92) + +typedef struct Port92State { + ISADevice parent_obj; + + MemoryRegion io; + uint8_t outport; + qemu_irq a20_out; +} Port92State; + +static void port92_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + Port92State *s = opaque; + int oldval = s->outport; + + trace_port92_write(val); + s->outport = val; + qemu_set_irq(s->a20_out, (val >> 1) & 1); + if ((val & 1) && !(oldval & 1)) { + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + } +} + +static uint64_t port92_read(void *opaque, hwaddr addr, + unsigned size) +{ + Port92State *s = opaque; + uint32_t ret; + + ret = s->outport; + trace_port92_read(ret); + + return ret; +} + +static const VMStateDescription vmstate_port92_isa = { + .name = "port92", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(outport, Port92State), + VMSTATE_END_OF_LIST() + } +}; + +static void port92_reset(DeviceState *d) +{ + Port92State *s = PORT92(d); + + s->outport &= ~1; +} + +static const MemoryRegionOps port92_ops = { + .read = port92_read, + .write = port92_write, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void port92_initfn(Object *obj) +{ + Port92State *s = PORT92(obj); + + memory_region_init_io(&s->io, OBJECT(s), &port92_ops, s, "port92", 1); + + s->outport = 0; + + qdev_init_gpio_out_named(DEVICE(obj), &s->a20_out, PORT92_A20_LINE, 1); +} + +static void port92_realizefn(DeviceState *dev, Error **errp) +{ + ISADevice *isadev = ISA_DEVICE(dev); + Port92State *s = PORT92(dev); + + isa_register_ioport(isadev, &s->io, 0x92); +} + +static void port92_class_initfn(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = port92_realizefn; + dc->reset = port92_reset; + dc->vmsd = &vmstate_port92_isa; + /* + * Reason: unlike ordinary ISA devices, this one needs additional + * wiring: its A20 output line needs to be wired up with + * qdev_connect_gpio_out_named(). + */ + dc->user_creatable = false; +} + +static const TypeInfo port92_info = { + .name = TYPE_PORT92, + .parent = TYPE_ISA_DEVICE, + .instance_size = sizeof(Port92State), + .instance_init = port92_initfn, + .class_init = port92_class_initfn, +}; + +static void port92_register_types(void) +{ + type_register_static(&port92_info); +} + +type_init(port92_register_types) diff --git a/hw/i386/trace-events b/hw/i386/trace-events index c8bc464bc5..e48bef2b0d 100644 --- a/hw/i386/trace-events +++ b/hw/i386/trace-events @@ -111,3 +111,11 @@ amdvi_ir_irte_ga_val(uint64_t hi, uint64_t lo) "hi 0x%"PRIx64" lo 0x%"PRIx64 # vmport.c vmport_register(unsigned char command, void *func, void *opaque) "command: 0x%02x func: %p opaque: %p" vmport_command(unsigned char command) "command: 0x%02x" + +# x86.c +x86_gsi_interrupt(int irqn, int level) "GSI interrupt #%d level:%d" +x86_pic_interrupt(int irqn, int level) "PIC interrupt #%d level:%d" + +# port92.c +port92_read(uint8_t val) "port92: read 0x%02x" +port92_write(uint8_t val) "port92: write 0x%02x" diff --git a/hw/i386/x86-iommu-stub.c b/hw/i386/x86-iommu-stub.c new file mode 100644 index 0000000000..03576cdccb --- /dev/null +++ b/hw/i386/x86-iommu-stub.c @@ -0,0 +1,34 @@ +/* + * Stubs for X86 IOMMU emulation + * + * Copyright (C) 2019 Red Hat, Inc. + * + * Author: Paolo Bonzini <pbonzini@redhat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "hw/i386/x86-iommu.h" + +void x86_iommu_iec_register_notifier(X86IOMMUState *iommu, + iec_notify_fn fn, void *data) +{ +} + +X86IOMMUState *x86_iommu_get_default(void) +{ + return NULL; +} + diff --git a/hw/i386/x86.c b/hw/i386/x86.c index 394edc2f72..d8bb5c2a96 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -34,18 +34,23 @@ #include "sysemu/numa.h" #include "sysemu/replay.h" #include "sysemu/sysemu.h" +#include "trace.h" #include "hw/i386/x86.h" #include "target/i386/cpu.h" #include "hw/i386/topology.h" #include "hw/i386/fw_cfg.h" +#include "hw/intc/i8259.h" #include "hw/acpi/cpu_hotplug.h" +#include "hw/irq.h" #include "hw/nmi.h" #include "hw/loader.h" #include "multiboot.h" #include "elf.h" #include "standard-headers/asm-x86/bootparam.h" +#include "config-devices.h" +#include "kvm_i386.h" #define BIOS_FILENAME "bios.bin" @@ -220,6 +225,105 @@ static long get_file_size(FILE *f) return size; } +/* TSC handling */ +uint64_t cpu_get_tsc(CPUX86State *env) +{ + return cpu_get_ticks(); +} + +/* IRQ handling */ +static void pic_irq_request(void *opaque, int irq, int level) +{ + CPUState *cs = first_cpu; + X86CPU *cpu = X86_CPU(cs); + + trace_x86_pic_interrupt(irq, level); + if (cpu->apic_state && !kvm_irqchip_in_kernel()) { + CPU_FOREACH(cs) { + cpu = X86_CPU(cs); + if (apic_accept_pic_intr(cpu->apic_state)) { + apic_deliver_pic_intr(cpu->apic_state, level); + } + } + } else { + if (level) { + cpu_interrupt(cs, CPU_INTERRUPT_HARD); + } else { + cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); + } + } +} + +qemu_irq x86_allocate_cpu_irq(void) +{ + return qemu_allocate_irq(pic_irq_request, NULL, 0); +} + +int cpu_get_pic_interrupt(CPUX86State *env) +{ + X86CPU *cpu = env_archcpu(env); + int intno; + + if (!kvm_irqchip_in_kernel()) { + intno = apic_get_interrupt(cpu->apic_state); + if (intno >= 0) { + return intno; + } + /* read the irq from the PIC */ + if (!apic_accept_pic_intr(cpu->apic_state)) { + return -1; + } + } + + intno = pic_read_irq(isa_pic); + return intno; +} + +DeviceState *cpu_get_current_apic(void) +{ + if (current_cpu) { + X86CPU *cpu = X86_CPU(current_cpu); + return cpu->apic_state; + } else { + return NULL; + } +} + +void gsi_handler(void *opaque, int n, int level) +{ + GSIState *s = opaque; + + trace_x86_gsi_interrupt(n, level); + if (n < ISA_NUM_IRQS) { + /* Under KVM, Kernel will forward to both PIC and IOAPIC */ + qemu_set_irq(s->i8259_irq[n], level); + } + qemu_set_irq(s->ioapic_irq[n], level); +} + +void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name) +{ + DeviceState *dev; + SysBusDevice *d; + unsigned int i; + + assert(parent_name); + if (kvm_ioapic_in_kernel()) { + dev = qdev_create(NULL, TYPE_KVM_IOAPIC); + } else { + dev = qdev_create(NULL, TYPE_IOAPIC); + } + object_property_add_child(object_resolve_path(parent_name, NULL), + "ioapic", OBJECT(dev), NULL); + qdev_init_nofail(dev); + d = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(d, 0, IO_APIC_DEFAULT_ADDRESS); + + for (i = 0; i < IOAPIC_NUM_PINS; i++) { + gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i); + } +} + struct setup_data { uint64_t next; uint32_t type; @@ -745,10 +849,53 @@ static void x86_machine_set_max_ram_below_4g(Object *obj, Visitor *v, x86ms->max_ram_below_4g = value; } +bool x86_machine_is_smm_enabled(X86MachineState *x86ms) +{ + bool smm_available = false; + + if (x86ms->smm == ON_OFF_AUTO_OFF) { + return false; + } + + if (tcg_enabled() || qtest_enabled()) { + smm_available = true; + } else if (kvm_enabled()) { + smm_available = kvm_has_smm(); + } + + if (smm_available) { + return true; + } + + if (x86ms->smm == ON_OFF_AUTO_ON) { + error_report("System Management Mode not supported by this hypervisor."); + exit(1); + } + return false; +} + +static void x86_machine_get_smm(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + X86MachineState *x86ms = X86_MACHINE(obj); + OnOffAuto smm = x86ms->smm; + + visit_type_OnOffAuto(v, name, &smm, errp); +} + +static void x86_machine_set_smm(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + X86MachineState *x86ms = X86_MACHINE(obj); + + visit_type_OnOffAuto(v, name, &x86ms->smm, errp); +} + static void x86_machine_initfn(Object *obj) { X86MachineState *x86ms = X86_MACHINE(obj); + x86ms->smm = ON_OFF_AUTO_AUTO; x86ms->max_ram_below_4g = 0; /* use default */ x86ms->smp_dies = 1; } @@ -769,9 +916,14 @@ static void x86_machine_class_init(ObjectClass *oc, void *data) object_class_property_add(oc, X86_MACHINE_MAX_RAM_BELOW_4G, "size", x86_machine_get_max_ram_below_4g, x86_machine_set_max_ram_below_4g, NULL, NULL, &error_abort); - object_class_property_set_description(oc, X86_MACHINE_MAX_RAM_BELOW_4G, "Maximum ram below the 4G boundary (32bit boundary)", &error_abort); + + object_class_property_add(oc, X86_MACHINE_SMM, "OnOffAuto", + x86_machine_get_smm, x86_machine_set_smm, + NULL, NULL, &error_abort); + object_class_property_set_description(oc, X86_MACHINE_SMM, + "Enable SMM", &error_abort); } static const TypeInfo x86_machine_info = { diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c index f0acfd86f7..2f09f780ba 100644 --- a/hw/input/pckbd.c +++ b/hw/input/pckbd.c @@ -26,7 +26,6 @@ #include "qemu/log.h" #include "hw/isa/isa.h" #include "migration/vmstate.h" -#include "hw/i386/pc.h" #include "hw/input/ps2.h" #include "hw/irq.h" #include "hw/input/i8042.h" diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig index 5347f8412c..10a680b53a 100644 --- a/hw/intc/Kconfig +++ b/hw/intc/Kconfig @@ -9,6 +9,7 @@ config PL190 config IOAPIC bool + select I8259 config ARM_GIC bool @@ -21,6 +22,7 @@ config OPENPIC config APIC bool select MSI_NONBROKEN + select I8259 config ARM_GIC_KVM bool diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 2a74f7b4bf..bd40467965 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -22,10 +22,10 @@ #include "hw/i386/apic_internal.h" #include "hw/i386/apic.h" #include "hw/i386/ioapic.h" +#include "hw/intc/i8259.h" #include "hw/pci/msi.h" #include "qemu/host-utils.h" #include "trace.h" -#include "hw/i386/pc.h" #include "hw/i386/apic-msidef.h" #include "qapi/error.h" diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c index 211a98962e..51b27f6a34 100644 --- a/hw/intc/i8259.c +++ b/hw/intc/i8259.c @@ -23,7 +23,7 @@ */ #include "qemu/osdep.h" -#include "hw/i386/pc.h" +#include "hw/intc/i8259.h" #include "hw/irq.h" #include "hw/isa/isa.h" #include "qemu/timer.h" diff --git a/hw/intc/i8259_common.c b/hw/intc/i8259_common.c index bd37bb5e68..e7b1a10436 100644 --- a/hw/intc/i8259_common.c +++ b/hw/intc/i8259_common.c @@ -24,7 +24,7 @@ */ #include "qemu/osdep.h" -#include "hw/i386/pc.h" +#include "hw/intc/i8259.h" #include "hw/isa/i8259_internal.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c index ead14e1888..4f5577678a 100644 --- a/hw/intc/ioapic.c +++ b/hw/intc/ioapic.c @@ -23,10 +23,11 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "monitor/monitor.h" -#include "hw/i386/pc.h" #include "hw/i386/apic.h" #include "hw/i386/ioapic.h" #include "hw/i386/ioapic_internal.h" +#include "hw/i386/x86.h" +#include "hw/intc/i8259.h" #include "hw/pci/msi.h" #include "hw/qdev-properties.h" #include "sysemu/kvm.h" diff --git a/hw/isa/i82378.c b/hw/isa/i82378.c index de276cdf10..dcb6b479ea 100644 --- a/hw/isa/i82378.c +++ b/hw/isa/i82378.c @@ -19,8 +19,8 @@ #include "qemu/osdep.h" #include "hw/pci/pci.h" -#include "hw/i386/pc.h" #include "hw/irq.h" +#include "hw/intc/i8259.h" #include "hw/timer/i8254.h" #include "migration/vmstate.h" #include "hw/audio/pcspk.h" diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c index 388800603b..798dd9194e 100644 --- a/hw/isa/isa-bus.c +++ b/hw/isa/isa-bus.c @@ -82,24 +82,27 @@ void isa_bus_irqs(ISABus *bus, qemu_irq *irqs) * This function is only for special cases such as the 'ferr', and * temporary use for normal devices until they are converted to qdev. */ -qemu_irq isa_get_irq(ISADevice *dev, int isairq) +qemu_irq isa_get_irq(ISADevice *dev, unsigned isairq) { assert(!dev || ISA_BUS(qdev_get_parent_bus(DEVICE(dev))) == isabus); - if (isairq < 0 || isairq > 15) { + if (isairq >= ISA_NUM_IRQS) { hw_error("isa irq %d invalid", isairq); } return isabus->irqs[isairq]; } -void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq) +void isa_init_irq(ISADevice *dev, qemu_irq *p, unsigned isairq) { assert(dev->nirqs < ARRAY_SIZE(dev->isairq)); + if (isairq >= ISA_NUM_IRQS) { + hw_error("isa irq %d invalid", isairq); + } dev->isairq[dev->nirqs] = isairq; *p = isa_get_irq(dev, isairq); dev->nirqs++; } -void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, int isairq) +void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, unsigned isairq) { qemu_irq irq; isa_init_irq(isadev, &irq, isairq); diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 17c292e306..170792a4fc 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -35,7 +35,6 @@ #include "hw/isa/isa.h" #include "hw/sysbus.h" #include "migration/vmstate.h" -#include "hw/i386/pc.h" #include "hw/irq.h" #include "hw/isa/apm.h" #include "hw/i386/ioapic.h" diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 86678e6829..7edec5e149 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -26,11 +26,11 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/irq.h" -#include "hw/i386/pc.h" #include "hw/southbridge/piix.h" #include "hw/pci/pci.h" #include "hw/isa/isa.h" #include "hw/sysbus.h" +#include "hw/intc/i8259.h" #include "hw/dma/i8257.h" #include "hw/timer/i8254.h" #include "hw/rtc/mc146818rtc.h" diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c index f1af840d8e..b2ea13f09d 100644 --- a/hw/mips/gt64xxx_pci.c +++ b/hw/mips/gt64xxx_pci.c @@ -30,7 +30,7 @@ #include "hw/pci/pci_host.h" #include "hw/southbridge/piix.h" #include "migration/vmstate.h" -#include "hw/i386/pc.h" +#include "hw/intc/i8259.h" #include "hw/irq.h" #include "exec/address-spaces.h" #include "trace.h" diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index 03a27e1767..9eaa6e2222 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -23,7 +23,7 @@ #include "qemu/units.h" #include "qapi/error.h" #include "cpu.h" -#include "hw/i386/pc.h" +#include "hw/intc/i8259.h" #include "hw/dma/i8257.h" #include "hw/isa/superio.h" #include "net/net.h" diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c index ac4d7acb2b..291fd6c1b8 100644 --- a/hw/mips/mips_jazz.c +++ b/hw/mips/mips_jazz.c @@ -26,7 +26,7 @@ #include "qemu-common.h" #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" -#include "hw/i386/pc.h" +#include "hw/intc/i8259.h" #include "hw/dma/i8257.h" #include "hw/char/serial.h" #include "hw/char/parallel.h" diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c index 3891be657c..fd926a3575 100644 --- a/hw/mips/mips_r4k.c +++ b/hw/mips/mips_r4k.c @@ -15,7 +15,7 @@ #include "cpu.h" #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" -#include "hw/i386/pc.h" +#include "hw/intc/i8259.h" #include "hw/char/serial.h" #include "hw/isa/isa.h" #include "net/net.h" diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig index b0aa8351c4..9642c77e98 100644 --- a/hw/pci-host/Kconfig +++ b/hw/pci-host/Kconfig @@ -1,6 +1,11 @@ config PAM bool +config XEN_IGD_PASSTHROUGH + bool + default y + depends on XEN && PCI_I440FX + config PREP_PCI bool select PCI diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs index efd752b766..9c466fab01 100644 --- a/hw/pci-host/Makefile.objs +++ b/hw/pci-host/Makefile.objs @@ -14,6 +14,7 @@ common-obj-$(CONFIG_VERSATILE_PCI) += versatile.o common-obj-$(CONFIG_PCI_SABRE) += sabre.o common-obj-$(CONFIG_FULONG) += bonito.o common-obj-$(CONFIG_PCI_I440FX) += i440fx.o +common-obj-$(CONFIG_XEN_IGD_PASSTHROUGH) += xen_igd_pt.o common-obj-$(CONFIG_PCI_EXPRESS_Q35) += q35.o common-obj-$(CONFIG_PCI_EXPRESS_GENERIC_BRIDGE) += gpex.o common-obj-$(CONFIG_PCI_EXPRESS_XILINX) += xilinx-pcie.o diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c index 4692d419e5..cc6545c8a8 100644 --- a/hw/pci-host/bonito.c +++ b/hw/pci-host/bonito.c @@ -41,7 +41,6 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" #include "hw/pci/pci.h" -#include "hw/i386/pc.h" #include "hw/irq.h" #include "hw/mips/mips.h" #include "hw/pci/pci_host.h" diff --git a/hw/pci-host/i440fx.c b/hw/pci-host/i440fx.c index f27131102d..bae7b42327 100644 --- a/hw/pci-host/i440fx.c +++ b/hw/pci-host/i440fx.c @@ -1,5 +1,5 @@ /* - * QEMU i440FX/PIIX3 PCI Bridge Emulation + * QEMU i440FX PCI Bridge Emulation * * Copyright (c) 2006 Fabrice Bellard * @@ -31,7 +31,6 @@ #include "hw/sysbus.h" #include "qapi/error.h" #include "migration/vmstate.h" -#include "hw/pci-host/pam.h" #include "qapi/visitor.h" #include "qemu/error-report.h" @@ -51,23 +50,6 @@ typedef struct I440FXState { uint32_t short_root_bus; } I440FXState; -#define I440FX_PCI_DEVICE(obj) \ - OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE) - -struct PCII440FXState { - /*< private >*/ - PCIDevice parent_obj; - /*< public >*/ - - MemoryRegion *system_memory; - MemoryRegion *pci_address_space; - MemoryRegion *ram_memory; - PAMMemoryRegion pam_regions[13]; - MemoryRegion smram_region; - MemoryRegion smram, low_smram; -}; - - #define I440FX_PAM 0x59 #define I440FX_PAM_SIZE 7 #define I440FX_SMRAM 0x72 @@ -386,90 +368,6 @@ static const TypeInfo i440fx_info = { }, }; -/* IGD Passthrough Host Bridge. */ -typedef struct { - uint8_t offset; - uint8_t len; -} IGDHostInfo; - -/* Here we just expose minimal host bridge offset subset. */ -static const IGDHostInfo igd_host_bridge_infos[] = { - {0x08, 2}, /* revision id */ - {0x2c, 2}, /* sybsystem vendor id */ - {0x2e, 2}, /* sybsystem id */ - {0x50, 2}, /* SNB: processor graphics control register */ - {0x52, 2}, /* processor graphics control register */ - {0xa4, 4}, /* SNB: graphics base of stolen memory */ - {0xa8, 4}, /* SNB: base of GTT stolen memory */ -}; - -static void host_pci_config_read(int pos, int len, uint32_t *val, Error **errp) -{ - int rc, config_fd; - /* Access real host bridge. */ - char *path = g_strdup_printf("/sys/bus/pci/devices/%04x:%02x:%02x.%d/%s", - 0, 0, 0, 0, "config"); - - config_fd = open(path, O_RDWR); - if (config_fd < 0) { - error_setg_errno(errp, errno, "Failed to open: %s", path); - goto out; - } - - if (lseek(config_fd, pos, SEEK_SET) != pos) { - error_setg_errno(errp, errno, "Failed to seek: %s", path); - goto out_close_fd; - } - - do { - rc = read(config_fd, (uint8_t *)val, len); - } while (rc < 0 && (errno == EINTR || errno == EAGAIN)); - if (rc != len) { - error_setg_errno(errp, errno, "Failed to read: %s", path); - } - -out_close_fd: - close(config_fd); -out: - g_free(path); -} - -static void igd_pt_i440fx_realize(PCIDevice *pci_dev, Error **errp) -{ - uint32_t val = 0; - int i, num; - int pos, len; - Error *local_err = NULL; - - num = ARRAY_SIZE(igd_host_bridge_infos); - for (i = 0; i < num; i++) { - pos = igd_host_bridge_infos[i].offset; - len = igd_host_bridge_infos[i].len; - host_pci_config_read(pos, len, &val, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - pci_default_write_config(pci_dev, pos, val, len); - } -} - -static void igd_passthrough_i440fx_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = igd_pt_i440fx_realize; - dc->desc = "IGD Passthrough Host bridge"; -} - -static const TypeInfo igd_passthrough_i440fx_info = { - .name = TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE, - .parent = TYPE_I440FX_PCI_DEVICE, - .instance_size = sizeof(PCII440FXState), - .class_init = igd_passthrough_i440fx_class_init, -}; - static const char *i440fx_pcihost_root_bus_path(PCIHostState *host_bridge, PCIBus *rootbus) { @@ -514,7 +412,6 @@ static const TypeInfo i440fx_pcihost_info = { static void i440fx_register_types(void) { type_register_static(&i440fx_info); - type_register_static(&igd_passthrough_i440fx_info); type_register_static(&i440fx_pcihost_info); } diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c index 85d7ba9037..afa136ded3 100644 --- a/hw/pci-host/prep.c +++ b/hw/pci-host/prep.c @@ -32,7 +32,7 @@ #include "hw/pci/pci_host.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" -#include "hw/i386/pc.h" +#include "hw/intc/i8259.h" #include "hw/irq.h" #include "hw/loader.h" #include "hw/or-irq.h" diff --git a/hw/pci-host/xen_igd_pt.c b/hw/pci-host/xen_igd_pt.c new file mode 100644 index 0000000000..efcc9347ff --- /dev/null +++ b/hw/pci-host/xen_igd_pt.c @@ -0,0 +1,120 @@ +/* + * QEMU Intel IGD Passthrough Host Bridge Emulation + * + * Copyright (c) 2006 Fabrice Bellard + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_host.h" +#include "hw/pci-host/i440fx.h" +#include "qapi/error.h" + +typedef struct { + uint8_t offset; + uint8_t len; +} IGDHostInfo; + +/* Here we just expose minimal host bridge offset subset. */ +static const IGDHostInfo igd_host_bridge_infos[] = { + {PCI_REVISION_ID, 2}, + {PCI_SUBSYSTEM_VENDOR_ID, 2}, + {PCI_SUBSYSTEM_ID, 2}, + {0x50, 2}, /* SNB: processor graphics control register */ + {0x52, 2}, /* processor graphics control register */ + {0xa4, 4}, /* SNB: graphics base of stolen memory */ + {0xa8, 4}, /* SNB: base of GTT stolen memory */ +}; + +static void host_pci_config_read(int pos, int len, uint32_t *val, Error **errp) +{ + int rc, config_fd; + /* Access real host bridge. */ + char *path = g_strdup_printf("/sys/bus/pci/devices/%04x:%02x:%02x.%d/%s", + 0, 0, 0, 0, "config"); + + config_fd = open(path, O_RDWR); + if (config_fd < 0) { + error_setg_errno(errp, errno, "Failed to open: %s", path); + goto out; + } + + if (lseek(config_fd, pos, SEEK_SET) != pos) { + error_setg_errno(errp, errno, "Failed to seek: %s", path); + goto out_close_fd; + } + + do { + rc = read(config_fd, (uint8_t *)val, len); + } while (rc < 0 && (errno == EINTR || errno == EAGAIN)); + if (rc != len) { + error_setg_errno(errp, errno, "Failed to read: %s", path); + } + + out_close_fd: + close(config_fd); + out: + g_free(path); +} + +static void igd_pt_i440fx_realize(PCIDevice *pci_dev, Error **errp) +{ + uint32_t val = 0; + size_t i; + int pos, len; + Error *local_err = NULL; + + for (i = 0; i < ARRAY_SIZE(igd_host_bridge_infos); i++) { + pos = igd_host_bridge_infos[i].offset; + len = igd_host_bridge_infos[i].len; + host_pci_config_read(pos, len, &val, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + pci_default_write_config(pci_dev, pos, val, len); + } +} + +static void igd_passthrough_i440fx_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->realize = igd_pt_i440fx_realize; + dc->desc = "IGD Passthrough Host bridge"; +} + +static const TypeInfo igd_passthrough_i440fx_info = { + .name = TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE, + .parent = TYPE_I440FX_PCI_DEVICE, + .instance_size = sizeof(PCII440FXState), + .class_init = igd_passthrough_i440fx_class_init, +}; + +static void igd_pt_i440fx_register_types(void) +{ + type_register_static(&igd_passthrough_i440fx_info); +} + +type_init(igd_pt_i440fx_register_types) diff --git a/hw/pci/pci-stub.c b/hw/pci/pci-stub.c index c04a5df651..cc2a2e1f73 100644 --- a/hw/pci/pci-stub.c +++ b/hw/pci/pci-stub.c @@ -26,6 +26,7 @@ #include "qapi/qmp/qerror.h" #include "hw/pci/pci.h" #include "hw/pci/msi.h" +#include "hw/pci/msix.h" bool msi_nonbroken; bool pci_available; @@ -64,3 +65,29 @@ void msi_notify(PCIDevice *dev, unsigned int vector) { g_assert_not_reached(); } + +/* Required by target/i386/kvm.c */ +bool msi_is_masked(const PCIDevice *dev, unsigned vector) +{ + g_assert_not_reached(); +} + +MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector) +{ + g_assert_not_reached(); +} + +int msix_enabled(PCIDevice *dev) +{ + return false; +} + +bool msix_is_masked(PCIDevice *dev, unsigned vector) +{ + g_assert_not_reached(); +} + +MSIMessage msix_get_message(PCIDevice *dev, unsigned int vector) +{ + g_assert_not_reached(); +} diff --git a/hw/pci/pci.c b/hw/pci/pci.c index cbc7a32568..e3d310365d 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -69,8 +69,6 @@ static Property pci_props[] = { DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1), DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present, QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false), - DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present, - QEMU_PCI_CAP_SERR_BITNR, true), DEFINE_PROP_BIT("x-pcie-lnksta-dllla", PCIDevice, cap_present, QEMU_PCIE_LNKSTA_DLLLA_BITNR, true), DEFINE_PROP_BIT("x-pcie-extcap-init", PCIDevice, cap_present, @@ -751,9 +749,7 @@ static void pci_init_wmask(PCIDevice *dev) pci_set_word(dev->wmask + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INTX_DISABLE); - if (dev->cap_present & QEMU_PCI_CAP_SERR) { - pci_word_test_and_set_mask(dev->wmask + PCI_COMMAND, PCI_COMMAND_SERR); - } + pci_word_test_and_set_mask(dev->wmask + PCI_COMMAND, PCI_COMMAND_SERR); memset(dev->wmask + PCI_CONFIG_HEADER_SIZE, 0xff, config_size - PCI_CONFIG_HEADER_SIZE); diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 91cd4c26f9..12b6a5b2a8 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -793,7 +793,6 @@ static DeviceState *ppce500_init_mpic(PPCE500MachineState *pms, MemoryRegion *ccsr, IrqLines *irqs) { - MachineState *machine = MACHINE(pms); const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms); DeviceState *dev = NULL; SysBusDevice *s; @@ -801,10 +800,10 @@ static DeviceState *ppce500_init_mpic(PPCE500MachineState *pms, if (kvm_enabled()) { Error *err = NULL; - if (machine_kernel_irqchip_allowed(machine)) { + if (kvm_kernel_irqchip_allowed()) { dev = ppce500_init_mpic_kvm(pmc, irqs, &err); } - if (machine_kernel_irqchip_required(machine) && !dev) { + if (kvm_kernel_irqchip_required() && !dev) { error_reportf_err(err, "kernel_irqchip requested but unavailable: "); exit(1); diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c index 07e08d6544..373505d28b 100644 --- a/hw/ppc/spapr_irq.c +++ b/hw/ppc/spapr_irq.c @@ -75,12 +75,11 @@ int spapr_irq_init_kvm(SpaprInterruptControllerInitKvm fn, uint32_t nr_servers, Error **errp) { - MachineState *machine = MACHINE(qdev_get_machine()); Error *local_err = NULL; - if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) { + if (kvm_enabled() && kvm_kernel_irqchip_allowed()) { if (fn(intc, nr_servers, &local_err) < 0) { - if (machine_kernel_irqchip_required(machine)) { + if (kvm_kernel_irqchip_required()) { error_prepend(&local_err, "kernel_irqchip requested but unavailable: "); error_propagate(errp, local_err); @@ -185,7 +184,7 @@ static int spapr_irq_check(SpaprMachineState *spapr, Error **errp) */ if (kvm_enabled() && spapr->irq == &spapr_irq_dual && - machine_kernel_irqchip_required(machine) && + kvm_kernel_irqchip_required() && xics_kvm_has_broken_disconnect(spapr)) { error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on"); return -1; @@ -288,20 +287,13 @@ uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr) void spapr_irq_init(SpaprMachineState *spapr, Error **errp) { - MachineState *machine = MACHINE(spapr); SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); - if (machine_kernel_irqchip_split(machine)) { + if (kvm_enabled() && kvm_kernel_irqchip_split()) { error_setg(errp, "kernel_irqchip split mode not supported on pseries"); return; } - if (!kvm_enabled() && machine_kernel_irqchip_required(machine)) { - error_setg(errp, - "kernel_irqchip requested but only available with KVM"); - return; - } - if (spapr_irq_check(spapr, errp) < 0) { return; } diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig index 3724ff8bac..f87def27a6 100644 --- a/hw/virtio/Kconfig +++ b/hw/virtio/Kconfig @@ -1,3 +1,6 @@ +config VHOST + bool + config VIRTIO bool diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs index e2f70fbb89..de0f5fc39b 100644 --- a/hw/virtio/Makefile.objs +++ b/hw/virtio/Makefile.objs @@ -2,8 +2,8 @@ ifeq ($(CONFIG_VIRTIO),y) common-obj-y += virtio-bus.o obj-y += virtio.o -obj-$(call lor,$(CONFIG_VHOST_USER),$(CONFIG_VHOST_KERNEL)) += vhost.o vhost-backend.o -common-obj-$(call lnot,$(call lor,$(CONFIG_VHOST_USER),$(CONFIG_VHOST_KERNEL))) += vhost-stub.o +obj-$(CONFIG_VHOST) += vhost.o vhost-backend.o +common-obj-$(call lnot,$(CONFIG_VHOST)) += vhost-stub.o obj-$(CONFIG_VHOST_USER) += vhost-user.o common-obj-$(CONFIG_VIRTIO_RNG) += virtio-rng.o diff --git a/hw/xen/xen-common.c b/hw/xen/xen-common.c index 5284b0dec1..15650d7f6a 100644 --- a/hw/xen/xen-common.c +++ b/hw/xen/xen-common.c @@ -11,7 +11,9 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" #include "qemu/module.h" +#include "qapi/error.h" #include "hw/xen/xen-legacy-backend.h" +#include "hw/xen/xen_pt.h" #include "chardev/char.h" #include "sysemu/accel.h" #include "sysemu/runstate.h" @@ -124,6 +126,16 @@ static void xen_change_state_handler(void *opaque, int running, } } +static bool xen_get_igd_gfx_passthru(Object *obj, Error **errp) +{ + return has_igd_gfx_passthru; +} + +static void xen_set_igd_gfx_passthru(Object *obj, bool value, Error **errp) +{ + has_igd_gfx_passthru = value; +} + static void xen_setup_post(MachineState *ms, AccelState *accel) { int rc; @@ -177,6 +189,12 @@ static void xen_accel_class_init(ObjectClass *oc, void *data) ac->compat_props = g_ptr_array_new(); compat_props_add(ac->compat_props, compat, G_N_ELEMENTS(compat)); + + object_class_property_add_bool(oc, "igd-passthru", + xen_get_igd_gfx_passthru, xen_set_igd_gfx_passthru, + &error_abort); + object_class_property_set_description(oc, "igd-passthru", + "Set on/off to enable/disable igd passthrou", &error_abort); } #define TYPE_XEN_ACCEL ACCEL_CLASS_NAME("xen") diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c index 8fbaf2eae9..9e767d4244 100644 --- a/hw/xen/xen_pt.c +++ b/hw/xen/xen_pt.c @@ -65,6 +65,8 @@ #include "qemu/range.h" #include "exec/address-spaces.h" +bool has_igd_gfx_passthru; + #define XEN_PT_NR_IRQS (256) static uint8_t xen_pt_mapped_machine_irq[XEN_PT_NR_IRQS] = {0}; |