Merge tag 'pull-vfio-20250311' of https://github.com/legoater/qemu into staging

vfio queue:

* Fixed endianness of VFIO device state packets
* Improved IGD passthrough support with legacy mode
* Improved build
* Added support for old AMD GPUs (x550)
* Updated property documentation

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmfQfQcACgkQUaNDx8/7
# 7KEUNw/+PjFpHrz5muQ8itkbyd36eJJdcxCl+9IPIWfnUfB582epkLcgvWyswGUo
# krFTregoRG0PKtgZDtv95owGtVJOgK6XYFadGHiYkvvsb41twOYsP7/SuI+KMiEv
# IDFLMvCTyorSIIoEF8i2EexfGPRV1VoWwvBoHgRRmYlzwzXnufjABpoZ0a25DTye
# DQ4yhSfqoIh1gOcdL9tPictnZg9OxKr2ePXNdrtymtEIhg3ZobD3Jd8J4WCcsfKT
# fxxBO5NsGgA8oM7i02fYN9kgMwqTnVhSAu1wq9PXsbrnNXam+trywAWSO6CjL+rV
# ++STWNSrRoHzuotRBr7BzrTpTFyQyfwBWqUT5L4NlhgXB3Xybk+M6Zj08Yva8pjE
# w78JQKvKp54gU34AWBW0/J6+u3v+iE8l1Eywx6xueF9Q+YSUDeW9B1LDdjFJryhF
# d8j3J+vuglbdsp05D+tVErf5cqFvFDfrjTkXkZNtmx7wky45XS9ZvNazYW1KI3f9
# bg8Wjb7ZujuvxpSjycPRZzdKa8kqSgSZg7fg91Wimiy1Iqe3SZVVWNchLYiPp8Dm
# nXMfOEpVHQZ1vzeo7dVWyxu9Y1ujgvUQy8kMa9q2W2S7HQ5Sna79n7eMVJxqZQ4G
# m0ETFToOcPPOnZBWgqNOSUlSQncFuIVgNTDvycQ9dMhGorYcBDI=
# =Vh0m
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 12 Mar 2025 02:12:23 HKT
# gpg:                using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1
# gpg: Good signature from "Cédric Le Goater <clg@redhat.com>" [full]
# gpg:                 aka "Cédric Le Goater <clg@kaod.org>" [full]
# Primary key fingerprint: A0F6 6548 F048 95EB FE6B  0B60 51A3 43C7 CFFB ECA1

