aboutsummaryrefslogtreecommitdiff
path: root/hw/vfio
diff options
context:
space:
mode:
Diffstat (limited to 'hw/vfio')
-rw-r--r--hw/vfio/cpr.c2
-rw-r--r--hw/vfio/display.c4
-rw-r--r--hw/vfio/igd.c19
-rw-r--r--hw/vfio/pci.c31
-rw-r--r--hw/vfio/pci.h13
-rw-r--r--hw/vfio/types.h23
-rw-r--r--hw/vfio/vfio-migration-internal.h1
7 files changed, 69 insertions, 24 deletions
diff --git a/hw/vfio/cpr.c b/hw/vfio/cpr.c
index af0f12a..384b56c 100644
--- a/hw/vfio/cpr.c
+++ b/hw/vfio/cpr.c
@@ -116,6 +116,8 @@ static int vfio_cpr_pci_post_load(void *opaque, int version_id)
PCIDevice *pdev = &vdev->pdev;
int nr_vectors;
+ vfio_sub_page_bar_update_mappings(vdev);
+
if (msix_enabled(pdev)) {
vfio_pci_msix_set_notifiers(vdev);
nr_vectors = vdev->msix->entries;
diff --git a/hw/vfio/display.c b/hw/vfio/display.c
index 9c6f5aa..faacd90 100644
--- a/hw/vfio/display.c
+++ b/hw/vfio/display.c
@@ -365,7 +365,7 @@ static bool vfio_display_dmabuf_init(VFIOPCIDevice *vdev, Error **errp)
&vfio_display_dmabuf_ops,
vdev);
if (vdev->enable_ramfb) {
- vdev->dpy->ramfb = ramfb_setup(errp);
+ vdev->dpy->ramfb = ramfb_setup(vdev->use_legacy_x86_rom, errp);
if (!vdev->dpy->ramfb) {
return false;
}
@@ -494,7 +494,7 @@ static bool vfio_display_region_init(VFIOPCIDevice *vdev, Error **errp)
&vfio_display_region_ops,
vdev);
if (vdev->enable_ramfb) {
- vdev->dpy->ramfb = ramfb_setup(errp);
+ vdev->dpy->ramfb = ramfb_setup(vdev->use_legacy_x86_rom, errp);
if (!vdev->dpy->ramfb) {
return false;
}
diff --git a/hw/vfio/igd.c b/hw/vfio/igd.c
index e7a9d1f..ee0767b 100644
--- a/hw/vfio/igd.c
+++ b/hw/vfio/igd.c
@@ -113,6 +113,7 @@ static int igd_gen(VFIOPCIDevice *vdev)
#define IGD_BDSM 0x5c /* Base Data of Stolen Memory */
#define IGD_BDSM_GEN11 0xc0 /* Base Data of Stolen Memory of gen 11 and later */
+#define IGD_GMCH_VGA_DISABLE BIT(1)
#define IGD_GMCH_GEN6_GMS_SHIFT 3 /* SNB_GMCH in i915 */
#define IGD_GMCH_GEN6_GMS_MASK 0x1f
#define IGD_GMCH_GEN8_GMS_SHIFT 8 /* BDW_GMCH in i915 */
@@ -533,12 +534,14 @@ static bool vfio_pci_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp)
/*
* For backward compatibility, enable legacy mode when
* - Device geneation is 6 to 9 (including both)
+ * - IGD claims VGA cycles on host
* - Machine type is i440fx (pc_piix)
* - IGD device is at guest BDF 00:02.0
* - Not manually disabled by x-igd-legacy-mode=off
*/
if ((vdev->igd_legacy_mode != ON_OFF_AUTO_OFF) &&
(gen >= 6 && gen <= 9) &&
+ !(gmch & IGD_GMCH_VGA_DISABLE) &&
!strcmp(MACHINE_GET_CLASS(qdev_get_machine())->family, "pc_piix") &&
(&vdev->pdev == pci_find_device(pci_device_root_bus(&vdev->pdev),
0, PCI_DEVFN(0x2, 0)))) {
@@ -568,14 +571,16 @@ static bool vfio_pci_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp)
}
/*
- * If IGD VGA Disable is clear (expected) and VGA is not already
- * enabled, try to enable it. Probably shouldn't be using legacy mode
- * without VGA, but also no point in us enabling VGA if disabled in
- * hardware.
+ * If VGA is not already enabled, try to enable it. We shouldn't be
+ * using legacy mode without VGA.
*/
- if (!(gmch & 0x2) && !vdev->vga && !vfio_populate_vga(vdev, &err)) {
- error_setg(&err, "Unable to enable VGA access");
- goto error;
+ if (!vdev->vga) {
+ if (vfio_populate_vga(vdev, &err)) {
+ vfio_pci_config_register_vga(vdev);
+ } else {
+ error_setg(&err, "Unable to enable VGA access");
+ goto error;
+ }
}
/* Enable OpRegion and LPC bridge quirk */
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index be05002..4fa692c 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -49,8 +49,6 @@
#include "vfio-migration-internal.h"
#include "vfio-helpers.h"
-#define TYPE_VFIO_PCI_NOHOTPLUG "vfio-pci-nohotplug"
-
/* Protected by BQL */
static KVMRouteChange vfio_route_change;
@@ -2826,6 +2824,20 @@ static int vfio_pci_load_config(VFIODevice *vbasedev, QEMUFile *f)
return ret;
}
+void vfio_sub_page_bar_update_mappings(VFIOPCIDevice *vdev)
+{
+ PCIDevice *pdev = &vdev->pdev;
+ int page_size = qemu_real_host_page_size();
+ int bar;
+
+ for (bar = 0; bar < PCI_ROM_SLOT; bar++) {
+ PCIIORegion *r = &pdev->io_regions[bar];
+ if (r->addr != PCI_BAR_UNMAPPED && r->size > 0 && r->size < page_size) {
+ vfio_sub_page_bar_update_mapping(pdev, bar);
+ }
+ }
+}
+
static VFIODeviceOps vfio_pci_ops = {
.vfio_compute_needs_reset = vfio_pci_compute_needs_reset,
.vfio_hot_reset_multi = vfio_pci_hot_reset_multi,
@@ -3150,6 +3162,15 @@ static void vfio_unregister_req_notifier(VFIOPCIDevice *vdev)
vdev->req_enabled = false;
}
+void vfio_pci_config_register_vga(VFIOPCIDevice *vdev)
+{
+ assert(vdev->vga != NULL);
+
+ pci_register_vga(&vdev->pdev, &vdev->vga->region[QEMU_PCI_VGA_MEM].mem,
+ &vdev->vga->region[QEMU_PCI_VGA_IO_LO].mem,
+ &vdev->vga->region[QEMU_PCI_VGA_IO_HI].mem);
+}
+
bool vfio_pci_config_setup(VFIOPCIDevice *vdev, Error **errp)
{
PCIDevice *pdev = &vdev->pdev;
@@ -3271,9 +3292,7 @@ bool vfio_pci_config_setup(VFIOPCIDevice *vdev, Error **errp)
vfio_bars_register(vdev);
if (vdev->vga && vfio_is_vga(vdev)) {
- pci_register_vga(&vdev->pdev, &vdev->vga->region[QEMU_PCI_VGA_MEM].mem,
- &vdev->vga->region[QEMU_PCI_VGA_IO_LO].mem,
- &vdev->vga->region[QEMU_PCI_VGA_IO_HI].mem);
+ vfio_pci_config_register_vga(vdev);
}
return true;
@@ -3849,6 +3868,8 @@ static const TypeInfo vfio_pci_dev_info = {
static const Property vfio_pci_dev_nohotplug_properties[] = {
DEFINE_PROP_BOOL("ramfb", VFIOPCIDevice, enable_ramfb, false),
+ DEFINE_PROP_BOOL("use-legacy-x86-rom", VFIOPCIDevice,
+ use_legacy_x86_rom, false),
DEFINE_PROP_ON_OFF_AUTO("x-ramfb-migrate", VFIOPCIDevice, ramfb_migrate,
ON_OFF_AUTO_AUTO),
};
diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index 4aa6461..81465a8 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -14,6 +14,7 @@
#include "system/memory.h"
#include "hw/pci/pci_device.h"
+#include "hw/vfio/types.h"
#include "hw/vfio/vfio-device.h"
#include "hw/vfio/vfio-region.h"
#include "qemu/event_notifier.h"
@@ -119,17 +120,8 @@ typedef struct VFIOMSIXInfo {
MemoryRegion *pba_region;
} VFIOMSIXInfo;
-/*
- * TYPE_VFIO_PCI_BASE is an abstract type used to share code
- * between VFIO implementations that use a kernel driver
- * with those that use user sockets.
- */
-#define TYPE_VFIO_PCI_BASE "vfio-pci-base"
OBJECT_DECLARE_SIMPLE_TYPE(VFIOPCIDevice, VFIO_PCI_BASE)
-#define TYPE_VFIO_PCI "vfio-pci"
-/* TYPE_VFIO_PCI shares struct VFIOPCIDevice. */
-
struct VFIOPCIDevice {
PCIDevice pdev;
VFIODevice vbasedev;
@@ -189,6 +181,7 @@ struct VFIOPCIDevice {
bool no_kvm_ioeventfd;
bool no_vfio_ioeventfd;
bool enable_ramfb;
+ bool use_legacy_x86_rom;
OnOffAuto ramfb_migrate;
bool defer_kvm_irq_routing;
bool clear_parent_atomics_on_exit;
@@ -226,6 +219,7 @@ void vfio_pci_write_config(PCIDevice *pdev,
uint64_t vfio_vga_read(void *opaque, hwaddr addr, unsigned size);
void vfio_vga_write(void *opaque, hwaddr addr, uint64_t data, unsigned size);
+void vfio_sub_page_bar_update_mappings(VFIOPCIDevice *vdev);
bool vfio_opt_rom_in_denylist(VFIOPCIDevice *vdev);
bool vfio_config_quirk_setup(VFIOPCIDevice *vdev, Error **errp);
void vfio_vga_quirk_setup(VFIOPCIDevice *vdev);
@@ -259,6 +253,7 @@ extern const VMStateDescription vfio_display_vmstate;
void vfio_pci_bars_exit(VFIOPCIDevice *vdev);
bool vfio_pci_add_capabilities(VFIOPCIDevice *vdev, Error **errp);
+void vfio_pci_config_register_vga(VFIOPCIDevice *vdev);
bool vfio_pci_config_setup(VFIOPCIDevice *vdev, Error **errp);
bool vfio_pci_interrupt_setup(VFIOPCIDevice *vdev, Error **errp);
void vfio_pci_intx_eoi(VFIODevice *vbasedev);
diff --git a/hw/vfio/types.h b/hw/vfio/types.h
new file mode 100644
index 0000000..c19334f
--- /dev/null
+++ b/hw/vfio/types.h
@@ -0,0 +1,23 @@
+/*
+ * VFIO types definition
+ *
+ * Copyright Red Hat, Inc. 2025
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_VFIO_VFIO_TYPES_H
+#define HW_VFIO_VFIO_TYPES_H
+
+/*
+ * TYPE_VFIO_PCI_BASE is an abstract type used to share code
+ * between VFIO implementations that use a kernel driver
+ * with those that use user sockets.
+ */
+#define TYPE_VFIO_PCI_BASE "vfio-pci-base"
+
+#define TYPE_VFIO_PCI "vfio-pci"
+/* TYPE_VFIO_PCI shares struct VFIOPCIDevice. */
+
+#define TYPE_VFIO_PCI_NOHOTPLUG "vfio-pci-nohotplug"
+
+#endif /* HW_VFIO_VFIO_TYPES_H */
diff --git a/hw/vfio/vfio-migration-internal.h b/hw/vfio/vfio-migration-internal.h
index 54141e2..814fbd9 100644
--- a/hw/vfio/vfio-migration-internal.h
+++ b/hw/vfio/vfio-migration-internal.h
@@ -13,7 +13,6 @@
#include <linux/vfio.h>
#endif
-#include "qemu/typedefs.h"
#include "qemu/notify.h"
/*