QEMU 2.12 introduced a new type of display for mediated devices using
vfio-pci backend which allows a mediated device to be used as a VGA
compatible device as an alternative to an emulated video device. QEMU
exposes this feature via a vfio device property 'display' with supported
values 'on/off/auto' (default is 'off').
This patch adds the necessary bits to domain config handling in order to
expose this feature. Since there's no convenient way for libvirt to come
up with usable defaults for the display setting, simply because libvirt
is not able to figure out which of the display implementations - dma-buf
which requires OpenGL support vs vfio regions which doesn't need OpenGL
(works with OpenGL enabled too) - the underlying mdev uses.
Signed-off-by: Erik Skultety <eskultet(a)redhat.com>
---
docs/formatdomain.html.in | 19 +++++-
docs/schemas/domaincommon.rng | 5 ++
src/conf/domain_conf.c | 18 +++++-
src/conf/domain_conf.h | 1 +
src/qemu/qemu_domain.c | 71 +++++++++++++++++++++-
.../hostdev-mdev-display-missing-graphics.xml | 35 +++++++++++
tests/qemuxml2argvdata/hostdev-mdev-display.xml | 39 ++++++++++++
.../hostdev-mdev-display-active.xml | 47 ++++++++++++++
.../hostdev-mdev-display-inactive.xml | 47 ++++++++++++++
tests/qemuxml2xmltest.c | 2 +
10 files changed, 279 insertions(+), 5 deletions(-)
create mode 100644 tests/qemuxml2argvdata/hostdev-mdev-display-missing-graphics.xml
create mode 100644 tests/qemuxml2argvdata/hostdev-mdev-display.xml
create mode 100644 tests/qemuxml2xmloutdata/hostdev-mdev-display-active.xml
create mode 100644 tests/qemuxml2xmloutdata/hostdev-mdev-display-inactive.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index c6ebd39bd9..f45eee6812 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -4502,9 +4502,22 @@
guest. Currently, <code>model='vfio-pci'</code> and
<code>model='vfio-ccw'</code> (<span
class="since">Since 4.4.0</span>)
is supported. Refer <a
href="drvnodedev.html#MDEV">MDEV</a> to create
- a mediated device on the host. There are also some implications on the
- usage of guest's address type depending on the
<code>model</code>
- attribute, see the <code>address</code> element below.
+ a mediated device on the host.
+ <span class="since">Since 4.6.0 (QEMU 2.12)</span> an
optional
+ <code>display</code> attribute may be used to enable or disable
+ support for an accelerated remote desktop backed by a mediated
+ device (such as NVIDIA vGPU or Intel GVT-g) as an alternative to
+ emulated <a href="#elementsVideo">video devices</a>. This
attribute
+ is limited to <code>model='vfio-pci'</code> only. Supported
values
+ are either 'on' or 'off' (default is 'off'). It is
required to use a
+ <a href="#elementsGraphics">graphical framebuffer</a> in
order to
+ use this attribute, currently only supported with VNC and Spice
+ graphics devices.
+ <p>
+ Note: There are also some implications on the usage of guest's
+ address type depending on the <code>model</code> attribute,
+ see the <code>address</code> element below.
+ </p>
</dd>
</dl>
<p>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 4ad53d976b..1df479cda2 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -4590,6 +4590,11 @@
<value>vfio-ccw</value>
</choice>
</attribute>
+ <optional>
+ <attribute name="display">
+ <ref name="virOnOff"/>
+ </attribute>
+ </optional>
<element name="source">
<ref name="mdevaddress"/>
</element>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 6d399a198e..23d646cb63 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -7651,6 +7651,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
char *rawio = NULL;
char *backendStr = NULL;
char *model = NULL;
+ char *display = NULL;
int backend;
int ret = -1;
virDomainHostdevSubsysPCIPtr pcisrc = &def->source.subsys.u.pci;
@@ -7670,6 +7671,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
sgio = virXMLPropString(node, "sgio");
rawio = virXMLPropString(node, "rawio");
model = virXMLPropString(node, "model");
+ display = virXMLPropString(node, "display");
/* @type is passed in from the caller rather than read from the
* xml document, because it is specified in different places for
@@ -7757,6 +7759,15 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
model);
goto error;
}
+
+ if (display &&
+ (mdevsrc->display = virTristateSwitchTypeFromString(display)) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("unknown value '%s' for <hostdev>
attribute "
+ "'display'"),
+ display);
+ goto error;
+ }
}
switch (def->source.subsys.type) {
@@ -26574,9 +26585,14 @@ virDomainHostdevDefFormat(virBufferPtr buf,
virTristateBoolTypeToString(scsisrc->rawio));
}
- if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV)
+ if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV) {
virBufferAsprintf(buf, " model='%s'",
virMediatedDeviceModelTypeToString(mdevsrc->model));
+ if (mdevsrc->display > VIR_TRISTATE_SWITCH_ABSENT)
+ virBufferAsprintf(buf, " display='%s'",
+ virTristateSwitchTypeToString(mdevsrc->display));
+ }
+
}
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 99b5896391..6b21d2bf4c 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -382,6 +382,7 @@ typedef struct _virDomainHostdevSubsysMediatedDev
virDomainHostdevSubsysMediated
typedef virDomainHostdevSubsysMediatedDev *virDomainHostdevSubsysMediatedDevPtr;
struct _virDomainHostdevSubsysMediatedDev {
int model; /* enum virMediatedDeviceModelType */
+ int display; /* virTristateSwitchType */
char uuidstr[VIR_UUID_STRING_BUFLEN]; /* mediated device's uuid string */
};
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 948b9b7fd0..d624383c61 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -6127,6 +6127,72 @@ qemuDomainVsockDefPostParse(virDomainVsockDefPtr vsock)
}
+static int
+qemuDomainHostdevMdevDefPostParse(const virDomainHostdevSubsysMediatedDev *mdevsrc,
+ const virDomainDef *def)
+{
+ if (mdevsrc->display > VIR_TRISTATE_SWITCH_ABSENT &&
+ mdevsrc->model != VIR_MDEV_MODEL_TYPE_VFIO_PCI) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("<hostdev> attribute 'display' is only
supported"
+ " with model='vfio-pci'"));
+
+ return -1;
+ }
+
+ if (mdevsrc->display == VIR_TRISTATE_SWITCH_ON) {
+ virDomainGraphicsDefPtr graphics = def->graphics[0];
+
+ if (def->ngraphics == 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("graphics device is needed for attribute value "
+ "'display=on' in <hostdev>"));
+ return -1;
+ }
+
+ /* We're not able to tell whether an mdev needs OpenGL or not at the
+ * moment, so print a warning that an extra <gl> element might be
+ * necessary to be added.
+ */
+ if (!graphics->gl ||
+ graphics->gl->enable != VIR_TRISTATE_BOOL_YES) {
+ VIR_WARN("<hostdev> attribute 'display' may need the
OpenGL to "
+ "be enabled");
+ }
+ }
+
+ return 0;
+}
+
+
+static int
+qemuDomainHostdevDefPostParse(const virDomainHostdevDef *hostdev,
+ const virDomainDef *def)
+{
+ const virDomainHostdevSubsysMediatedDev *mdevsrc;
+
+ if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
+ switch ((virDomainHostdevSubsysType) hostdev->source.subsys.type) {
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
+ break;
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
+ mdevsrc = &hostdev->source.subsys.u.mdev;
+ return qemuDomainHostdevMdevDefPostParse(mdevsrc, def);
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
+ default:
+ virReportEnumRangeError(virDomainHostdevSubsysType,
+ hostdev->source.subsys.type);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
static int
qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
const virDomainDef *def,
@@ -6177,11 +6243,14 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
ret = qemuDomainVsockDefPostParse(dev->data.vsock);
break;
+ case VIR_DOMAIN_DEVICE_HOSTDEV:
+ ret = qemuDomainHostdevDefPostParse(dev->data.hostdev, def);
+ break;
+
case VIR_DOMAIN_DEVICE_LEASE:
case VIR_DOMAIN_DEVICE_FS:
case VIR_DOMAIN_DEVICE_INPUT:
case VIR_DOMAIN_DEVICE_SOUND:
- case VIR_DOMAIN_DEVICE_HOSTDEV:
case VIR_DOMAIN_DEVICE_WATCHDOG:
case VIR_DOMAIN_DEVICE_GRAPHICS:
case VIR_DOMAIN_DEVICE_HUB:
diff --git a/tests/qemuxml2argvdata/hostdev-mdev-display-missing-graphics.xml
b/tests/qemuxml2argvdata/hostdev-mdev-display-missing-graphics.xml
new file mode 100644
index 0000000000..ea559a6444
--- /dev/null
+++ b/tests/qemuxml2argvdata/hostdev-mdev-display-missing-graphics.xml
@@ -0,0 +1,35 @@
+<domain type='qemu'>
+ <name>QEMUGuest2</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-i686</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <controller type='ide' index='0'>
+ </controller>
+ <hostdev mode='subsystem' type='mdev' model='vfio-pci'
display='on'>
+ <source>
+ <address uuid='53764d0e-85a0-42b4-af5c-2046b460b1dc'/>
+ </source>
+ </hostdev>
+ <memballoon model='none'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/hostdev-mdev-display.xml
b/tests/qemuxml2argvdata/hostdev-mdev-display.xml
new file mode 100644
index 0000000000..f5b3575c04
--- /dev/null
+++ b/tests/qemuxml2argvdata/hostdev-mdev-display.xml
@@ -0,0 +1,39 @@
+<domain type='qemu' id='1'>
+ <name>QEMUGuest2</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-i686</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <controller type='ide' index='0'>
+ </controller>
+ <graphics type='vnc'/>
+ <hostdev mode='subsystem' type='mdev' model='vfio-pci'
display='on'>
+ <source>
+ <address uuid='53764d0e-85a0-42b4-af5c-2046b460b1dc'/>
+ </source>
+ </hostdev>
+ <video>
+ <model type='qxl' heads='1'/>
+ </video>
+ <memballoon model='none'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/hostdev-mdev-display-active.xml
b/tests/qemuxml2xmloutdata/hostdev-mdev-display-active.xml
new file mode 100644
index 0000000000..63a1a00278
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/hostdev-mdev-display-active.xml
@@ -0,0 +1,47 @@
+<domain type='qemu' id='1'>
+ <name>QEMUGuest2</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-i686</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <controller type='ide' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x01' function='0x1'/>
+ </controller>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes'>
+ <listen type='address'/>
+ </graphics>
+ <video>
+ <model type='qxl' ram='65536' vram='65536'
vgamem='16384' heads='1' primary='yes'/>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x02' function='0x0'/>
+ </video>
+ <hostdev mode='subsystem' type='mdev' managed='no'
model='vfio-pci' display='on'>
+ <source>
+ <address uuid='53764d0e-85a0-42b4-af5c-2046b460b1dc'/>
+ </source>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x03' function='0x0'/>
+ </hostdev>
+ <memballoon model='none'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/hostdev-mdev-display-inactive.xml
b/tests/qemuxml2xmloutdata/hostdev-mdev-display-inactive.xml
new file mode 100644
index 0000000000..95a692aee5
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/hostdev-mdev-display-inactive.xml
@@ -0,0 +1,47 @@
+<domain type='qemu'>
+ <name>QEMUGuest2</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-i686</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <controller type='ide' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x01' function='0x1'/>
+ </controller>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes'>
+ <listen type='address'/>
+ </graphics>
+ <video>
+ <model type='qxl' ram='65536' vram='65536'
vgamem='16384' heads='1' primary='yes'/>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x02' function='0x0'/>
+ </video>
+ <hostdev mode='subsystem' type='mdev' managed='no'
model='vfio-pci'>
+ <source>
+ <address uuid='53764d0e-85a0-42b4-af5c-2046b460b1dc'/>
+ </source>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x03' function='0x0'/>
+ </hostdev>
+ <memballoon model='none'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index eac6d5b073..0095c27cf6 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -477,6 +477,8 @@ mymain(void)
DO_TEST("hostdev-pci-address", NONE);
DO_TEST("hostdev-vfio", NONE);
DO_TEST("hostdev-mdev-precreated", NONE);
+ DO_TEST_FULL("hostdev-mdev-display", WHEN_ACTIVE, GIC_NONE,
+ QEMU_CAPS_VFIO_PCI_DISPLAY);
DO_TEST("pci-rom", NONE);
DO_TEST("pci-rom-disabled", NONE);
DO_TEST("pci-rom-disabled-invalid", NONE);
--
2.14.4