982648
From 2d16cb96407ed22af46b892e3319f04ac61924ed Mon Sep 17 00:00:00 2001
982648
Message-Id: <2d16cb96407ed22af46b892e3319f04ac61924ed@dist-git>
982648
From: Erik Skultety <eskultet@redhat.com>
982648
Date: Thu, 19 Jul 2018 15:04:02 +0200
982648
Subject: [PATCH] conf: Introduce new <hostdev> attribute 'display'
982648
MIME-Version: 1.0
982648
Content-Type: text/plain; charset=UTF-8
982648
Content-Transfer-Encoding: 8bit
982648
982648
QEMU 2.12 introduced a new type of display for mediated devices using
982648
vfio-pci backend which allows a mediated device to be used as a VGA
982648
compatible device as an alternative to an emulated video device. QEMU
982648
exposes this feature via a vfio device property 'display' with supported
982648
values 'on/off/auto' (libvirt will default to 'off').
982648
982648
This patch adds the necessary bits to domain config handling in order to
982648
expose this feature. Since there's no convenient way for libvirt to come
982648
up with usable defaults for the display setting, simply because libvirt
982648
is not able to figure out which of the display implementations - dma-buf
982648
which requires OpenGL support vs vfio regions which doesn't need OpenGL
982648
(works with OpenGL enabled too) - the underlying mdev uses.
982648
982648
Reviewed-by: Ján Tomko <jtomko@redhat.com>
982648
Signed-off-by: Erik Skultety <eskultet@redhat.com>
982648
(cherry picked from commit d54e45b6edd7623e488a19e30bc4148a21fa8b03)
982648
982648
https://bugzilla.redhat.com/show_bug.cgi?id=1475770
982648
Signed-off-by: Erik Skultety <eskultet@redhat.com>
982648
Reviewed-by: Ján Tomko <jtomko@redhat.com>
982648
---
982648
 docs/formatdomain.html.in                     | 20 +++-
982648
 docs/schemas/domaincommon.rng                 |  5 +
982648
 src/conf/domain_conf.c                        | 19 +++-
982648
 src/conf/domain_conf.h                        |  1 +
982648
 src/qemu/qemu_domain.c                        | 98 ++++++++++++++++++-
982648
 .../qemuxml2argvdata/hostdev-mdev-display.xml | 39 ++++++++
982648
 .../hostdev-mdev-display.xml                  | 47 +++++++++
982648
 tests/qemuxml2xmltest.c                       |  1 +
982648
 8 files changed, 222 insertions(+), 8 deletions(-)
982648
 create mode 100644 tests/qemuxml2argvdata/hostdev-mdev-display.xml
982648
 create mode 100644 tests/qemuxml2xmloutdata/hostdev-mdev-display.xml
982648
982648
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
982648
index 9dd22554ad..3554c3dc30 100644
982648
--- a/docs/formatdomain.html.in
982648
+++ b/docs/formatdomain.html.in
982648
@@ -4510,9 +4510,23 @@
982648
           guest. Currently, model='vfio-pci' and
982648
           model='vfio-ccw' (Since 4.4.0)
982648
           is supported. Refer MDEV to create
982648
-          a mediated device on the host. There are also some implications on the
982648
-          usage of guest's address type depending on the model
982648
-          attribute, see the address element below.
982648
+          a mediated device on the host.
982648
+          Since 4.6.0 (QEMU 2.12) an optional
982648
+          display attribute may be used to enable or disable
982648
+          support for an accelerated remote desktop backed by a mediated
982648
+          device (such as NVIDIA vGPU or Intel GVT-g) as an alternative to
982648
+          emulated video devices. This attribute
982648
+          is limited to model='vfio-pci' only. Supported values
982648
+          are either on or off (default is 'off').
982648
+          It is required to use a
982648
+          graphical framebuffer in order to
982648
+          use this attribute, currently only supported with VNC, Spice and
982648
+          egl-headless graphics devices.
982648
+          

