diff --git a/MAINTAINERS b/MAINTAINERS index 716d5a24ad..a2773108f2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1659,8 +1659,8 @@ F: hw/isa/piix3.c F: hw/isa/lpc_ich9.c F: hw/i2c/smbus_ich9.c F: hw/acpi/piix4.c -F: hw/acpi/ich9.c -F: include/hw/acpi/ich9.h +F: hw/acpi/ich9*.c +F: include/hw/acpi/ich9*.h F: include/hw/southbridge/piix.h F: hw/misc/sga.c F: hw/isa/apm.c diff --git a/contrib/vhost-user-blk/vhost-user-blk.c b/contrib/vhost-user-blk/vhost-user-blk.c index aa99877fcd..7941694e53 100644 --- a/contrib/vhost-user-blk/vhost-user-blk.c +++ b/contrib/vhost-user-blk/vhost-user-blk.c @@ -532,9 +532,9 @@ vub_get_blocksize(int fd) static void vub_initialize_config(int fd, struct virtio_blk_config *config) { - off64_t capacity; + off_t capacity; - capacity = lseek64(fd, 0, SEEK_END); + capacity = lseek(fd, 0, SEEK_END); config->capacity = capacity >> 9; config->blk_size = vub_get_blocksize(fd); config->size_max = 65536; diff --git a/docs/devel/acpi-bits.rst b/docs/devel/acpi-bits.rst index 4a94c7d83d..9eb4b9e666 100644 --- a/docs/devel/acpi-bits.rst +++ b/docs/devel/acpi-bits.rst @@ -52,6 +52,9 @@ Under ``tests/avocado/`` as the root we have: for their tests. In order to enable debugging, you can set **V=1** environment variable. This enables verbose mode for the test and also dumps the entire log from bios bits and more information in case failure happens. + You can also set **BITS_DEBUG=1** to turn on debug mode. It will enable + verbose logs and also retain the temporary work directory the test used for + you to inspect and run the specific commands manually. In order to run this test, please perform the following steps from the QEMU build directory: diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index bd9bbade70..a93c470e9d 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -34,7 +34,7 @@ #include "sysemu/reset.h" #include "sysemu/runstate.h" #include "hw/acpi/acpi.h" -#include "hw/acpi/tco.h" +#include "hw/acpi/ich9_tco.h" #include "hw/i386/ich9.h" #include "hw/mem/pc-dimm.h" @@ -316,8 +316,9 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, pm->smm_enabled = smm_enabled; - pm->enable_tco = true; - acpi_pm_tco_init(&pm->tco_regs, &pm->io); + if (pm->enable_tco) { + acpi_pm_tco_init(&pm->tco_regs, &pm->io); + } if (pm->use_acpi_hotplug_bridge) { acpi_pcihp_init(OBJECT(lpc_pci), @@ -440,6 +441,7 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm) pm->s4_val = 2; pm->use_acpi_hotplug_bridge = true; pm->keep_pci_slot_hpc = true; + pm->enable_tco = true; object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE, &pm->pm_io_base, OBJ_PROP_FLAG_READ); diff --git a/hw/acpi/tco.c b/hw/acpi/ich9_tco.c similarity index 91% rename from hw/acpi/tco.c rename to hw/acpi/ich9_tco.c index 4783721e4e..fbf97f81f4 100644 --- a/hw/acpi/tco.c +++ b/hw/acpi/ich9_tco.c @@ -12,7 +12,7 @@ #include "hw/i386/ich9.h" #include "migration/vmstate.h" -#include "hw/acpi/tco.h" +#include "hw/acpi/ich9_tco.h" #include "trace.h" enum { @@ -86,6 +86,7 @@ static inline int can_start_tco_timer(TCOIORegs *tr) static uint32_t tco_ioport_readw(TCOIORegs *tr, uint32_t addr) { uint16_t rld; + uint32_t ret = 0; switch (addr) { case TCO_RLD: @@ -96,35 +97,49 @@ static uint32_t tco_ioport_readw(TCOIORegs *tr, uint32_t addr) } else { rld = tr->tco.rld; } - return rld; + ret = rld; + break; case TCO_DAT_IN: - return tr->tco.din; + ret = tr->tco.din; + break; case TCO_DAT_OUT: - return tr->tco.dout; + ret = tr->tco.dout; + break; case TCO1_STS: - return tr->tco.sts1; + ret = tr->tco.sts1; + break; case TCO2_STS: - return tr->tco.sts2; + ret = tr->tco.sts2; + break; case TCO1_CNT: - return tr->tco.cnt1; + ret = tr->tco.cnt1; + break; case TCO2_CNT: - return tr->tco.cnt2; + ret = tr->tco.cnt2; + break; case TCO_MESSAGE1: - return tr->tco.msg1; + ret = tr->tco.msg1; + break; case TCO_MESSAGE2: - return tr->tco.msg2; + ret = tr->tco.msg2; + break; case TCO_WDCNT: - return tr->tco.wdcnt; + ret = tr->tco.wdcnt; + break; case TCO_TMR: - return tr->tco.tmr; + ret = tr->tco.tmr; + break; case SW_IRQ_GEN: - return tr->sw_irq_gen; + ret = tr->sw_irq_gen; + break; } - return 0; + trace_tco_io_read(addr, ret); + return ret; } static void tco_ioport_writew(TCOIORegs *tr, uint32_t addr, uint32_t val) { + trace_tco_io_write(addr, val); switch (addr) { case TCO_RLD: tr->timeouts_no = 0; diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build index f8c820ca94..2ed29ae94c 100644 --- a/hw/acpi/meson.build +++ b/hw/acpi/meson.build @@ -22,7 +22,7 @@ acpi_ss.add(when: 'CONFIG_ACPI_PIIX4', if_true: files('piix4.c')) acpi_ss.add(when: 'CONFIG_ACPI_PCIHP', if_true: files('pcihp.c')) acpi_ss.add(when: 'CONFIG_ACPI_PCIHP', if_false: files('acpi-pci-hotplug-stub.c')) acpi_ss.add(when: 'CONFIG_ACPI_VIOT', if_true: files('viot.c')) -acpi_ss.add(when: 'CONFIG_ACPI_X86_ICH', if_true: files('ich9.c', 'tco.c')) +acpi_ss.add(when: 'CONFIG_ACPI_X86_ICH', if_true: files('ich9.c', 'ich9_tco.c')) acpi_ss.add(when: 'CONFIG_ACPI_ERST', if_true: files('erst.c')) acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c'), if_false: files('ipmi-stub.c')) acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c')) diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c index 84d75e6b84..99a898d9ae 100644 --- a/hw/acpi/pcihp.c +++ b/hw/acpi/pcihp.c @@ -186,7 +186,6 @@ static PCIBus *acpi_pcihp_find_hotplug_bus(AcpiPciHpState *s, int bsel) static bool acpi_pcihp_pc_no_hotplug(AcpiPciHpState *s, PCIDevice *dev) { - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); DeviceClass *dc = DEVICE_GET_CLASS(dev); /* * ACPI doesn't allow hotplug of bridge devices. Don't allow @@ -196,7 +195,7 @@ static bool acpi_pcihp_pc_no_hotplug(AcpiPciHpState *s, PCIDevice *dev) * Don't allow hot-unplug of SR-IOV Virtual Functions, as they * will be removed implicitly, when Physical Function is unplugged. */ - return (pc->is_bridge && !dev->qdev.hotplugged) || !dc->hotpluggable || + return (IS_PCI_BRIDGE(dev) && !dev->qdev.hotplugged) || !dc->hotpluggable || pci_is_vf(dev); } diff --git a/hw/acpi/trace-events b/hw/acpi/trace-events index eb60b04f9b..78e0a8670e 100644 --- a/hw/acpi/trace-events +++ b/hw/acpi/trace-events @@ -55,6 +55,8 @@ piix4_gpe_writeb(uint64_t addr, unsigned width, uint64_t val) "addr: 0x%" PRIx64 # tco.c tco_timer_reload(int ticks, int msec) "ticks=%d (%d ms)" tco_timer_expired(int timeouts_no, bool strap, bool no_reboot) "timeouts_no=%d no_reboot=%d/%d" +tco_io_write(uint64_t addr, uint32_t val) "addr=0x%" PRIx64 " val=0x%" PRIx32 +tco_io_read(uint64_t addr, uint32_t val) "addr=0x%" PRIx64 " val=0x%" PRIx32 # erst.c acpi_erst_reg_write(uint64_t addr, uint64_t val, unsigned size) "addr: 0x%04" PRIx64 " <== 0x%016" PRIx64 " (size: %u)" diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 04eb6c201d..ea2413a0ba 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -3218,10 +3218,17 @@ static void machvirt_machine_init(void) } type_init(machvirt_machine_init); -static void virt_machine_7_2_options(MachineClass *mc) +static void virt_machine_8_0_options(MachineClass *mc) { } -DEFINE_VIRT_MACHINE_AS_LATEST(7, 2) +DEFINE_VIRT_MACHINE_AS_LATEST(8, 0) + +static void virt_machine_7_2_options(MachineClass *mc) +{ + virt_machine_8_0_options(mc); + compat_props_add(mc->compat_props, hw_compat_7_2, hw_compat_7_2_len); +} +DEFINE_VIRT_MACHINE(7, 2) static void virt_machine_7_1_options(MachineClass *mc) { diff --git a/hw/core/machine.c b/hw/core/machine.c index 644b34cd24..f589b92909 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -40,6 +40,9 @@ #include "hw/virtio/virtio-pci.h" #include "qom/object_interfaces.h" +GlobalProperty hw_compat_7_2[] = {}; +const size_t hw_compat_7_2_len = G_N_ELEMENTS(hw_compat_7_2); + GlobalProperty hw_compat_7_1[] = { { "virtio-device", "queue_reset", "false" }, }; diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index d9eaa5fc4d..aa15b11cde 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -403,7 +403,6 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) { DeviceClass *dc; - PCIDeviceClass *pc; PCIDevice *pdev = bus->devices[devfn]; int slot = PCI_SLOT(devfn); int func = PCI_FUNC(devfn); @@ -414,14 +413,14 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, bool cold_plugged_bridge = false; if (pdev) { - pc = PCI_DEVICE_GET_CLASS(pdev); dc = DEVICE_GET_CLASS(pdev); /* * Cold plugged bridges aren't themselves hot-pluggable. * Hotplugged bridges *are* hot-pluggable. */ - cold_plugged_bridge = pc->is_bridge && !DEVICE(pdev)->hotplugged; + cold_plugged_bridge = IS_PCI_BRIDGE(pdev) && + !DEVICE(pdev)->hotplugged; bridge_in_acpi = cold_plugged_bridge && pcihp_bridge_en; hotpluggbale_slot = bsel && dc->hotpluggable && diff --git a/hw/i386/pc.c b/hw/i386/pc.c index fa69b6f43e..d489ecc0d1 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -107,6 +107,11 @@ { "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\ { "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, }, +GlobalProperty pc_compat_7_2[] = { + { "ICH9-LPC", "noreboot", "true" }, +}; +const size_t pc_compat_7_2_len = G_N_ELEMENTS(pc_compat_7_2); + GlobalProperty pc_compat_7_1[] = {}; const size_t pc_compat_7_1_len = G_N_ELEMENTS(pc_compat_7_1); diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 0ad0ed1603..b48047f50c 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -426,6 +426,7 @@ static void pc_i440fx_machine_options(MachineClass *m) PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pcmc->default_nic_model = "e1000"; pcmc->pci_root_uid = 0; + pcmc->default_cpu_version = 1; m->family = "pc_piix"; m->desc = "Standard PC (i440FX + PIIX, 1996)"; @@ -435,13 +436,23 @@ static void pc_i440fx_machine_options(MachineClass *m) machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); } -static void pc_i440fx_7_2_machine_options(MachineClass *m) +static void pc_i440fx_8_0_machine_options(MachineClass *m) { - PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_i440fx_machine_options(m); m->alias = "pc"; m->is_default = true; - pcmc->default_cpu_version = 1; +} + +DEFINE_I440FX_MACHINE(v8_0, "pc-i440fx-8.0", NULL, + pc_i440fx_8_0_machine_options); + +static void pc_i440fx_7_2_machine_options(MachineClass *m) +{ + pc_i440fx_8_0_machine_options(m); + m->alias = NULL; + m->is_default = false; + compat_props_add(m->compat_props, hw_compat_7_2, hw_compat_7_2_len); + compat_props_add(m->compat_props, pc_compat_7_2, pc_compat_7_2_len); } DEFINE_I440FX_MACHINE(v7_2, "pc-i440fx-7.2", NULL, @@ -451,8 +462,6 @@ static void pc_i440fx_7_1_machine_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_i440fx_7_2_machine_options(m); - m->alias = NULL; - m->is_default = false; pcmc->legacy_no_rng_seed = true; compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len); compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len); @@ -465,8 +474,6 @@ static void pc_i440fx_7_0_machine_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_i440fx_7_1_machine_options(m); - m->alias = NULL; - m->is_default = false; pcmc->enforce_amd_1tb_hole = false; compat_props_add(m->compat_props, hw_compat_7_0, hw_compat_7_0_len); compat_props_add(m->compat_props, pc_compat_7_0, pc_compat_7_0_len); @@ -478,8 +485,6 @@ DEFINE_I440FX_MACHINE(v7_0, "pc-i440fx-7.0", NULL, static void pc_i440fx_6_2_machine_options(MachineClass *m) { pc_i440fx_7_0_machine_options(m); - m->alias = NULL; - m->is_default = false; compat_props_add(m->compat_props, hw_compat_6_2, hw_compat_6_2_len); compat_props_add(m->compat_props, pc_compat_6_2, pc_compat_6_2_len); } @@ -490,8 +495,6 @@ DEFINE_I440FX_MACHINE(v6_2, "pc-i440fx-6.2", NULL, static void pc_i440fx_6_1_machine_options(MachineClass *m) { pc_i440fx_6_2_machine_options(m); - m->alias = NULL; - m->is_default = false; compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len); compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len); m->smp_props.prefer_sockets = true; @@ -503,8 +506,6 @@ DEFINE_I440FX_MACHINE(v6_1, "pc-i440fx-6.1", NULL, static void pc_i440fx_6_0_machine_options(MachineClass *m) { pc_i440fx_6_1_machine_options(m); - m->alias = NULL; - m->is_default = false; compat_props_add(m->compat_props, hw_compat_6_0, hw_compat_6_0_len); compat_props_add(m->compat_props, pc_compat_6_0, pc_compat_6_0_len); } @@ -515,8 +516,6 @@ DEFINE_I440FX_MACHINE(v6_0, "pc-i440fx-6.0", NULL, static void pc_i440fx_5_2_machine_options(MachineClass *m) { pc_i440fx_6_0_machine_options(m); - m->alias = NULL; - m->is_default = false; compat_props_add(m->compat_props, hw_compat_5_2, hw_compat_5_2_len); compat_props_add(m->compat_props, pc_compat_5_2, pc_compat_5_2_len); } @@ -529,8 +528,6 @@ static void pc_i440fx_5_1_machine_options(MachineClass *m) PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_i440fx_5_2_machine_options(m); - m->alias = NULL; - m->is_default = false; compat_props_add(m->compat_props, hw_compat_5_1, hw_compat_5_1_len); compat_props_add(m->compat_props, pc_compat_5_1, pc_compat_5_1_len); pcmc->kvmclock_create_always = false; @@ -543,8 +540,6 @@ DEFINE_I440FX_MACHINE(v5_1, "pc-i440fx-5.1", NULL, static void pc_i440fx_5_0_machine_options(MachineClass *m) { pc_i440fx_5_1_machine_options(m); - m->alias = NULL; - m->is_default = false; m->numa_mem_supported = true; compat_props_add(m->compat_props, hw_compat_5_0, hw_compat_5_0_len); compat_props_add(m->compat_props, pc_compat_5_0, pc_compat_5_0_len); @@ -557,8 +552,6 @@ DEFINE_I440FX_MACHINE(v5_0, "pc-i440fx-5.0", NULL, static void pc_i440fx_4_2_machine_options(MachineClass *m) { pc_i440fx_5_0_machine_options(m); - m->alias = NULL; - m->is_default = false; compat_props_add(m->compat_props, hw_compat_4_2, hw_compat_4_2_len); compat_props_add(m->compat_props, pc_compat_4_2, pc_compat_4_2_len); } @@ -569,8 +562,6 @@ DEFINE_I440FX_MACHINE(v4_2, "pc-i440fx-4.2", NULL, static void pc_i440fx_4_1_machine_options(MachineClass *m) { pc_i440fx_4_2_machine_options(m); - m->alias = NULL; - m->is_default = false; compat_props_add(m->compat_props, hw_compat_4_1, hw_compat_4_1_len); compat_props_add(m->compat_props, pc_compat_4_1, pc_compat_4_1_len); } @@ -582,8 +573,6 @@ static void pc_i440fx_4_0_machine_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_i440fx_4_1_machine_options(m); - m->alias = NULL; - m->is_default = false; pcmc->default_cpu_version = CPU_VERSION_LEGACY; compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len); compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len); @@ -597,9 +586,7 @@ static void pc_i440fx_3_1_machine_options(MachineClass *m) PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_i440fx_4_0_machine_options(m); - m->is_default = false; m->smbus_no_migration_support = true; - m->alias = NULL; pcmc->pvh_enabled = false; compat_props_add(m->compat_props, hw_compat_3_1, hw_compat_3_1_len); compat_props_add(m->compat_props, pc_compat_3_1, pc_compat_3_1_len); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index a496bd6e74..67ceb04bcc 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -355,6 +355,7 @@ static void pc_q35_machine_options(MachineClass *m) PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pcmc->default_nic_model = "e1000e"; pcmc->pci_root_uid = 0; + pcmc->default_cpu_version = 1; m->family = "pc_q35"; m->desc = "Standard PC (Q35 + ICH9, 2009)"; @@ -370,12 +371,21 @@ static void pc_q35_machine_options(MachineClass *m) m->max_cpus = 288; } -static void pc_q35_7_2_machine_options(MachineClass *m) +static void pc_q35_8_0_machine_options(MachineClass *m) { - PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_machine_options(m); m->alias = "q35"; - pcmc->default_cpu_version = 1; +} + +DEFINE_Q35_MACHINE(v8_0, "pc-q35-8.0", NULL, + pc_q35_8_0_machine_options); + +static void pc_q35_7_2_machine_options(MachineClass *m) +{ + pc_q35_8_0_machine_options(m); + m->alias = NULL; + compat_props_add(m->compat_props, hw_compat_7_2, hw_compat_7_2_len); + compat_props_add(m->compat_props, pc_compat_7_2, pc_compat_7_2_len); } DEFINE_Q35_MACHINE(v7_2, "pc-q35-7.2", NULL, @@ -385,7 +395,6 @@ static void pc_q35_7_1_machine_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_7_2_machine_options(m); - m->alias = NULL; pcmc->legacy_no_rng_seed = true; compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len); compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len); @@ -398,7 +407,6 @@ static void pc_q35_7_0_machine_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_7_1_machine_options(m); - m->alias = NULL; pcmc->enforce_amd_1tb_hole = false; compat_props_add(m->compat_props, hw_compat_7_0, hw_compat_7_0_len); compat_props_add(m->compat_props, pc_compat_7_0, pc_compat_7_0_len); @@ -410,7 +418,6 @@ DEFINE_Q35_MACHINE(v7_0, "pc-q35-7.0", NULL, static void pc_q35_6_2_machine_options(MachineClass *m) { pc_q35_7_0_machine_options(m); - m->alias = NULL; compat_props_add(m->compat_props, hw_compat_6_2, hw_compat_6_2_len); compat_props_add(m->compat_props, pc_compat_6_2, pc_compat_6_2_len); } @@ -421,7 +428,6 @@ DEFINE_Q35_MACHINE(v6_2, "pc-q35-6.2", NULL, static void pc_q35_6_1_machine_options(MachineClass *m) { pc_q35_6_2_machine_options(m); - m->alias = NULL; compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len); compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len); m->smp_props.prefer_sockets = true; @@ -433,7 +439,6 @@ DEFINE_Q35_MACHINE(v6_1, "pc-q35-6.1", NULL, static void pc_q35_6_0_machine_options(MachineClass *m) { pc_q35_6_1_machine_options(m); - m->alias = NULL; compat_props_add(m->compat_props, hw_compat_6_0, hw_compat_6_0_len); compat_props_add(m->compat_props, pc_compat_6_0, pc_compat_6_0_len); } @@ -444,7 +449,6 @@ DEFINE_Q35_MACHINE(v6_0, "pc-q35-6.0", NULL, static void pc_q35_5_2_machine_options(MachineClass *m) { pc_q35_6_0_machine_options(m); - m->alias = NULL; compat_props_add(m->compat_props, hw_compat_5_2, hw_compat_5_2_len); compat_props_add(m->compat_props, pc_compat_5_2, pc_compat_5_2_len); } @@ -457,7 +461,6 @@ static void pc_q35_5_1_machine_options(MachineClass *m) PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_5_2_machine_options(m); - m->alias = NULL; compat_props_add(m->compat_props, hw_compat_5_1, hw_compat_5_1_len); compat_props_add(m->compat_props, pc_compat_5_1, pc_compat_5_1_len); pcmc->kvmclock_create_always = false; @@ -470,7 +473,6 @@ DEFINE_Q35_MACHINE(v5_1, "pc-q35-5.1", NULL, static void pc_q35_5_0_machine_options(MachineClass *m) { pc_q35_5_1_machine_options(m); - m->alias = NULL; m->numa_mem_supported = true; compat_props_add(m->compat_props, hw_compat_5_0, hw_compat_5_0_len); compat_props_add(m->compat_props, pc_compat_5_0, pc_compat_5_0_len); @@ -483,7 +485,6 @@ DEFINE_Q35_MACHINE(v5_0, "pc-q35-5.0", NULL, static void pc_q35_4_2_machine_options(MachineClass *m) { pc_q35_5_0_machine_options(m); - m->alias = NULL; compat_props_add(m->compat_props, hw_compat_4_2, hw_compat_4_2_len); compat_props_add(m->compat_props, pc_compat_4_2, pc_compat_4_2_len); } @@ -494,7 +495,6 @@ DEFINE_Q35_MACHINE(v4_2, "pc-q35-4.2", NULL, static void pc_q35_4_1_machine_options(MachineClass *m) { pc_q35_4_2_machine_options(m); - m->alias = NULL; compat_props_add(m->compat_props, hw_compat_4_1, hw_compat_4_1_len); compat_props_add(m->compat_props, pc_compat_4_1, pc_compat_4_1_len); } @@ -506,7 +506,6 @@ static void pc_q35_4_0_1_machine_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_4_1_machine_options(m); - m->alias = NULL; pcmc->default_cpu_version = CPU_VERSION_LEGACY; /* * This is the default machine for the 4.0-stable branch. It is basically @@ -524,7 +523,6 @@ static void pc_q35_4_0_machine_options(MachineClass *m) { pc_q35_4_0_1_machine_options(m); m->default_kernel_irqchip_split = true; - m->alias = NULL; /* Compat props are applied by the 4.0.1 machine */ } @@ -538,7 +536,6 @@ static void pc_q35_3_1_machine_options(MachineClass *m) pc_q35_4_0_machine_options(m); m->default_kernel_irqchip_split = false; m->smbus_no_migration_support = true; - m->alias = NULL; pcmc->pvh_enabled = false; compat_props_add(m->compat_props, hw_compat_3_1, hw_compat_3_1_len); compat_props_add(m->compat_props, pc_compat_3_1, pc_compat_3_1_len); diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 6c44cc9767..8d541e2b54 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -52,6 +52,7 @@ #include "hw/nvram/fw_cfg.h" #include "qemu/cutils.h" #include "hw/acpi/acpi_aml_interface.h" +#include "trace.h" /*****************************************************************************/ /* ICH9 LPC PCI to ISA bridge */ @@ -162,6 +163,7 @@ static void ich9_cc_write(void *opaque, hwaddr addr, { ICH9LPCState *lpc = (ICH9LPCState *)opaque; + trace_ich9_cc_write(addr, val, len); ich9_cc_addr_len(&addr, &len); memcpy(lpc->chip_config + addr, &val, len); pci_bus_fire_intx_routing_notifier(pci_get_bus(&lpc->d)); @@ -177,6 +179,7 @@ static uint64_t ich9_cc_read(void *opaque, hwaddr addr, uint32_t val = 0; ich9_cc_addr_len(&addr, &len); memcpy(&val, lpc->chip_config + addr, len); + trace_ich9_cc_read(addr, val, len); return val; } @@ -789,7 +792,7 @@ static const VMStateDescription vmstate_ich9_lpc = { }; static Property ich9_lpc_properties[] = { - DEFINE_PROP_BOOL("noreboot", ICH9LPCState, pin_strap.spkr_hi, true), + DEFINE_PROP_BOOL("noreboot", ICH9LPCState, pin_strap.spkr_hi, false), DEFINE_PROP_BOOL("smm-compat", ICH9LPCState, pm.smm_compat, false), DEFINE_PROP_BIT64("x-smi-broadcast", ICH9LPCState, smi_host_features, ICH9_LPC_SMI_F_BROADCAST_BIT, true), diff --git a/hw/isa/trace-events b/hw/isa/trace-events index b8f877e1ed..c4567a9b47 100644 --- a/hw/isa/trace-events +++ b/hw/isa/trace-events @@ -21,3 +21,7 @@ via_pm_io_read(uint32_t addr, uint32_t val, int len) "addr 0x%x val 0x%x len 0x% via_pm_io_write(uint32_t addr, uint32_t val, int len) "addr 0x%x val 0x%x len 0x%x" via_superio_read(uint8_t addr, uint8_t val) "addr 0x%x val 0x%x" via_superio_write(uint8_t addr, uint32_t val) "addr 0x%x val 0x%x" + +# lpc_ich9.c +ich9_cc_write(uint64_t addr, uint64_t val, unsigned len) "addr=0x%"PRIx64 " val=0x%"PRIx64 " len=%u" +ich9_cc_read(uint64_t addr, uint64_t val, unsigned len) "addr=0x%"PRIx64 " val=0x%"PRIx64 " len=%u" diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c index da5eafd275..4cb5beef1a 100644 --- a/hw/m68k/virt.c +++ b/hw/m68k/virt.c @@ -346,10 +346,17 @@ type_init(virt_machine_register_types) } \ type_init(machvirt_machine_##major##_##minor##_init); -static void virt_machine_7_2_options(MachineClass *mc) +static void virt_machine_8_0_options(MachineClass *mc) { } -DEFINE_VIRT_MACHINE(7, 2, true) +DEFINE_VIRT_MACHINE(8, 0, true) + +static void virt_machine_7_2_options(MachineClass *mc) +{ + virt_machine_8_0_options(mc); + compat_props_add(mc->compat_props, hw_compat_7_2, hw_compat_7_2_len); +} +DEFINE_VIRT_MACHINE(7, 2, false) static void virt_machine_7_1_options(MachineClass *mc) { diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c index 255590201a..dae4fd89ca 100644 --- a/hw/mem/cxl_type3.c +++ b/hw/mem/cxl_type3.c @@ -295,6 +295,17 @@ static void build_dvsecs(CXLType3Dev *ct3d) cxl_component_create_dvsec(cxl_cstate, CXL2_TYPE3_DEVICE, GPF_DEVICE_DVSEC_LENGTH, GPF_DEVICE_DVSEC, GPF_DEVICE_DVSEC_REVID, dvsec); + + dvsec = (uint8_t *)&(CXLDVSECPortFlexBus){ + .cap = 0x26, /* 68B, IO, Mem, non-MLD */ + .ctrl = 0x02, /* IO always enabled */ + .status = 0x26, /* same as capabilities */ + .rcvd_mod_ts_data_phase1 = 0xef, /* WTF? */ + }; + cxl_component_create_dvsec(cxl_cstate, CXL2_TYPE3_DEVICE, + PCIE_FLEXBUS_PORT_DVSEC_LENGTH_2_0, + PCIE_FLEXBUS_PORT_DVSEC, + PCIE_FLEXBUS_PORT_DVSEC_REVID_2_0, dvsec); } static void hdm_decoder_commit(CXLType3Dev *ct3d, int which) diff --git a/hw/pci-bridge/cxl_downstream.c b/hw/pci-bridge/cxl_downstream.c index a361e519d0..3d4e6b59cd 100644 --- a/hw/pci-bridge/cxl_downstream.c +++ b/hw/pci-bridge/cxl_downstream.c @@ -217,7 +217,6 @@ static void cxl_dsp_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); PCIDeviceClass *k = PCI_DEVICE_CLASS(oc); - k->is_bridge = true; k->config_write = cxl_dsp_config_write; k->realize = cxl_dsp_realize; k->exit = cxl_dsp_exitfn; diff --git a/hw/pci-bridge/cxl_upstream.c b/hw/pci-bridge/cxl_upstream.c index 9b8b57df9d..9df436cb73 100644 --- a/hw/pci-bridge/cxl_upstream.c +++ b/hw/pci-bridge/cxl_upstream.c @@ -375,7 +375,6 @@ static void cxl_upstream_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); PCIDeviceClass *k = PCI_DEVICE_CLASS(oc); - k->is_bridge = true; k->config_write = cxl_usp_write_config; k->config_read = cxl_usp_read_config; k->realize = cxl_usp_realize; diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c deleted file mode 100644 index 4773d07e6d..0000000000 --- a/hw/pci-bridge/dec.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * QEMU DEC 21154 PCI bridge - * - * Copyright (c) 2006-2007 Fabrice Bellard - * Copyright (c) 2007 Jocelyn Mayer - * - * 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 "dec.h" -#include "hw/sysbus.h" -#include "qapi/error.h" -#include "qemu/module.h" -#include "hw/pci/pci.h" -#include "hw/pci/pci_host.h" -#include "hw/pci/pci_bridge.h" -#include "hw/pci/pci_bus.h" -#include "qom/object.h" - -OBJECT_DECLARE_SIMPLE_TYPE(DECState, DEC_21154) - -struct DECState { - PCIHostState parent_obj; -}; - -static int dec_map_irq(PCIDevice *pci_dev, int irq_num) -{ - return irq_num; -} - -static void dec_pci_bridge_realize(PCIDevice *pci_dev, Error **errp) -{ - pci_bridge_initfn(pci_dev, TYPE_PCI_BUS); -} - -static void dec_21154_pci_bridge_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - k->realize = dec_pci_bridge_realize; - k->exit = pci_bridge_exitfn; - k->vendor_id = PCI_VENDOR_ID_DEC; - k->device_id = PCI_DEVICE_ID_DEC_21154; - k->config_write = pci_bridge_write_config; - k->is_bridge = true; - dc->desc = "DEC 21154 PCI-PCI bridge"; - dc->reset = pci_bridge_reset; - dc->vmsd = &vmstate_pci_device; -} - -static const TypeInfo dec_21154_pci_bridge_info = { - .name = "dec-21154-p2p-bridge", - .parent = TYPE_PCI_BRIDGE, - .instance_size = sizeof(PCIBridge), - .class_init = dec_21154_pci_bridge_class_init, - .interfaces = (InterfaceInfo[]) { - { INTERFACE_CONVENTIONAL_PCI_DEVICE }, - { }, - }, -}; - -PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn) -{ - PCIDevice *dev; - PCIBridge *br; - - dev = pci_new_multifunction(devfn, false, "dec-21154-p2p-bridge"); - br = PCI_BRIDGE(dev); - pci_bridge_map_irq(br, "DEC 21154 PCI-PCI bridge", dec_map_irq); - pci_realize_and_unref(dev, parent_bus, &error_fatal); - return pci_bridge_get_sec_bus(br); -} - -static void pci_dec_21154_device_realize(DeviceState *dev, Error **errp) -{ - PCIHostState *phb; - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - - phb = PCI_HOST_BRIDGE(dev); - - memory_region_init_io(&phb->conf_mem, OBJECT(dev), &pci_host_conf_le_ops, - dev, "pci-conf-idx", 0x1000); - memory_region_init_io(&phb->data_mem, OBJECT(dev), &pci_host_data_le_ops, - dev, "pci-data-idx", 0x1000); - sysbus_init_mmio(sbd, &phb->conf_mem); - sysbus_init_mmio(sbd, &phb->data_mem); -} - -static void dec_21154_pci_host_realize(PCIDevice *d, Error **errp) -{ - /* PCI2PCI bridge same values as PearPC - check this */ -} - -static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - k->realize = dec_21154_pci_host_realize; - k->vendor_id = PCI_VENDOR_ID_DEC; - k->device_id = PCI_DEVICE_ID_DEC_21154; - k->revision = 0x02; - k->class_id = PCI_CLASS_BRIDGE_PCI; - k->is_bridge = true; - /* - * PCI-facing part of the host bridge, not usable without the - * host-facing part, which can't be device_add'ed, yet. - */ - dc->user_creatable = false; -} - -static const TypeInfo dec_21154_pci_host_info = { - .name = "dec-21154", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIDevice), - .class_init = dec_21154_pci_host_class_init, - .interfaces = (InterfaceInfo[]) { - { INTERFACE_CONVENTIONAL_PCI_DEVICE }, - { }, - }, -}; - -static void pci_dec_21154_device_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = pci_dec_21154_device_realize; -} - -static const TypeInfo pci_dec_21154_device_info = { - .name = TYPE_DEC_21154, - .parent = TYPE_PCI_HOST_BRIDGE, - .instance_size = sizeof(DECState), - .class_init = pci_dec_21154_device_class_init, -}; - -static void dec_register_types(void) -{ - type_register_static(&pci_dec_21154_device_info); - type_register_static(&dec_21154_pci_host_info); - type_register_static(&dec_21154_pci_bridge_info); -} - -type_init(dec_register_types) diff --git a/hw/pci-bridge/dec.h b/hw/pci-bridge/dec.h deleted file mode 100644 index 869e90b136..0000000000 --- a/hw/pci-bridge/dec.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef HW_PCI_BRIDGE_DEC_H -#define HW_PCI_BRIDGE_DEC_H - - -#define TYPE_DEC_21154 "dec-21154-sysbus" - -PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn); - -#endif diff --git a/hw/pci-bridge/i82801b11.c b/hw/pci-bridge/i82801b11.c index f28181e210..d9f224818b 100644 --- a/hw/pci-bridge/i82801b11.c +++ b/hw/pci-bridge/i82801b11.c @@ -92,7 +92,6 @@ static void i82801b11_bridge_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->is_bridge = true; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82801BA_11; k->revision = ICH9_D2P_A2_REVISION; diff --git a/hw/pci-bridge/meson.build b/hw/pci-bridge/meson.build index 243ceeda50..fe92d43de6 100644 --- a/hw/pci-bridge/meson.build +++ b/hw/pci-bridge/meson.build @@ -8,8 +8,6 @@ pci_ss.add(when: 'CONFIG_PXB', if_true: files('pci_expander_bridge.c'), pci_ss.add(when: 'CONFIG_XIO3130', if_true: files('xio3130_upstream.c', 'xio3130_downstream.c')) pci_ss.add(when: 'CONFIG_CXL', if_true: files('cxl_root_port.c', 'cxl_upstream.c', 'cxl_downstream.c')) -# NewWorld PowerMac -pci_ss.add(when: 'CONFIG_DEC_PCI', if_true: files('dec.c')) # Sun4u pci_ss.add(when: 'CONFIG_SIMBA', if_true: files('simba.c')) diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c index 657a06ddbe..3435df8d73 100644 --- a/hw/pci-bridge/pci_bridge_dev.c +++ b/hw/pci-bridge/pci_bridge_dev.c @@ -254,7 +254,6 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data) k->vendor_id = PCI_VENDOR_ID_REDHAT; k->device_id = PCI_DEVICE_ID_REDHAT_BRIDGE; k->class_id = PCI_CLASS_BRIDGE_PCI; - k->is_bridge = true; dc->desc = "Standard PCI Bridge"; dc->reset = qdev_pci_bridge_dev_reset; device_class_set_props(dc, pci_bridge_dev_properties); diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c index 1cd917a459..2301b2ca0b 100644 --- a/hw/pci-bridge/pcie_pci_bridge.c +++ b/hw/pci-bridge/pcie_pci_bridge.c @@ -145,7 +145,6 @@ static void pcie_pci_bridge_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); - k->is_bridge = true; k->vendor_id = PCI_VENDOR_ID_REDHAT; k->device_id = PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE; k->realize = pcie_pci_bridge_realize; diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c index 36bc0bafa7..efd96bf174 100644 --- a/hw/pci-bridge/pcie_root_port.c +++ b/hw/pci-bridge/pcie_root_port.c @@ -174,7 +174,6 @@ static void rp_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ResettableClass *rc = RESETTABLE_CLASS(klass); - k->is_bridge = true; k->config_write = rp_write_config; k->realize = rp_realize; k->exit = rp_exit; diff --git a/hw/pci-bridge/simba.c b/hw/pci-bridge/simba.c index ba55ab1939..17aa0d7b21 100644 --- a/hw/pci-bridge/simba.c +++ b/hw/pci-bridge/simba.c @@ -77,7 +77,6 @@ static void simba_pci_bridge_class_init(ObjectClass *klass, void *data) k->device_id = PCI_DEVICE_ID_SUN_SIMBA; k->revision = 0x11; k->config_write = pci_bridge_write_config; - k->is_bridge = true; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->reset = pci_bridge_reset; dc->vmsd = &vmstate_pci_device; diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c index 05e2b06c0c..38a2361fa2 100644 --- a/hw/pci-bridge/xio3130_downstream.c +++ b/hw/pci-bridge/xio3130_downstream.c @@ -159,7 +159,6 @@ static void xio3130_downstream_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->is_bridge = true; k->config_write = xio3130_downstream_write_config; k->realize = xio3130_downstream_realize; k->exit = xio3130_downstream_exitfn; diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c index 5ff46ef050..a48bfe3bc5 100644 --- a/hw/pci-bridge/xio3130_upstream.c +++ b/hw/pci-bridge/xio3130_upstream.c @@ -128,7 +128,6 @@ static void xio3130_upstream_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->is_bridge = true; k->config_write = xio3130_upstream_write_config; k->realize = xio3130_upstream_realize; k->exit = xio3130_upstream_exitfn; diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c index bde3a343a2..9e183caa48 100644 --- a/hw/pci-host/designware.c +++ b/hw/pci-host/designware.c @@ -600,7 +600,6 @@ static void designware_pcie_root_class_init(ObjectClass *klass, void *data) k->device_id = 0xABCD; k->revision = 0; k->class_id = PCI_CLASS_BRIDGE_PCI; - k->is_bridge = true; k->exit = pci_bridge_exitfn; k->realize = designware_pcie_root_realize; k->config_read = designware_pcie_root_config_read; diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c index aebd44d265..8396c91d59 100644 --- a/hw/pci-host/uninorth.c +++ b/hw/pci-host/uninorth.c @@ -128,11 +128,10 @@ static void pci_unin_main_realize(DeviceState *dev, Error **errp) pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-pci"); - /* DEC 21154 bridge */ -#if 0 - /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */ - pci_create_simple(h->bus, PCI_DEVFN(12, 0), "dec-21154"); -#endif + /* + * DEC 21154 bridge was unused for many years, this comment is + * a placeholder for whoever wishes to resurrect it + */ } static void pci_unin_main_init(Object *obj) diff --git a/hw/pci-host/xilinx-pcie.c b/hw/pci-host/xilinx-pcie.c index 38d5901a45..c9ab7052f4 100644 --- a/hw/pci-host/xilinx-pcie.c +++ b/hw/pci-host/xilinx-pcie.c @@ -298,7 +298,6 @@ static void xilinx_pcie_root_class_init(ObjectClass *klass, void *data) k->device_id = 0x7021; k->revision = 0; k->class_id = PCI_CLASS_BRIDGE_HOST; - k->is_bridge = true; k->realize = xilinx_pcie_root_realize; k->exit = pci_bridge_exitfn; dc->reset = pci_bridge_reset; diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 9598b4b546..c2fb88f9a3 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -573,7 +573,7 @@ void pci_bus_range(PCIBus *bus, int *min_bus, int *max_bus) for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { PCIDevice *dev = bus->devices[i]; - if (dev && PCI_DEVICE_GET_CLASS(dev)->is_bridge) { + if (dev && IS_PCI_BRIDGE(dev)) { *min_bus = MIN(*min_bus, dev->config[PCI_SECONDARY_BUS]); *max_bus = MAX(*max_bus, dev->config[PCI_SUBORDINATE_BUS]); } @@ -589,7 +589,6 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size, const VMStateField *field) { PCIDevice *s = container_of(pv, PCIDevice, config); - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(s); uint8_t *config; int i; @@ -611,9 +610,8 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size, memcpy(s->config, config, size); pci_update_mappings(s); - if (pc->is_bridge) { - PCIBridge *b = PCI_BRIDGE(s); - pci_bridge_update_mappings(b); + if (IS_PCI_BRIDGE(s)) { + pci_bridge_update_mappings(PCI_BRIDGE(s)); } memory_region_set_enabled(&s->bus_master_enable_region, @@ -1087,9 +1085,10 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, Error *local_err = NULL; DeviceState *dev = DEVICE(pci_dev); PCIBus *bus = pci_get_bus(pci_dev); + bool is_bridge = IS_PCI_BRIDGE(pci_dev); /* Only pci bridges can be attached to extra PCI root buses */ - if (pci_bus_is_root(bus) && bus->parent_dev && !pc->is_bridge) { + if (pci_bus_is_root(bus) && bus->parent_dev && !is_bridge) { error_setg(errp, "PCI: Only PCI/PCIe bridges can be plugged into %s", bus->parent_dev->name); @@ -1151,7 +1150,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, pci_config_set_revision(pci_dev->config, pc->revision); pci_config_set_class(pci_dev->config, pc->class_id); - if (!pc->is_bridge) { + if (!is_bridge) { if (pc->subsystem_vendor_id || pc->subsystem_id) { pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID, pc->subsystem_vendor_id); @@ -1168,7 +1167,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, pci_init_cmask(pci_dev); pci_init_wmask(pci_dev); pci_init_w1cmask(pci_dev); - if (pc->is_bridge) { + if (is_bridge) { pci_init_mask_bridge(pci_dev); } pci_init_multifunction(bus, pci_dev, &local_err); @@ -1916,7 +1915,7 @@ static bool pci_root_bus_in_range(PCIBus *bus, int bus_num) for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { PCIDevice *dev = bus->devices[i]; - if (dev && PCI_DEVICE_GET_CLASS(dev)->is_bridge) { + if (dev && IS_PCI_BRIDGE(dev)) { if (pci_secondary_bus_in_range(dev, bus_num)) { return true; } @@ -2623,7 +2622,6 @@ void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque) static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque) { Range *range = opaque; - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); uint16_t cmd = pci_get_word(dev->config + PCI_COMMAND); int i; @@ -2631,7 +2629,7 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque) return; } - if (pc->is_bridge) { + if (IS_PCI_BRIDGE(dev)) { pcibus_t base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); pcibus_t limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index dc850032ae..f067879c06 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -4734,14 +4734,25 @@ static void spapr_machine_latest_class_options(MachineClass *mc) type_init(spapr_machine_register_##suffix) /* - * pseries-7.2 + * pseries-8.0 */ -static void spapr_machine_7_2_class_options(MachineClass *mc) +static void spapr_machine_8_0_class_options(MachineClass *mc) { /* Defaults for the latest behaviour inherited from the base class */ } -DEFINE_SPAPR_MACHINE(7_2, "7.2", true); +DEFINE_SPAPR_MACHINE(8_0, "8.0", true); + +/* + * pseries-7.2 + */ +static void spapr_machine_7_2_class_options(MachineClass *mc) +{ + spapr_machine_8_0_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_7_2, hw_compat_7_2_len); +} + +DEFINE_SPAPR_MACHINE(7_2, "7.2", false); /* * pseries-7.1 diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 7b7618d5da..75aacda65a 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1361,7 +1361,6 @@ static int spapr_dt_pci_device(SpaprPhbState *sphb, PCIDevice *dev, { int offset; g_autofree gchar *nodename = spapr_pci_fw_dev_name(dev); - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); ResourceProps rp; SpaprDrc *drc = drc_from_dev(sphb, dev); uint32_t vendor_id = pci_default_read_config(dev, PCI_VENDOR_ID, 2); @@ -1446,7 +1445,7 @@ static int spapr_dt_pci_device(SpaprPhbState *sphb, PCIDevice *dev, spapr_phb_nvgpu_populate_pcidev_dt(dev, fdt, offset, sphb); - if (!pc->is_bridge) { + if (!IS_PCI_BRIDGE(dev)) { /* Properties only for non-bridges */ uint32_t min_grant = pci_default_read_config(dev, PCI_MIN_GNT, 1); uint32_t max_latency = pci_default_read_config(dev, PCI_MAX_LAT, 1); @@ -1544,7 +1543,6 @@ static void spapr_pci_pre_plug(HotplugHandler *plug_handler, { SpaprPhbState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler)); PCIDevice *pdev = PCI_DEVICE(plugged_dev); - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(plugged_dev); SpaprDrc *drc = drc_from_dev(phb, pdev); PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(pdev))); uint32_t slotnr = PCI_SLOT(pdev->devfn); @@ -1560,7 +1558,7 @@ static void spapr_pci_pre_plug(HotplugHandler *plug_handler, } } - if (pc->is_bridge) { + if (IS_PCI_BRIDGE(plugged_dev)) { if (!bridge_has_valid_chassis_nr(OBJECT(plugged_dev), errp)) { return; } @@ -1589,7 +1587,6 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, { SpaprPhbState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler)); PCIDevice *pdev = PCI_DEVICE(plugged_dev); - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(plugged_dev); SpaprDrc *drc = drc_from_dev(phb, pdev); uint32_t slotnr = PCI_SLOT(pdev->devfn); @@ -1603,7 +1600,7 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, g_assert(drc); - if (pc->is_bridge) { + if (IS_PCI_BRIDGE(plugged_dev)) { spapr_pci_bridge_plug(phb, PCI_BRIDGE(plugged_dev)); } @@ -1646,7 +1643,6 @@ static void spapr_pci_bridge_unplug(SpaprPhbState *phb, static void spapr_pci_unplug(HotplugHandler *plug_handler, DeviceState *plugged_dev, Error **errp) { - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(plugged_dev); SpaprPhbState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler)); /* some version guests do not wait for completion of a device @@ -1661,7 +1657,7 @@ static void spapr_pci_unplug(HotplugHandler *plug_handler, */ pci_device_reset(PCI_DEVICE(plugged_dev)); - if (pc->is_bridge) { + if (IS_PCI_BRIDGE(plugged_dev)) { spapr_pci_bridge_unplug(phb, PCI_BRIDGE(plugged_dev)); return; } @@ -1686,7 +1682,6 @@ static void spapr_pci_unplug_request(HotplugHandler *plug_handler, g_assert(drc->dev == plugged_dev); if (!spapr_drc_unplug_requested(drc)) { - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(plugged_dev); uint32_t slotnr = PCI_SLOT(pdev->devfn); SpaprDrc *func_drc; SpaprDrcClass *func_drck; @@ -1694,7 +1689,7 @@ static void spapr_pci_unplug_request(HotplugHandler *plug_handler, int i; uint8_t chassis = chassis_from_bus(pci_get_bus(pdev)); - if (pc->is_bridge) { + if (IS_PCI_BRIDGE(plugged_dev)) { error_setg(errp, "PCI: Hot unplug of PCI bridges not supported"); return; } diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index fab79045dd..f22f61b8b6 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -823,14 +823,26 @@ bool css_migration_enabled(void) } \ type_init(ccw_machine_register_##suffix) +static void ccw_machine_8_0_instance_options(MachineState *machine) +{ +} + +static void ccw_machine_8_0_class_options(MachineClass *mc) +{ +} +DEFINE_CCW_MACHINE(8_0, "8.0", true); + static void ccw_machine_7_2_instance_options(MachineState *machine) { + ccw_machine_8_0_instance_options(machine); } static void ccw_machine_7_2_class_options(MachineClass *mc) { + ccw_machine_8_0_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_7_2, hw_compat_7_2_len); } -DEFINE_CCW_MACHINE(7_2, "7.2", true); +DEFINE_CCW_MACHINE(7_2, "7.2", false); static void ccw_machine_7_1_instance_options(MachineState *machine) { diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig index cbfd8c7173..89e9e426d8 100644 --- a/hw/virtio/Kconfig +++ b/hw/virtio/Kconfig @@ -85,3 +85,8 @@ config VHOST_USER_GPIO bool default y depends on VIRTIO && VHOST_USER + +config VHOST_VDPA_DEV + bool + default y + depends on VIRTIO && VHOST_VDPA && LINUX diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build index dfed1e7af5..f93be2e137 100644 --- a/hw/virtio/meson.build +++ b/hw/virtio/meson.build @@ -3,34 +3,36 @@ softmmu_virtio_ss.add(files('virtio-bus.c')) softmmu_virtio_ss.add(when: 'CONFIG_VIRTIO_PCI', if_true: files('virtio-pci.c')) softmmu_virtio_ss.add(when: 'CONFIG_VIRTIO_MMIO', if_true: files('virtio-mmio.c')) -virtio_ss = ss.source_set() -virtio_ss.add(files('virtio.c')) +specific_virtio_ss = ss.source_set() +specific_virtio_ss.add(files('virtio.c')) +specific_virtio_ss.add(files('virtio-config-io.c', 'virtio-qmp.c')) if have_vhost - virtio_ss.add(files('vhost.c', 'vhost-backend.c', 'vhost-iova-tree.c')) + specific_virtio_ss.add(files('vhost.c', 'vhost-backend.c', 'vhost-iova-tree.c')) if have_vhost_user - virtio_ss.add(files('vhost-user.c')) + specific_virtio_ss.add(files('vhost-user.c')) endif if have_vhost_vdpa - virtio_ss.add(files('vhost-vdpa.c', 'vhost-shadow-virtqueue.c')) + specific_virtio_ss.add(files('vhost-vdpa.c', 'vhost-shadow-virtqueue.c')) endif else softmmu_virtio_ss.add(files('vhost-stub.c')) endif -virtio_ss.add(when: 'CONFIG_VIRTIO_BALLOON', if_true: files('virtio-balloon.c')) -virtio_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('virtio-crypto.c')) -virtio_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs.c')) -virtio_ss.add(when: 'CONFIG_VIRTIO_PMEM', if_true: files('virtio-pmem.c')) -virtio_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock.c', 'vhost-vsock-common.c')) -virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vsock.c', 'vhost-vsock-common.c')) -virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c')) -virtio_ss.add(when: 'CONFIG_VIRTIO_IOMMU', if_true: files('virtio-iommu.c')) -virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c')) -virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c')) -virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: files('vhost-user-rng.c')) -virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true: files('vhost-user-gpio.c')) -virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_GPIO'], if_true: files('vhost-user-gpio-pci.c')) +specific_virtio_ss.add(when: 'CONFIG_VIRTIO_BALLOON', if_true: files('virtio-balloon.c')) +specific_virtio_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('virtio-crypto.c')) +specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs.c')) +specific_virtio_ss.add(when: 'CONFIG_VIRTIO_PMEM', if_true: files('virtio-pmem.c')) +specific_virtio_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock.c', 'vhost-vsock-common.c')) +specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vsock.c', 'vhost-vsock-common.c')) +specific_virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c')) +specific_virtio_ss.add(when: 'CONFIG_VIRTIO_IOMMU', if_true: files('virtio-iommu.c')) +specific_virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c')) +specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c')) +specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: files('vhost-user-rng.c')) +specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true: files('vhost-user-gpio.c')) +specific_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_GPIO'], if_true: files('vhost-user-gpio-pci.c')) +specific_virtio_ss.add(when: 'CONFIG_VHOST_VDPA_DEV', if_true: files('vdpa-dev.c')) virtio_pci_ss = ss.source_set() virtio_pci_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-pci.c')) @@ -56,12 +58,14 @@ virtio_pci_ss.add(when: 'CONFIG_VIRTIO_SERIAL', if_true: files('virtio-serial-pc virtio_pci_ss.add(when: 'CONFIG_VIRTIO_PMEM', if_true: files('virtio-pmem-pci.c')) virtio_pci_ss.add(when: 'CONFIG_VIRTIO_IOMMU', if_true: files('virtio-iommu-pci.c')) virtio_pci_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VHOST_VDPA_DEV', if_true: files('vdpa-dev-pci.c')) -virtio_ss.add_all(when: 'CONFIG_VIRTIO_PCI', if_true: virtio_pci_ss) +specific_virtio_ss.add_all(when: 'CONFIG_VIRTIO_PCI', if_true: virtio_pci_ss) -specific_ss.add_all(when: 'CONFIG_VIRTIO', if_true: virtio_ss) softmmu_ss.add_all(when: 'CONFIG_VIRTIO', if_true: softmmu_virtio_ss) softmmu_ss.add(when: 'CONFIG_VIRTIO', if_false: files('vhost-stub.c')) softmmu_ss.add(when: 'CONFIG_VIRTIO', if_false: files('virtio-stub.c')) softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('vhost-stub.c')) softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('virtio-stub.c')) + +specific_ss.add_all(when: 'CONFIG_VIRTIO', if_true: specific_virtio_ss) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 14fc5b9bb2..96da58a41f 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -30,8 +30,8 @@ vhost_user_write(uint32_t req, uint32_t flags) "req:%d flags:0x%"PRIx32"" vhost_user_create_notifier(int idx, void *n) "idx:%d n:%p" # vhost-vdpa.c -vhost_vdpa_dma_map(void *vdpa, int fd, uint32_t msg_type, uint64_t iova, uint64_t size, uint64_t uaddr, uint8_t perm, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" uaddr: 0x%"PRIx64" perm: 0x%"PRIx8" type: %"PRIu8 -vhost_vdpa_dma_unmap(void *vdpa, int fd, uint32_t msg_type, uint64_t iova, uint64_t size, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" type: %"PRIu8 +vhost_vdpa_dma_map(void *vdpa, int fd, uint32_t msg_type, uint32_t asid, uint64_t iova, uint64_t size, uint64_t uaddr, uint8_t perm, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" asid: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" uaddr: 0x%"PRIx64" perm: 0x%"PRIx8" type: %"PRIu8 +vhost_vdpa_dma_unmap(void *vdpa, int fd, uint32_t msg_type, uint32_t asid, uint64_t iova, uint64_t size, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" asid: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" type: %"PRIu8 vhost_vdpa_listener_begin_batch(void *v, int fd, uint32_t msg_type, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8 vhost_vdpa_listener_commit(void *v, int fd, uint32_t msg_type, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8 vhost_vdpa_listener_region_add(void *vdpa, uint64_t iova, uint64_t llend, void *vaddr, bool readonly) "vdpa: %p iova 0x%"PRIx64" llend 0x%"PRIx64" vaddr: %p read-only: %d" diff --git a/hw/virtio/vdpa-dev-pci.c b/hw/virtio/vdpa-dev-pci.c new file mode 100644 index 0000000000..5446e6b393 --- /dev/null +++ b/hw/virtio/vdpa-dev-pci.c @@ -0,0 +1,102 @@ +/* + * Vhost Vdpa Device PCI Bindings + * + * Copyright (c) Huawei Technologies Co., Ltd. 2022. All Rights Reserved. + * + * Authors: + * Longpeng + * + * Largely based on the "vhost-user-blk-pci.c" and "vhost-user-blk.c" + * implemented by: + * Changpeng Liu + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + */ +#include "qemu/osdep.h" +#include +#include +#include "hw/virtio/virtio.h" +#include "hw/virtio/vdpa-dev.h" +#include "hw/pci/pci.h" +#include "hw/qdev-properties.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/module.h" +#include "hw/virtio/virtio-pci.h" +#include "qom/object.h" + + +typedef struct VhostVdpaDevicePCI VhostVdpaDevicePCI; + +#define TYPE_VHOST_VDPA_DEVICE_PCI "vhost-vdpa-device-pci-base" +DECLARE_INSTANCE_CHECKER(VhostVdpaDevicePCI, VHOST_VDPA_DEVICE_PCI, + TYPE_VHOST_VDPA_DEVICE_PCI) + +struct VhostVdpaDevicePCI { + VirtIOPCIProxy parent_obj; + VhostVdpaDevice vdev; +}; + +static void vhost_vdpa_device_pci_instance_init(Object *obj) +{ + VhostVdpaDevicePCI *dev = VHOST_VDPA_DEVICE_PCI(obj); + + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VHOST_VDPA_DEVICE); + object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), + "bootindex"); +} + +static Property vhost_vdpa_device_pci_properties[] = { + DEFINE_PROP_END_OF_LIST(), +}; + +static int vhost_vdpa_device_pci_post_init(VhostVdpaDevice *v, Error **errp) +{ + VhostVdpaDevicePCI *dev = container_of(v, VhostVdpaDevicePCI, vdev); + VirtIOPCIProxy *vpci_dev = &dev->parent_obj; + + vpci_dev->class_code = virtio_pci_get_class_id(v->vdev_id); + vpci_dev->trans_devid = virtio_pci_get_trans_devid(v->vdev_id); + /* one for config vector */ + vpci_dev->nvectors = v->num_queues + 1; + + return 0; +} + +static void +vhost_vdpa_device_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) +{ + VhostVdpaDevicePCI *dev = VHOST_VDPA_DEVICE_PCI(vpci_dev); + + dev->vdev.post_init = vhost_vdpa_device_pci_post_init; + qdev_realize(DEVICE(&dev->vdev), BUS(&vpci_dev->bus), errp); +} + +static void vhost_vdpa_device_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); + + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + device_class_set_props(dc, vhost_vdpa_device_pci_properties); + k->realize = vhost_vdpa_device_pci_realize; +} + +static const VirtioPCIDeviceTypeInfo vhost_vdpa_device_pci_info = { + .base_name = TYPE_VHOST_VDPA_DEVICE_PCI, + .generic_name = "vhost-vdpa-device-pci", + .transitional_name = "vhost-vdpa-device-pci-transitional", + .non_transitional_name = "vhost-vdpa-device-pci-non-transitional", + .instance_size = sizeof(VhostVdpaDevicePCI), + .instance_init = vhost_vdpa_device_pci_instance_init, + .class_init = vhost_vdpa_device_pci_class_init, +}; + +static void vhost_vdpa_device_pci_register(void) +{ + virtio_pci_types_register(&vhost_vdpa_device_pci_info); +} + +type_init(vhost_vdpa_device_pci_register); diff --git a/hw/virtio/vdpa-dev.c b/hw/virtio/vdpa-dev.c new file mode 100644 index 0000000000..db6ba61152 --- /dev/null +++ b/hw/virtio/vdpa-dev.c @@ -0,0 +1,377 @@ +/* + * Vhost Vdpa Device + * + * Copyright (c) Huawei Technologies Co., Ltd. 2022. All Rights Reserved. + * + * Authors: + * Longpeng + * + * Largely based on the "vhost-user-blk-pci.c" and "vhost-user-blk.c" + * implemented by: + * Changpeng Liu + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + */ +#include "qemu/osdep.h" +#include +#include +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/cutils.h" +#include "hw/qdev-core.h" +#include "hw/qdev-properties.h" +#include "hw/qdev-properties-system.h" +#include "hw/virtio/vhost.h" +#include "hw/virtio/virtio.h" +#include "hw/virtio/virtio-bus.h" +#include "hw/virtio/virtio-access.h" +#include "hw/virtio/vdpa-dev.h" +#include "sysemu/sysemu.h" +#include "sysemu/runstate.h" + +static void +vhost_vdpa_device_dummy_handle_output(VirtIODevice *vdev, VirtQueue *vq) +{ + /* Nothing to do */ +} + +static uint32_t +vhost_vdpa_device_get_u32(int fd, unsigned long int cmd, Error **errp) +{ + uint32_t val = (uint32_t)-1; + + if (ioctl(fd, cmd, &val) < 0) { + error_setg(errp, "vhost-vdpa-device: cmd 0x%lx failed: %s", + cmd, strerror(errno)); + } + + return val; +} + +static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VhostVdpaDevice *v = VHOST_VDPA_DEVICE(vdev); + uint16_t max_queue_size; + struct vhost_virtqueue *vqs; + int i, ret; + + if (!v->vhostdev) { + error_setg(errp, "vhost-vdpa-device: vhostdev are missing"); + return; + } + + v->vhostfd = qemu_open(v->vhostdev, O_RDWR, errp); + if (*errp) { + return; + } + v->vdpa.device_fd = v->vhostfd; + + v->vdev_id = vhost_vdpa_device_get_u32(v->vhostfd, + VHOST_VDPA_GET_DEVICE_ID, errp); + if (*errp) { + goto out; + } + + max_queue_size = vhost_vdpa_device_get_u32(v->vhostfd, + VHOST_VDPA_GET_VRING_NUM, errp); + if (*errp) { + goto out; + } + + if (v->queue_size > max_queue_size) { + error_setg(errp, "vhost-vdpa-device: invalid queue_size: %u (max:%u)", + v->queue_size, max_queue_size); + goto out; + } else if (!v->queue_size) { + v->queue_size = max_queue_size; + } + + v->num_queues = vhost_vdpa_device_get_u32(v->vhostfd, + VHOST_VDPA_GET_VQS_COUNT, errp); + if (*errp) { + goto out; + } + + if (!v->num_queues || v->num_queues > VIRTIO_QUEUE_MAX) { + error_setg(errp, "invalid number of virtqueues: %u (max:%u)", + v->num_queues, VIRTIO_QUEUE_MAX); + goto out; + } + + v->dev.nvqs = v->num_queues; + vqs = g_new0(struct vhost_virtqueue, v->dev.nvqs); + v->dev.vqs = vqs; + v->dev.vq_index = 0; + v->dev.vq_index_end = v->dev.nvqs; + v->dev.backend_features = 0; + v->started = false; + + ret = vhost_dev_init(&v->dev, &v->vdpa, VHOST_BACKEND_TYPE_VDPA, 0, NULL); + if (ret < 0) { + error_setg(errp, "vhost-vdpa-device: vhost initialization failed: %s", + strerror(-ret)); + goto free_vqs; + } + + v->config_size = vhost_vdpa_device_get_u32(v->vhostfd, + VHOST_VDPA_GET_CONFIG_SIZE, + errp); + if (*errp) { + goto vhost_cleanup; + } + + /* + * Invoke .post_init() to initialize the transport-specific fields + * before calling virtio_init(). + */ + if (v->post_init && v->post_init(v, errp) < 0) { + goto vhost_cleanup; + } + + v->config = g_malloc0(v->config_size); + + ret = vhost_dev_get_config(&v->dev, v->config, v->config_size, NULL); + if (ret < 0) { + error_setg(errp, "vhost-vdpa-device: get config failed"); + goto free_config; + } + + virtio_init(vdev, v->vdev_id, v->config_size); + + v->virtqs = g_new0(VirtQueue *, v->dev.nvqs); + for (i = 0; i < v->dev.nvqs; i++) { + v->virtqs[i] = virtio_add_queue(vdev, v->queue_size, + vhost_vdpa_device_dummy_handle_output); + } + + return; + +free_config: + g_free(v->config); +vhost_cleanup: + vhost_dev_cleanup(&v->dev); +free_vqs: + g_free(vqs); +out: + qemu_close(v->vhostfd); + v->vhostfd = -1; +} + +static void vhost_vdpa_device_unrealize(DeviceState *dev) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev); + int i; + + virtio_set_status(vdev, 0); + + for (i = 0; i < s->num_queues; i++) { + virtio_delete_queue(s->virtqs[i]); + } + g_free(s->virtqs); + virtio_cleanup(vdev); + + g_free(s->config); + g_free(s->dev.vqs); + vhost_dev_cleanup(&s->dev); + qemu_close(s->vhostfd); + s->vhostfd = -1; +} + +static void +vhost_vdpa_device_get_config(VirtIODevice *vdev, uint8_t *config) +{ + VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev); + + memcpy(config, s->config, s->config_size); +} + +static void +vhost_vdpa_device_set_config(VirtIODevice *vdev, const uint8_t *config) +{ + VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev); + int ret; + + ret = vhost_dev_set_config(&s->dev, s->config, 0, s->config_size, + VHOST_SET_CONFIG_TYPE_MASTER); + if (ret) { + error_report("set device config space failed"); + return; + } +} + +static uint64_t vhost_vdpa_device_get_features(VirtIODevice *vdev, + uint64_t features, + Error **errp) +{ + VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev); + uint64_t backend_features = s->dev.features; + + if (!virtio_has_feature(features, VIRTIO_F_IOMMU_PLATFORM)) { + virtio_clear_feature(&backend_features, VIRTIO_F_IOMMU_PLATFORM); + } + + return backend_features; +} + +static int vhost_vdpa_device_start(VirtIODevice *vdev, Error **errp) +{ + VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev); + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + int i, ret; + + if (!k->set_guest_notifiers) { + error_setg(errp, "binding does not support guest notifiers"); + return -ENOSYS; + } + + ret = vhost_dev_enable_notifiers(&s->dev, vdev); + if (ret < 0) { + error_setg_errno(errp, -ret, "Error enabling host notifiers"); + return ret; + } + + ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, true); + if (ret < 0) { + error_setg_errno(errp, -ret, "Error binding guest notifier"); + goto err_host_notifiers; + } + + s->dev.acked_features = vdev->guest_features; + + ret = vhost_dev_start(&s->dev, vdev, false); + if (ret < 0) { + error_setg_errno(errp, -ret, "Error starting vhost"); + goto err_guest_notifiers; + } + s->started = true; + + /* + * guest_notifier_mask/pending not used yet, so just unmask + * everything here. virtio-pci will do the right thing by + * enabling/disabling irqfd. + */ + for (i = 0; i < s->dev.nvqs; i++) { + vhost_virtqueue_mask(&s->dev, vdev, i, false); + } + + return ret; + +err_guest_notifiers: + k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false); +err_host_notifiers: + vhost_dev_disable_notifiers(&s->dev, vdev); + return ret; +} + +static void vhost_vdpa_device_stop(VirtIODevice *vdev) +{ + VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev); + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + int ret; + + if (!s->started) { + return; + } + s->started = false; + + if (!k->set_guest_notifiers) { + return; + } + + vhost_dev_stop(&s->dev, vdev, false); + + ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false); + if (ret < 0) { + error_report("vhost guest notifier cleanup failed: %d", ret); + return; + } + + vhost_dev_disable_notifiers(&s->dev, vdev); +} + +static void vhost_vdpa_device_set_status(VirtIODevice *vdev, uint8_t status) +{ + VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev); + bool should_start = virtio_device_started(vdev, status); + Error *local_err = NULL; + int ret; + + if (!vdev->vm_running) { + should_start = false; + } + + if (s->started == should_start) { + return; + } + + if (should_start) { + ret = vhost_vdpa_device_start(vdev, &local_err); + if (ret < 0) { + error_reportf_err(local_err, "vhost-vdpa-device: start failed: "); + } + } else { + vhost_vdpa_device_stop(vdev); + } +} + +static Property vhost_vdpa_device_properties[] = { + DEFINE_PROP_STRING("vhostdev", VhostVdpaDevice, vhostdev), + DEFINE_PROP_UINT16("queue-size", VhostVdpaDevice, queue_size, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static const VMStateDescription vmstate_vhost_vdpa_device = { + .name = "vhost-vdpa-device", + .unmigratable = 1, + .minimum_version_id = 1, + .version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_VIRTIO_DEVICE, + VMSTATE_END_OF_LIST() + }, +}; + +static void vhost_vdpa_device_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + + device_class_set_props(dc, vhost_vdpa_device_properties); + dc->desc = "VDPA-based generic device assignment"; + dc->vmsd = &vmstate_vhost_vdpa_device; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + vdc->realize = vhost_vdpa_device_realize; + vdc->unrealize = vhost_vdpa_device_unrealize; + vdc->get_config = vhost_vdpa_device_get_config; + vdc->set_config = vhost_vdpa_device_set_config; + vdc->get_features = vhost_vdpa_device_get_features; + vdc->set_status = vhost_vdpa_device_set_status; +} + +static void vhost_vdpa_device_instance_init(Object *obj) +{ + VhostVdpaDevice *s = VHOST_VDPA_DEVICE(obj); + + device_add_bootindex_property(obj, &s->bootindex, "bootindex", + NULL, DEVICE(obj)); +} + +static const TypeInfo vhost_vdpa_device_info = { + .name = TYPE_VHOST_VDPA_DEVICE, + .parent = TYPE_VIRTIO_DEVICE, + .instance_size = sizeof(VhostVdpaDevice), + .class_init = vhost_vdpa_device_class_init, + .instance_init = vhost_vdpa_device_instance_init, +}; + +static void register_vhost_vdpa_device_type(void) +{ + type_register_static(&vhost_vdpa_device_info); +} + +type_init(register_vhost_vdpa_device_type); diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c index 5bd14cad96..4307296358 100644 --- a/hw/virtio/vhost-shadow-virtqueue.c +++ b/hw/virtio/vhost-shadow-virtqueue.c @@ -642,18 +642,21 @@ void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd) * @svq: Shadow Virtqueue * @vdev: VirtIO device * @vq: Virtqueue to shadow + * @iova_tree: Tree to perform descriptors translations */ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, - VirtQueue *vq) + VirtQueue *vq, VhostIOVATree *iova_tree) { size_t desc_size, driver_size, device_size; + event_notifier_set_handler(&svq->hdev_call, vhost_svq_handle_call); svq->next_guest_avail_elem = NULL; svq->shadow_avail_idx = 0; svq->shadow_used_idx = 0; svq->last_used_idx = 0; svq->vdev = vdev; svq->vq = vq; + svq->iova_tree = iova_tree; svq->vring.num = virtio_queue_get_num(vdev, virtio_get_queue_index(vq)); driver_size = vhost_svq_driver_area_size(svq); @@ -704,53 +707,25 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq) g_free(svq->desc_state); qemu_vfree(svq->vring.desc); qemu_vfree(svq->vring.used); + event_notifier_set_handler(&svq->hdev_call, NULL); } /** * Creates vhost shadow virtqueue, and instructs the vhost device to use the * shadow methods and file descriptors. * - * @iova_tree: Tree to perform descriptors translations * @ops: SVQ owner callbacks * @ops_opaque: ops opaque pointer - * - * Returns the new virtqueue or NULL. - * - * In case of error, reason is reported through error_report. */ -VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree, - const VhostShadowVirtqueueOps *ops, +VhostShadowVirtqueue *vhost_svq_new(const VhostShadowVirtqueueOps *ops, void *ops_opaque) { - g_autofree VhostShadowVirtqueue *svq = g_new0(VhostShadowVirtqueue, 1); - int r; - - r = event_notifier_init(&svq->hdev_kick, 0); - if (r != 0) { - error_report("Couldn't create kick event notifier: %s (%d)", - g_strerror(errno), errno); - goto err_init_hdev_kick; - } - - r = event_notifier_init(&svq->hdev_call, 0); - if (r != 0) { - error_report("Couldn't create call event notifier: %s (%d)", - g_strerror(errno), errno); - goto err_init_hdev_call; - } + VhostShadowVirtqueue *svq = g_new0(VhostShadowVirtqueue, 1); event_notifier_init_fd(&svq->svq_kick, VHOST_FILE_UNBIND); - event_notifier_set_handler(&svq->hdev_call, vhost_svq_handle_call); - svq->iova_tree = iova_tree; svq->ops = ops; svq->ops_opaque = ops_opaque; - return g_steal_pointer(&svq); - -err_init_hdev_call: - event_notifier_cleanup(&svq->hdev_kick); - -err_init_hdev_kick: - return NULL; + return svq; } /** @@ -762,8 +737,5 @@ void vhost_svq_free(gpointer pvq) { VhostShadowVirtqueue *vq = pvq; vhost_svq_stop(vq); - event_notifier_cleanup(&vq->hdev_kick); - event_notifier_set_handler(&vq->hdev_call, NULL); - event_notifier_cleanup(&vq->hdev_call); g_free(vq); } diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h index d04c34a589..926a4897b1 100644 --- a/hw/virtio/vhost-shadow-virtqueue.h +++ b/hw/virtio/vhost-shadow-virtqueue.h @@ -126,11 +126,10 @@ size_t vhost_svq_driver_area_size(const VhostShadowVirtqueue *svq); size_t vhost_svq_device_area_size(const VhostShadowVirtqueue *svq); void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, - VirtQueue *vq); + VirtQueue *vq, VhostIOVATree *iova_tree); void vhost_svq_stop(VhostShadowVirtqueue *svq); -VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree, - const VhostShadowVirtqueueOps *ops, +VhostShadowVirtqueue *vhost_svq_new(const VhostShadowVirtqueueOps *ops, void *ops_opaque); void vhost_svq_free(gpointer vq); diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index b8aaa99ab5..d9ce0501b2 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -527,6 +527,11 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, .hdr.size = sizeof(msg.payload.log), }; + /* Send only once with first queue pair */ + if (dev->vq_index != 0) { + return 0; + } + if (shmfd && log->fd != -1) { fds[fd_num++] = log->fd; } diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index bc1c79b325..fd0c33b0e1 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -72,22 +72,28 @@ static bool vhost_vdpa_listener_skipped_section(MemoryRegionSection *section, return false; } -int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size, - void *vaddr, bool readonly) +/* + * The caller must set asid = 0 if the device does not support asid. + * This is not an ABI break since it is set to 0 by the initializer anyway. + */ +int vhost_vdpa_dma_map(struct vhost_vdpa *v, uint32_t asid, hwaddr iova, + hwaddr size, void *vaddr, bool readonly) { struct vhost_msg_v2 msg = {}; int fd = v->device_fd; int ret = 0; msg.type = v->msg_type; + msg.asid = asid; msg.iotlb.iova = iova; msg.iotlb.size = size; msg.iotlb.uaddr = (uint64_t)(uintptr_t)vaddr; msg.iotlb.perm = readonly ? VHOST_ACCESS_RO : VHOST_ACCESS_RW; msg.iotlb.type = VHOST_IOTLB_UPDATE; - trace_vhost_vdpa_dma_map(v, fd, msg.type, msg.iotlb.iova, msg.iotlb.size, - msg.iotlb.uaddr, msg.iotlb.perm, msg.iotlb.type); + trace_vhost_vdpa_dma_map(v, fd, msg.type, msg.asid, msg.iotlb.iova, + msg.iotlb.size, msg.iotlb.uaddr, msg.iotlb.perm, + msg.iotlb.type); if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) { error_report("failed to write, fd=%d, errno=%d (%s)", @@ -98,18 +104,24 @@ int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size, return ret; } -int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova, hwaddr size) +/* + * The caller must set asid = 0 if the device does not support asid. + * This is not an ABI break since it is set to 0 by the initializer anyway. + */ +int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, uint32_t asid, hwaddr iova, + hwaddr size) { struct vhost_msg_v2 msg = {}; int fd = v->device_fd; int ret = 0; msg.type = v->msg_type; + msg.asid = asid; msg.iotlb.iova = iova; msg.iotlb.size = size; msg.iotlb.type = VHOST_IOTLB_INVALIDATE; - trace_vhost_vdpa_dma_unmap(v, fd, msg.type, msg.iotlb.iova, + trace_vhost_vdpa_dma_unmap(v, fd, msg.type, msg.asid, msg.iotlb.iova, msg.iotlb.size, msg.iotlb.type); if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) { @@ -212,7 +224,7 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener, vaddr, section->readonly); llsize = int128_sub(llend, int128_make64(iova)); - if (v->shadow_vqs_enabled) { + if (v->shadow_data) { int r; mem_region.translated_addr = (hwaddr)(uintptr_t)vaddr, @@ -229,8 +241,8 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener, } vhost_vdpa_iotlb_batch_begin_once(v); - ret = vhost_vdpa_dma_map(v, iova, int128_get64(llsize), - vaddr, section->readonly); + ret = vhost_vdpa_dma_map(v, VHOST_VDPA_GUEST_PA_ASID, iova, + int128_get64(llsize), vaddr, section->readonly); if (ret) { error_report("vhost vdpa map fail!"); goto fail_map; @@ -239,7 +251,7 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener, return; fail_map: - if (v->shadow_vqs_enabled) { + if (v->shadow_data) { vhost_iova_tree_remove(v->iova_tree, mem_region); } @@ -284,7 +296,7 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener, llsize = int128_sub(llend, int128_make64(iova)); - if (v->shadow_vqs_enabled) { + if (v->shadow_data) { const DMAMap *result; const void *vaddr = memory_region_get_ram_ptr(section->mr) + section->offset_within_region + @@ -303,7 +315,8 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener, vhost_iova_tree_remove(v->iova_tree, *result); } vhost_vdpa_iotlb_batch_begin_once(v); - ret = vhost_vdpa_dma_unmap(v, iova, int128_get64(llsize)); + ret = vhost_vdpa_dma_unmap(v, VHOST_VDPA_GUEST_PA_ASID, iova, + int128_get64(llsize)); if (ret) { error_report("vhost_vdpa dma unmap error!"); } @@ -365,19 +378,6 @@ static int vhost_vdpa_add_status(struct vhost_dev *dev, uint8_t status) return 0; } -static void vhost_vdpa_get_iova_range(struct vhost_vdpa *v) -{ - int ret = vhost_vdpa_call(v->dev, VHOST_VDPA_GET_IOVA_RANGE, - &v->iova_range); - if (ret != 0) { - v->iova_range.first = 0; - v->iova_range.last = UINT64_MAX; - } - - trace_vhost_vdpa_get_iova_range(v->dev, v->iova_range.first, - v->iova_range.last); -} - /* * The use of this function is for requests that only need to be * applied once. Typically such request occurs at the beginning @@ -402,45 +402,19 @@ static int vhost_vdpa_get_dev_features(struct vhost_dev *dev, return ret; } -static int vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v, - Error **errp) +static void vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v) { g_autoptr(GPtrArray) shadow_vqs = NULL; - uint64_t dev_features, svq_features; - int r; - bool ok; - - if (!v->shadow_vqs_enabled) { - return 0; - } - - r = vhost_vdpa_get_dev_features(hdev, &dev_features); - if (r != 0) { - error_setg_errno(errp, -r, "Can't get vdpa device features"); - return r; - } - - svq_features = dev_features; - ok = vhost_svq_valid_features(svq_features, errp); - if (unlikely(!ok)) { - return -1; - } shadow_vqs = g_ptr_array_new_full(hdev->nvqs, vhost_svq_free); for (unsigned n = 0; n < hdev->nvqs; ++n) { - g_autoptr(VhostShadowVirtqueue) svq; + VhostShadowVirtqueue *svq; - svq = vhost_svq_new(v->iova_tree, v->shadow_vq_ops, - v->shadow_vq_ops_opaque); - if (unlikely(!svq)) { - error_setg(errp, "Cannot create svq %u", n); - return -1; - } - g_ptr_array_add(shadow_vqs, g_steal_pointer(&svq)); + svq = vhost_svq_new(v->shadow_vq_ops, v->shadow_vq_ops_opaque); + g_ptr_array_add(shadow_vqs, svq); } v->shadow_vqs = g_steal_pointer(&shadow_vqs); - return 0; } static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp) @@ -465,12 +439,7 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp) dev->opaque = opaque ; v->listener = vhost_vdpa_memory_listener; v->msg_type = VHOST_IOTLB_MSG_V2; - ret = vhost_vdpa_init_svq(dev, v, errp); - if (ret) { - goto err; - } - - vhost_vdpa_get_iova_range(v); + vhost_vdpa_init_svq(dev, v); if (!vhost_vdpa_first_dev(dev)) { return 0; @@ -480,10 +449,6 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp) VIRTIO_CONFIG_S_DRIVER); return 0; - -err: - ram_block_discard_disable(false); - return ret; } static void vhost_vdpa_host_notifier_uninit(struct vhost_dev *dev, @@ -580,10 +545,6 @@ static void vhost_vdpa_svq_cleanup(struct vhost_dev *dev) struct vhost_vdpa *v = dev->opaque; size_t idx; - if (!v->shadow_vqs) { - return; - } - for (idx = 0; idx < v->shadow_vqs->len; ++idx) { vhost_svq_stop(g_ptr_array_index(v->shadow_vqs, idx)); } @@ -677,7 +638,8 @@ static int vhost_vdpa_set_backend_cap(struct vhost_dev *dev) { uint64_t features; uint64_t f = 0x1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2 | - 0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH; + 0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH | + 0x1ULL << VHOST_BACKEND_F_IOTLB_ASID; int r; if (vhost_vdpa_call(dev, VHOST_GET_BACKEND_FEATURES, &features)) { @@ -864,11 +826,23 @@ static int vhost_vdpa_svq_set_fds(struct vhost_dev *dev, const EventNotifier *event_notifier = &svq->hdev_kick; int r; + r = event_notifier_init(&svq->hdev_kick, 0); + if (r != 0) { + error_setg_errno(errp, -r, "Couldn't create kick event notifier"); + goto err_init_hdev_kick; + } + + r = event_notifier_init(&svq->hdev_call, 0); + if (r != 0) { + error_setg_errno(errp, -r, "Couldn't create call event notifier"); + goto err_init_hdev_call; + } + file.fd = event_notifier_get_fd(event_notifier); r = vhost_vdpa_set_vring_dev_kick(dev, &file); if (unlikely(r != 0)) { error_setg_errno(errp, -r, "Can't set device kick fd"); - return r; + goto err_init_set_dev_fd; } event_notifier = &svq->hdev_call; @@ -876,8 +850,18 @@ static int vhost_vdpa_svq_set_fds(struct vhost_dev *dev, r = vhost_vdpa_set_vring_dev_call(dev, &file); if (unlikely(r != 0)) { error_setg_errno(errp, -r, "Can't set device call fd"); + goto err_init_set_dev_fd; } + return 0; + +err_init_set_dev_fd: + event_notifier_set_handler(&svq->hdev_call, NULL); + +err_init_hdev_call: + event_notifier_cleanup(&svq->hdev_kick); + +err_init_hdev_kick: return r; } @@ -899,7 +883,7 @@ static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, hwaddr addr) } size = ROUND_UP(result->size, qemu_real_host_page_size()); - r = vhost_vdpa_dma_unmap(v, result->iova, size); + r = vhost_vdpa_dma_unmap(v, v->address_space_id, result->iova, size); if (unlikely(r < 0)) { error_report("Unable to unmap SVQ vring: %s (%d)", g_strerror(-r), -r); return; @@ -939,7 +923,8 @@ static bool vhost_vdpa_svq_map_ring(struct vhost_vdpa *v, DMAMap *needle, return false; } - r = vhost_vdpa_dma_map(v, needle->iova, needle->size + 1, + r = vhost_vdpa_dma_map(v, v->address_space_id, needle->iova, + needle->size + 1, (void *)(uintptr_t)needle->translated_addr, needle->perm == IOMMU_RO); if (unlikely(r != 0)) { @@ -1029,7 +1014,7 @@ static bool vhost_vdpa_svqs_start(struct vhost_dev *dev) Error *err = NULL; unsigned i; - if (!v->shadow_vqs) { + if (!v->shadow_vqs_enabled) { return true; } @@ -1045,7 +1030,7 @@ static bool vhost_vdpa_svqs_start(struct vhost_dev *dev) goto err; } - vhost_svq_start(svq, dev->vdev, vq); + vhost_svq_start(svq, dev->vdev, vq, v->iova_tree); ok = vhost_vdpa_svq_map_rings(dev, svq, &addr, &err); if (unlikely(!ok)) { goto err_map; @@ -1082,13 +1067,16 @@ static void vhost_vdpa_svqs_stop(struct vhost_dev *dev) { struct vhost_vdpa *v = dev->opaque; - if (!v->shadow_vqs) { + if (!v->shadow_vqs_enabled) { return; } for (unsigned i = 0; i < v->shadow_vqs->len; ++i) { VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); vhost_vdpa_svq_unmap_rings(dev, svq); + + event_notifier_cleanup(&svq->hdev_kick); + event_notifier_cleanup(&svq->hdev_call); } } diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 7fb008bc9e..fdcd1a8fdf 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -20,6 +20,7 @@ #include "qemu/range.h" #include "qemu/error-report.h" #include "qemu/memfd.h" +#include "qemu/log.h" #include "standard-headers/linux/vhost_types.h" #include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-access.h" @@ -106,6 +107,24 @@ static void vhost_dev_sync_region(struct vhost_dev *dev, } } +static bool vhost_dev_has_iommu(struct vhost_dev *dev) +{ + VirtIODevice *vdev = dev->vdev; + + /* + * For vhost, VIRTIO_F_IOMMU_PLATFORM means the backend support + * incremental memory mapping API via IOTLB API. For platform that + * does not have IOMMU, there's no need to enable this feature + * which may cause unnecessary IOTLB miss/update transactions. + */ + if (vdev) { + return virtio_bus_device_iommu_enabled(vdev) && + virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); + } else { + return false; + } +} + static int vhost_sync_dirty_bitmap(struct vhost_dev *dev, MemoryRegionSection *section, hwaddr first, @@ -137,8 +156,51 @@ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev, continue; } - vhost_dev_sync_region(dev, section, start_addr, end_addr, vq->used_phys, - range_get_last(vq->used_phys, vq->used_size)); + if (vhost_dev_has_iommu(dev)) { + IOMMUTLBEntry iotlb; + hwaddr used_phys = vq->used_phys, used_size = vq->used_size; + hwaddr phys, s, offset; + + while (used_size) { + rcu_read_lock(); + iotlb = address_space_get_iotlb_entry(dev->vdev->dma_as, + used_phys, + true, + MEMTXATTRS_UNSPECIFIED); + rcu_read_unlock(); + + if (!iotlb.target_as) { + qemu_log_mask(LOG_GUEST_ERROR, "translation " + "failure for used_iova %"PRIx64"\n", + used_phys); + return -EINVAL; + } + + offset = used_phys & iotlb.addr_mask; + phys = iotlb.translated_addr + offset; + + /* + * Distance from start of used ring until last byte of + * IOMMU page. + */ + s = iotlb.addr_mask - offset; + /* + * Size of used ring, or of the part of it until end + * of IOMMU page. To avoid zero result, do the adding + * outside of MIN(). + */ + s = MIN(s, used_size - 1) + 1; + + vhost_dev_sync_region(dev, section, start_addr, end_addr, phys, + range_get_last(phys, s)); + used_size -= s; + used_phys += s; + } + } else { + vhost_dev_sync_region(dev, section, start_addr, + end_addr, vq->used_phys, + range_get_last(vq->used_phys, vq->used_size)); + } } return 0; } @@ -306,24 +368,6 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size) dev->log_size = size; } -static bool vhost_dev_has_iommu(struct vhost_dev *dev) -{ - VirtIODevice *vdev = dev->vdev; - - /* - * For vhost, VIRTIO_F_IOMMU_PLATFORM means the backend support - * incremental memory mapping API via IOTLB API. For platform that - * does not have IOMMU, there's no need to enable this feature - * which may cause unnecessary IOTLB miss/update transactions. - */ - if (vdev) { - return virtio_bus_device_iommu_enabled(vdev) && - virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); - } else { - return false; - } -} - static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr, hwaddr *plen, bool is_write) { diff --git a/hw/virtio/virtio-config-io.c b/hw/virtio/virtio-config-io.c new file mode 100644 index 0000000000..ad78e0b9bc --- /dev/null +++ b/hw/virtio/virtio-config-io.c @@ -0,0 +1,204 @@ +/* + * Virtio Support + * + * Copyright IBM, Corp. 2007 + * + * Authors: + * Anthony Liguori + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/virtio/virtio.h" +#include "cpu.h" + +uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint8_t val; + + if (addr + sizeof(val) > vdev->config_len) { + return (uint32_t)-1; + } + + k->get_config(vdev, vdev->config); + + val = ldub_p(vdev->config + addr); + return val; +} + +uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint16_t val; + + if (addr + sizeof(val) > vdev->config_len) { + return (uint32_t)-1; + } + + k->get_config(vdev, vdev->config); + + val = lduw_p(vdev->config + addr); + return val; +} + +uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint32_t val; + + if (addr + sizeof(val) > vdev->config_len) { + return (uint32_t)-1; + } + + k->get_config(vdev, vdev->config); + + val = ldl_p(vdev->config + addr); + return val; +} + +void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint8_t val = data; + + if (addr + sizeof(val) > vdev->config_len) { + return; + } + + stb_p(vdev->config + addr, val); + + if (k->set_config) { + k->set_config(vdev, vdev->config); + } +} + +void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint16_t val = data; + + if (addr + sizeof(val) > vdev->config_len) { + return; + } + + stw_p(vdev->config + addr, val); + + if (k->set_config) { + k->set_config(vdev, vdev->config); + } +} + +void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint32_t val = data; + + if (addr + sizeof(val) > vdev->config_len) { + return; + } + + stl_p(vdev->config + addr, val); + + if (k->set_config) { + k->set_config(vdev, vdev->config); + } +} + +uint32_t virtio_config_modern_readb(VirtIODevice *vdev, uint32_t addr) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint8_t val; + + if (addr + sizeof(val) > vdev->config_len) { + return (uint32_t)-1; + } + + k->get_config(vdev, vdev->config); + + val = ldub_p(vdev->config + addr); + return val; +} + +uint32_t virtio_config_modern_readw(VirtIODevice *vdev, uint32_t addr) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint16_t val; + + if (addr + sizeof(val) > vdev->config_len) { + return (uint32_t)-1; + } + + k->get_config(vdev, vdev->config); + + val = lduw_le_p(vdev->config + addr); + return val; +} + +uint32_t virtio_config_modern_readl(VirtIODevice *vdev, uint32_t addr) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint32_t val; + + if (addr + sizeof(val) > vdev->config_len) { + return (uint32_t)-1; + } + + k->get_config(vdev, vdev->config); + + val = ldl_le_p(vdev->config + addr); + return val; +} + +void virtio_config_modern_writeb(VirtIODevice *vdev, + uint32_t addr, uint32_t data) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint8_t val = data; + + if (addr + sizeof(val) > vdev->config_len) { + return; + } + + stb_p(vdev->config + addr, val); + + if (k->set_config) { + k->set_config(vdev, vdev->config); + } +} + +void virtio_config_modern_writew(VirtIODevice *vdev, + uint32_t addr, uint32_t data) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint16_t val = data; + + if (addr + sizeof(val) > vdev->config_len) { + return; + } + + stw_le_p(vdev->config + addr, val); + + if (k->set_config) { + k->set_config(vdev, vdev->config); + } +} + +void virtio_config_modern_writel(VirtIODevice *vdev, + uint32_t addr, uint32_t data) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint32_t val = data; + + if (addr + sizeof(val) > vdev->config_len) { + return; + } + + stl_le_p(vdev->config + addr, val); + + if (k->set_config) { + k->set_config(vdev, vdev->config); + } +} + diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 7873083b86..70639300aa 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -19,6 +19,7 @@ #include "exec/memop.h" #include "standard-headers/linux/virtio_pci.h" +#include "standard-headers/linux/virtio_ids.h" #include "hw/boards.h" #include "hw/virtio/virtio.h" #include "migration/qemu-file-types.h" @@ -224,6 +225,90 @@ static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f) return 0; } +typedef struct VirtIOPCIIDInfo { + /* virtio id */ + uint16_t vdev_id; + /* pci device id for the transitional device */ + uint16_t trans_devid; + uint16_t class_id; +} VirtIOPCIIDInfo; + +static const VirtIOPCIIDInfo virtio_pci_id_info[] = { + { + .vdev_id = VIRTIO_ID_CRYPTO, + .class_id = PCI_CLASS_OTHERS, + }, { + .vdev_id = VIRTIO_ID_FS, + .class_id = PCI_CLASS_STORAGE_OTHER, + }, { + .vdev_id = VIRTIO_ID_NET, + .trans_devid = PCI_DEVICE_ID_VIRTIO_NET, + .class_id = PCI_CLASS_NETWORK_ETHERNET, + }, { + .vdev_id = VIRTIO_ID_BLOCK, + .trans_devid = PCI_DEVICE_ID_VIRTIO_BLOCK, + .class_id = PCI_CLASS_STORAGE_SCSI, + }, { + .vdev_id = VIRTIO_ID_CONSOLE, + .trans_devid = PCI_DEVICE_ID_VIRTIO_CONSOLE, + .class_id = PCI_CLASS_COMMUNICATION_OTHER, + }, { + .vdev_id = VIRTIO_ID_SCSI, + .trans_devid = PCI_DEVICE_ID_VIRTIO_SCSI, + .class_id = PCI_CLASS_STORAGE_SCSI + }, { + .vdev_id = VIRTIO_ID_9P, + .trans_devid = PCI_DEVICE_ID_VIRTIO_9P, + .class_id = PCI_BASE_CLASS_NETWORK, + }, { + .vdev_id = VIRTIO_ID_BALLOON, + .trans_devid = PCI_DEVICE_ID_VIRTIO_BALLOON, + .class_id = PCI_CLASS_OTHERS, + }, { + .vdev_id = VIRTIO_ID_RNG, + .trans_devid = PCI_DEVICE_ID_VIRTIO_RNG, + .class_id = PCI_CLASS_OTHERS, + }, +}; + +static const VirtIOPCIIDInfo *virtio_pci_get_id_info(uint16_t vdev_id) +{ + const VirtIOPCIIDInfo *info = NULL; + int i; + + for (i = 0; i < ARRAY_SIZE(virtio_pci_id_info); i++) { + if (virtio_pci_id_info[i].vdev_id == vdev_id) { + info = &virtio_pci_id_info[i]; + break; + } + } + + if (!info) { + /* The device id is invalid or not added to the id_info yet. */ + error_report("Invalid virtio device(id %u)", vdev_id); + abort(); + } + + return info; +} + +/* + * Get the Transitional Device ID for the specific device, return + * zero if the device is non-transitional. + */ +uint16_t virtio_pci_get_trans_devid(uint16_t device_id) +{ + return virtio_pci_get_id_info(device_id)->trans_devid; +} + +/* + * Get the Class ID for the specific device. + */ +uint16_t virtio_pci_get_class_id(uint16_t device_id) +{ + return virtio_pci_get_id_info(device_id)->class_id; +} + static bool virtio_pci_ioeventfd_enabled(DeviceState *d) { VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); @@ -1729,6 +1814,9 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) * is set to PCI_SUBVENDOR_ID_REDHAT_QUMRANET by default. */ pci_set_word(config + PCI_SUBSYSTEM_ID, virtio_bus_get_vdev_id(bus)); + if (proxy->trans_devid) { + pci_config_set_device_id(config, proxy->trans_devid); + } } else { /* pure virtio-1.0 */ pci_set_word(config + PCI_VENDOR_ID, diff --git a/hw/virtio/virtio-qmp.c b/hw/virtio/virtio-qmp.c new file mode 100644 index 0000000000..8e7282658f --- /dev/null +++ b/hw/virtio/virtio-qmp.c @@ -0,0 +1,659 @@ +/* + * Virtio QMP helpers + * + * Copyright IBM, Corp. 2007 + * + * Authors: + * Anthony Liguori + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/virtio/virtio.h" +#include "virtio-qmp.h" + +#include "standard-headers/linux/virtio_ids.h" +#include "standard-headers/linux/vhost_types.h" +#include "standard-headers/linux/virtio_blk.h" +#include "standard-headers/linux/virtio_console.h" +#include "standard-headers/linux/virtio_gpu.h" +#include "standard-headers/linux/virtio_net.h" +#include "standard-headers/linux/virtio_scsi.h" +#include "standard-headers/linux/virtio_i2c.h" +#include "standard-headers/linux/virtio_balloon.h" +#include "standard-headers/linux/virtio_iommu.h" +#include "standard-headers/linux/virtio_mem.h" +#include "standard-headers/linux/virtio_vsock.h" + +#include CONFIG_DEVICES + +#define FEATURE_ENTRY(name, desc) (qmp_virtio_feature_map_t) \ + { .virtio_bit = name, .feature_desc = desc } + +enum VhostUserProtocolFeature { + VHOST_USER_PROTOCOL_F_MQ = 0, + VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1, + VHOST_USER_PROTOCOL_F_RARP = 2, + VHOST_USER_PROTOCOL_F_REPLY_ACK = 3, + VHOST_USER_PROTOCOL_F_NET_MTU = 4, + VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5, + VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6, + VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7, + VHOST_USER_PROTOCOL_F_PAGEFAULT = 8, + VHOST_USER_PROTOCOL_F_CONFIG = 9, + VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD = 10, + VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11, + VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD = 12, + VHOST_USER_PROTOCOL_F_RESET_DEVICE = 13, + VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS = 14, + VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS = 15, + VHOST_USER_PROTOCOL_F_MAX +}; + +/* Virtio transport features mapping */ +static const qmp_virtio_feature_map_t virtio_transport_map[] = { + /* Virtio device transport features */ +#ifndef VIRTIO_CONFIG_NO_LEGACY + FEATURE_ENTRY(VIRTIO_F_NOTIFY_ON_EMPTY, \ + "VIRTIO_F_NOTIFY_ON_EMPTY: Notify when device runs out of avail. " + "descs. on VQ"), + FEATURE_ENTRY(VIRTIO_F_ANY_LAYOUT, \ + "VIRTIO_F_ANY_LAYOUT: Device accepts arbitrary desc. layouts"), +#endif /* !VIRTIO_CONFIG_NO_LEGACY */ + FEATURE_ENTRY(VIRTIO_F_VERSION_1, \ + "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)"), + FEATURE_ENTRY(VIRTIO_F_IOMMU_PLATFORM, \ + "VIRTIO_F_IOMMU_PLATFORM: Device can be used on IOMMU platform"), + FEATURE_ENTRY(VIRTIO_F_RING_PACKED, \ + "VIRTIO_F_RING_PACKED: Device supports packed VQ layout"), + FEATURE_ENTRY(VIRTIO_F_IN_ORDER, \ + "VIRTIO_F_IN_ORDER: Device uses buffers in same order as made " + "available by driver"), + FEATURE_ENTRY(VIRTIO_F_ORDER_PLATFORM, \ + "VIRTIO_F_ORDER_PLATFORM: Memory accesses ordered by platform"), + FEATURE_ENTRY(VIRTIO_F_SR_IOV, \ + "VIRTIO_F_SR_IOV: Device supports single root I/O virtualization"), + /* Virtio ring transport features */ + FEATURE_ENTRY(VIRTIO_RING_F_INDIRECT_DESC, \ + "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported"), + FEATURE_ENTRY(VIRTIO_RING_F_EVENT_IDX, \ + "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled"), + { -1, "" } +}; + +/* Vhost-user protocol features mapping */ +static const qmp_virtio_feature_map_t vhost_user_protocol_map[] = { + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_MQ, \ + "VHOST_USER_PROTOCOL_F_MQ: Multiqueue protocol supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_LOG_SHMFD, \ + "VHOST_USER_PROTOCOL_F_LOG_SHMFD: Shared log memory fd supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_RARP, \ + "VHOST_USER_PROTOCOL_F_RARP: Vhost-user back-end RARP broadcasting " + "supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_REPLY_ACK, \ + "VHOST_USER_PROTOCOL_F_REPLY_ACK: Requested operation status ack. " + "supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_NET_MTU, \ + "VHOST_USER_PROTOCOL_F_NET_MTU: Expose host MTU to guest supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_SLAVE_REQ, \ + "VHOST_USER_PROTOCOL_F_SLAVE_REQ: Socket fd for back-end initiated " + "requests supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CROSS_ENDIAN, \ + "VHOST_USER_PROTOCOL_F_CROSS_ENDIAN: Endianness of VQs for legacy " + "devices supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CRYPTO_SESSION, \ + "VHOST_USER_PROTOCOL_F_CRYPTO_SESSION: Session creation for crypto " + "operations supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_PAGEFAULT, \ + "VHOST_USER_PROTOCOL_F_PAGEFAULT: Request servicing on userfaultfd " + "for accessed pages supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CONFIG, \ + "VHOST_USER_PROTOCOL_F_CONFIG: Vhost-user messaging for virtio " + "device configuration space supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD, \ + "VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD: Slave fd communication " + "channel supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_HOST_NOTIFIER, \ + "VHOST_USER_PROTOCOL_F_HOST_NOTIFIER: Host notifiers for specified " + "VQs supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD, \ + "VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD: Shared inflight I/O buffers " + "supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_RESET_DEVICE, \ + "VHOST_USER_PROTOCOL_F_RESET_DEVICE: Disabling all rings and " + "resetting internal device state supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS, \ + "VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS: In-band messaging " + "supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS, \ + "VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS: Configuration for " + "memory slots supported"), + { -1, "" } +}; + +/* virtio device configuration statuses */ +static const qmp_virtio_feature_map_t virtio_config_status_map[] = { + FEATURE_ENTRY(VIRTIO_CONFIG_S_DRIVER_OK, \ + "VIRTIO_CONFIG_S_DRIVER_OK: Driver setup and ready"), + FEATURE_ENTRY(VIRTIO_CONFIG_S_FEATURES_OK, \ + "VIRTIO_CONFIG_S_FEATURES_OK: Feature negotiation complete"), + FEATURE_ENTRY(VIRTIO_CONFIG_S_DRIVER, \ + "VIRTIO_CONFIG_S_DRIVER: Guest OS compatible with device"), + FEATURE_ENTRY(VIRTIO_CONFIG_S_NEEDS_RESET, \ + "VIRTIO_CONFIG_S_NEEDS_RESET: Irrecoverable error, device needs " + "reset"), + FEATURE_ENTRY(VIRTIO_CONFIG_S_FAILED, \ + "VIRTIO_CONFIG_S_FAILED: Error in guest, device failed"), + FEATURE_ENTRY(VIRTIO_CONFIG_S_ACKNOWLEDGE, \ + "VIRTIO_CONFIG_S_ACKNOWLEDGE: Valid virtio device found"), + { -1, "" } +}; + +/* virtio-blk features mapping */ +#ifdef CONFIG_VIRTIO_BLK +static const qmp_virtio_feature_map_t virtio_blk_feature_map[] = { + FEATURE_ENTRY(VIRTIO_BLK_F_SIZE_MAX, \ + "VIRTIO_BLK_F_SIZE_MAX: Max segment size is size_max"), + FEATURE_ENTRY(VIRTIO_BLK_F_SEG_MAX, \ + "VIRTIO_BLK_F_SEG_MAX: Max segments in a request is seg_max"), + FEATURE_ENTRY(VIRTIO_BLK_F_GEOMETRY, \ + "VIRTIO_BLK_F_GEOMETRY: Legacy geometry available"), + FEATURE_ENTRY(VIRTIO_BLK_F_RO, \ + "VIRTIO_BLK_F_RO: Device is read-only"), + FEATURE_ENTRY(VIRTIO_BLK_F_BLK_SIZE, \ + "VIRTIO_BLK_F_BLK_SIZE: Block size of disk available"), + FEATURE_ENTRY(VIRTIO_BLK_F_TOPOLOGY, \ + "VIRTIO_BLK_F_TOPOLOGY: Topology information available"), + FEATURE_ENTRY(VIRTIO_BLK_F_MQ, \ + "VIRTIO_BLK_F_MQ: Multiqueue supported"), + FEATURE_ENTRY(VIRTIO_BLK_F_DISCARD, \ + "VIRTIO_BLK_F_DISCARD: Discard command supported"), + FEATURE_ENTRY(VIRTIO_BLK_F_WRITE_ZEROES, \ + "VIRTIO_BLK_F_WRITE_ZEROES: Write zeroes command supported"), +#ifndef VIRTIO_BLK_NO_LEGACY + FEATURE_ENTRY(VIRTIO_BLK_F_BARRIER, \ + "VIRTIO_BLK_F_BARRIER: Request barriers supported"), + FEATURE_ENTRY(VIRTIO_BLK_F_SCSI, \ + "VIRTIO_BLK_F_SCSI: SCSI packet commands supported"), + FEATURE_ENTRY(VIRTIO_BLK_F_FLUSH, \ + "VIRTIO_BLK_F_FLUSH: Flush command supported"), + FEATURE_ENTRY(VIRTIO_BLK_F_CONFIG_WCE, \ + "VIRTIO_BLK_F_CONFIG_WCE: Cache writeback and writethrough modes " + "supported"), +#endif /* !VIRTIO_BLK_NO_LEGACY */ + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; +#endif + +/* virtio-serial features mapping */ +#ifdef CONFIG_VIRTIO_SERIAL +static const qmp_virtio_feature_map_t virtio_serial_feature_map[] = { + FEATURE_ENTRY(VIRTIO_CONSOLE_F_SIZE, \ + "VIRTIO_CONSOLE_F_SIZE: Host providing console size"), + FEATURE_ENTRY(VIRTIO_CONSOLE_F_MULTIPORT, \ + "VIRTIO_CONSOLE_F_MULTIPORT: Multiple ports for device supported"), + FEATURE_ENTRY(VIRTIO_CONSOLE_F_EMERG_WRITE, \ + "VIRTIO_CONSOLE_F_EMERG_WRITE: Emergency write supported"), + { -1, "" } +}; +#endif + +/* virtio-gpu features mapping */ +#ifdef CONFIG_VIRTIO_GPU +static const qmp_virtio_feature_map_t virtio_gpu_feature_map[] = { + FEATURE_ENTRY(VIRTIO_GPU_F_VIRGL, \ + "VIRTIO_GPU_F_VIRGL: Virgl 3D mode supported"), + FEATURE_ENTRY(VIRTIO_GPU_F_EDID, \ + "VIRTIO_GPU_F_EDID: EDID metadata supported"), + FEATURE_ENTRY(VIRTIO_GPU_F_RESOURCE_UUID, \ + "VIRTIO_GPU_F_RESOURCE_UUID: Resource UUID assigning supported"), + FEATURE_ENTRY(VIRTIO_GPU_F_RESOURCE_BLOB, \ + "VIRTIO_GPU_F_RESOURCE_BLOB: Size-based blob resources supported"), + FEATURE_ENTRY(VIRTIO_GPU_F_CONTEXT_INIT, \ + "VIRTIO_GPU_F_CONTEXT_INIT: Context types and synchronization " + "timelines supported"), + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; +#endif + +/* virtio-input features mapping */ +#ifdef CONFIG_VIRTIO_INPUT +static const qmp_virtio_feature_map_t virtio_input_feature_map[] = { + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; +#endif + +/* virtio-net features mapping */ +#ifdef CONFIG_VIRTIO_NET +static const qmp_virtio_feature_map_t virtio_net_feature_map[] = { + FEATURE_ENTRY(VIRTIO_NET_F_CSUM, \ + "VIRTIO_NET_F_CSUM: Device handling packets with partial checksum " + "supported"), + FEATURE_ENTRY(VIRTIO_NET_F_GUEST_CSUM, \ + "VIRTIO_NET_F_GUEST_CSUM: Driver handling packets with partial " + "checksum supported"), + FEATURE_ENTRY(VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \ + "VIRTIO_NET_F_CTRL_GUEST_OFFLOADS: Control channel offloading " + "reconfig. supported"), + FEATURE_ENTRY(VIRTIO_NET_F_MTU, \ + "VIRTIO_NET_F_MTU: Device max MTU reporting supported"), + FEATURE_ENTRY(VIRTIO_NET_F_MAC, \ + "VIRTIO_NET_F_MAC: Device has given MAC address"), + FEATURE_ENTRY(VIRTIO_NET_F_GUEST_TSO4, \ + "VIRTIO_NET_F_GUEST_TSO4: Driver can receive TSOv4"), + FEATURE_ENTRY(VIRTIO_NET_F_GUEST_TSO6, \ + "VIRTIO_NET_F_GUEST_TSO6: Driver can receive TSOv6"), + FEATURE_ENTRY(VIRTIO_NET_F_GUEST_ECN, \ + "VIRTIO_NET_F_GUEST_ECN: Driver can receive TSO with ECN"), + FEATURE_ENTRY(VIRTIO_NET_F_GUEST_UFO, \ + "VIRTIO_NET_F_GUEST_UFO: Driver can receive UFO"), + FEATURE_ENTRY(VIRTIO_NET_F_HOST_TSO4, \ + "VIRTIO_NET_F_HOST_TSO4: Device can receive TSOv4"), + FEATURE_ENTRY(VIRTIO_NET_F_HOST_TSO6, \ + "VIRTIO_NET_F_HOST_TSO6: Device can receive TSOv6"), + FEATURE_ENTRY(VIRTIO_NET_F_HOST_ECN, \ + "VIRTIO_NET_F_HOST_ECN: Device can receive TSO with ECN"), + FEATURE_ENTRY(VIRTIO_NET_F_HOST_UFO, \ + "VIRTIO_NET_F_HOST_UFO: Device can receive UFO"), + FEATURE_ENTRY(VIRTIO_NET_F_MRG_RXBUF, \ + "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers"), + FEATURE_ENTRY(VIRTIO_NET_F_STATUS, \ + "VIRTIO_NET_F_STATUS: Configuration status field available"), + FEATURE_ENTRY(VIRTIO_NET_F_CTRL_VQ, \ + "VIRTIO_NET_F_CTRL_VQ: Control channel available"), + FEATURE_ENTRY(VIRTIO_NET_F_CTRL_RX, \ + "VIRTIO_NET_F_CTRL_RX: Control channel RX mode supported"), + FEATURE_ENTRY(VIRTIO_NET_F_CTRL_VLAN, \ + "VIRTIO_NET_F_CTRL_VLAN: Control channel VLAN filtering supported"), + FEATURE_ENTRY(VIRTIO_NET_F_CTRL_RX_EXTRA, \ + "VIRTIO_NET_F_CTRL_RX_EXTRA: Extra RX mode control supported"), + FEATURE_ENTRY(VIRTIO_NET_F_GUEST_ANNOUNCE, \ + "VIRTIO_NET_F_GUEST_ANNOUNCE: Driver sending gratuitous packets " + "supported"), + FEATURE_ENTRY(VIRTIO_NET_F_MQ, \ + "VIRTIO_NET_F_MQ: Multiqueue with automatic receive steering " + "supported"), + FEATURE_ENTRY(VIRTIO_NET_F_CTRL_MAC_ADDR, \ + "VIRTIO_NET_F_CTRL_MAC_ADDR: MAC address set through control " + "channel"), + FEATURE_ENTRY(VIRTIO_NET_F_HASH_REPORT, \ + "VIRTIO_NET_F_HASH_REPORT: Hash reporting supported"), + FEATURE_ENTRY(VIRTIO_NET_F_RSS, \ + "VIRTIO_NET_F_RSS: RSS RX steering supported"), + FEATURE_ENTRY(VIRTIO_NET_F_RSC_EXT, \ + "VIRTIO_NET_F_RSC_EXT: Extended coalescing info supported"), + FEATURE_ENTRY(VIRTIO_NET_F_STANDBY, \ + "VIRTIO_NET_F_STANDBY: Device acting as standby for primary " + "device with same MAC addr. supported"), + FEATURE_ENTRY(VIRTIO_NET_F_SPEED_DUPLEX, \ + "VIRTIO_NET_F_SPEED_DUPLEX: Device set linkspeed and duplex"), +#ifndef VIRTIO_NET_NO_LEGACY + FEATURE_ENTRY(VIRTIO_NET_F_GSO, \ + "VIRTIO_NET_F_GSO: Handling GSO-type packets supported"), +#endif /* !VIRTIO_NET_NO_LEGACY */ + FEATURE_ENTRY(VHOST_NET_F_VIRTIO_NET_HDR, \ + "VHOST_NET_F_VIRTIO_NET_HDR: Virtio-net headers for RX and TX " + "packets supported"), + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; +#endif + +/* virtio-scsi features mapping */ +#ifdef CONFIG_VIRTIO_SCSI +static const qmp_virtio_feature_map_t virtio_scsi_feature_map[] = { + FEATURE_ENTRY(VIRTIO_SCSI_F_INOUT, \ + "VIRTIO_SCSI_F_INOUT: Requests including read and writable data " + "buffers suppoted"), + FEATURE_ENTRY(VIRTIO_SCSI_F_HOTPLUG, \ + "VIRTIO_SCSI_F_HOTPLUG: Reporting and handling hot-plug events " + "supported"), + FEATURE_ENTRY(VIRTIO_SCSI_F_CHANGE, \ + "VIRTIO_SCSI_F_CHANGE: Reporting and handling LUN changes " + "supported"), + FEATURE_ENTRY(VIRTIO_SCSI_F_T10_PI, \ + "VIRTIO_SCSI_F_T10_PI: T10 info included in request header"), + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; +#endif + +/* virtio/vhost-user-fs features mapping */ +#ifdef CONFIG_VHOST_USER_FS +static const qmp_virtio_feature_map_t virtio_fs_feature_map[] = { + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; +#endif + +/* virtio/vhost-user-i2c features mapping */ +#ifdef CONFIG_VIRTIO_I2C_ADAPTER +static const qmp_virtio_feature_map_t virtio_i2c_feature_map[] = { + FEATURE_ENTRY(VIRTIO_I2C_F_ZERO_LENGTH_REQUEST, \ + "VIRTIO_I2C_F_ZERO_LEGNTH_REQUEST: Zero length requests supported"), + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; +#endif + +/* virtio/vhost-vsock features mapping */ +#ifdef CONFIG_VHOST_VSOCK +static const qmp_virtio_feature_map_t virtio_vsock_feature_map[] = { + FEATURE_ENTRY(VIRTIO_VSOCK_F_SEQPACKET, \ + "VIRTIO_VSOCK_F_SEQPACKET: SOCK_SEQPACKET supported"), + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; +#endif + +/* virtio-balloon features mapping */ +#ifdef CONFIG_VIRTIO_BALLOON +static const qmp_virtio_feature_map_t virtio_balloon_feature_map[] = { + FEATURE_ENTRY(VIRTIO_BALLOON_F_MUST_TELL_HOST, \ + "VIRTIO_BALLOON_F_MUST_TELL_HOST: Tell host before reclaiming " + "pages"), + FEATURE_ENTRY(VIRTIO_BALLOON_F_STATS_VQ, \ + "VIRTIO_BALLOON_F_STATS_VQ: Guest memory stats VQ available"), + FEATURE_ENTRY(VIRTIO_BALLOON_F_DEFLATE_ON_OOM, \ + "VIRTIO_BALLOON_F_DEFLATE_ON_OOM: Deflate balloon when guest OOM"), + FEATURE_ENTRY(VIRTIO_BALLOON_F_FREE_PAGE_HINT, \ + "VIRTIO_BALLOON_F_FREE_PAGE_HINT: VQ reporting free pages enabled"), + FEATURE_ENTRY(VIRTIO_BALLOON_F_PAGE_POISON, \ + "VIRTIO_BALLOON_F_PAGE_POISON: Guest page poisoning enabled"), + FEATURE_ENTRY(VIRTIO_BALLOON_F_REPORTING, \ + "VIRTIO_BALLOON_F_REPORTING: Page reporting VQ enabled"), + { -1, "" } +}; +#endif + +/* virtio-crypto features mapping */ +#ifdef CONFIG_VIRTIO_CRYPTO +static const qmp_virtio_feature_map_t virtio_crypto_feature_map[] = { + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + { -1, "" } +}; +#endif + +/* virtio-iommu features mapping */ +#ifdef CONFIG_VIRTIO_IOMMU +static const qmp_virtio_feature_map_t virtio_iommu_feature_map[] = { + FEATURE_ENTRY(VIRTIO_IOMMU_F_INPUT_RANGE, \ + "VIRTIO_IOMMU_F_INPUT_RANGE: Range of available virtual addrs. " + "available"), + FEATURE_ENTRY(VIRTIO_IOMMU_F_DOMAIN_RANGE, \ + "VIRTIO_IOMMU_F_DOMAIN_RANGE: Number of supported domains " + "available"), + FEATURE_ENTRY(VIRTIO_IOMMU_F_MAP_UNMAP, \ + "VIRTIO_IOMMU_F_MAP_UNMAP: Map and unmap requests available"), + FEATURE_ENTRY(VIRTIO_IOMMU_F_BYPASS, \ + "VIRTIO_IOMMU_F_BYPASS: Endpoints not attached to domains are in " + "bypass mode"), + FEATURE_ENTRY(VIRTIO_IOMMU_F_PROBE, \ + "VIRTIO_IOMMU_F_PROBE: Probe requests available"), + FEATURE_ENTRY(VIRTIO_IOMMU_F_MMIO, \ + "VIRTIO_IOMMU_F_MMIO: VIRTIO_IOMMU_MAP_F_MMIO flag available"), + FEATURE_ENTRY(VIRTIO_IOMMU_F_BYPASS_CONFIG, \ + "VIRTIO_IOMMU_F_BYPASS_CONFIG: Bypass field of IOMMU config " + "available"), + { -1, "" } +}; +#endif + +/* virtio-mem features mapping */ +#ifdef CONFIG_VIRTIO_MEM +static const qmp_virtio_feature_map_t virtio_mem_feature_map[] = { +#ifndef CONFIG_ACPI + FEATURE_ENTRY(VIRTIO_MEM_F_ACPI_PXM, \ + "VIRTIO_MEM_F_ACPI_PXM: node_id is an ACPI PXM and is valid"), +#endif /* !CONFIG_ACPI */ + FEATURE_ENTRY(VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, \ + "VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE: Unplugged memory cannot be " + "accessed"), + { -1, "" } +}; +#endif + +/* virtio-rng features mapping */ +#ifdef CONFIG_VIRTIO_RNG +static const qmp_virtio_feature_map_t virtio_rng_feature_map[] = { + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; +#endif + +#define CONVERT_FEATURES(type, map, is_status, bitmap) \ + ({ \ + type *list = NULL; \ + type *node; \ + for (i = 0; map[i].virtio_bit != -1; i++) { \ + if (is_status) { \ + bit = map[i].virtio_bit; \ + } \ + else { \ + bit = 1ULL << map[i].virtio_bit; \ + } \ + if ((bitmap & bit) == 0) { \ + continue; \ + } \ + node = g_new0(type, 1); \ + node->value = g_strdup(map[i].feature_desc); \ + node->next = list; \ + list = node; \ + bitmap ^= bit; \ + } \ + list; \ + }) + +VirtioDeviceStatus *qmp_decode_status(uint8_t bitmap) +{ + VirtioDeviceStatus *status; + uint8_t bit; + int i; + + status = g_new0(VirtioDeviceStatus, 1); + status->statuses = CONVERT_FEATURES(strList, virtio_config_status_map, + 1, bitmap); + status->has_unknown_statuses = bitmap != 0; + if (status->has_unknown_statuses) { + status->unknown_statuses = bitmap; + } + + return status; +} + +VhostDeviceProtocols *qmp_decode_protocols(uint64_t bitmap) +{ + VhostDeviceProtocols *vhu_protocols; + uint64_t bit; + int i; + + vhu_protocols = g_new0(VhostDeviceProtocols, 1); + vhu_protocols->protocols = + CONVERT_FEATURES(strList, + vhost_user_protocol_map, 0, bitmap); + vhu_protocols->has_unknown_protocols = bitmap != 0; + if (vhu_protocols->has_unknown_protocols) { + vhu_protocols->unknown_protocols = bitmap; + } + + return vhu_protocols; +} + +VirtioDeviceFeatures *qmp_decode_features(uint16_t device_id, uint64_t bitmap) +{ + VirtioDeviceFeatures *features; + uint64_t bit; + int i; + + features = g_new0(VirtioDeviceFeatures, 1); + features->has_dev_features = true; + + /* transport features */ + features->transports = CONVERT_FEATURES(strList, virtio_transport_map, 0, + bitmap); + + /* device features */ + switch (device_id) { +#ifdef CONFIG_VIRTIO_SERIAL + case VIRTIO_ID_CONSOLE: + features->dev_features = + CONVERT_FEATURES(strList, virtio_serial_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_BLK + case VIRTIO_ID_BLOCK: + features->dev_features = + CONVERT_FEATURES(strList, virtio_blk_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_GPU + case VIRTIO_ID_GPU: + features->dev_features = + CONVERT_FEATURES(strList, virtio_gpu_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_NET + case VIRTIO_ID_NET: + features->dev_features = + CONVERT_FEATURES(strList, virtio_net_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_SCSI + case VIRTIO_ID_SCSI: + features->dev_features = + CONVERT_FEATURES(strList, virtio_scsi_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_BALLOON + case VIRTIO_ID_BALLOON: + features->dev_features = + CONVERT_FEATURES(strList, virtio_balloon_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_IOMMU + case VIRTIO_ID_IOMMU: + features->dev_features = + CONVERT_FEATURES(strList, virtio_iommu_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_INPUT + case VIRTIO_ID_INPUT: + features->dev_features = + CONVERT_FEATURES(strList, virtio_input_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VHOST_USER_FS + case VIRTIO_ID_FS: + features->dev_features = + CONVERT_FEATURES(strList, virtio_fs_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VHOST_VSOCK + case VIRTIO_ID_VSOCK: + features->dev_features = + CONVERT_FEATURES(strList, virtio_vsock_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_CRYPTO + case VIRTIO_ID_CRYPTO: + features->dev_features = + CONVERT_FEATURES(strList, virtio_crypto_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_MEM + case VIRTIO_ID_MEM: + features->dev_features = + CONVERT_FEATURES(strList, virtio_mem_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_I2C_ADAPTER + case VIRTIO_ID_I2C_ADAPTER: + features->dev_features = + CONVERT_FEATURES(strList, virtio_i2c_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_RNG + case VIRTIO_ID_RNG: + features->dev_features = + CONVERT_FEATURES(strList, virtio_rng_feature_map, 0, bitmap); + break; +#endif + /* No features */ + case VIRTIO_ID_9P: + case VIRTIO_ID_PMEM: + case VIRTIO_ID_IOMEM: + case VIRTIO_ID_RPMSG: + case VIRTIO_ID_CLOCK: + case VIRTIO_ID_MAC80211_WLAN: + case VIRTIO_ID_MAC80211_HWSIM: + case VIRTIO_ID_RPROC_SERIAL: + case VIRTIO_ID_MEMORY_BALLOON: + case VIRTIO_ID_CAIF: + case VIRTIO_ID_SIGNAL_DIST: + case VIRTIO_ID_PSTORE: + case VIRTIO_ID_SOUND: + case VIRTIO_ID_BT: + case VIRTIO_ID_RPMB: + case VIRTIO_ID_VIDEO_ENCODER: + case VIRTIO_ID_VIDEO_DECODER: + case VIRTIO_ID_SCMI: + case VIRTIO_ID_NITRO_SEC_MOD: + case VIRTIO_ID_WATCHDOG: + case VIRTIO_ID_CAN: + case VIRTIO_ID_DMABUF: + case VIRTIO_ID_PARAM_SERV: + case VIRTIO_ID_AUDIO_POLICY: + case VIRTIO_ID_GPIO: + break; + default: + g_assert_not_reached(); + } + + features->has_unknown_dev_features = bitmap != 0; + if (features->has_unknown_dev_features) { + features->unknown_dev_features = bitmap; + } + + return features; +} diff --git a/hw/virtio/virtio-qmp.h b/hw/virtio/virtio-qmp.h new file mode 100644 index 0000000000..075fc27030 --- /dev/null +++ b/hw/virtio/virtio-qmp.h @@ -0,0 +1,20 @@ +/* + * Virtio QMP helpers + * + * Copyright IBM, Corp. 2007 + * + * Authors: + * Anthony Liguori + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef HW_VIRTIO_QMP_H +#define HW_VIRTIO_QMP_H + +#include "qapi/qapi-types-virtio.h" + +VirtioDeviceStatus *qmp_decode_status(uint8_t bitmap); +VhostDeviceProtocols *qmp_decode_protocols(uint64_t bitmap); +VirtioDeviceFeatures *qmp_decode_features(uint16_t device_id, uint64_t bitmap); + +#endif diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 2118efbe72..289eb71045 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -16,15 +16,14 @@ #include "qapi/qmp/qdict.h" #include "qapi/qapi-commands-virtio.h" #include "qapi/qapi-commands-qom.h" -#include "qapi/qapi-visit-virtio.h" #include "qapi/qmp/qjson.h" -#include "cpu.h" #include "trace.h" #include "qemu/error-report.h" #include "qemu/log.h" #include "qemu/main-loop.h" #include "qemu/module.h" #include "qom/object_interfaces.h" +#include "hw/core/cpu.h" #include "hw/virtio/virtio.h" #include "migration/qemu-file-types.h" #include "qemu/atomic.h" @@ -33,6 +32,8 @@ #include "hw/virtio/virtio-access.h" #include "sysemu/dma.h" #include "sysemu/runstate.h" +#include "virtio-qmp.h" + #include "standard-headers/linux/virtio_ids.h" #include "standard-headers/linux/vhost_types.h" #include "standard-headers/linux/virtio_blk.h" @@ -45,7 +46,6 @@ #include "standard-headers/linux/virtio_iommu.h" #include "standard-headers/linux/virtio_mem.h" #include "standard-headers/linux/virtio_vsock.h" -#include CONFIG_DEVICES /* QAPI list of realized VirtIODevices */ static QTAILQ_HEAD(, VirtIODevice) virtio_list; @@ -55,412 +55,6 @@ static QTAILQ_HEAD(, VirtIODevice) virtio_list; */ #define VHOST_USER_MAX_CONFIG_SIZE 256 -#define FEATURE_ENTRY(name, desc) (qmp_virtio_feature_map_t) \ - { .virtio_bit = name, .feature_desc = desc } - -enum VhostUserProtocolFeature { - VHOST_USER_PROTOCOL_F_MQ = 0, - VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1, - VHOST_USER_PROTOCOL_F_RARP = 2, - VHOST_USER_PROTOCOL_F_REPLY_ACK = 3, - VHOST_USER_PROTOCOL_F_NET_MTU = 4, - VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5, - VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6, - VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7, - VHOST_USER_PROTOCOL_F_PAGEFAULT = 8, - VHOST_USER_PROTOCOL_F_CONFIG = 9, - VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD = 10, - VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11, - VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD = 12, - VHOST_USER_PROTOCOL_F_RESET_DEVICE = 13, - VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS = 14, - VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS = 15, - VHOST_USER_PROTOCOL_F_MAX -}; - -/* Virtio transport features mapping */ -static qmp_virtio_feature_map_t virtio_transport_map[] = { - /* Virtio device transport features */ -#ifndef VIRTIO_CONFIG_NO_LEGACY - FEATURE_ENTRY(VIRTIO_F_NOTIFY_ON_EMPTY, \ - "VIRTIO_F_NOTIFY_ON_EMPTY: Notify when device runs out of avail. " - "descs. on VQ"), - FEATURE_ENTRY(VIRTIO_F_ANY_LAYOUT, \ - "VIRTIO_F_ANY_LAYOUT: Device accepts arbitrary desc. layouts"), -#endif /* !VIRTIO_CONFIG_NO_LEGACY */ - FEATURE_ENTRY(VIRTIO_F_VERSION_1, \ - "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)"), - FEATURE_ENTRY(VIRTIO_F_IOMMU_PLATFORM, \ - "VIRTIO_F_IOMMU_PLATFORM: Device can be used on IOMMU platform"), - FEATURE_ENTRY(VIRTIO_F_RING_PACKED, \ - "VIRTIO_F_RING_PACKED: Device supports packed VQ layout"), - FEATURE_ENTRY(VIRTIO_F_IN_ORDER, \ - "VIRTIO_F_IN_ORDER: Device uses buffers in same order as made " - "available by driver"), - FEATURE_ENTRY(VIRTIO_F_ORDER_PLATFORM, \ - "VIRTIO_F_ORDER_PLATFORM: Memory accesses ordered by platform"), - FEATURE_ENTRY(VIRTIO_F_SR_IOV, \ - "VIRTIO_F_SR_IOV: Device supports single root I/O virtualization"), - /* Virtio ring transport features */ - FEATURE_ENTRY(VIRTIO_RING_F_INDIRECT_DESC, \ - "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported"), - FEATURE_ENTRY(VIRTIO_RING_F_EVENT_IDX, \ - "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled"), - { -1, "" } -}; - -/* Vhost-user protocol features mapping */ -static qmp_virtio_feature_map_t vhost_user_protocol_map[] = { - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_MQ, \ - "VHOST_USER_PROTOCOL_F_MQ: Multiqueue protocol supported"), - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_LOG_SHMFD, \ - "VHOST_USER_PROTOCOL_F_LOG_SHMFD: Shared log memory fd supported"), - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_RARP, \ - "VHOST_USER_PROTOCOL_F_RARP: Vhost-user back-end RARP broadcasting " - "supported"), - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_REPLY_ACK, \ - "VHOST_USER_PROTOCOL_F_REPLY_ACK: Requested operation status ack. " - "supported"), - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_NET_MTU, \ - "VHOST_USER_PROTOCOL_F_NET_MTU: Expose host MTU to guest supported"), - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_SLAVE_REQ, \ - "VHOST_USER_PROTOCOL_F_SLAVE_REQ: Socket fd for back-end initiated " - "requests supported"), - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CROSS_ENDIAN, \ - "VHOST_USER_PROTOCOL_F_CROSS_ENDIAN: Endianness of VQs for legacy " - "devices supported"), - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CRYPTO_SESSION, \ - "VHOST_USER_PROTOCOL_F_CRYPTO_SESSION: Session creation for crypto " - "operations supported"), - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_PAGEFAULT, \ - "VHOST_USER_PROTOCOL_F_PAGEFAULT: Request servicing on userfaultfd " - "for accessed pages supported"), - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CONFIG, \ - "VHOST_USER_PROTOCOL_F_CONFIG: Vhost-user messaging for virtio " - "device configuration space supported"), - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD, \ - "VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD: Slave fd communication " - "channel supported"), - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_HOST_NOTIFIER, \ - "VHOST_USER_PROTOCOL_F_HOST_NOTIFIER: Host notifiers for specified " - "VQs supported"), - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD, \ - "VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD: Shared inflight I/O buffers " - "supported"), - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_RESET_DEVICE, \ - "VHOST_USER_PROTOCOL_F_RESET_DEVICE: Disabling all rings and " - "resetting internal device state supported"), - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS, \ - "VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS: In-band messaging " - "supported"), - FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS, \ - "VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS: Configuration for " - "memory slots supported"), - { -1, "" } -}; - -/* virtio device configuration statuses */ -static qmp_virtio_feature_map_t virtio_config_status_map[] = { - FEATURE_ENTRY(VIRTIO_CONFIG_S_DRIVER_OK, \ - "VIRTIO_CONFIG_S_DRIVER_OK: Driver setup and ready"), - FEATURE_ENTRY(VIRTIO_CONFIG_S_FEATURES_OK, \ - "VIRTIO_CONFIG_S_FEATURES_OK: Feature negotiation complete"), - FEATURE_ENTRY(VIRTIO_CONFIG_S_DRIVER, \ - "VIRTIO_CONFIG_S_DRIVER: Guest OS compatible with device"), - FEATURE_ENTRY(VIRTIO_CONFIG_S_NEEDS_RESET, \ - "VIRTIO_CONFIG_S_NEEDS_RESET: Irrecoverable error, device needs " - "reset"), - FEATURE_ENTRY(VIRTIO_CONFIG_S_FAILED, \ - "VIRTIO_CONFIG_S_FAILED: Error in guest, device failed"), - FEATURE_ENTRY(VIRTIO_CONFIG_S_ACKNOWLEDGE, \ - "VIRTIO_CONFIG_S_ACKNOWLEDGE: Valid virtio device found"), - { -1, "" } -}; - -/* virtio-blk features mapping */ -qmp_virtio_feature_map_t virtio_blk_feature_map[] = { - FEATURE_ENTRY(VIRTIO_BLK_F_SIZE_MAX, \ - "VIRTIO_BLK_F_SIZE_MAX: Max segment size is size_max"), - FEATURE_ENTRY(VIRTIO_BLK_F_SEG_MAX, \ - "VIRTIO_BLK_F_SEG_MAX: Max segments in a request is seg_max"), - FEATURE_ENTRY(VIRTIO_BLK_F_GEOMETRY, \ - "VIRTIO_BLK_F_GEOMETRY: Legacy geometry available"), - FEATURE_ENTRY(VIRTIO_BLK_F_RO, \ - "VIRTIO_BLK_F_RO: Device is read-only"), - FEATURE_ENTRY(VIRTIO_BLK_F_BLK_SIZE, \ - "VIRTIO_BLK_F_BLK_SIZE: Block size of disk available"), - FEATURE_ENTRY(VIRTIO_BLK_F_TOPOLOGY, \ - "VIRTIO_BLK_F_TOPOLOGY: Topology information available"), - FEATURE_ENTRY(VIRTIO_BLK_F_MQ, \ - "VIRTIO_BLK_F_MQ: Multiqueue supported"), - FEATURE_ENTRY(VIRTIO_BLK_F_DISCARD, \ - "VIRTIO_BLK_F_DISCARD: Discard command supported"), - FEATURE_ENTRY(VIRTIO_BLK_F_WRITE_ZEROES, \ - "VIRTIO_BLK_F_WRITE_ZEROES: Write zeroes command supported"), -#ifndef VIRTIO_BLK_NO_LEGACY - FEATURE_ENTRY(VIRTIO_BLK_F_BARRIER, \ - "VIRTIO_BLK_F_BARRIER: Request barriers supported"), - FEATURE_ENTRY(VIRTIO_BLK_F_SCSI, \ - "VIRTIO_BLK_F_SCSI: SCSI packet commands supported"), - FEATURE_ENTRY(VIRTIO_BLK_F_FLUSH, \ - "VIRTIO_BLK_F_FLUSH: Flush command supported"), - FEATURE_ENTRY(VIRTIO_BLK_F_CONFIG_WCE, \ - "VIRTIO_BLK_F_CONFIG_WCE: Cache writeback and writethrough modes " - "supported"), -#endif /* !VIRTIO_BLK_NO_LEGACY */ - FEATURE_ENTRY(VHOST_F_LOG_ALL, \ - "VHOST_F_LOG_ALL: Logging write descriptors supported"), - FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ - "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " - "negotiation supported"), - { -1, "" } -}; - -/* virtio-serial features mapping */ -qmp_virtio_feature_map_t virtio_serial_feature_map[] = { - FEATURE_ENTRY(VIRTIO_CONSOLE_F_SIZE, \ - "VIRTIO_CONSOLE_F_SIZE: Host providing console size"), - FEATURE_ENTRY(VIRTIO_CONSOLE_F_MULTIPORT, \ - "VIRTIO_CONSOLE_F_MULTIPORT: Multiple ports for device supported"), - FEATURE_ENTRY(VIRTIO_CONSOLE_F_EMERG_WRITE, \ - "VIRTIO_CONSOLE_F_EMERG_WRITE: Emergency write supported"), - { -1, "" } -}; - -/* virtio-gpu features mapping */ -qmp_virtio_feature_map_t virtio_gpu_feature_map[] = { - FEATURE_ENTRY(VIRTIO_GPU_F_VIRGL, \ - "VIRTIO_GPU_F_VIRGL: Virgl 3D mode supported"), - FEATURE_ENTRY(VIRTIO_GPU_F_EDID, \ - "VIRTIO_GPU_F_EDID: EDID metadata supported"), - FEATURE_ENTRY(VIRTIO_GPU_F_RESOURCE_UUID, \ - "VIRTIO_GPU_F_RESOURCE_UUID: Resource UUID assigning supported"), - FEATURE_ENTRY(VIRTIO_GPU_F_RESOURCE_BLOB, \ - "VIRTIO_GPU_F_RESOURCE_BLOB: Size-based blob resources supported"), - FEATURE_ENTRY(VIRTIO_GPU_F_CONTEXT_INIT, \ - "VIRTIO_GPU_F_CONTEXT_INIT: Context types and synchronization " - "timelines supported"), - FEATURE_ENTRY(VHOST_F_LOG_ALL, \ - "VHOST_F_LOG_ALL: Logging write descriptors supported"), - FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ - "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " - "negotiation supported"), - { -1, "" } -}; - -/* virtio-input features mapping */ -qmp_virtio_feature_map_t virtio_input_feature_map[] = { - FEATURE_ENTRY(VHOST_F_LOG_ALL, \ - "VHOST_F_LOG_ALL: Logging write descriptors supported"), - FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ - "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " - "negotiation supported"), - { -1, "" } -}; - -/* virtio-net features mapping */ -qmp_virtio_feature_map_t virtio_net_feature_map[] = { - FEATURE_ENTRY(VIRTIO_NET_F_CSUM, \ - "VIRTIO_NET_F_CSUM: Device handling packets with partial checksum " - "supported"), - FEATURE_ENTRY(VIRTIO_NET_F_GUEST_CSUM, \ - "VIRTIO_NET_F_GUEST_CSUM: Driver handling packets with partial " - "checksum supported"), - FEATURE_ENTRY(VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \ - "VIRTIO_NET_F_CTRL_GUEST_OFFLOADS: Control channel offloading " - "reconfig. supported"), - FEATURE_ENTRY(VIRTIO_NET_F_MTU, \ - "VIRTIO_NET_F_MTU: Device max MTU reporting supported"), - FEATURE_ENTRY(VIRTIO_NET_F_MAC, \ - "VIRTIO_NET_F_MAC: Device has given MAC address"), - FEATURE_ENTRY(VIRTIO_NET_F_GUEST_TSO4, \ - "VIRTIO_NET_F_GUEST_TSO4: Driver can receive TSOv4"), - FEATURE_ENTRY(VIRTIO_NET_F_GUEST_TSO6, \ - "VIRTIO_NET_F_GUEST_TSO6: Driver can receive TSOv6"), - FEATURE_ENTRY(VIRTIO_NET_F_GUEST_ECN, \ - "VIRTIO_NET_F_GUEST_ECN: Driver can receive TSO with ECN"), - FEATURE_ENTRY(VIRTIO_NET_F_GUEST_UFO, \ - "VIRTIO_NET_F_GUEST_UFO: Driver can receive UFO"), - FEATURE_ENTRY(VIRTIO_NET_F_HOST_TSO4, \ - "VIRTIO_NET_F_HOST_TSO4: Device can receive TSOv4"), - FEATURE_ENTRY(VIRTIO_NET_F_HOST_TSO6, \ - "VIRTIO_NET_F_HOST_TSO6: Device can receive TSOv6"), - FEATURE_ENTRY(VIRTIO_NET_F_HOST_ECN, \ - "VIRTIO_NET_F_HOST_ECN: Device can receive TSO with ECN"), - FEATURE_ENTRY(VIRTIO_NET_F_HOST_UFO, \ - "VIRTIO_NET_F_HOST_UFO: Device can receive UFO"), - FEATURE_ENTRY(VIRTIO_NET_F_MRG_RXBUF, \ - "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers"), - FEATURE_ENTRY(VIRTIO_NET_F_STATUS, \ - "VIRTIO_NET_F_STATUS: Configuration status field available"), - FEATURE_ENTRY(VIRTIO_NET_F_CTRL_VQ, \ - "VIRTIO_NET_F_CTRL_VQ: Control channel available"), - FEATURE_ENTRY(VIRTIO_NET_F_CTRL_RX, \ - "VIRTIO_NET_F_CTRL_RX: Control channel RX mode supported"), - FEATURE_ENTRY(VIRTIO_NET_F_CTRL_VLAN, \ - "VIRTIO_NET_F_CTRL_VLAN: Control channel VLAN filtering supported"), - FEATURE_ENTRY(VIRTIO_NET_F_CTRL_RX_EXTRA, \ - "VIRTIO_NET_F_CTRL_RX_EXTRA: Extra RX mode control supported"), - FEATURE_ENTRY(VIRTIO_NET_F_GUEST_ANNOUNCE, \ - "VIRTIO_NET_F_GUEST_ANNOUNCE: Driver sending gratuitous packets " - "supported"), - FEATURE_ENTRY(VIRTIO_NET_F_MQ, \ - "VIRTIO_NET_F_MQ: Multiqueue with automatic receive steering " - "supported"), - FEATURE_ENTRY(VIRTIO_NET_F_CTRL_MAC_ADDR, \ - "VIRTIO_NET_F_CTRL_MAC_ADDR: MAC address set through control " - "channel"), - FEATURE_ENTRY(VIRTIO_NET_F_HASH_REPORT, \ - "VIRTIO_NET_F_HASH_REPORT: Hash reporting supported"), - FEATURE_ENTRY(VIRTIO_NET_F_RSS, \ - "VIRTIO_NET_F_RSS: RSS RX steering supported"), - FEATURE_ENTRY(VIRTIO_NET_F_RSC_EXT, \ - "VIRTIO_NET_F_RSC_EXT: Extended coalescing info supported"), - FEATURE_ENTRY(VIRTIO_NET_F_STANDBY, \ - "VIRTIO_NET_F_STANDBY: Device acting as standby for primary " - "device with same MAC addr. supported"), - FEATURE_ENTRY(VIRTIO_NET_F_SPEED_DUPLEX, \ - "VIRTIO_NET_F_SPEED_DUPLEX: Device set linkspeed and duplex"), -#ifndef VIRTIO_NET_NO_LEGACY - FEATURE_ENTRY(VIRTIO_NET_F_GSO, \ - "VIRTIO_NET_F_GSO: Handling GSO-type packets supported"), -#endif /* !VIRTIO_NET_NO_LEGACY */ - FEATURE_ENTRY(VHOST_NET_F_VIRTIO_NET_HDR, \ - "VHOST_NET_F_VIRTIO_NET_HDR: Virtio-net headers for RX and TX " - "packets supported"), - FEATURE_ENTRY(VHOST_F_LOG_ALL, \ - "VHOST_F_LOG_ALL: Logging write descriptors supported"), - FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ - "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " - "negotiation supported"), - { -1, "" } -}; - -/* virtio-scsi features mapping */ -qmp_virtio_feature_map_t virtio_scsi_feature_map[] = { - FEATURE_ENTRY(VIRTIO_SCSI_F_INOUT, \ - "VIRTIO_SCSI_F_INOUT: Requests including read and writable data " - "buffers suppoted"), - FEATURE_ENTRY(VIRTIO_SCSI_F_HOTPLUG, \ - "VIRTIO_SCSI_F_HOTPLUG: Reporting and handling hot-plug events " - "supported"), - FEATURE_ENTRY(VIRTIO_SCSI_F_CHANGE, \ - "VIRTIO_SCSI_F_CHANGE: Reporting and handling LUN changes " - "supported"), - FEATURE_ENTRY(VIRTIO_SCSI_F_T10_PI, \ - "VIRTIO_SCSI_F_T10_PI: T10 info included in request header"), - FEATURE_ENTRY(VHOST_F_LOG_ALL, \ - "VHOST_F_LOG_ALL: Logging write descriptors supported"), - FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ - "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " - "negotiation supported"), - { -1, "" } -}; - -/* virtio/vhost-user-fs features mapping */ -qmp_virtio_feature_map_t virtio_fs_feature_map[] = { - FEATURE_ENTRY(VHOST_F_LOG_ALL, \ - "VHOST_F_LOG_ALL: Logging write descriptors supported"), - FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ - "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " - "negotiation supported"), - { -1, "" } -}; - -/* virtio/vhost-user-i2c features mapping */ -qmp_virtio_feature_map_t virtio_i2c_feature_map[] = { - FEATURE_ENTRY(VIRTIO_I2C_F_ZERO_LENGTH_REQUEST, \ - "VIRTIO_I2C_F_ZERO_LEGNTH_REQUEST: Zero length requests supported"), - FEATURE_ENTRY(VHOST_F_LOG_ALL, \ - "VHOST_F_LOG_ALL: Logging write descriptors supported"), - FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ - "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " - "negotiation supported"), - { -1, "" } -}; - -/* virtio/vhost-vsock features mapping */ -qmp_virtio_feature_map_t virtio_vsock_feature_map[] = { - FEATURE_ENTRY(VIRTIO_VSOCK_F_SEQPACKET, \ - "VIRTIO_VSOCK_F_SEQPACKET: SOCK_SEQPACKET supported"), - FEATURE_ENTRY(VHOST_F_LOG_ALL, \ - "VHOST_F_LOG_ALL: Logging write descriptors supported"), - FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ - "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " - "negotiation supported"), - { -1, "" } -}; - -/* virtio-balloon features mapping */ -qmp_virtio_feature_map_t virtio_balloon_feature_map[] = { - FEATURE_ENTRY(VIRTIO_BALLOON_F_MUST_TELL_HOST, \ - "VIRTIO_BALLOON_F_MUST_TELL_HOST: Tell host before reclaiming " - "pages"), - FEATURE_ENTRY(VIRTIO_BALLOON_F_STATS_VQ, \ - "VIRTIO_BALLOON_F_STATS_VQ: Guest memory stats VQ available"), - FEATURE_ENTRY(VIRTIO_BALLOON_F_DEFLATE_ON_OOM, \ - "VIRTIO_BALLOON_F_DEFLATE_ON_OOM: Deflate balloon when guest OOM"), - FEATURE_ENTRY(VIRTIO_BALLOON_F_FREE_PAGE_HINT, \ - "VIRTIO_BALLOON_F_FREE_PAGE_HINT: VQ reporting free pages enabled"), - FEATURE_ENTRY(VIRTIO_BALLOON_F_PAGE_POISON, \ - "VIRTIO_BALLOON_F_PAGE_POISON: Guest page poisoning enabled"), - FEATURE_ENTRY(VIRTIO_BALLOON_F_REPORTING, \ - "VIRTIO_BALLOON_F_REPORTING: Page reporting VQ enabled"), - { -1, "" } -}; - -/* virtio-crypto features mapping */ -qmp_virtio_feature_map_t virtio_crypto_feature_map[] = { - FEATURE_ENTRY(VHOST_F_LOG_ALL, \ - "VHOST_F_LOG_ALL: Logging write descriptors supported"), - { -1, "" } -}; - -/* virtio-iommu features mapping */ -qmp_virtio_feature_map_t virtio_iommu_feature_map[] = { - FEATURE_ENTRY(VIRTIO_IOMMU_F_INPUT_RANGE, \ - "VIRTIO_IOMMU_F_INPUT_RANGE: Range of available virtual addrs. " - "available"), - FEATURE_ENTRY(VIRTIO_IOMMU_F_DOMAIN_RANGE, \ - "VIRTIO_IOMMU_F_DOMAIN_RANGE: Number of supported domains " - "available"), - FEATURE_ENTRY(VIRTIO_IOMMU_F_MAP_UNMAP, \ - "VIRTIO_IOMMU_F_MAP_UNMAP: Map and unmap requests available"), - FEATURE_ENTRY(VIRTIO_IOMMU_F_BYPASS, \ - "VIRTIO_IOMMU_F_BYPASS: Endpoints not attached to domains are in " - "bypass mode"), - FEATURE_ENTRY(VIRTIO_IOMMU_F_PROBE, \ - "VIRTIO_IOMMU_F_PROBE: Probe requests available"), - FEATURE_ENTRY(VIRTIO_IOMMU_F_MMIO, \ - "VIRTIO_IOMMU_F_MMIO: VIRTIO_IOMMU_MAP_F_MMIO flag available"), - FEATURE_ENTRY(VIRTIO_IOMMU_F_BYPASS_CONFIG, \ - "VIRTIO_IOMMU_F_BYPASS_CONFIG: Bypass field of IOMMU config " - "available"), - { -1, "" } -}; - -/* virtio-mem features mapping */ -qmp_virtio_feature_map_t virtio_mem_feature_map[] = { -#ifndef CONFIG_ACPI - FEATURE_ENTRY(VIRTIO_MEM_F_ACPI_PXM, \ - "VIRTIO_MEM_F_ACPI_PXM: node_id is an ACPI PXM and is valid"), -#endif /* !CONFIG_ACPI */ - FEATURE_ENTRY(VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, \ - "VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE: Unplugged memory cannot be " - "accessed"), - { -1, "" } -}; - -/* virtio-rng features mapping */ -qmp_virtio_feature_map_t virtio_rng_feature_map[] = { - FEATURE_ENTRY(VHOST_F_LOG_ALL, \ - "VHOST_F_LOG_ALL: Logging write descriptors supported"), - FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ - "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " - "negotiation supported"), - { -1, "" } -}; - /* * The alignment to use between consumer and producer parts of vring. * x86 pagesize again. This is the default, used by transports like PCI @@ -2551,195 +2145,6 @@ void virtio_reset(void *opaque) } } -uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr) -{ - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - uint8_t val; - - if (addr + sizeof(val) > vdev->config_len) { - return (uint32_t)-1; - } - - k->get_config(vdev, vdev->config); - - val = ldub_p(vdev->config + addr); - return val; -} - -uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr) -{ - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - uint16_t val; - - if (addr + sizeof(val) > vdev->config_len) { - return (uint32_t)-1; - } - - k->get_config(vdev, vdev->config); - - val = lduw_p(vdev->config + addr); - return val; -} - -uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr) -{ - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - uint32_t val; - - if (addr + sizeof(val) > vdev->config_len) { - return (uint32_t)-1; - } - - k->get_config(vdev, vdev->config); - - val = ldl_p(vdev->config + addr); - return val; -} - -void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data) -{ - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - uint8_t val = data; - - if (addr + sizeof(val) > vdev->config_len) { - return; - } - - stb_p(vdev->config + addr, val); - - if (k->set_config) { - k->set_config(vdev, vdev->config); - } -} - -void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data) -{ - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - uint16_t val = data; - - if (addr + sizeof(val) > vdev->config_len) { - return; - } - - stw_p(vdev->config + addr, val); - - if (k->set_config) { - k->set_config(vdev, vdev->config); - } -} - -void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data) -{ - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - uint32_t val = data; - - if (addr + sizeof(val) > vdev->config_len) { - return; - } - - stl_p(vdev->config + addr, val); - - if (k->set_config) { - k->set_config(vdev, vdev->config); - } -} - -uint32_t virtio_config_modern_readb(VirtIODevice *vdev, uint32_t addr) -{ - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - uint8_t val; - - if (addr + sizeof(val) > vdev->config_len) { - return (uint32_t)-1; - } - - k->get_config(vdev, vdev->config); - - val = ldub_p(vdev->config + addr); - return val; -} - -uint32_t virtio_config_modern_readw(VirtIODevice *vdev, uint32_t addr) -{ - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - uint16_t val; - - if (addr + sizeof(val) > vdev->config_len) { - return (uint32_t)-1; - } - - k->get_config(vdev, vdev->config); - - val = lduw_le_p(vdev->config + addr); - return val; -} - -uint32_t virtio_config_modern_readl(VirtIODevice *vdev, uint32_t addr) -{ - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - uint32_t val; - - if (addr + sizeof(val) > vdev->config_len) { - return (uint32_t)-1; - } - - k->get_config(vdev, vdev->config); - - val = ldl_le_p(vdev->config + addr); - return val; -} - -void virtio_config_modern_writeb(VirtIODevice *vdev, - uint32_t addr, uint32_t data) -{ - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - uint8_t val = data; - - if (addr + sizeof(val) > vdev->config_len) { - return; - } - - stb_p(vdev->config + addr, val); - - if (k->set_config) { - k->set_config(vdev, vdev->config); - } -} - -void virtio_config_modern_writew(VirtIODevice *vdev, - uint32_t addr, uint32_t data) -{ - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - uint16_t val = data; - - if (addr + sizeof(val) > vdev->config_len) { - return; - } - - stw_le_p(vdev->config + addr, val); - - if (k->set_config) { - k->set_config(vdev, vdev->config); - } -} - -void virtio_config_modern_writel(VirtIODevice *vdev, - uint32_t addr, uint32_t data) -{ - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - uint32_t val = data; - - if (addr + sizeof(val) > vdev->config_len) { - return; - } - - stl_le_p(vdev->config + addr, val); - - if (k->set_config) { - k->set_config(vdev, vdev->config); - } -} - void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr) { if (!vdev->vq[n].vring.num) { @@ -4457,203 +3862,6 @@ static VirtIODevice *virtio_device_find(const char *path) return NULL; } -#define CONVERT_FEATURES(type, map, is_status, bitmap) \ - ({ \ - type *list = NULL; \ - type *node; \ - for (i = 0; map[i].virtio_bit != -1; i++) { \ - if (is_status) { \ - bit = map[i].virtio_bit; \ - } \ - else { \ - bit = 1ULL << map[i].virtio_bit; \ - } \ - if ((bitmap & bit) == 0) { \ - continue; \ - } \ - node = g_new0(type, 1); \ - node->value = g_strdup(map[i].feature_desc); \ - node->next = list; \ - list = node; \ - bitmap ^= bit; \ - } \ - list; \ - }) - -static VirtioDeviceStatus *qmp_decode_status(uint8_t bitmap) -{ - VirtioDeviceStatus *status; - uint8_t bit; - int i; - - status = g_new0(VirtioDeviceStatus, 1); - status->statuses = CONVERT_FEATURES(strList, virtio_config_status_map, - 1, bitmap); - status->has_unknown_statuses = bitmap != 0; - if (status->has_unknown_statuses) { - status->unknown_statuses = bitmap; - } - - return status; -} - -static VhostDeviceProtocols *qmp_decode_protocols(uint64_t bitmap) -{ - VhostDeviceProtocols *vhu_protocols; - uint64_t bit; - int i; - - vhu_protocols = g_new0(VhostDeviceProtocols, 1); - vhu_protocols->protocols = - CONVERT_FEATURES(strList, - vhost_user_protocol_map, 0, bitmap); - vhu_protocols->has_unknown_protocols = bitmap != 0; - if (vhu_protocols->has_unknown_protocols) { - vhu_protocols->unknown_protocols = bitmap; - } - - return vhu_protocols; -} - -static VirtioDeviceFeatures *qmp_decode_features(uint16_t device_id, - uint64_t bitmap) -{ - VirtioDeviceFeatures *features; - uint64_t bit; - int i; - - features = g_new0(VirtioDeviceFeatures, 1); - features->has_dev_features = true; - - /* transport features */ - features->transports = CONVERT_FEATURES(strList, virtio_transport_map, 0, - bitmap); - - /* device features */ - switch (device_id) { -#ifdef CONFIG_VIRTIO_SERIAL - case VIRTIO_ID_CONSOLE: - features->dev_features = - CONVERT_FEATURES(strList, virtio_serial_feature_map, 0, bitmap); - break; -#endif -#ifdef CONFIG_VIRTIO_BLK - case VIRTIO_ID_BLOCK: - features->dev_features = - CONVERT_FEATURES(strList, virtio_blk_feature_map, 0, bitmap); - break; -#endif -#ifdef CONFIG_VIRTIO_GPU - case VIRTIO_ID_GPU: - features->dev_features = - CONVERT_FEATURES(strList, virtio_gpu_feature_map, 0, bitmap); - break; -#endif -#ifdef CONFIG_VIRTIO_NET - case VIRTIO_ID_NET: - features->dev_features = - CONVERT_FEATURES(strList, virtio_net_feature_map, 0, bitmap); - break; -#endif -#ifdef CONFIG_VIRTIO_SCSI - case VIRTIO_ID_SCSI: - features->dev_features = - CONVERT_FEATURES(strList, virtio_scsi_feature_map, 0, bitmap); - break; -#endif -#ifdef CONFIG_VIRTIO_BALLOON - case VIRTIO_ID_BALLOON: - features->dev_features = - CONVERT_FEATURES(strList, virtio_balloon_feature_map, 0, bitmap); - break; -#endif -#ifdef CONFIG_VIRTIO_IOMMU - case VIRTIO_ID_IOMMU: - features->dev_features = - CONVERT_FEATURES(strList, virtio_iommu_feature_map, 0, bitmap); - break; -#endif -#ifdef CONFIG_VIRTIO_INPUT - case VIRTIO_ID_INPUT: - features->dev_features = - CONVERT_FEATURES(strList, virtio_input_feature_map, 0, bitmap); - break; -#endif -#ifdef CONFIG_VHOST_USER_FS - case VIRTIO_ID_FS: - features->dev_features = - CONVERT_FEATURES(strList, virtio_fs_feature_map, 0, bitmap); - break; -#endif -#ifdef CONFIG_VHOST_VSOCK - case VIRTIO_ID_VSOCK: - features->dev_features = - CONVERT_FEATURES(strList, virtio_vsock_feature_map, 0, bitmap); - break; -#endif -#ifdef CONFIG_VIRTIO_CRYPTO - case VIRTIO_ID_CRYPTO: - features->dev_features = - CONVERT_FEATURES(strList, virtio_crypto_feature_map, 0, bitmap); - break; -#endif -#ifdef CONFIG_VIRTIO_MEM - case VIRTIO_ID_MEM: - features->dev_features = - CONVERT_FEATURES(strList, virtio_mem_feature_map, 0, bitmap); - break; -#endif -#ifdef CONFIG_VIRTIO_I2C_ADAPTER - case VIRTIO_ID_I2C_ADAPTER: - features->dev_features = - CONVERT_FEATURES(strList, virtio_i2c_feature_map, 0, bitmap); - break; -#endif -#ifdef CONFIG_VIRTIO_RNG - case VIRTIO_ID_RNG: - features->dev_features = - CONVERT_FEATURES(strList, virtio_rng_feature_map, 0, bitmap); - break; -#endif - /* No features */ - case VIRTIO_ID_9P: - case VIRTIO_ID_PMEM: - case VIRTIO_ID_IOMEM: - case VIRTIO_ID_RPMSG: - case VIRTIO_ID_CLOCK: - case VIRTIO_ID_MAC80211_WLAN: - case VIRTIO_ID_MAC80211_HWSIM: - case VIRTIO_ID_RPROC_SERIAL: - case VIRTIO_ID_MEMORY_BALLOON: - case VIRTIO_ID_CAIF: - case VIRTIO_ID_SIGNAL_DIST: - case VIRTIO_ID_PSTORE: - case VIRTIO_ID_SOUND: - case VIRTIO_ID_BT: - case VIRTIO_ID_RPMB: - case VIRTIO_ID_VIDEO_ENCODER: - case VIRTIO_ID_VIDEO_DECODER: - case VIRTIO_ID_SCMI: - case VIRTIO_ID_NITRO_SEC_MOD: - case VIRTIO_ID_WATCHDOG: - case VIRTIO_ID_CAN: - case VIRTIO_ID_DMABUF: - case VIRTIO_ID_PARAM_SERV: - case VIRTIO_ID_AUDIO_POLICY: - case VIRTIO_ID_GPIO: - break; - default: - g_assert_not_reached(); - } - - features->has_unknown_dev_features = bitmap != 0; - if (features->has_unknown_dev_features) { - features->unknown_dev_features = bitmap; - } - - return features; -} - VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp) { VirtIODevice *vdev; diff --git a/hw/watchdog/trace-events b/hw/watchdog/trace-events index 89ccbcfdfd..54371ae075 100644 --- a/hw/watchdog/trace-events +++ b/hw/watchdog/trace-events @@ -16,3 +16,7 @@ spapr_watchdog_stop(uint64_t num, uint64_t ret) "num=%" PRIu64 " ret=%" PRId64 spapr_watchdog_query(uint64_t caps) "caps=0x%" PRIx64 spapr_watchdog_query_lpm(uint64_t caps) "caps=0x%" PRIx64 spapr_watchdog_expired(uint64_t num, unsigned action) "num=%" PRIu64 " action=%u" + +# watchdog.c +watchdog_perform_action(unsigned int action) "action=%u" +watchdog_set_action(unsigned int action) "action=%u" diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c index 6c082a3263..955046161b 100644 --- a/hw/watchdog/watchdog.c +++ b/hw/watchdog/watchdog.c @@ -30,6 +30,7 @@ #include "sysemu/watchdog.h" #include "hw/nmi.h" #include "qemu/help_option.h" +#include "trace.h" static WatchdogAction watchdog_action = WATCHDOG_ACTION_RESET; @@ -43,6 +44,8 @@ WatchdogAction get_watchdog_action(void) */ void watchdog_perform_action(void) { + trace_watchdog_perform_action(watchdog_action); + switch (watchdog_action) { case WATCHDOG_ACTION_RESET: /* same as 'system_reset' in monitor */ qapi_event_send_watchdog(WATCHDOG_ACTION_RESET); @@ -89,4 +92,5 @@ void watchdog_perform_action(void) void qmp_watchdog_set_action(WatchdogAction action, Error **errp) { watchdog_action = action; + trace_watchdog_set_action(watchdog_action); } diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h index 7ca92843c6..d41866a229 100644 --- a/include/hw/acpi/ich9.h +++ b/include/hw/acpi/ich9.h @@ -27,7 +27,7 @@ #include "hw/acpi/pcihp.h" #include "hw/acpi/memory_hotplug.h" #include "hw/acpi/acpi_dev_interface.h" -#include "hw/acpi/tco.h" +#include "hw/acpi/ich9_tco.h" #define ACPI_PCIHP_ADDR_ICH9 0x0cc0 diff --git a/include/hw/acpi/tco.h b/include/hw/acpi/ich9_tco.h similarity index 97% rename from include/hw/acpi/tco.h rename to include/hw/acpi/ich9_tco.h index a1e0da8213..c4393caee0 100644 --- a/include/hw/acpi/tco.h +++ b/include/hw/acpi/ich9_tco.h @@ -1,5 +1,5 @@ /* - * QEMU ICH9 TCO emulation + * QEMU ICH9 TCO emulation (total cost of ownership) * * Copyright (c) 2015 Paulo Alcantara * diff --git a/include/hw/boards.h b/include/hw/boards.h index 90f1dd3aeb..d18d6d0073 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -379,6 +379,9 @@ struct MachineState { } \ type_init(machine_initfn##_register_types) +extern GlobalProperty hw_compat_7_2[]; +extern const size_t hw_compat_7_2_len; + extern GlobalProperty hw_compat_7_1[]; extern const size_t hw_compat_7_1_len; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index c95333514e..991f905f5d 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -200,6 +200,9 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, /* sgx.c */ void pc_machine_init_sgx_epc(PCMachineState *pcms); +extern GlobalProperty pc_compat_7_2[]; +extern const size_t pc_compat_7_2_len; + extern GlobalProperty pc_compat_7_1[]; extern const size_t pc_compat_7_1_len; diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 06e2d5f889..954f260f84 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -251,15 +251,7 @@ struct PCIDeviceClass { uint16_t subsystem_vendor_id; /* only for header type = 0 */ uint16_t subsystem_id; /* only for header type = 0 */ - /* - * pci-to-pci bridge or normal device. - * This doesn't mean pci host switch. - * When card bus bridge is supported, this would be enhanced. - */ - bool is_bridge; - - /* rom bar */ - const char *romfile; + const char *romfile; /* rom bar */ }; typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev); diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h index ba4bafac7c..ca6caf487e 100644 --- a/include/hw/pci/pci_bridge.h +++ b/include/hw/pci/pci_bridge.h @@ -53,6 +53,7 @@ struct PCIBridgeWindows { #define TYPE_PCI_BRIDGE "base-pci-bridge" OBJECT_DECLARE_SIMPLE_TYPE(PCIBridge, PCI_BRIDGE) +#define IS_PCI_BRIDGE(dev) object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE) struct PCIBridge { /*< private >*/ diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h index bc9f834fd1..e4386ebb20 100644 --- a/include/hw/pci/pci_ids.h +++ b/include/hw/pci/pci_ids.h @@ -169,7 +169,6 @@ #define PCI_VENDOR_ID_DEC 0x1011 #define PCI_DEVICE_ID_DEC_21143 0x0019 -#define PCI_DEVICE_ID_DEC_21154 0x0026 #define PCI_VENDOR_ID_CIRRUS 0x1013 diff --git a/include/hw/virtio/vdpa-dev.h b/include/hw/virtio/vdpa-dev.h new file mode 100644 index 0000000000..4dbf98195c --- /dev/null +++ b/include/hw/virtio/vdpa-dev.h @@ -0,0 +1,43 @@ +/* + * Vhost Vdpa Device + * + * Copyright (c) Huawei Technologies Co., Ltd. 2022. All Rights Reserved. + * + * Authors: + * Longpeng + * + * Largely based on the "vhost-user-blk.h" implemented by: + * Changpeng Liu + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + */ +#ifndef _VHOST_VDPA_DEVICE_H +#define _VHOST_VDPA_DEVICE_H + +#include "hw/virtio/vhost.h" +#include "hw/virtio/vhost-vdpa.h" +#include "qom/object.h" + + +#define TYPE_VHOST_VDPA_DEVICE "vhost-vdpa-device" +OBJECT_DECLARE_SIMPLE_TYPE(VhostVdpaDevice, VHOST_VDPA_DEVICE) + +struct VhostVdpaDevice { + VirtIODevice parent_obj; + char *vhostdev; + int vhostfd; + int32_t bootindex; + uint32_t vdev_id; + uint32_t num_queues; + struct vhost_dev dev; + struct vhost_vdpa vdpa; + VirtQueue **virtqs; + uint8_t *config; + int config_size; + uint16_t queue_size; + bool started; + int (*post_init)(VhostVdpaDevice *v, Error **errp); +}; + +#endif diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h index 1111d85643..45b969a311 100644 --- a/include/hw/virtio/vhost-vdpa.h +++ b/include/hw/virtio/vhost-vdpa.h @@ -19,6 +19,12 @@ #include "hw/virtio/virtio.h" #include "standard-headers/linux/vhost_types.h" +/* + * ASID dedicated to map guest's addresses. If SVQ is disabled it maps GPA to + * qemu's IOVA. If SVQ is enabled it maps also the SVQ vring here + */ +#define VHOST_VDPA_GUEST_PA_ASID 0 + typedef struct VhostVDPAHostNotifier { MemoryRegion mr; void *addr; @@ -29,10 +35,13 @@ typedef struct vhost_vdpa { int index; uint32_t msg_type; bool iotlb_batch_begin_sent; + uint32_t address_space_id; MemoryListener listener; struct vhost_vdpa_iova_range iova_range; uint64_t acked_features; bool shadow_vqs_enabled; + /* Vdpa must send shadow addresses as IOTLB key for data queues, not GPA */ + bool shadow_data; /* IOVA mapping used by the Shadow Virtqueue */ VhostIOVATree *iova_tree; GPtrArray *shadow_vqs; @@ -42,8 +51,9 @@ typedef struct vhost_vdpa { VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX]; } VhostVDPA; -int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size, - void *vaddr, bool readonly); -int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova, hwaddr size); +int vhost_vdpa_dma_map(struct vhost_vdpa *v, uint32_t asid, hwaddr iova, + hwaddr size, void *vaddr, bool readonly); +int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, uint32_t asid, hwaddr iova, + hwaddr size); #endif diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 67a6807fac..1cafa0d776 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -88,13 +88,32 @@ struct vhost_dev { int vq_index_end; /* if non-zero, minimum required value for max_queues */ int num_queues; + /** + * vhost feature handling requires matching the feature set + * offered by a backend which may be a subset of the total + * features eventually offered to the guest. + * + * @features: available features provided by the backend + * @acked_features: final negotiated features with front-end driver + * + * @backend_features: this is used in a couple of places to either + * store VHOST_USER_F_PROTOCOL_FEATURES to apply to + * VHOST_USER_SET_FEATURES or VHOST_NET_F_VIRTIO_NET_HDR. Its + * future use should be discouraged and the variable retired as + * its easy to confuse with the VirtIO backend_features. + */ uint64_t features; - /** @acked_features: final set of negotiated features */ uint64_t acked_features; - /** @backend_features: backend specific feature bits */ uint64_t backend_features; - /** @protocol_features: final negotiated protocol features */ + + /** + * @protocol_features: is the vhost-user only feature set by + * VHOST_USER_SET_PROTOCOL_FEATURES. Protocol features are only + * negotiated if VHOST_USER_F_PROTOCOL_FEATURES has been offered + * by the backend (see @features). + */ uint64_t protocol_features; + uint64_t max_queues; uint64_t backend_cap; /* @started: is the vhost device started? */ diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h index 938799e8f6..24fba1604b 100644 --- a/include/hw/virtio/virtio-pci.h +++ b/include/hw/virtio/virtio-pci.h @@ -151,6 +151,8 @@ struct VirtIOPCIProxy { bool disable_modern; bool ignore_backend_features; OnOffAuto disable_legacy; + /* Transitional device id */ + uint16_t trans_devid; uint32_t class_code; uint32_t nvectors; uint32_t dfselect; @@ -184,6 +186,9 @@ static inline void virtio_pci_disable_modern(VirtIOPCIProxy *proxy) proxy->disable_modern = true; } +uint16_t virtio_pci_get_trans_devid(uint16_t device_id); +uint16_t virtio_pci_get_class_id(uint16_t device_id); + /* * virtio-input-pci: This extends VirtioPCIProxy. */ diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index acfd4df125..24561e933a 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -93,6 +93,12 @@ enum virtio_device_endian { VIRTIO_DEVICE_ENDIAN_BIG, }; +/** + * struct VirtIODevice - common VirtIO structure + * @name: name of the device + * @status: VirtIO Device Status field + * + */ struct VirtIODevice { DeviceState parent_obj; @@ -100,9 +106,20 @@ struct VirtIODevice uint8_t status; uint8_t isr; uint16_t queue_sel; - uint64_t guest_features; + /** + * These fields represent a set of VirtIO features at various + * levels of the stack. @host_features indicates the complete + * feature set the VirtIO device can offer to the driver. + * @guest_features indicates which features the VirtIO driver has + * selected by writing to the feature register. Finally + * @backend_features represents everything supported by the + * backend (e.g. vhost) and could potentially be a subset of the + * total feature set offered by QEMU. + */ uint64_t host_features; + uint64_t guest_features; uint64_t backend_features; + size_t config_len; void *config; uint16_t config_vector; diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 260e474863..d36664f33a 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -38,6 +38,8 @@ typedef struct VhostVDPAState { void *cvq_cmd_out_buffer; virtio_net_ctrl_ack *status; + /* The device always have SVQ enabled */ + bool always_svq; bool started; } VhostVDPAState; @@ -100,6 +102,8 @@ static const uint64_t vdpa_svq_device_features = BIT_ULL(VIRTIO_NET_F_RSC_EXT) | BIT_ULL(VIRTIO_NET_F_STANDBY); +#define VHOST_VDPA_NET_CVQ_ASID 1 + VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc) { VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); @@ -107,6 +111,23 @@ VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc) return s->vhost_net; } +static bool vhost_vdpa_net_valid_svq_features(uint64_t features, Error **errp) +{ + uint64_t invalid_dev_features = + features & ~vdpa_svq_device_features & + /* Transport are all accepted at this point */ + ~MAKE_64BIT_MASK(VIRTIO_TRANSPORT_F_START, + VIRTIO_TRANSPORT_F_END - VIRTIO_TRANSPORT_F_START); + + if (invalid_dev_features) { + error_setg(errp, "vdpa svq does not work with features 0x%" PRIx64, + invalid_dev_features); + return false; + } + + return vhost_svq_valid_features(features, errp); +} + static int vhost_vdpa_net_check_device_id(struct vhost_net *net) { uint32_t device_id; @@ -224,6 +245,40 @@ static NetClientInfo net_vhost_vdpa_info = { .check_peer_type = vhost_vdpa_check_peer_type, }; +static int64_t vhost_vdpa_get_vring_group(int device_fd, unsigned vq_index) +{ + struct vhost_vring_state state = { + .index = vq_index, + }; + int r = ioctl(device_fd, VHOST_VDPA_GET_VRING_GROUP, &state); + + if (unlikely(r < 0)) { + error_report("Cannot get VQ %u group: %s", vq_index, + g_strerror(errno)); + return r; + } + + return state.num; +} + +static int vhost_vdpa_set_address_space_id(struct vhost_vdpa *v, + unsigned vq_group, + unsigned asid_num) +{ + struct vhost_vring_state asid = { + .index = vq_group, + .num = asid_num, + }; + int r; + + r = ioctl(v->device_fd, VHOST_VDPA_SET_GROUP_ASID, &asid); + if (unlikely(r < 0)) { + error_report("Can't set vq group %u asid %u, errno=%d (%s)", + asid.index, asid.num, errno, g_strerror(errno)); + } + return r; +} + static void vhost_vdpa_cvq_unmap_buf(struct vhost_vdpa *v, void *addr) { VhostIOVATree *tree = v->iova_tree; @@ -242,7 +297,7 @@ static void vhost_vdpa_cvq_unmap_buf(struct vhost_vdpa *v, void *addr) return; } - r = vhost_vdpa_dma_unmap(v, map->iova, map->size + 1); + r = vhost_vdpa_dma_unmap(v, v->address_space_id, map->iova, map->size + 1); if (unlikely(r != 0)) { error_report("Device cannot unmap: %s(%d)", g_strerror(r), r); } @@ -282,8 +337,8 @@ static int vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, void *buf, size_t size, return r; } - r = vhost_vdpa_dma_map(v, map.iova, vhost_vdpa_net_cvq_cmd_page_len(), buf, - !write); + r = vhost_vdpa_dma_map(v, v->address_space_id, map.iova, + vhost_vdpa_net_cvq_cmd_page_len(), buf, !write); if (unlikely(r < 0)) { goto dma_map_err; } @@ -298,11 +353,75 @@ dma_map_err: static int vhost_vdpa_net_cvq_start(NetClientState *nc) { VhostVDPAState *s; - int r; + struct vhost_vdpa *v; + uint64_t backend_features; + int64_t cvq_group; + int cvq_index, r; assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); s = DO_UPCAST(VhostVDPAState, nc, nc); + v = &s->vhost_vdpa; + + v->shadow_data = s->always_svq; + v->shadow_vqs_enabled = s->always_svq; + s->vhost_vdpa.address_space_id = VHOST_VDPA_GUEST_PA_ASID; + + if (s->always_svq) { + /* SVQ is already configured for all virtqueues */ + goto out; + } + + /* + * If we early return in these cases SVQ will not be enabled. The migration + * will be blocked as long as vhost-vdpa backends will not offer _F_LOG. + * + * Calling VHOST_GET_BACKEND_FEATURES as they are not available in v->dev + * yet. + */ + r = ioctl(v->device_fd, VHOST_GET_BACKEND_FEATURES, &backend_features); + if (unlikely(r < 0)) { + error_report("Cannot get vdpa backend_features: %s(%d)", + g_strerror(errno), errno); + return -1; + } + if (!(backend_features & VHOST_BACKEND_F_IOTLB_ASID) || + !vhost_vdpa_net_valid_svq_features(v->dev->features, NULL)) { + return 0; + } + + /* + * Check if all the virtqueues of the virtio device are in a different vq + * than the last vq. VQ group of last group passed in cvq_group. + */ + cvq_index = v->dev->vq_index_end - 1; + cvq_group = vhost_vdpa_get_vring_group(v->device_fd, cvq_index); + if (unlikely(cvq_group < 0)) { + return cvq_group; + } + for (int i = 0; i < cvq_index; ++i) { + int64_t group = vhost_vdpa_get_vring_group(v->device_fd, i); + + if (unlikely(group < 0)) { + return group; + } + + if (group == cvq_group) { + return 0; + } + } + + r = vhost_vdpa_set_address_space_id(v, cvq_group, VHOST_VDPA_NET_CVQ_ASID); + if (unlikely(r < 0)) { + return r; + } + + v->iova_tree = vhost_iova_tree_new(v->iova_range.first, + v->iova_range.last); + v->shadow_vqs_enabled = true; + s->vhost_vdpa.address_space_id = VHOST_VDPA_NET_CVQ_ASID; + +out: if (!s->vhost_vdpa.shadow_vqs_enabled) { return 0; } @@ -331,6 +450,14 @@ static void vhost_vdpa_net_cvq_stop(NetClientState *nc) if (s->vhost_vdpa.shadow_vqs_enabled) { vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer); vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->status); + if (!s->always_svq) { + /* + * If only the CVQ is shadowed we can delete this safely. + * If all the VQs are shadows this will be needed by the time the + * device is started again to register SVQ vrings and similar. + */ + g_clear_pointer(&s->vhost_vdpa.iova_tree, vhost_iova_tree_delete); + } } } @@ -525,14 +652,15 @@ static const VhostShadowVirtqueueOps vhost_vdpa_net_svq_ops = { }; static NetClientState *net_vhost_vdpa_init(NetClientState *peer, - const char *device, - const char *name, - int vdpa_device_fd, - int queue_pair_index, - int nvqs, - bool is_datapath, - bool svq, - VhostIOVATree *iova_tree) + const char *device, + const char *name, + int vdpa_device_fd, + int queue_pair_index, + int nvqs, + bool is_datapath, + bool svq, + struct vhost_vdpa_iova_range iova_range, + VhostIOVATree *iova_tree) { NetClientState *nc = NULL; VhostVDPAState *s; @@ -550,7 +678,10 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, s->vhost_vdpa.device_fd = vdpa_device_fd; s->vhost_vdpa.index = queue_pair_index; + s->always_svq = svq; s->vhost_vdpa.shadow_vqs_enabled = svq; + s->vhost_vdpa.iova_range = iova_range; + s->vhost_vdpa.shadow_data = svq; s->vhost_vdpa.iova_tree = iova_tree; if (!is_datapath) { s->cvq_cmd_out_buffer = qemu_memalign(qemu_real_host_page_size(), @@ -630,6 +761,7 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, int vdpa_device_fd; g_autofree NetClientState **ncs = NULL; g_autoptr(VhostIOVATree) iova_tree = NULL; + struct vhost_vdpa_iova_range iova_range; NetClientState *nc; int queue_pairs, r, i = 0, has_cvq = 0; @@ -673,22 +805,12 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, return queue_pairs; } + vhost_vdpa_get_iova_range(vdpa_device_fd, &iova_range); if (opts->x_svq) { - struct vhost_vdpa_iova_range iova_range; - - uint64_t invalid_dev_features = - features & ~vdpa_svq_device_features & - /* Transport are all accepted at this point */ - ~MAKE_64BIT_MASK(VIRTIO_TRANSPORT_F_START, - VIRTIO_TRANSPORT_F_END - VIRTIO_TRANSPORT_F_START); - - if (invalid_dev_features) { - error_setg(errp, "vdpa svq does not work with features 0x%" PRIx64, - invalid_dev_features); + if (!vhost_vdpa_net_valid_svq_features(features, errp)) { goto err_svq; } - vhost_vdpa_get_iova_range(vdpa_device_fd, &iova_range); iova_tree = vhost_iova_tree_new(iova_range.first, iova_range.last); } @@ -697,7 +819,7 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, for (i = 0; i < queue_pairs; i++) { ncs[i] = net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name, vdpa_device_fd, i, 2, true, opts->x_svq, - iova_tree); + iova_range, iova_tree); if (!ncs[i]) goto err; } @@ -705,7 +827,7 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, if (has_cvq) { nc = net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name, vdpa_device_fd, i, 1, false, - opts->x_svq, iova_tree); + opts->x_svq, iova_range, iova_tree); if (!nc) goto err; } diff --git a/subprojects/libvhost-user/libvhost-user.h b/subprojects/libvhost-user/libvhost-user.h index aea7ec5061..8cda9b8f57 100644 --- a/subprojects/libvhost-user/libvhost-user.h +++ b/subprojects/libvhost-user/libvhost-user.h @@ -343,7 +343,7 @@ typedef struct VuVirtq { /* Notification enabled? */ bool notification; - int inuse; + unsigned int inuse; vu_queue_handler_cb handler; diff --git a/tests/avocado/acpi-bits.py b/tests/avocado/acpi-bits.py index 898c837f26..14038fa3c4 100644 --- a/tests/avocado/acpi-bits.py +++ b/tests/avocado/acpi-bits.py @@ -50,7 +50,7 @@ from qemu.machine import QEMUMachine from avocado import skipIf from avocado_qemu import QemuBaseTest -deps = ["xorriso"] # dependent tools needed in the test setup/box. +deps = ["xorriso", "mformat"] # dependent tools needed in the test setup/box. supported_platforms = ['x86_64'] # supported test platforms. diff --git a/tests/avocado/acpi-bits/bits-tests/smbios.py2 b/tests/avocado/acpi-bits/bits-tests/smbios.py2 index 9667d0542c..fc623de072 100644 --- a/tests/avocado/acpi-bits/bits-tests/smbios.py2 +++ b/tests/avocado/acpi-bits/bits-tests/smbios.py2 @@ -1,6 +1,8 @@ # Copyright (c) 2015, Intel Corporation # All rights reserved. # +# SPDX-License-Identifier: BSD-3-Clause +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # @@ -24,6 +26,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# This script runs only from the biosbits VM. + """SMBIOS/DMI module.""" import bits diff --git a/tests/avocado/acpi-bits/bits-tests/testacpi.py2 b/tests/avocado/acpi-bits/bits-tests/testacpi.py2 index dbc150076e..f818a9cce6 100644 --- a/tests/avocado/acpi-bits/bits-tests/testacpi.py2 +++ b/tests/avocado/acpi-bits/bits-tests/testacpi.py2 @@ -1,6 +1,8 @@ # Copyright (c) 2015, Intel Corporation # All rights reserved. # +# SPDX-License-Identifier: BSD-3-Clause +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # @@ -24,6 +26,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# This script runs only from the biosbits VM. + """Tests for ACPI""" import acpi diff --git a/tests/avocado/acpi-bits/bits-tests/testcpuid.py2 b/tests/avocado/acpi-bits/bits-tests/testcpuid.py2 index ac55d912e1..7adefbe355 100644 --- a/tests/avocado/acpi-bits/bits-tests/testcpuid.py2 +++ b/tests/avocado/acpi-bits/bits-tests/testcpuid.py2 @@ -1,6 +1,8 @@ # Copyright (c) 2012, Intel Corporation # All rights reserved. # +# SPDX-License-Identifier: BSD-3-Clause +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # @@ -24,6 +26,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# This script runs only from the biosbits VM. + """Tests and helpers for CPUID.""" import bits diff --git a/tests/qtest/tco-test.c b/tests/qtest/tco-test.c index 254f735370..d865e95dfc 100644 --- a/tests/qtest/tco-test.c +++ b/tests/qtest/tco-test.c @@ -16,7 +16,7 @@ #include "hw/pci/pci_regs.h" #include "hw/i386/ich9.h" #include "hw/acpi/ich9.h" -#include "hw/acpi/tco.h" +#include "hw/acpi/ich9_tco.h" #define RCBA_BASE_ADDR 0xfed1c000 #define PM_IO_BASE_ADDR 0xb000 @@ -60,7 +60,7 @@ static void test_init(TestData *d) QTestState *qs; qs = qtest_initf("-machine q35 %s %s", - d->noreboot ? "" : "-global ICH9-LPC.noreboot=false", + d->noreboot ? "-global ICH9-LPC.noreboot=true" : "", !d->args ? "" : d->args); qtest_irq_intercept_in(qs, "ioapic");