* tag 'pull-vfio-20250311' of https://github.com/legoater/qemu: (21 commits)
  vfio/pci: Drop debug commentary from x-device-dirty-page-tracking
  vfio/pci-quirks: Exclude non-ioport BAR from ATI quirk
  hw/vfio: Compile display.c once
  hw/vfio: Compile iommufd.c once
  hw/vfio: Compile more objects once
  hw/vfio: Compile some common objects once
  hw/vfio/common: Get target page size using runtime helpers
  hw/vfio/common: Include missing 'system/tcg.h' header
  hw/vfio/spapr: Do not include <linux/kvm.h>
  system: Declare qemu_[min/max]rampagesize() in 'system/hostmem.h'
  vfio/migration: Use BE byte order for device state wire packets
  vfio/igd: Fix broken KVMGT OpRegion support
  vfio/igd: Introduce x-igd-lpc option for LPC bridge ID quirk
  vfio/igd: Handle x-igd-opregion option in config quirk
  vfio/igd: Decouple common quirks from legacy mode
  vfio/igd: Refactor vfio_probe_igd_bar4_quirk into pci config quirk
  vfio/pci: Add placeholder for device-specific config space quirks
  vfio/igd: Move LPC bridge initialization to a separate function
  vfio/igd: Consolidate OpRegion initialization into a single function
  vfio/igd: Do not include GTT stolen size in etc/igd-bdsm-size
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi
2025-03-13 10:35:12 +08:00
14 changed files with 297 additions and 414 deletions
+1
View File
@@ -34,6 +34,7 @@
#include "kvm_ppc.h"
#include "migration/vmstate.h"
#include "system/tcg.h"
#include "system/hostmem.h"
#include "hw/ppc/spapr.h"
+1
View File
@@ -41,6 +41,7 @@
#include "hw/s390x/tod.h"
#include "system/system.h"
#include "system/cpus.h"
#include "system/hostmem.h"
#include "target/s390x/kvm/pv.h"
#include "migration/blocker.h"
#include "qapi/visitor.h"
+6 -3
View File
@@ -30,6 +30,7 @@
#include "exec/address-spaces.h"
#include "exec/memory.h"
#include "exec/ram_addr.h"
#include "exec/target_page.h"
#include "hw/hw.h"
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
@@ -42,6 +43,7 @@
#include "migration/misc.h"
#include "migration/blocker.h"
#include "migration/qemu-file.h"
#include "system/tcg.h"
#include "system/tpm.h"
VFIODeviceList vfio_device_list =
@@ -392,13 +394,14 @@ static void vfio_register_ram_discard_listener(VFIOContainerBase *bcontainer,
MemoryRegionSection *section)
{
RamDiscardManager *rdm = memory_region_get_ram_discard_manager(section->mr);
int target_page_size = qemu_target_page_size();
VFIORamDiscardListener *vrdl;
/* Ignore some corner cases not relevant in practice. */
g_assert(QEMU_IS_ALIGNED(section->offset_within_region, TARGET_PAGE_SIZE));
g_assert(QEMU_IS_ALIGNED(section->offset_within_region, target_page_size));
g_assert(QEMU_IS_ALIGNED(section->offset_within_address_space,
TARGET_PAGE_SIZE));
g_assert(QEMU_IS_ALIGNED(int128_get64(section->size), TARGET_PAGE_SIZE));
target_page_size));
g_assert(QEMU_IS_ALIGNED(int128_get64(section->size), target_page_size));
vrdl = g_new0(VFIORamDiscardListener, 1);
vrdl->bcontainer = bcontainer;
+233 -304
View File
File diff suppressed because it is too large Load Diff
-1
View File
@@ -25,7 +25,6 @@
#include "qemu/cutils.h"
#include "qemu/chardev_open.h"
#include "pci.h"
#include "exec/ram_addr.h"
static int iommufd_cdev_map(const VFIOContainerBase *bcontainer, hwaddr iova,
ram_addr_t size, void *vaddr, bool readonly)
+16 -11
View File
@@ -1,27 +1,32 @@
vfio_ss = ss.source_set()
vfio_ss.add(files(
'helpers.c',
'common.c',
'container-base.c',
'container.c',
'migration.c',
'migration-multifd.c',
'cpr.c',
))
vfio_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr.c'))
vfio_ss.add(when: 'CONFIG_IOMMUFD', if_true: files(
'iommufd.c',
))
vfio_ss.add(when: 'CONFIG_VFIO_PCI', if_true: files(
'display.c',
'pci-quirks.c',
'pci.c',
))
vfio_ss.add(when: 'CONFIG_VFIO_CCW', if_true: files('ccw.c'))
vfio_ss.add(when: 'CONFIG_VFIO_PLATFORM', if_true: files('platform.c'))
vfio_ss.add(when: 'CONFIG_VFIO_XGMAC', if_true: files('calxeda-xgmac.c'))
vfio_ss.add(when: 'CONFIG_VFIO_AMD_XGBE', if_true: files('amd-xgbe.c'))
vfio_ss.add(when: 'CONFIG_VFIO_AP', if_true: files('ap.c'))
vfio_ss.add(when: 'CONFIG_VFIO_IGD', if_true: files('igd.c'))
specific_ss.add_all(when: 'CONFIG_VFIO', if_true: vfio_ss)
system_ss.add(when: 'CONFIG_VFIO_XGMAC', if_true: files('calxeda-xgmac.c'))
system_ss.add(when: 'CONFIG_VFIO_AMD_XGBE', if_true: files('amd-xgbe.c'))
system_ss.add(when: 'CONFIG_VFIO', if_true: files(
'helpers.c',
'container-base.c',
'migration.c',
'migration-multifd.c',
'cpr.c',
))
system_ss.add(when: ['CONFIG_VFIO', 'CONFIG_IOMMUFD'], if_true: files(
'iommufd.c',
))
system_ss.add(when: 'CONFIG_VFIO_PCI', if_true: files(
'display.c',
))
+10 -5
View File
@@ -13,6 +13,7 @@
#include "hw/vfio/vfio-common.h"
#include "migration/misc.h"
#include "qapi/error.h"
#include "qemu/bswap.h"
#include "qemu/error-report.h"
#include "qemu/lockable.h"
#include "qemu/main-loop.h"
@@ -155,12 +156,16 @@ bool vfio_multifd_load_state_buffer(void *opaque, char *data, size_t data_size,
return false;
}
packet->version = be32_to_cpu(packet->version);
if (packet->version != VFIO_DEVICE_STATE_PACKET_VER_CURRENT) {
error_setg(errp, "%s: packet has unknown version %" PRIu32,
vbasedev->name, packet->version);
return false;
}
packet->idx = be32_to_cpu(packet->idx);
packet->flags = be32_to_cpu(packet->flags);
if (packet->idx == UINT32_MAX) {
error_setg(errp, "%s: packet index is invalid", vbasedev->name);
return false;
@@ -558,9 +563,9 @@ vfio_save_complete_precopy_thread_config_state(VFIODevice *vbasedev,
packet_len = sizeof(*packet) + bioc->usage;
packet = g_malloc0(packet_len);
packet->version = VFIO_DEVICE_STATE_PACKET_VER_CURRENT;
packet->idx = idx;
packet->flags = VFIO_DEVICE_STATE_CONFIG_STATE;
packet->version = cpu_to_be32(VFIO_DEVICE_STATE_PACKET_VER_CURRENT);
packet->idx = cpu_to_be32(idx);
packet->flags = cpu_to_be32(VFIO_DEVICE_STATE_CONFIG_STATE);
memcpy(&packet->data, bioc->data, bioc->usage);
if (!multifd_queue_device_state(idstr, instance_id,
@@ -610,7 +615,7 @@ vfio_multifd_save_complete_precopy_thread(SaveLiveCompletePrecopyThreadData *d,
}
packet = g_malloc0(sizeof(*packet) + migration->data_buffer_size);
packet->version = VFIO_DEVICE_STATE_PACKET_VER_CURRENT;
packet->version = cpu_to_be32(VFIO_DEVICE_STATE_PACKET_VER_CURRENT);
for (idx = 0; ; idx++) {
ssize_t data_size;
@@ -631,7 +636,7 @@ vfio_multifd_save_complete_precopy_thread(SaveLiveCompletePrecopyThreadData *d,
break;
}
packet->idx = idx;
packet->idx = cpu_to_be32(idx);
packet_size = sizeof(*packet) + data_size;
if (!multifd_queue_device_state(d->idstr, d->instance_id,
-1
View File
@@ -27,7 +27,6 @@
#include "qapi/error.h"
#include "qapi/qapi-events-vfio.h"
#include "exec/ramlist.h"
#include "exec/ram_addr.h"
#include "pci.h"
#include "trace.h"
#include "hw/hw.h"
+11 -52
View File
@@ -403,7 +403,7 @@ static void vfio_probe_ati_bar4_quirk(VFIOPCIDevice *vdev, int nr)
/* This windows doesn't seem to be used except by legacy VGA code */
if (!vfio_pci_is(vdev, PCI_VENDOR_ID_ATI, PCI_ANY_ID) ||
!vdev->vga || nr != 4) {
!vdev->vga || nr != 4 || !vdev->bars[4].ioport) {
return;
}
@@ -1114,59 +1114,19 @@ static void vfio_probe_rtl8168_bar2_quirk(VFIOPCIDevice *vdev, int nr)
trace_vfio_quirk_rtl8168_probe(vdev->vbasedev.name);
}
#define IGD_ASLS 0xfc /* ASL Storage Register */
/*
* The OpRegion includes the Video BIOS Table, which seems important for
* telling the driver what sort of outputs it has. Without this, the device
* may work in the guest, but we may not get output. This also requires BIOS
* support to reserve and populate a section of guest memory sufficient for
* the table and to write the base address of that memory to the ASLS register
* of the IGD device.
*/
bool vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev,
struct vfio_region_info *info, Error **errp)
{
int ret;
vdev->igd_opregion = g_malloc0(info->size);
ret = pread(vdev->vbasedev.fd, vdev->igd_opregion,
info->size, info->offset);
if (ret != info->size) {
error_setg(errp, "failed to read IGD OpRegion");
g_free(vdev->igd_opregion);
vdev->igd_opregion = NULL;
return false;
}
/*
* Provide fw_cfg with a copy of the OpRegion which the VM firmware is to
* allocate 32bit reserved memory for, copy these contents into, and write
* the reserved memory base address to the device ASLS register at 0xFC.
* Alignment of this reserved region seems flexible, but using a 4k page
* alignment seems to work well. This interface assumes a single IGD
* device, which may be at VM address 00:02.0 in legacy mode or another
* address in UPT mode.
*
* NB, there may be future use cases discovered where the VM should have
* direct interaction with the host OpRegion, in which case the write to
* the ASLS register would trigger MemoryRegion setup to enable that.
*/
fw_cfg_add_file(fw_cfg_find(), "etc/igd-opregion",
vdev->igd_opregion, info->size);
trace_vfio_pci_igd_opregion_enabled(vdev->vbasedev.name);
pci_set_long(vdev->pdev.config + IGD_ASLS, 0);
pci_set_long(vdev->pdev.wmask + IGD_ASLS, ~0);
pci_set_long(vdev->emulated_config_bits + IGD_ASLS, ~0);
return true;
}
/*
* Common quirk probe entry points.
*/
bool vfio_config_quirk_setup(VFIOPCIDevice *vdev, Error **errp)
{
#ifdef CONFIG_VFIO_IGD
if (!vfio_probe_igd_config_quirk(vdev, errp)) {
return false;
}
#endif
return true;
}
void vfio_vga_quirk_setup(VFIOPCIDevice *vdev)
{
vfio_vga_probe_ati_3c3_quirk(vdev);
@@ -1215,7 +1175,6 @@ void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr)
vfio_probe_rtl8168_bar2_quirk(vdev, nr);
#ifdef CONFIG_VFIO_IGD
vfio_probe_igd_bar0_quirk(vdev, nr);
vfio_probe_igd_bar4_quirk(vdev, nr);
#endif
}
+9 -26
View File
@@ -3128,6 +3128,10 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
goto out_unset_idev;
}
if (!vfio_config_quirk_setup(vdev, errp)) {
goto out_unset_idev;
}
if (vdev->vga) {
vfio_vga_quirk_setup(vdev);
}
@@ -3136,31 +3140,6 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
vfio_bar_quirk_setup(vdev, i);
}
if (!vdev->igd_opregion &&
vdev->features & VFIO_FEATURE_ENABLE_IGD_OPREGION) {
g_autofree struct vfio_region_info *opregion = NULL;
if (vdev->pdev.qdev.hotplugged) {
error_setg(errp,
"cannot support IGD OpRegion feature on hotplugged "
"device");
goto out_unset_idev;
}
ret = vfio_get_dev_region_info(vbasedev,
VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, &opregion);
if (ret) {
error_setg_errno(errp, -ret,
"does not support requested IGD OpRegion feature");
goto out_unset_idev;
}
if (!vfio_pci_igd_opregion_init(vdev, opregion, errp)) {
goto out_unset_idev;
}
}
/* QEMU emulates all of MSI & MSIX */
if (pdev->cap_present & QEMU_PCI_CAP_MSIX) {
memset(vdev->emulated_config_bits + pdev->msix_cap, 0xff,
@@ -3381,6 +3360,10 @@ static const Property vfio_pci_dev_properties[] = {
VFIO_FEATURE_ENABLE_REQ_BIT, true),
DEFINE_PROP_BIT("x-igd-opregion", VFIOPCIDevice, features,
VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT, false),
DEFINE_PROP_BIT("x-igd-lpc", VFIOPCIDevice, features,
VFIO_FEATURE_ENABLE_IGD_LPC_BIT, false),
DEFINE_PROP_ON_OFF_AUTO("x-igd-legacy-mode", VFIOPCIDevice,
igd_legacy_mode, ON_OFF_AUTO_AUTO),
DEFINE_PROP_ON_OFF_AUTO("enable-migration", VFIOPCIDevice,
vbasedev.enable_migration, ON_OFF_AUTO_AUTO),
DEFINE_PROP("x-migration-multifd-transfer", VFIOPCIDevice,
@@ -3549,7 +3532,7 @@ static void vfio_pci_dev_class_init(ObjectClass *klass, void *data)
object_class_property_set_description(klass, /* 9.1 */
"x-device-dirty-page-tracking",
"Disable device dirty page tracking and use "
"container-based dirty page tracking (DEBUG)");
"container-based dirty page tracking");
object_class_property_set_description(klass, /* 9.1 */
"migration-events",
"Emit VFIO migration QAPI event when a VFIO device "
+6 -5
View File
@@ -154,10 +154,14 @@ struct VFIOPCIDevice {
#define VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT 2
#define VFIO_FEATURE_ENABLE_IGD_OPREGION \
(1 << VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT)
#define VFIO_FEATURE_ENABLE_IGD_LPC_BIT 3
#define VFIO_FEATURE_ENABLE_IGD_LPC \
(1 << VFIO_FEATURE_ENABLE_IGD_LPC_BIT)
OnOffAuto display;
uint32_t display_xres;
uint32_t display_yres;
int32_t bootindex;
OnOffAuto igd_legacy_mode;
uint32_t igd_gms;
OffAutoPCIBAR msix_relo;
uint8_t nv_gpudirect_clique;
@@ -204,6 +208,7 @@ uint64_t vfio_vga_read(void *opaque, hwaddr addr, unsigned size);
void vfio_vga_write(void *opaque, hwaddr addr, uint64_t data, unsigned size);
bool vfio_opt_rom_in_denylist(VFIOPCIDevice *vdev);
bool vfio_config_quirk_setup(VFIOPCIDevice *vdev, Error **errp);
void vfio_vga_quirk_setup(VFIOPCIDevice *vdev);
void vfio_vga_quirk_exit(VFIOPCIDevice *vdev);
void vfio_vga_quirk_finalize(VFIOPCIDevice *vdev);
@@ -215,7 +220,7 @@ bool vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp);
void vfio_quirk_reset(VFIOPCIDevice *vdev);
VFIOQuirk *vfio_quirk_alloc(int nr_mem);
void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev, int nr);
void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr);
bool vfio_probe_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp);
extern const PropertyInfo qdev_prop_nv_gpudirect_clique;
@@ -227,10 +232,6 @@ int vfio_pci_get_pci_hot_reset_info(VFIOPCIDevice *vdev,
bool vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp);
bool vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev,
struct vfio_region_info *info,
Error **errp);
void vfio_display_reset(VFIOPCIDevice *vdev);
bool vfio_display_probe(VFIOPCIDevice *vdev, Error **errp);
void vfio_display_finalize(VFIOPCIDevice *vdev);
+1 -3
View File
@@ -11,10 +11,8 @@
#include "qemu/osdep.h"
#include <sys/ioctl.h>
#include <linux/vfio.h>
#ifdef CONFIG_KVM
#include <linux/kvm.h>
#endif
#include "system/kvm.h"
#include "system/hostmem.h"
#include "exec/address-spaces.h"
#include "hw/vfio/vfio-common.h"
-3
View File
@@ -102,9 +102,6 @@ static inline unsigned long int ramblock_recv_bitmap_offset(void *host_addr,
bool ramblock_is_pmem(RAMBlock *rb);
long qemu_minrampagesize(void);
long qemu_maxrampagesize(void);
/**
* qemu_ram_alloc_from_file,
* qemu_ram_alloc_from_fd: Allocate a ram block from the specified backing
+3
View File
@@ -93,4 +93,7 @@ bool host_memory_backend_is_mapped(HostMemoryBackend *backend);
size_t host_memory_backend_pagesize(HostMemoryBackend *memdev);
char *host_memory_backend_get_name(HostMemoryBackend *backend);
long qemu_minrampagesize(void);
long qemu_maxrampagesize(void);
#endif