982648
+            Note: There are also some implications on the usage of guest's
982648
+            address type depending on the model attribute,
982648
+            see the address element below.
982648
+          

982648
           
982648
         
982648
         

982648
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
982648
index 157726752c..be8430ab22 100644
982648
--- a/docs/schemas/domaincommon.rng
982648
+++ b/docs/schemas/domaincommon.rng
982648
@@ -4579,6 +4579,11 @@
982648
         <value>vfio-ccw</value>
982648
       </choice>
982648
     </attribute>
982648
+    <optional>
982648
+      <attribute name="display">
982648
+        <ref name="virOnOff"/>
982648
+      </attribute>
982648
+    </optional>
982648
     <element name="source">
982648
       <ref name="mdevaddress"/>
982648
     </element>
982648
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
982648
index 72086f9e86..830c298158 100644
982648
--- a/src/conf/domain_conf.c
982648
+++ b/src/conf/domain_conf.c
982648
@@ -7656,6 +7656,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
982648
     char *rawio = NULL;
982648
     char *backendStr = NULL;
982648
     char *model = NULL;
982648
+    char *display = NULL;
982648
     int backend;
982648
     int ret = -1;
982648
     virDomainHostdevSubsysPCIPtr pcisrc = &def->source.subsys.u.pci;
982648
@@ -7675,6 +7676,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
982648
     sgio = virXMLPropString(node, "sgio");
982648
     rawio = virXMLPropString(node, "rawio");
982648
     model = virXMLPropString(node, "model");
982648
+    display = virXMLPropString(node, "display");
982648
 
982648
     /* @type is passed in from the caller rather than read from the
982648
      * xml document, because it is specified in different places for
982648
@@ -7762,6 +7764,15 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
982648
                            model);
982648
             goto cleanup;
982648
         }
982648
+
982648
+        if (display &&
982648
+            (mdevsrc->display = virTristateSwitchTypeFromString(display)) <= 0) {
982648
+            virReportError(VIR_ERR_XML_ERROR,
982648
+                           _("unknown value '%s' for <hostdev> attribute "
982648
+                             "'display'"),
982648
+                           display);
982648
+            goto cleanup;
982648
+        }
982648
     }
982648
 
982648
     switch (def->source.subsys.type) {
982648
@@ -7815,6 +7826,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
982648
     VIR_FREE(rawio);
982648
     VIR_FREE(backendStr);
982648
     VIR_FREE(model);
982648
+    VIR_FREE(display);
982648
     return ret;
982648
 }
982648
 
982648
@@ -26568,9 +26580,14 @@ virDomainHostdevDefFormat(virBufferPtr buf,
982648
                               virTristateBoolTypeToString(scsisrc->rawio));
982648
         }
982648
 
982648
-        if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV)
982648
+        if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV) {
982648
             virBufferAsprintf(buf, " model='%s'",
982648
                               virMediatedDeviceModelTypeToString(mdevsrc->model));
982648
+            if (mdevsrc->display != VIR_TRISTATE_SWITCH_ABSENT)
982648
+                virBufferAsprintf(buf, " display='%s'",
982648
+                                  virTristateSwitchTypeToString(mdevsrc->display));
982648
+        }
982648
+
982648
     }
982648
     virBufferAddLit(buf, ">\n");
982648
     virBufferAdjustIndent(buf, 2);
982648
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
982648
index 3deda1d978..8ca9558ceb 100644
982648
--- a/src/conf/domain_conf.h
982648
+++ b/src/conf/domain_conf.h
982648
@@ -382,6 +382,7 @@ typedef struct _virDomainHostdevSubsysMediatedDev virDomainHostdevSubsysMediated
982648
 typedef virDomainHostdevSubsysMediatedDev *virDomainHostdevSubsysMediatedDevPtr;
982648
 struct _virDomainHostdevSubsysMediatedDev {
982648
     int model;                          /* enum virMediatedDeviceModelType */
