[libvirt] [PATCH v2 5/7] conf: Introduce new <hostdev> attribute 'display'

Michal Privoznik mprivozn at redhat.com
Tue Jul 10 11:39:03 UTC 2018


On 07/09/2018 06:24 PM, Erik Skultety wrote:
> 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 at 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                             | 68 +++++++++++++++++++++-
>  .../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, 276 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 9dd22554ad..06d30565dd 100644
> --- a/docs/formatdomain.html.in
> +++ b/docs/formatdomain.html.in
> @@ -4510,9 +4510,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

Nit pick, I usually write it as <code>on</code>, <code>off</code>.

> +          <a href="#elementsGraphics">graphical framebuffer</a> in order to
> +          use this attribute, currently only supported with VNC, Spice and
> +          egl-headless 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 8f7d273d9f..b8ec9c758a 100644
> --- a/docs/schemas/domaincommon.rng
> +++ b/docs/schemas/domaincommon.rng
> @@ -4576,6 +4576,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 54fc599e5d..027c3de329 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -7619,6 +7619,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;
> @@ -7638,6 +7639,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
>      sgio = virXMLPropString(node, "sgio");
>      rawio = virXMLPropString(node, "rawio");
>      model = virXMLPropString(node, "model");
> +    display = virXMLPropString(node, "display");

Don't forget to VIR_FREE(display) ;-)

>  
>      /* @type is passed in from the caller rather than read from the
>       * xml document, because it is specified in different places for
> @@ -7725,6 +7727,15 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
>                             model);
>              goto error;
>          }
> +
> +        if (display &&
> +            (mdevsrc->display = virTristateSwitchTypeFromString(display)) < 0) {

I guess you don't want to accept 'absent' do you? s/</<=/

> +            virReportError(VIR_ERR_XML_ERROR,
> +                           _("unknown value '%s' for <hostdev> attribute "
> +                             "'display'"),
> +                           display);
> +            goto error;

Pre-existing, but this label should be renamed to 'cleanup' because it
is executed on both success and failure.

> +        }
>      }
>  
>      switch (def->source.subsys.type) {
> @@ -26530,9 +26541,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 31d77e49c5..2ab1faa556 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 */

Actually, it's called just "virTristateSwitch"

>      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 f488050bf8..a2c5201139 100644
> --- a/src/qemu/qemu_domain.c
> +++ b/src/qemu/qemu_domain.c
> @@ -6235,6 +6235,69 @@ 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) {
> +        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 or
> +         * <graphics type='egl-headless/>' might be necessary to be added,
> +         * depending on whether we're running with SPICE or VNC respectively.
> +         */
> +        if (!virDomainGraphicsDefHasOpenGL(def))
> +            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;
> +}
> +

Again, these two ^^ are validate callbacks not PostParse. You are not
filling in missing information, you are checking (=validating) whether
user provided XML is valid.

> +
>  static int
>  qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
>                               const virDomainDef *def,
> @@ -6285,11 +6348,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 fa57221d62..49e0e03f03 100644
> --- a/tests/qemuxml2xmltest.c
> +++ b/tests/qemuxml2xmltest.c
> @@ -479,6 +479,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);

-ENOSUCHCAP

Michal




More information about the libvir-list mailing list