From: "Cédric Le Goater" <clg@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Alex Williamson" <alex.williamson@redhat.com>,
"Tomita Moeko" <tomitamoeko@gmail.com>,
"Corvin Köhne" <c.koehne@beckhoff.com>,
"Cédric Le Goater" <clg@redhat.com>
Subject: [PULL 03/21] vfio/igd: Consolidate OpRegion initialization into a single function
Date: Tue, 11 Mar 2025 19:13:10 +0100 [thread overview]
Message-ID: <20250311181328.1200431-4-clg@redhat.com> (raw)
In-Reply-To: <20250311181328.1200431-1-clg@redhat.com>
From: Tomita Moeko <tomitamoeko@gmail.com>
Both x-igd-opregion option and legacy mode require identical steps to
set up OpRegion for IGD devices. Consolidate these steps into a single
vfio_pci_igd_setup_opregion function.
The function call in pci.c is wrapped with ifdef temporarily to prevent
build error for non-x86 archs, it will be removed after we decouple it
from legacy mode.
Additionally, move vfio_pci_igd_opregion_init to igd.c to prevent it
from being compiled in non-x86 builds.
Signed-off-by: Tomita Moeko <tomitamoeko@gmail.com>
Reviewed-by: Alex Williamson <alex.williamson@redhat.com>
Tested-by: Alex Williamson <alex.williamson@redhat.com>
Reviewed-by: Corvin Köhne <c.koehne@beckhoff.com>
Link: https://lore.kernel.org/qemu-devel/20250306180131.32970-4-tomitamoeko@gmail.com
[ clg: Fixed spelling in vfio_pci_igd_setup_opregion() ]
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
hw/vfio/pci.h | 4 +-
hw/vfio/igd.c | 101 +++++++++++++++++++++++++++++++++++--------
hw/vfio/pci-quirks.c | 50 ---------------------
hw/vfio/pci.c | 22 ++--------
4 files changed, 88 insertions(+), 89 deletions(-)
diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index d638c781f6f168a71d3a44b48ba0c4edfd334f44..f660b0d80fcfcb81129d443732fe887b084d7a52 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -227,9 +227,7 @@ 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);
+bool vfio_pci_igd_setup_opregion(VFIOPCIDevice *vdev, Error **errp);
void vfio_display_reset(VFIOPCIDevice *vdev);
bool vfio_display_probe(VFIOPCIDevice *vdev, Error **errp);
diff --git a/hw/vfio/igd.c b/hw/vfio/igd.c
index dda4c7bb5df8bd056c3e06eae38533da7586c6c9..113ad56ad4206e29198717d944ffe944e1c2e27c 100644
--- a/hw/vfio/igd.c
+++ b/hw/vfio/igd.c
@@ -106,6 +106,7 @@ static int igd_gen(VFIOPCIDevice *vdev)
return -1;
}
+#define IGD_ASLS 0xfc /* ASL Storage Register */
#define IGD_GMCH 0x50 /* Graphics Control Register */
#define IGD_BDSM 0x5c /* Base Data of Stolen Memory */
#define IGD_BDSM_GEN11 0xc0 /* Base Data of Stolen Memory of gen 11 and later */
@@ -138,6 +139,82 @@ static uint64_t igd_stolen_memory_size(int gen, uint32_t gmch)
return 0;
}
+/*
+ * 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.
+ */
+static 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;
+}
+
+bool vfio_pci_igd_setup_opregion(VFIOPCIDevice *vdev, Error **errp)
+{
+ g_autofree struct vfio_region_info *opregion = NULL;
+ int ret;
+
+ /* Hotplugging is not supported for opregion access */
+ if (vdev->pdev.qdev.hotplugged) {
+ error_setg(errp, "IGD OpRegion is not supported on hotplugged device");
+ return false;
+ }
+
+ ret = vfio_get_dev_region_info(&vdev->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,
+ "Device does not supports IGD OpRegion feature");
+ return false;
+ }
+
+ if (!vfio_pci_igd_opregion_init(vdev, opregion, errp)) {
+ return false;
+ }
+
+ return true;
+}
+
/*
* The rather short list of registers that we copy from the host devices.
* The LPC/ISA bridge values are definitely needed to support the vBIOS, the
@@ -342,7 +419,6 @@ void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev, int nr)
void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
{
g_autofree struct vfio_region_info *rom = NULL;
- g_autofree struct vfio_region_info *opregion = NULL;
g_autofree struct vfio_region_info *host = NULL;
g_autofree struct vfio_region_info *lpc = NULL;
PCIDevice *lpc_bridge;
@@ -418,15 +494,6 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
* Check whether we have all the vfio device specific regions to
* support legacy mode (added in Linux v4.6). If not, bail.
*/
- ret = vfio_get_dev_region_info(&vdev->vbasedev,
- VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
- VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, &opregion);
- if (ret) {
- error_report("IGD device %s does not support OpRegion access,"
- "legacy mode disabled", vdev->vbasedev.name);
- return;
- }
-
ret = vfio_get_dev_region_info(&vdev->vbasedev,
VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG, &host);
@@ -459,6 +526,13 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
return;
}
+ /* Setup OpRegion access */
+ if (!vfio_pci_igd_setup_opregion(vdev, &err)) {
+ error_append_hint(&err, "IGD legacy mode disabled\n");
+ error_report_err(err);
+ return;
+ }
+
/* Create our LPC/ISA bridge */
ret = vfio_pci_igd_lpc_init(vdev, lpc);
if (ret) {
@@ -475,13 +549,6 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
return;
}
- /* Setup OpRegion access */
- if (!vfio_pci_igd_opregion_init(vdev, opregion, &err)) {
- error_append_hint(&err, "IGD legacy mode disabled\n");
- error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
- return;
- }
-
/*
* Allow user to override dsm size using x-igd-gms option, in multiples of
* 32MiB. This option should only be used when the desired size cannot be
diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c
index c53591fe2ba5f71364befb7c916ae4f7abde4cbf..37966e17f0178bbf2d82b2d84da40ba2e261d9f3 100644
--- a/hw/vfio/pci-quirks.c
+++ b/hw/vfio/pci-quirks.c
@@ -1114,56 +1114,6 @@ 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.
*/
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index fdbc15885d442ee20343e6b7127d54a70b1688ce..419dc2c4c85ffeed3b794e65f8040e11ba58bb0e 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -3136,30 +3136,14 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
vfio_bar_quirk_setup(vdev, i);
}
+#ifdef CONFIG_VFIO_IGD
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)) {
+ if (!vfio_pci_igd_setup_opregion(vdev, errp)) {
goto out_unset_idev;
}
}
+#endif
/* QEMU emulates all of MSI & MSIX */
if (pdev->cap_present & QEMU_PCI_CAP_MSIX) {
--
2.48.1
next prev parent reply other threads:[~2025-03-11 18:15 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-11 18:13 [PULL 00/21] vfio queue Cédric Le Goater
2025-03-11 18:13 ` [PULL 01/21] vfio/igd: Remove GTT write quirk in IO BAR 4 Cédric Le Goater
2025-03-11 18:13 ` [PULL 02/21] vfio/igd: Do not include GTT stolen size in etc/igd-bdsm-size Cédric Le Goater
2025-03-11 18:13 ` Cédric Le Goater [this message]
2025-03-11 18:13 ` [PULL 04/21] vfio/igd: Move LPC bridge initialization to a separate function Cédric Le Goater
2025-03-11 18:13 ` [PULL 05/21] vfio/pci: Add placeholder for device-specific config space quirks Cédric Le Goater
2025-03-11 18:13 ` [PULL 06/21] vfio/igd: Refactor vfio_probe_igd_bar4_quirk into pci config quirk Cédric Le Goater
2025-03-11 18:13 ` [PULL 07/21] vfio/igd: Decouple common quirks from legacy mode Cédric Le Goater
2025-03-11 18:13 ` [PULL 08/21] vfio/igd: Handle x-igd-opregion option in config quirk Cédric Le Goater
2025-03-11 18:13 ` [PULL 09/21] vfio/igd: Introduce x-igd-lpc option for LPC bridge ID quirk Cédric Le Goater
2025-03-11 18:13 ` [PULL 10/21] vfio/igd: Fix broken KVMGT OpRegion support Cédric Le Goater
2025-03-11 18:13 ` [PULL 11/21] vfio/migration: Use BE byte order for device state wire packets Cédric Le Goater
2025-03-11 18:13 ` [PULL 12/21] system: Declare qemu_[min/max]rampagesize() in 'system/hostmem.h' Cédric Le Goater
2025-03-11 18:13 ` [PULL 13/21] hw/vfio/spapr: Do not include <linux/kvm.h> Cédric Le Goater
2025-03-11 18:13 ` [PULL 14/21] hw/vfio/common: Include missing 'system/tcg.h' header Cédric Le Goater
2025-03-11 18:13 ` [PULL 15/21] hw/vfio/common: Get target page size using runtime helpers Cédric Le Goater
2025-03-11 18:13 ` [PULL 16/21] hw/vfio: Compile some common objects once Cédric Le Goater
2025-03-11 18:13 ` [PULL 17/21] hw/vfio: Compile more " Cédric Le Goater
2025-03-11 18:13 ` [PULL 18/21] hw/vfio: Compile iommufd.c once Cédric Le Goater
2025-03-11 18:13 ` [PULL 19/21] hw/vfio: Compile display.c once Cédric Le Goater
2025-03-11 18:13 ` [PULL 20/21] vfio/pci-quirks: Exclude non-ioport BAR from ATI quirk Cédric Le Goater
2025-03-11 18:13 ` [PULL 21/21] vfio/pci: Drop debug commentary from x-device-dirty-page-tracking Cédric Le Goater
2025-03-13 7:05 ` [PULL 00/21] vfio queue Stefan Hajnoczi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250311181328.1200431-4-clg@redhat.com \
--to=clg@redhat.com \
--cc=alex.williamson@redhat.com \
--cc=c.koehne@beckhoff.com \
--cc=qemu-devel@nongnu.org \
--cc=tomitamoeko@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.