982648
+    int display; /* virTristateSwitch */
982648
     char uuidstr[VIR_UUID_STRING_BUFLEN];   /* mediated device's uuid string */
982648
 };
982648
 
982648
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
982648
index 9498594857..5337f1ce55 100644
982648
--- a/src/qemu/qemu_domain.c
982648
+++ b/src/qemu/qemu_domain.c
982648
@@ -4451,9 +4451,48 @@ qemuDomainDeviceDefValidateNetwork(const virDomainNetDef *net)
982648
 
982648
 
982648
 static int
982648
-qemuDomainDeviceDefValidateHostdev(const virDomainHostdevDef *hostdev,
982648
-                                   const virDomainDef *def)
982648
+qemuDomainMdevDefValidate(const virDomainHostdevSubsysMediatedDev *mdevsrc,
982648
+                          const virDomainDef *def,
982648
+                          virQEMUCapsPtr qemuCaps)
982648
 {
982648
+    if (mdevsrc->display == VIR_TRISTATE_SWITCH_ABSENT)
982648
+        return 0;
982648
+
982648
+    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VFIO_PCI_DISPLAY)) {
982648
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
982648
+                       _("display property of device vfio-pci is "
982648
+                         "not supported by this version of QEMU"));
982648
+        return -1;
982648
+    }
982648
+
982648
+    if (mdevsrc->model != VIR_MDEV_MODEL_TYPE_VFIO_PCI) {
982648
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
982648
+                       _("<hostdev> attribute 'display' is only supported"
982648
+                         " with model='vfio-pci'"));
982648
+
982648
+        return -1;
982648
+    }
982648
+
982648
+    if (mdevsrc->display == VIR_TRISTATE_SWITCH_ON) {
982648
+        if (def->ngraphics == 0) {
982648
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
982648
+                           _("graphics device is needed for attribute value "
982648
+                             "'display=on' in <hostdev>"));
982648
+            return -1;
982648
+        }
982648
+    }
982648
+
982648
+    return 0;
982648
+}
982648
+
982648
+
982648
+static int
982648
+qemuDomainDeviceDefValidateHostdev(const virDomainHostdevDef *hostdev,
982648
+                                   const virDomainDef *def,
982648
+                                   virQEMUCapsPtr qemuCaps)
982648
+{
982648
+    const virDomainHostdevSubsysMediatedDev *mdevsrc;
982648
+
982648
     /* forbid capabilities mode hostdev in this kind of hypervisor */
982648
     if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES) {
982648
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
982648
@@ -4463,6 +4502,24 @@ qemuDomainDeviceDefValidateHostdev(const virDomainHostdevDef *hostdev,
982648
         return -1;
982648
     }
982648
 
982648
+    if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
982648
+        switch ((virDomainHostdevSubsysType) hostdev->source.subsys.type) {
982648
+        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
982648
+        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
982648
+        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
982648
+        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
982648
+            break;
982648
+        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
982648
+            mdevsrc = &hostdev->source.subsys.u.mdev;
982648
+            return qemuDomainMdevDefValidate(mdevsrc, def, qemuCaps);
982648
+        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
982648
+        default:
982648
+            virReportEnumRangeError(virDomainHostdevSubsysType,
982648
+                                    hostdev->source.subsys.type);
982648
+            return -1;
982648
+        }
982648
+    }
982648
+
982648
     return 0;
982648
 }
982648
 
982648
@@ -5595,7 +5652,8 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev,
982648
         break;
982648
 
982648
     case VIR_DOMAIN_DEVICE_HOSTDEV:
982648
-        ret = qemuDomainDeviceDefValidateHostdev(dev->data.hostdev, def);
982648
+        ret = qemuDomainDeviceDefValidateHostdev(dev->data.hostdev, def,
982648
+                                                 qemuCaps);
982648
         break;
982648
 
982648
     case VIR_DOMAIN_DEVICE_VIDEO:
