[PATCH] Support x-vga=on for PCI host passthrough devices

Steven Newbury steve at snewbury.org.uk
Wed Oct 7 12:59:35 UTC 2020


When using a passthrough GPU with libvirt there is no option to
pass "x-vga=on" to the device specification.  This means legacy
VGA support isn't available which prevents any non-UEFI cards from
POSTing and prevents some drivers from initialising for example
Windows 10 NVIDIA driver for GeForce 8800.

Signed-off-by: Steven Newbury <steve at snewbury.org.uk>
---
 src/conf/device_conf.c       | 9 +++++++++
 src/conf/domain_conf.c       | 4 ++++
 src/qemu/qemu_capabilities.c | 1 +
 src/qemu/qemu_capabilities.h | 1 +
 src/qemu/qemu_command.c      | 4 ++++
 src/util/virpci.h            | 1 +
 tools/virsh-domain.c         | 6 ++++++
 7 files changed, 26 insertions(+)

diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
index 87bf32bbc6..02d226747e 100644
--- a/src/conf/device_conf.c
+++ b/src/conf/device_conf.c
@@ -215,6 +215,7 @@ virPCIDeviceAddressParseXML(xmlNodePtr node,
     g_autofree char *slot     = virXMLPropString(node, "slot");
     g_autofree char *function = virXMLPropString(node, "function");
     g_autofree char *multi    = virXMLPropString(node, "multifunction");
+    g_autofree char *vga      = virXMLPropString(node, "vga");
 
     memset(addr, 0, sizeof(*addr));
 
@@ -253,6 +254,14 @@ virPCIDeviceAddressParseXML(xmlNodePtr node,
                        multi);
         return -1;
 
+    }
+    if (vga &&
+        ((addr->vga = virTristateSwitchTypeFromString(vga)) <= 0)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Unknown value '%s' for <address> 'vga' attribute"),
+                       vga);
+        return -1;
+
     }
     if (!virPCIDeviceAddressIsEmpty(addr) && !virPCIDeviceAddressIsValid(addr, true))
         return -1;
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c003b5c030..048b0f4028 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -7587,6 +7587,10 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
             virBufferAsprintf(&attrBuf, " multifunction='%s'",
                               virTristateSwitchTypeToString(info->addr.pci.multi));
         }
+        if (info->addr.pci.vga) {
+            virBufferAsprintf(&attrBuf, " vga='%s'",
+                              virTristateSwitchTypeToString(info->addr.pci.vga));
+        }
 
         if (virZPCIDeviceAddressIsPresent(&info->addr.pci.zpci)) {
             virBufferAsprintf(&childBuf,
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 38b901a6c4..b2864c1e9b 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -600,6 +600,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
 
               /* 380 */
               "usb-host.hostdevice",
+              "pci-vga",
     );
 
 
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 107056ba17..d2d456fc43 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -580,6 +580,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
 
     /* 380 */
     QEMU_CAPS_USB_HOST_HOSTDEVICE, /* -device usb-host.hostdevice */
+    X_QEMU_CAPS_PCI_VGA, /* -device x-vga=on|off */
 
     QEMU_CAPS_LAST /* this must always be the last item */
 } virQEMUCapsFlags;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 476cf6972e..b4285425ed 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -350,6 +350,10 @@ qemuBuildDeviceAddressStr(virBufferPtr buf,
             virBufferAddLit(buf, ",multifunction=on");
         else if (info->addr.pci.multi == VIR_TRISTATE_SWITCH_OFF)
             virBufferAddLit(buf, ",multifunction=off");
+        if (info->addr.pci.vga == VIR_TRISTATE_SWITCH_ON)
+            virBufferAddLit(buf, ",x-vga=on");
+        else if (info->addr.pci.vga == VIR_TRISTATE_SWITCH_OFF)
+            virBufferAddLit(buf, ",x-vga=off");
         virBufferAsprintf(buf, ",addr=0x%x", info->addr.pci.slot);
         if (info->addr.pci.function != 0)
            virBufferAsprintf(buf, ".0x%x", info->addr.pci.function);
diff --git a/src/util/virpci.h b/src/util/virpci.h
index b3322ba61b..1ec2e3ba34 100644
--- a/src/util/virpci.h
+++ b/src/util/virpci.h
@@ -61,6 +61,7 @@ struct _virPCIDeviceAddress {
     unsigned int slot;
     unsigned int function;
     int multi; /* virTristateSwitch */
+    int vga; /* virTristateSwitch */
     int extFlags; /* enum virPCIDeviceAddressExtensionFlags */
     virZPCIDeviceAddress zpci;
     /* Don't forget to update virPCIDeviceAddressCopy if needed. */
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 8f11393197..587efbdb2a 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -294,6 +294,10 @@ static const vshCmdOptDef opts_attach_disk[] = {
      .type = VSH_OT_BOOL,
      .help = N_("use multifunction pci under specified address")
     },
+    {.name = "vga",
+     .type = VSH_OT_BOOL,
+     .help = N_("enable legacy VGA")
+    },
     {.name = "print-xml",
      .type = VSH_OT_BOOL,
      .help = N_("print XML document rather than attach the disk")
@@ -694,6 +698,8 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
                                   diskAddr.addr.pci.slot, diskAddr.addr.pci.function);
                 if (vshCommandOptBool(cmd, "multifunction"))
                     virBufferAddLit(&buf, " multifunction='on'");
+                if (vshCommandOptBool(cmd, "vga"))
+                    virBufferAddLit(&buf, " vga='on'");
                 virBufferAddLit(&buf, "/>\n");
             } else if (diskAddr.type == DISK_ADDR_TYPE_CCW) {
                 virBufferAsprintf(&buf,
-- 
2.28.0




More information about the libvir-list mailing list