aboutsummaryrefslogtreecommitdiff
path: root/hw/vfio
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2016-05-26 09:43:22 -0600
committerAlex Williamson <alex.williamson@redhat.com>2016-05-26 11:12:03 -0600
commit6ced0bba70ff557792b781ad35366de03bcd105b (patch)
treeec36f82ca2405383597b4b4db1f1c15c7ba6d9de /hw/vfio
parentc4c45e943e519f5ac220f7af1afb2a0025d03c54 (diff)
vfio/pci: Add a separate option for IGD OpRegion support
The IGD OpRegion is enabled automatically when running in legacy mode, but it can sometimes be useful in universal passthrough mode as well. Without an OpRegion, output spigots don't work, and even though Intel doesn't officially support physical outputs in UPT mode, it's a useful feature. Note that if an OpRegion is enabled but a monitor is not connected, some graphics features will be disabled in the guest versus a headless system without an OpRegion, where they would work. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> Tested-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'hw/vfio')
-rw-r--r--hw/vfio/pci-quirks.c4
-rw-r--r--hw/vfio/pci.c31
-rw-r--r--hw/vfio/pci.h6
3 files changed, 39 insertions, 2 deletions
diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c
index f2b8ed54ab..35d32b78f4 100644
--- a/hw/vfio/pci-quirks.c
+++ b/hw/vfio/pci-quirks.c
@@ -1055,8 +1055,8 @@ typedef struct VFIOIGDQuirk {
* the table and to write the base address of that memory to the ASLS register
* of the IGD device.
*/
-static int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev,
- struct vfio_region_info *info)
+int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev,
+ struct vfio_region_info *info)
{
int ret;
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 06d91cc892..deab0c601a 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -2562,6 +2562,35 @@ static int vfio_initfn(PCIDevice *pdev)
vfio_bar_quirk_setup(vdev, i);
}
+ if (!vdev->igd_opregion &&
+ vdev->features & VFIO_FEATURE_ENABLE_IGD_OPREGION) {
+ struct vfio_region_info *opregion;
+
+ if (vdev->pdev.qdev.hotplugged) {
+ error_report("Cannot support IGD OpRegion feature on hotplugged "
+ "device %s", vdev->vbasedev.name);
+ ret = -EINVAL;
+ goto out_teardown;
+ }
+
+ 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("Device %s does not support requested IGD OpRegion "
+ "feature", vdev->vbasedev.name);
+ goto out_teardown;
+ }
+
+ ret = vfio_pci_igd_opregion_init(vdev, opregion);
+ g_free(opregion);
+ if (ret) {
+ error_report("Device %s IGD OpRegion initialization failed",
+ vdev->vbasedev.name);
+ goto out_teardown;
+ }
+ }
+
/* QEMU emulates all of MSI & MSIX */
if (pdev->cap_present & QEMU_PCI_CAP_MSIX) {
memset(vdev->emulated_config_bits + pdev->msix_cap, 0xff,
@@ -2686,6 +2715,8 @@ static Property vfio_pci_dev_properties[] = {
VFIO_FEATURE_ENABLE_VGA_BIT, false),
DEFINE_PROP_BIT("x-req", VFIOPCIDevice, features,
VFIO_FEATURE_ENABLE_REQ_BIT, true),
+ DEFINE_PROP_BIT("x-igd-opregion", VFIOPCIDevice, features,
+ VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT, false),
DEFINE_PROP_BOOL("x-no-mmap", VFIOPCIDevice, vbasedev.no_mmap, false),
DEFINE_PROP_BOOL("x-no-kvm-intx", VFIOPCIDevice, no_kvm_intx, false),
DEFINE_PROP_BOOL("x-no-kvm-msi", VFIOPCIDevice, no_kvm_msi, false),
diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index 31ee8da4de..b3eb0d838e 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -129,6 +129,9 @@ typedef struct VFIOPCIDevice {
#define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT)
#define VFIO_FEATURE_ENABLE_REQ_BIT 1
#define VFIO_FEATURE_ENABLE_REQ (1 << VFIO_FEATURE_ENABLE_REQ_BIT)
+#define VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT 2
+#define VFIO_FEATURE_ENABLE_IGD_OPREGION \
+ (1 << VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT)
int32_t bootindex;
uint32_t igd_gms;
uint8_t pm_cap;
@@ -161,4 +164,7 @@ void vfio_setup_resetfn_quirk(VFIOPCIDevice *vdev);
int vfio_populate_vga(VFIOPCIDevice *vdev);
+int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev,
+ struct vfio_region_info *info);
+
#endif /* HW_VFIO_VFIO_PCI_H */