982648
@@ -6205,6 +6263,35 @@ qemuDomainVsockDefPostParse(virDomainVsockDefPtr vsock)
982648
 }
982648
 
982648
 
982648
+static int
982648
+qemuDomainHostdevDefMdevPostParse(virDomainHostdevSubsysMediatedDevPtr mdevsrc,
982648
+                                  virQEMUCapsPtr qemuCaps)
982648
+{
982648
+    /* QEMU 2.12 added support for vfio-pci display type, we default to
982648
+     * 'display=off' to stay safe from future changes */
982648
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VFIO_PCI_DISPLAY) &&
982648
+        mdevsrc->display == VIR_TRISTATE_SWITCH_ABSENT)
982648
+        mdevsrc->display = VIR_TRISTATE_SWITCH_OFF;
982648
+
982648
+    return 0;
982648
+}
982648
+
982648
+
982648
+static int
982648
+qemuDomainHostdevDefPostParse(virDomainHostdevDefPtr hostdev,
982648
+                              virQEMUCapsPtr qemuCaps)
982648
+{
982648
+    virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys;
982648
+
982648
+    if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
982648
+        hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV &&
982648
+        qemuDomainHostdevDefMdevPostParse(&subsys->u.mdev, qemuCaps) < 0)
982648
+        return -1;
982648
+
982648
+    return 0;
982648
+}
982648
+
982648
+
982648
 static int
982648
 qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
982648
                              const virDomainDef *def,
982648
@@ -6255,11 +6342,14 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
982648
         ret = qemuDomainVsockDefPostParse(dev->data.vsock);
982648
         break;
982648
 
982648
+    case VIR_DOMAIN_DEVICE_HOSTDEV:
982648
+        ret = qemuDomainHostdevDefPostParse(dev->data.hostdev, qemuCaps);
982648
+        break;
982648
+
982648
     case VIR_DOMAIN_DEVICE_LEASE:
982648
     case VIR_DOMAIN_DEVICE_FS:
982648
     case VIR_DOMAIN_DEVICE_INPUT:
982648
     case VIR_DOMAIN_DEVICE_SOUND:
982648
-    case VIR_DOMAIN_DEVICE_HOSTDEV:
982648
     case VIR_DOMAIN_DEVICE_WATCHDOG:
982648
     case VIR_DOMAIN_DEVICE_GRAPHICS:
982648
     case VIR_DOMAIN_DEVICE_HUB:
982648
diff --git a/tests/qemuxml2argvdata/hostdev-mdev-display.xml b/tests/qemuxml2argvdata/hostdev-mdev-display.xml
982648
new file mode 100644
982648
index 0000000000..f37e08e1b9
982648
--- /dev/null
982648
+++ b/tests/qemuxml2argvdata/hostdev-mdev-display.xml
982648
@@ -0,0 +1,39 @@
982648
+<domain type='qemu'>
982648
+  <name>QEMUGuest2</name>
982648
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
982648
+  <memory unit='KiB'>219136</memory>
982648
+  <currentMemory unit='KiB'>219136</currentMemory>
982648
+  <vcpu placement='static'>1</vcpu>
982648
+  <os>
982648
+    <type arch='i686' machine='pc'>hvm</type>
982648
+    <boot dev='hd'/>
982648
+  </os>
982648
+  <clock offset='utc'/>
982648
+  <on_poweroff>destroy</on_poweroff>
982648
+  <on_reboot>restart</on_reboot>
982648
+  <on_crash>destroy</on_crash>
982648
+  <devices>
982648
+    <emulator>/usr/bin/qemu-system-i686</emulator>
982648
+    <disk type='block' device='disk'>
982648
+      <driver name='qemu' type='raw'/>
982648
+      <source dev='/dev/HostVG/QEMUGuest2'/>
982648
+      <target dev='hda' bus='ide'/>
982648
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
982648
+    </disk>
982648
+    <controller type='usb' index='0'>
982648
+    </controller>
982648
+    <controller type='pci' index='0' model='pci-root'/>
982648
+    <controller type='ide' index='0'>
982648
+    </controller>
982648
+    <graphics type='vnc'/>
982648
+    <hostdev mode='subsystem' type='mdev' model='vfio-pci' display='on'>
982648
+      <source>
982648
+        <address uuid='53764d0e-85a0-42b4-af5c-2046b460b1dc'/>
982648
+      </source>
982648
+    </hostdev>
982648
+    <video>
982648
+      <model type='qxl' heads='1'/>
982648
+    </video>
982648
+    <memballoon model='none'/>
982648
+  </devices>
982648
+</domain>
982648
diff --git a/tests/qemuxml2xmloutdata/hostdev-mdev-display.xml b/tests/qemuxml2xmloutdata/hostdev-mdev-display.xml
982648
new file mode 100644
982648
index 0000000000..94c11b1199
982648
--- /dev/null
982648
+++ b/tests/qemuxml2xmloutdata/hostdev-mdev-display.xml
982648
@@ -0,0 +1,47 @@
982648
+<domain type='qemu'>
982648
+  <name>QEMUGuest2</name>
982648
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
982648
+  <memory unit='KiB'>219136</memory>
982648
+  <currentMemory unit='KiB'>219136</currentMemory>
982648
+  <vcpu placement='static'>1</vcpu>
982648
+  <os>
982648
+    <type arch='i686' machine='pc'>hvm</type>
982648
+    <boot dev='hd'/>
982648
+  </os>
982648
+  <clock offset='utc'/>
982648
+  <on_poweroff>destroy</on_poweroff>
982648
+  <on_reboot>restart</on_reboot>
982648
+  <on_crash>destroy</on_crash>
982648
+  <devices>
982648
+    <emulator>/usr/bin/qemu-system-i686</emulator>
982648
+    <disk type='block' device='disk'>
982648
+      <driver name='qemu' type='raw'/>
982648
+      <source dev='/dev/HostVG/QEMUGuest2'/>
982648
+      <target dev='hda' bus='ide'/>
982648
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
982648
+    </disk>
982648
+    <controller type='usb' index='0'>
982648
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
982648
+    </controller>
982648
+    <controller type='pci' index='0' model='pci-root'/>
982648
+    <controller type='ide' index='0'>
982648
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
982648
+    </controller>
982648
+    <input type='mouse' bus='ps2'/>
982648
+    <input type='keyboard' bus='ps2'/>
982648
+    <graphics type='vnc' port='-1' autoport='yes'>
982648
+      <listen type='address'/>
982648
+    </graphics>
982648
+    <video>
982648
+      <model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1' primary='yes'/>
982648
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
982648
+    </video>
982648
+    <hostdev mode='subsystem' type='mdev' managed='no' model='vfio-pci' display='on'>
982648
+      <source>
982648
+        <address uuid='53764d0e-85a0-42b4-af5c-2046b460b1dc'/>
982648
+      </source>
982648
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
982648
+    </hostdev>
982648
+    <memballoon model='none'/>
982648
+  </devices>
982648
+</domain>
982648
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
982648
index fa57221d62..e418e67f6c 100644
982648
--- a/tests/qemuxml2xmltest.c
982648
+++ b/tests/qemuxml2xmltest.c
982648
@@ -479,6 +479,7 @@ mymain(void)
982648
     DO_TEST("hostdev-pci-address", NONE);
982648
     DO_TEST("hostdev-vfio", NONE);
982648
     DO_TEST("hostdev-mdev-precreated", NONE);
982648
+    DO_TEST("hostdev-mdev-display", QEMU_CAPS_VFIO_PCI_DISPLAY);
982648
     DO_TEST("pci-rom", NONE);
982648
     DO_TEST("pci-rom-disabled", NONE);
982648
     DO_TEST("pci-rom-disabled-invalid", NONE);
982648
-- 
982648
2.18.0
982648