[libvirt PATCH v6 0/8] Add support for 'blob' to virtio video device

Add support to libvirt for the 'blob' option for virtio video devices in qemu. Also do a little preparatory refactoring of the video device xml parsing code. This series was basically acked by Jan some time ago, but I made a couple changes and apparently I dropped the ball and forgot to send out the revised series. So here's a v6 after rebasing yet again to current master. changes in v6: - added two new patches: - conf: explicitly set VIR_DOMAIN_VIDEO_TYPE_DEFAULT to 0 - util: add virXMLPropUIntDefault() function - other minor fixes from Jan's review Jonathon Jongsma (8): conf: explicitly set VIR_DOMAIN_VIDEO_TYPE_DEFAULT to 0 conf: Refactor video model parsing util: add virXMLPropUIntDefault() function conf: switch to virXMLProp* functions for parsing video conf: use enum variable for video type conf: add support for 'blob' in virtio video device qemu: Add capability for virtio-gpu.blob qemu: Implement 'blob' support for virtio gpu docs/formatdomain.rst | 7 + src/conf/cpu_conf.c | 9 +- src/conf/domain_conf.c | 134 ++++++++---------- src/conf/domain_conf.h | 5 +- src/conf/domain_validate.c | 13 +- src/conf/numa_conf.c | 7 +- src/conf/schemas/domaincommon.rng | 5 + src/libxl/libxl_conf.c | 10 ++ src/libxl/libxl_domain.c | 11 ++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_cgroup.c | 22 ++- src/qemu/qemu_command.c | 3 + src/qemu/qemu_domain.h | 1 + src/qemu/qemu_monitor_json.c | 16 ++- src/qemu/qemu_namespace.c | 22 +++ src/qemu/qemu_process.c | 7 + src/qemu/qemu_validate.c | 9 ++ src/util/virxml.c | 29 +++- src/util/virxml.h | 9 ++ .../caps_6.1.0.x86_64.xml | 1 + .../caps_6.2.0.aarch64.xml | 1 + .../qemucapabilitiesdata/caps_6.2.0.ppc64.xml | 1 + .../caps_6.2.0.x86_64.xml | 1 + .../caps_7.0.0.aarch64.xml | 1 + .../qemucapabilitiesdata/caps_7.0.0.ppc64.xml | 1 + .../caps_7.0.0.x86_64.xml | 1 + .../qemucapabilitiesdata/caps_7.1.0.ppc64.xml | 1 + .../caps_7.1.0.x86_64.xml | 1 + .../caps_7.2.0.x86_64.xml | 1 + .../caps_8.0.0.riscv64.xml | 1 + .../caps_8.0.0.x86_64.xml | 1 + .../video-virtio-blob-off.x86_64-latest.args | 39 +++++ .../video-virtio-blob-off.xml | 36 +++++ .../video-virtio-blob-on.x86_64-latest.args | 39 +++++ .../qemuxml2argvdata/video-virtio-blob-on.xml | 36 +++++ tests/qemuxml2argvtest.c | 2 + .../video-virtio-blob-off.x86_64-latest.xml | 48 +++++++ .../video-virtio-blob-on.x86_64-latest.xml | 48 +++++++ tests/qemuxml2xmltest.c | 2 + 40 files changed, 483 insertions(+), 101 deletions(-) create mode 100644 tests/qemuxml2argvdata/video-virtio-blob-off.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/video-virtio-blob-off.xml create mode 100644 tests/qemuxml2argvdata/video-virtio-blob-on.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/video-virtio-blob-on.xml create mode 100644 tests/qemuxml2xmloutdata/video-virtio-blob-off.x86_64-latest.xml create mode 100644 tests/qemuxml2xmloutdata/video-virtio-blob-on.x86_64-latest.xml -- 2.39.0

Ensure that new virDomainVideoDef objects have their 'type' set to VIR_DOMAIN_VIDEO_TYPE_DEFAULT and remove places that this value is set after construction. Since virDomainVideoDefNew() uses g_new0() allocate the instance, all fields are initialized to 0. Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> --- src/conf/domain_conf.c | 3 --- src/conf/domain_conf.h | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 89672deb38..42d2f2ed52 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -12871,8 +12871,6 @@ virDomainVideoDefParseXML(virDomainXMLOption *xmlopt, _("unknown video model '%s'"), type); return NULL; } - } else { - def->type = VIR_DOMAIN_VIDEO_TYPE_DEFAULT; } if ((ram = virXPathString("string(./model/@ram)", ctxt))) { @@ -21708,7 +21706,6 @@ virDomainDefAddImplicitVideo(virDomainDef *def, virDomainXMLOption *xmlopt) if (!(video = virDomainVideoDefNew(xmlopt))) return -1; - video->type = VIR_DOMAIN_VIDEO_TYPE_DEFAULT; VIR_APPEND_ELEMENT(def->videos, def->nvideos, video); return 0; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index d99bbbc3ff..e35923e3d7 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1781,7 +1781,7 @@ typedef enum { typedef enum { - VIR_DOMAIN_VIDEO_TYPE_DEFAULT, + VIR_DOMAIN_VIDEO_TYPE_DEFAULT = 0, VIR_DOMAIN_VIDEO_TYPE_VGA, VIR_DOMAIN_VIDEO_TYPE_CIRRUS, VIR_DOMAIN_VIDEO_TYPE_VMVGA, -- 2.39.0

On a Wednesday in 2023, Jonathon Jongsma wrote:
Ensure that new virDomainVideoDef objects have their 'type' set to VIR_DOMAIN_VIDEO_TYPE_DEFAULT and remove places that this value is set after construction. Since virDomainVideoDefNew() uses g_new0() allocate the instance, all fields are initialized to 0.
Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> --- src/conf/domain_conf.c | 3 --- src/conf/domain_conf.h | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

Factor out a separate function to parse out the <model> element for video devices. Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com> --- src/conf/domain_conf.c | 91 ++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 35 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 42d2f2ed52..951c15ac58 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -12821,14 +12821,11 @@ virDomainVideoDriverDefParseXML(xmlNodePtr node, return g_steal_pointer(&def); } -static virDomainVideoDef * -virDomainVideoDefParseXML(virDomainXMLOption *xmlopt, - xmlNodePtr node, - xmlXPathContextPtr ctxt, - unsigned int flags) +static int +virDomainVideoModelDefParseXML(virDomainVideoDef *def, + xmlNodePtr node, + xmlXPathContextPtr ctxt) { - g_autoptr(virDomainVideoDef) def = NULL; - xmlNodePtr driver; xmlNodePtr accel_node; xmlNodePtr res_node; VIR_XPATH_NODE_AUTORESTORE(ctxt) @@ -12840,79 +12837,103 @@ virDomainVideoDefParseXML(virDomainXMLOption *xmlopt, g_autofree char *vgamem = NULL; g_autofree char *primary = NULL; - if (!(def = virDomainVideoDefNew(xmlopt))) - return NULL; - ctxt->node = node; - if ((primary = virXPathString("string(./model/@primary)", ctxt)) != NULL) + if ((primary = virXPathString("string(./@primary)", ctxt)) != NULL) ignore_value(virStringParseYesNo(primary, &def->primary)); - if ((accel_node = virXPathNode("./model/acceleration", ctxt)) && + if ((accel_node = virXPathNode("./acceleration", ctxt)) && (def->accel = virDomainVideoAccelDefParseXML(accel_node)) == NULL) - return NULL; + return -1; - if ((res_node = virXPathNode("./model/resolution", ctxt)) && + if ((res_node = virXPathNode("./resolution", ctxt)) && (def->res = virDomainVideoResolutionDefParseXML(res_node)) == NULL) - return NULL; + return -1; - if ((driver = virXPathNode("./driver", ctxt))) { - if (virXMLPropEnum(driver, "name", - virDomainVideoBackendTypeFromString, - VIR_XML_PROP_NONZERO, &def->backend) < 0) - return NULL; - if (virDomainVirtioOptionsParseXML(driver, &def->virtio) < 0) - return NULL; - } - if ((type = virXPathString("string(./model/@type)", ctxt))) { + + if ((type = virXPathString("string(./@type)", ctxt))) { if ((def->type = virDomainVideoTypeFromString(type)) < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown video model '%s'"), type); - return NULL; + return -1; } } - if ((ram = virXPathString("string(./model/@ram)", ctxt))) { + if ((ram = virXPathString("string(./@ram)", ctxt))) { if (virStrToLong_uip(ram, NULL, 10, &def->ram) < 0) { virReportError(VIR_ERR_XML_ERROR, _("cannot parse video ram '%s'"), ram); - return NULL; + return -1; } } - if ((vram = virXPathString("string(./model/@vram)", ctxt))) { + if ((vram = virXPathString("string(./@vram)", ctxt))) { if (virStrToLong_uip(vram, NULL, 10, &def->vram) < 0) { virReportError(VIR_ERR_XML_ERROR, _("cannot parse video vram '%s'"), vram); - return NULL; + return -1; } } - if ((vram64 = virXPathString("string(./model/@vram64)", ctxt))) { + if ((vram64 = virXPathString("string(./@vram64)", ctxt))) { if (virStrToLong_uip(vram64, NULL, 10, &def->vram64) < 0) { virReportError(VIR_ERR_XML_ERROR, _("cannot parse video vram64 '%s'"), vram64); - return NULL; + return -1; } } - if ((vgamem = virXPathString("string(./model/@vgamem)", ctxt))) { + if ((vgamem = virXPathString("string(./@vgamem)", ctxt))) { if (virStrToLong_uip(vgamem, NULL, 10, &def->vgamem) < 0) { virReportError(VIR_ERR_XML_ERROR, _("cannot parse video vgamem '%s'"), vgamem); - return NULL; + return -1; } } - if ((heads = virXPathString("string(./model/@heads)", ctxt))) { + if ((heads = virXPathString("string(./@heads)", ctxt))) { if (virStrToLong_uip(heads, NULL, 10, &def->heads) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot parse video heads '%s'"), heads); - return NULL; + return -1; } } + return 0; +} + +static virDomainVideoDef * +virDomainVideoDefParseXML(virDomainXMLOption *xmlopt, + xmlNodePtr node, + xmlXPathContextPtr ctxt, + unsigned int flags) +{ + g_autoptr(virDomainVideoDef) def = NULL; + xmlNodePtr driver; + xmlNodePtr model; + + VIR_XPATH_NODE_AUTORESTORE(ctxt) + + if (!(def = virDomainVideoDefNew(xmlopt))) + return NULL; + + ctxt->node = node; + + if ((model = virXPathNode("./model", ctxt))) { + if (virDomainVideoModelDefParseXML(def, model, ctxt) < 0) + return NULL; + } + + if ((driver = virXPathNode("./driver", ctxt))) { + if (virXMLPropEnum(driver, "name", + virDomainVideoBackendTypeFromString, + VIR_XML_PROP_NONZERO, &def->backend) < 0) + return NULL; + if (virDomainVirtioOptionsParseXML(driver, &def->virtio) < 0) + return NULL; + } + if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) < 0) return NULL; -- 2.39.0

This function allows you to specify a default value to return if the property is not found rather than always setting *result to 0. Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> --- src/conf/cpu_conf.c | 9 +++------ src/conf/domain_conf.c | 6 +----- src/conf/numa_conf.c | 7 +------ src/util/virxml.c | 29 ++++++++++++++++++++++++++++- src/util/virxml.h | 9 +++++++++ 5 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index a33f39ef31..d1d11e3257 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -570,7 +570,6 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt, } if ((topology = virXPathNode("./topology[1]", ctxt))) { - int rc; if (virXMLPropUInt(topology, "sockets", 10, VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO, @@ -578,12 +577,10 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt, return -1; } - if ((rc = virXMLPropUInt(topology, "dies", 10, - VIR_XML_PROP_NONZERO, - &def->dies)) < 0) { + if (virXMLPropUIntDefault(topology, "dies", 10, + VIR_XML_PROP_NONZERO, + &def->dies, 1) < 0) { return -1; - } else if (rc == 0) { - def->dies = 1; } if (virXMLPropUInt(topology, "cores", 10, diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 951c15ac58..04c9b1d174 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -16971,7 +16971,6 @@ virDomainVcpuParse(virDomainDef *def, unsigned int vcpus; g_autofree char *tmp = NULL; g_autofree xmlNodePtr *nodes = NULL; - int rc; vcpus = maxvcpus = 1; @@ -16986,11 +16985,8 @@ virDomainVcpuParse(virDomainDef *def, } VIR_FREE(tmp); - if ((rc = virXMLPropUInt(vcpuNode, "current", 10, VIR_XML_PROP_NONE, &vcpus)) < 0) { + if (virXMLPropUIntDefault(vcpuNode, "current", 10, VIR_XML_PROP_NONE, &vcpus, maxvcpus) < 0) return -1; - } else if (rc == 0) { - vcpus = maxvcpus; - } if (virXMLPropEnumDefault(vcpuNode, "placement", virDomainCpuPlacementModeTypeFromString, diff --git a/src/conf/numa_conf.c b/src/conf/numa_conf.c index b55bb3ffcb..7ef7aa5138 100644 --- a/src/conf/numa_conf.c +++ b/src/conf/numa_conf.c @@ -916,16 +916,11 @@ virDomainNumaDefParseXML(virDomainNuma *def, for (i = 0; i < n; i++) { VIR_XPATH_NODE_AUTORESTORE(ctxt) g_autofree char *tmp = NULL; - int rc; unsigned int cur_cell; - if ((rc = virXMLPropUInt(cell[i], "id", 10, VIR_XML_PROP_NONE, - &cur_cell)) < 0) + if (virXMLPropUIntDefault(cell[i], "id", 10, VIR_XML_PROP_NONE, &cur_cell, i) < 0) return -1; - if (rc == 0) - cur_cell = i; - /* cells are in order of parsing or explicitly numbered */ if (cur_cell >= n) { virReportError(VIR_ERR_XML_ERROR, "%s", diff --git a/src/util/virxml.c b/src/util/virxml.c index 9b6ccfd6c9..af4be4e443 100644 --- a/src/util/virxml.c +++ b/src/util/virxml.c @@ -560,12 +560,39 @@ virXMLPropUInt(xmlNodePtr node, int base, virXMLPropFlags flags, unsigned int *result) +{ + return virXMLPropUIntDefault(node, name, base, flags, result, 0); +} + + +/** + * virXMLPropUIntDefault: + * @node: XML dom node pointer + * @name: Name of the property (attribute) to get + * @base: Number base, see strtol + * @flags: Bitwise-OR of virXMLPropFlags + * @result: The returned value + * @defaultResult: Default value of @result in case the property is not found + * + * Convenience function to return value of an unsigned integer attribute. + * + * Returns 1 in case of success in which case @result is set, + * or 0 if the attribute is not present, + * or -1 and reports an error on failure. + */ +int +virXMLPropUIntDefault(xmlNodePtr node, + const char *name, + int base, + virXMLPropFlags flags, + unsigned int *result, + unsigned int defaultResult) { g_autofree char *tmp = NULL; int ret; unsigned int val; - *result = 0; + *result = defaultResult; if (!(tmp = virXMLPropString(node, name))) { if (!(flags & VIR_XML_PROP_REQUIRED)) diff --git a/src/util/virxml.h b/src/util/virxml.h index d5b998263c..cca9f222ab 100644 --- a/src/util/virxml.h +++ b/src/util/virxml.h @@ -132,6 +132,15 @@ virXMLPropUInt(xmlNodePtr node, unsigned int *result) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(5); +int +virXMLPropUIntDefault(xmlNodePtr node, + const char *name, + int base, + virXMLPropFlags flags, + unsigned int *result, + unsigned int defaultResult) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(5); + int virXMLPropLongLong(xmlNodePtr node, const char *name, -- 2.39.0

On a Wednesday in 2023, Jonathon Jongsma wrote:
This function allows you to specify a default value to return if the property is not found rather than always setting *result to 0.
Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> --- src/conf/cpu_conf.c | 9 +++------ src/conf/domain_conf.c | 6 +----- src/conf/numa_conf.c | 7 +------ src/util/virxml.c | 29 ++++++++++++++++++++++++++++- src/util/virxml.h | 9 +++++++++ 5 files changed, 42 insertions(+), 18 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

In virDomainVideoModelDefParseXML(), use the virXMLProp* functions rather than reimplementing them with virXPath* functions. Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com> --- src/conf/domain_conf.c | 73 ++++++++++++------------------------------ 1 file changed, 20 insertions(+), 53 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 04c9b1d174..48b208fd10 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -12829,18 +12829,13 @@ virDomainVideoModelDefParseXML(virDomainVideoDef *def, xmlNodePtr accel_node; xmlNodePtr res_node; VIR_XPATH_NODE_AUTORESTORE(ctxt) - g_autofree char *type = NULL; - g_autofree char *heads = NULL; - g_autofree char *vram = NULL; - g_autofree char *vram64 = NULL; - g_autofree char *ram = NULL; - g_autofree char *vgamem = NULL; - g_autofree char *primary = NULL; + virDomainVideoType type; + virTristateBool primary; ctxt->node = node; - if ((primary = virXPathString("string(./@primary)", ctxt)) != NULL) - ignore_value(virStringParseYesNo(primary, &def->primary)); + if (virXMLPropTristateBool(node, "primary", VIR_XML_PROP_NONE, &primary) >= 0) + def->primary = (primary == VIR_TRISTATE_BOOL_YES); if ((accel_node = virXPathNode("./acceleration", ctxt)) && (def->accel = virDomainVideoAccelDefParseXML(accel_node)) == NULL) @@ -12850,55 +12845,27 @@ virDomainVideoModelDefParseXML(virDomainVideoDef *def, (def->res = virDomainVideoResolutionDefParseXML(res_node)) == NULL) return -1; + if (virXMLPropEnumDefault(node, "type", + virDomainVideoTypeFromString, + VIR_XML_PROP_NONE, &type, + VIR_DOMAIN_VIDEO_TYPE_DEFAULT) < 0) + return -1; + def->type = type; + if (virXMLPropUInt(node, "ram", 10, VIR_XML_PROP_NONE, &def->ram) < 0) + return -1; - if ((type = virXPathString("string(./@type)", ctxt))) { - if ((def->type = virDomainVideoTypeFromString(type)) < 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("unknown video model '%s'"), type); - return -1; - } - } - - if ((ram = virXPathString("string(./@ram)", ctxt))) { - if (virStrToLong_uip(ram, NULL, 10, &def->ram) < 0) { - virReportError(VIR_ERR_XML_ERROR, - _("cannot parse video ram '%s'"), ram); - return -1; - } - } - - if ((vram = virXPathString("string(./@vram)", ctxt))) { - if (virStrToLong_uip(vram, NULL, 10, &def->vram) < 0) { - virReportError(VIR_ERR_XML_ERROR, - _("cannot parse video vram '%s'"), vram); - return -1; - } - } + if (virXMLPropUInt(node, "vram", 10, VIR_XML_PROP_NONE, &def->vram) < 0) + return -1; - if ((vram64 = virXPathString("string(./@vram64)", ctxt))) { - if (virStrToLong_uip(vram64, NULL, 10, &def->vram64) < 0) { - virReportError(VIR_ERR_XML_ERROR, - _("cannot parse video vram64 '%s'"), vram64); - return -1; - } - } + if (virXMLPropUInt(node, "vram64", 10, VIR_XML_PROP_NONE, &def->vram64) < 0) + return -1; - if ((vgamem = virXPathString("string(./@vgamem)", ctxt))) { - if (virStrToLong_uip(vgamem, NULL, 10, &def->vgamem) < 0) { - virReportError(VIR_ERR_XML_ERROR, - _("cannot parse video vgamem '%s'"), vgamem); - return -1; - } - } + if (virXMLPropUInt(node, "vgamem", 10, VIR_XML_PROP_NONE, &def->vgamem) < 0) + return -1; - if ((heads = virXPathString("string(./@heads)", ctxt))) { - if (virStrToLong_uip(heads, NULL, 10, &def->heads) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse video heads '%s'"), heads); - return -1; - } - } + if (virXMLPropUIntDefault(node, "heads", 10, VIR_XML_PROP_NONE, &def->heads, 1) < 0) + return -1; return 0; } -- 2.39.0

Rather than storing the video type as an integer, use the proper enum type within the struct. Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com> --- src/conf/domain_conf.c | 4 +--- src/conf/domain_conf.h | 2 +- src/libxl/libxl_conf.c | 10 ++++++++++ src/libxl/libxl_domain.c | 11 +++++++++++ src/qemu/qemu_monitor_json.c | 16 +++++++++++++++- src/qemu/qemu_process.c | 7 +++++++ 6 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 48b208fd10..fcc65011b0 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -12829,7 +12829,6 @@ virDomainVideoModelDefParseXML(virDomainVideoDef *def, xmlNodePtr accel_node; xmlNodePtr res_node; VIR_XPATH_NODE_AUTORESTORE(ctxt) - virDomainVideoType type; virTristateBool primary; ctxt->node = node; @@ -12847,10 +12846,9 @@ virDomainVideoModelDefParseXML(virDomainVideoDef *def, if (virXMLPropEnumDefault(node, "type", virDomainVideoTypeFromString, - VIR_XML_PROP_NONE, &type, + VIR_XML_PROP_NONE, &def->type, VIR_DOMAIN_VIDEO_TYPE_DEFAULT) < 0) return -1; - def->type = type; if (virXMLPropUInt(node, "ram", 10, VIR_XML_PROP_NONE, &def->ram) < 0) return -1; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index e35923e3d7..8890f5a3a5 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1828,7 +1828,7 @@ struct _virDomainVideoDriverDef { struct _virDomainVideoDef { virObject *privateData; - int type; /* enum virDomainVideoType */ + virDomainVideoType type; unsigned int ram; /* kibibytes (multiples of 1024) */ unsigned int vram; /* kibibytes (multiples of 1024) */ unsigned int vram64; /* kibibytes (multiples of 1024) */ diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 17ac880634..d72f28c19e 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -2376,6 +2376,16 @@ libxlMakeVideo(virDomainDef *def, libxl_domain_config *d_config) } break; + case VIR_DOMAIN_VIDEO_TYPE_DEFAULT: + case VIR_DOMAIN_VIDEO_TYPE_VMVGA: + case VIR_DOMAIN_VIDEO_TYPE_VBOX: + case VIR_DOMAIN_VIDEO_TYPE_PARALLELS: + case VIR_DOMAIN_VIDEO_TYPE_VIRTIO: + case VIR_DOMAIN_VIDEO_TYPE_GOP: + case VIR_DOMAIN_VIDEO_TYPE_NONE: + case VIR_DOMAIN_VIDEO_TYPE_BOCHS: + case VIR_DOMAIN_VIDEO_TYPE_RAMFB: + case VIR_DOMAIN_VIDEO_TYPE_LAST: default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("video type %s is not supported by libxl"), diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 66a82ca317..f28a6207a3 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -201,6 +201,17 @@ libxlDomainDeviceDefPostParse(virDomainDeviceDef *dev, if (dev->data.video->vram == 0) dev->data.video->vram = 128 * 1024; break; + case VIR_DOMAIN_VIDEO_TYPE_DEFAULT: + case VIR_DOMAIN_VIDEO_TYPE_VMVGA: + case VIR_DOMAIN_VIDEO_TYPE_VBOX: + case VIR_DOMAIN_VIDEO_TYPE_PARALLELS: + case VIR_DOMAIN_VIDEO_TYPE_VIRTIO: + case VIR_DOMAIN_VIDEO_TYPE_GOP: + case VIR_DOMAIN_VIDEO_TYPE_NONE: + case VIR_DOMAIN_VIDEO_TYPE_BOCHS: + case VIR_DOMAIN_VIDEO_TYPE_RAMFB: + case VIR_DOMAIN_VIDEO_TYPE_LAST: + break; } } } diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index db99017555..278ceb83d3 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -1786,9 +1786,16 @@ qemuMonitorJSONUpdateVideoMemorySize(qemuMonitor *mon, } video->vram = prop.val.ul * 1024; break; + case VIR_DOMAIN_VIDEO_TYPE_DEFAULT: case VIR_DOMAIN_VIDEO_TYPE_CIRRUS: case VIR_DOMAIN_VIDEO_TYPE_XEN: case VIR_DOMAIN_VIDEO_TYPE_VBOX: + case VIR_DOMAIN_VIDEO_TYPE_PARALLELS: + case VIR_DOMAIN_VIDEO_TYPE_VIRTIO: + case VIR_DOMAIN_VIDEO_TYPE_GOP: + case VIR_DOMAIN_VIDEO_TYPE_NONE: + case VIR_DOMAIN_VIDEO_TYPE_BOCHS: + case VIR_DOMAIN_VIDEO_TYPE_RAMFB: case VIR_DOMAIN_VIDEO_TYPE_LAST: break; } @@ -1826,11 +1833,18 @@ qemuMonitorJSONUpdateVideoVram64Size(qemuMonitor *mon, video->vram64 = prop.val.ul * 1024; } break; + case VIR_DOMAIN_VIDEO_TYPE_DEFAULT: case VIR_DOMAIN_VIDEO_TYPE_VGA: - case VIR_DOMAIN_VIDEO_TYPE_VMVGA: case VIR_DOMAIN_VIDEO_TYPE_CIRRUS: + case VIR_DOMAIN_VIDEO_TYPE_VMVGA: case VIR_DOMAIN_VIDEO_TYPE_XEN: case VIR_DOMAIN_VIDEO_TYPE_VBOX: + case VIR_DOMAIN_VIDEO_TYPE_PARALLELS: + case VIR_DOMAIN_VIDEO_TYPE_VIRTIO: + case VIR_DOMAIN_VIDEO_TYPE_GOP: + case VIR_DOMAIN_VIDEO_TYPE_NONE: + case VIR_DOMAIN_VIDEO_TYPE_BOCHS: + case VIR_DOMAIN_VIDEO_TYPE_RAMFB: case VIR_DOMAIN_VIDEO_TYPE_LAST: break; } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 9ac6b45e75..7a1ada6d65 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3038,9 +3038,16 @@ qemuProcessUpdateVideoRamSize(virQEMUDriver *driver, goto error; } break; + case VIR_DOMAIN_VIDEO_TYPE_DEFAULT: case VIR_DOMAIN_VIDEO_TYPE_CIRRUS: case VIR_DOMAIN_VIDEO_TYPE_XEN: case VIR_DOMAIN_VIDEO_TYPE_VBOX: + case VIR_DOMAIN_VIDEO_TYPE_PARALLELS: + case VIR_DOMAIN_VIDEO_TYPE_VIRTIO: + case VIR_DOMAIN_VIDEO_TYPE_GOP: + case VIR_DOMAIN_VIDEO_TYPE_NONE: + case VIR_DOMAIN_VIDEO_TYPE_BOCHS: + case VIR_DOMAIN_VIDEO_TYPE_RAMFB: case VIR_DOMAIN_VIDEO_TYPE_LAST: break; } -- 2.39.0

Add the ability to enable blob resources for the virtio video device. This will accelerate the display path due to less or no copying of pixel data. Blob resource support can be enabled with e.g.: <video> <model type='virtio' blob='on'/> </video> Some additional background information about blob resources: https://lists.freedesktop.org/archives/dri-devel/2020-August/275972.html https://www.kraxel.org/blog/2021/05/virtio-gpu-qemu-graphics-update/ Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2032406 Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com> --- docs/formatdomain.rst | 7 +++++++ src/conf/domain_conf.c | 5 +++++ src/conf/domain_conf.h | 1 + src/conf/domain_validate.c | 13 ++++++++++--- src/conf/schemas/domaincommon.rng | 5 +++++ 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index fbbee99a80..59d83bdf3c 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -6427,6 +6427,13 @@ A video device. :since:`since 1.3.3` ) extends secondary bar and makes it addressable as 64bit memory. + :since:`Since 8.10.0` (QEMU driver only), devices with type "virtio" have an + optional ``blob`` attribute that can be set to "on" or "off". Setting + ``blob`` to "on" will enable the use of blob resources in the device. This + can accelerate the display path by reducing or eliminating copying of pixel + data between the guest and host. Note that blob resource support requires + QEMU version 6.1 or newer. + :since:`Since 5.9.0` , the ``model`` element may also have an optional ``resolution`` sub-element. The ``resolution`` element has attributes ``x`` and ``y`` to set the minimum resolution for the video device. This diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index fcc65011b0..a7ee12defe 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -12865,6 +12865,9 @@ virDomainVideoModelDefParseXML(virDomainVideoDef *def, if (virXMLPropUIntDefault(node, "heads", 10, VIR_XML_PROP_NONE, &def->heads, 1) < 0) return -1; + if (virXMLPropTristateSwitch(node, "blob", VIR_XML_PROP_NONE, &def->blob) < 0) + return -1; + return 0; } @@ -25177,6 +25180,8 @@ virDomainVideoDefFormat(virBuffer *buf, virBufferAsprintf(buf, " heads='%u'", def->heads); if (def->primary) virBufferAddLit(buf, " primary='yes'"); + if (def->blob != VIR_TRISTATE_SWITCH_ABSENT) + virBufferAsprintf(buf, " blob='%s'", virTristateSwitchTypeToString(def->blob)); if (def->accel || def->res) { virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 8890f5a3a5..5bd5c0d5e4 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1837,6 +1837,7 @@ struct _virDomainVideoDef { bool primary; virDomainVideoAccelDef *accel; virDomainVideoResolutionDef *res; + virTristateSwitch blob; virDomainVideoDriverDef *driver; virDomainDeviceInfo info; virDomainVirtioOptions *virtio; diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index 5559a71e14..10eeceda74 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -225,9 +225,16 @@ virDomainVideoDefValidate(const virDomainVideoDef *video, } } - if (video->type != VIR_DOMAIN_VIDEO_TYPE_VIRTIO && - (virDomainCheckVirtioOptionsAreAbsent(video->virtio) < 0)) - return -1; + if (video->type != VIR_DOMAIN_VIDEO_TYPE_VIRTIO) { + if (virDomainCheckVirtioOptionsAreAbsent(video->virtio) < 0) + return -1; + if (video->blob != VIR_TRISTATE_SWITCH_ABSENT) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("video type '%s' does not support blob resources"), + virDomainVideoTypeToString(video->type)); + return -1; + } + } return 0; } diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 14044811c0..5661b930f7 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -4481,6 +4481,11 @@ <ref name="virYesNo"/> </attribute> </optional> + <optional> + <attribute name="blob"> + <ref name="virOnOff"/> + </attribute> + </optional> <optional> <element name="acceleration"> <optional> -- 2.39.0

Capability to determine whether this qemu supports the 'blob' option for virtio-gpu. Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.0.0.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.1.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_7.1.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.2.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_8.0.0.riscv64.xml | 1 + tests/qemucapabilitiesdata/caps_8.0.0.x86_64.xml | 1 + 14 files changed, 15 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 9c3650e022..b9646608df 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -686,6 +686,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "netdev.stream", /* QEMU_CAPS_NETDEV_STREAM */ "virtio-crypto", /* QEMU_CAPS_DEVICE_VIRTIO_CRYPTO */ "cryptodev-backend-lkcf", /* QEMU_CAPS_OBJECT_CRYPTO_LKCF */ + "virtio-gpu.blob", /* QEMU_CAPS_VIRTIO_GPU_BLOB */ ); @@ -1507,6 +1508,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsQxl[] = { static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsVirtioGpu[] = { { "virgl", QEMU_CAPS_VIRTIO_GPU_VIRGL, NULL }, { "acpi-index", QEMU_CAPS_ACPI_INDEX, NULL }, + { "blob", QEMU_CAPS_VIRTIO_GPU_BLOB, NULL }, }; static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsICH9[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 5bf87c2f8d..f8551f5473 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -665,6 +665,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_NETDEV_STREAM, /* -netdev stream */ QEMU_CAPS_DEVICE_VIRTIO_CRYPTO, /* virtio-crypto device */ QEMU_CAPS_OBJECT_CRYPTO_LKCF, /* -object cryptodev-backend-lkcf */ + QEMU_CAPS_VIRTIO_GPU_BLOB, /* -device virtio-gpu-*.blob= */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml index f303f439d6..99c33d1590 100644 --- a/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml @@ -189,6 +189,7 @@ <flag name='usb-host.guest-resets-all'/> <flag name='migration.blocked-reasons'/> <flag name='virtio-crypto'/> + <flag name='virtio-gpu.blob'/> <version>6001000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100243</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml b/tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml index a573d465fb..b6c1504662 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml @@ -156,6 +156,7 @@ <flag name='usb-host.guest-resets-all'/> <flag name='migration.blocked-reasons'/> <flag name='virtio-crypto'/> + <flag name='virtio-gpu.blob'/> <version>6001050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>61700244</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml index 56269483c0..261385cc76 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml @@ -150,6 +150,7 @@ <flag name='virtio-net.rss'/> <flag name='migration.blocked-reasons'/> <flag name='virtio-crypto'/> + <flag name='virtio-gpu.blob'/> <version>6002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900244</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml index e9f65434ee..f33b8d1034 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml @@ -191,6 +191,7 @@ <flag name='usb-host.guest-resets-all'/> <flag name='migration.blocked-reasons'/> <flag name='virtio-crypto'/> + <flag name='virtio-gpu.blob'/> <version>6002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100244</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_7.0.0.aarch64.xml b/tests/qemucapabilitiesdata/caps_7.0.0.aarch64.xml index 16c4df09c2..6118d3cf4b 100644 --- a/tests/qemucapabilitiesdata/caps_7.0.0.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_7.0.0.aarch64.xml @@ -164,6 +164,7 @@ <flag name='usb-host.guest-resets-all'/> <flag name='migration.blocked-reasons'/> <flag name='virtio-crypto'/> + <flag name='virtio-gpu.blob'/> <version>6002092</version> <kvmVersion>0</kvmVersion> <microcodeVersion>61700243</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml index 302ab8dacb..66f03a4427 100644 --- a/tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml @@ -168,6 +168,7 @@ <flag name='usb-host.guest-resets-all'/> <flag name='migration.blocked-reasons'/> <flag name='virtio-crypto'/> + <flag name='virtio-gpu.blob'/> <version>7000000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900243</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml index 893b5670e5..3422867e1d 100644 --- a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml @@ -197,6 +197,7 @@ <flag name='migration.blocked-reasons'/> <flag name='sgx-epc'/> <flag name='virtio-crypto'/> + <flag name='virtio-gpu.blob'/> <version>7000000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100243</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_7.1.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_7.1.0.ppc64.xml index 5ffc2213c1..06a7544c8d 100644 --- a/tests/qemucapabilitiesdata/caps_7.1.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_7.1.0.ppc64.xml @@ -168,6 +168,7 @@ <flag name='query-stats-schemas'/> <flag name='screenshot-format-png'/> <flag name='virtio-crypto'/> + <flag name='virtio-gpu.blob'/> <version>7001000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900244</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_7.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_7.1.0.x86_64.xml index 5d7d98bb56..5649eab014 100644 --- a/tests/qemucapabilitiesdata/caps_7.1.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_7.1.0.x86_64.xml @@ -200,6 +200,7 @@ <flag name='query-stats-schemas'/> <flag name='screenshot-format-png'/> <flag name='virtio-crypto'/> + <flag name='virtio-gpu.blob'/> <version>7001000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100244</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_7.2.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_7.2.0.x86_64.xml index fccf9b7923..39aaa7513e 100644 --- a/tests/qemucapabilitiesdata/caps_7.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_7.2.0.x86_64.xml @@ -204,6 +204,7 @@ <flag name='netdev.stream'/> <flag name='virtio-crypto'/> <flag name='cryptodev-backend-lkcf'/> + <flag name='virtio-gpu.blob'/> <version>7002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100245</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_8.0.0.riscv64.xml b/tests/qemucapabilitiesdata/caps_8.0.0.riscv64.xml index 0e273f168a..4d562bb1f1 100644 --- a/tests/qemucapabilitiesdata/caps_8.0.0.riscv64.xml +++ b/tests/qemucapabilitiesdata/caps_8.0.0.riscv64.xml @@ -143,6 +143,7 @@ <flag name='screenshot-format-png'/> <flag name='netdev.stream'/> <flag name='virtio-crypto'/> + <flag name='virtio-gpu.blob'/> <version>7002050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>0</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_8.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_8.0.0.x86_64.xml index c8b7f95c4a..082412bf1a 100644 --- a/tests/qemucapabilitiesdata/caps_8.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_8.0.0.x86_64.xml @@ -204,6 +204,7 @@ <flag name='netdev.stream'/> <flag name='virtio-crypto'/> <flag name='cryptodev-backend-lkcf'/> + <flag name='virtio-gpu.blob'/> <version>7002050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100244</microcodeVersion> -- 2.39.0

This can improve performance for some guests since it reduces copying of display data between host and guest. Requires udmabuf on the host. Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com> --- src/qemu/qemu_cgroup.c | 22 ++++++--- src/qemu/qemu_command.c | 3 ++ src/qemu/qemu_domain.h | 1 + src/qemu/qemu_namespace.c | 22 +++++++++ src/qemu/qemu_validate.c | 9 ++++ .../video-virtio-blob-off.x86_64-latest.args | 39 +++++++++++++++ .../video-virtio-blob-off.xml | 36 ++++++++++++++ .../video-virtio-blob-on.x86_64-latest.args | 39 +++++++++++++++ .../qemuxml2argvdata/video-virtio-blob-on.xml | 36 ++++++++++++++ tests/qemuxml2argvtest.c | 2 + .../video-virtio-blob-off.x86_64-latest.xml | 48 +++++++++++++++++++ .../video-virtio-blob-on.x86_64-latest.xml | 48 +++++++++++++++++++ tests/qemuxml2xmltest.c | 2 + 13 files changed, 300 insertions(+), 7 deletions(-) create mode 100644 tests/qemuxml2argvdata/video-virtio-blob-off.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/video-virtio-blob-off.xml create mode 100644 tests/qemuxml2argvdata/video-virtio-blob-on.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/video-virtio-blob-on.xml create mode 100644 tests/qemuxml2xmloutdata/video-virtio-blob-off.x86_64-latest.xml create mode 100644 tests/qemuxml2xmloutdata/video-virtio-blob-on.x86_64-latest.xml diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index aac7c70054..b1178e0146 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -629,16 +629,24 @@ qemuSetupVideoCgroup(virDomainObj *vm, { qemuDomainObjPrivate *priv = vm->privateData; virDomainVideoAccelDef *accel = def->accel; + int ret; - if (!accel) - return 0; - - if (!accel->rendernode || - !virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) + if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) return 0; - return qemuCgroupAllowDevicePath(vm, accel->rendernode, - VIR_CGROUP_DEVICE_RW, false); + if (accel && accel->rendernode) { + ret = qemuCgroupAllowDevicePath(vm, accel->rendernode, + VIR_CGROUP_DEVICE_RW, false); + if (ret != 0) + return ret; + } + if (def->blob == VIR_TRISTATE_SWITCH_ON) { + ret = qemuCgroupAllowDevicePath(vm, QEMU_DEV_UDMABUF, + VIR_CGROUP_DEVICE_RW, false); + if (ret != 0) + return ret; + } + return 0; } static int diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4ba978f3e6..efccdf505f 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4527,6 +4527,9 @@ qemuBuildDeviceVideoCmd(virCommand *cmd, "p:vgamem", video->vram * 1024, NULL) < 0) return -1; + } else if (video->type == VIR_DOMAIN_VIDEO_TYPE_VIRTIO) { + if (virJSONValueObjectAdd(&props, "T:blob", video->blob, NULL) < 0) + return -1; } if (video->res) { diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index eca5404cdc..ca191f7041 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -84,6 +84,7 @@ struct _qemuDomainUnpluggingDevice { #define QEMU_DEV_SGX_VEPVC "/dev/sgx_vepc" #define QEMU_DEV_SGX_PROVISION "/dev/sgx_provision" #define QEMU_DEVICE_MAPPER_CONTROL_PATH "/dev/mapper/control" +#define QEMU_DEV_UDMABUF "/dev/udmabuf" #define QEMU_DOMAIN_AES_IV_LEN 16 /* 16 bytes for 128 bit random */ diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c index 5769a4dfe0..e2d705d56c 100644 --- a/src/qemu/qemu_namespace.c +++ b/src/qemu/qemu_namespace.c @@ -517,6 +517,25 @@ qemuDomainSetupAllGraphics(virDomainObj *vm, } +static int +qemuDomainSetupAllVideos(virDomainObj *vm, + GSList **paths) +{ + size_t i; + + VIR_DEBUG("Setting up video devices"); + for (i = 0; i < vm->def->nvideos; i++) { + virDomainVideoDef *video = vm->def->videos[i]; + if (video->blob == VIR_TRISTATE_SWITCH_ON) { + *paths = g_slist_prepend(*paths, g_strdup(QEMU_DEV_UDMABUF)); + break; + } + } + + return 0; +} + + static int qemuDomainSetupInput(virDomainInputDef *input, GSList **paths) @@ -688,6 +707,9 @@ qemuDomainBuildNamespace(virQEMUDriverConfig *cfg, if (qemuDomainSetupAllGraphics(vm, &paths) < 0) return -1; + if (qemuDomainSetupAllVideos(vm, &paths) < 0) + return -1; + if (qemuDomainSetupAllInputs(vm, &paths) < 0) return -1; diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 9829c4e7ff..4858fed68c 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -2723,6 +2723,15 @@ qemuValidateDomainDeviceDefVideo(const virDomainVideoDef *video, } } + if (video->type == VIR_DOMAIN_VIDEO_TYPE_VIRTIO) { + if (video->blob != VIR_TRISTATE_SWITCH_ABSENT && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_GPU_BLOB)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("this QEMU does not support 'blob' for virtio-gpu devices")); + return -1; + } + } + if (video->type == VIR_DOMAIN_VIDEO_TYPE_RAMFB && video->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", diff --git a/tests/qemuxml2argvdata/video-virtio-blob-off.x86_64-latest.args b/tests/qemuxml2argvdata/video-virtio-blob-off.x86_64-latest.args new file mode 100644 index 0000000000..61bb5f2193 --- /dev/null +++ b/tests/qemuxml2argvdata/video-virtio-blob-off.x86_64-latest.args @@ -0,0 +1,39 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram \ +-accel tcg \ +-cpu qemu64 \ +-m 1024 \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/QEMUGuest1","node-name":"libvirt-1-storage","cache":{"direct":true,"no-flush":false},"auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-1-format","read-only":false,"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":"libvirt-1-storage"}' \ +-device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-format","id":"ide0-0-0","bootindex":1,"write-cache":"on"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-device '{"driver":"virtio-vga","id":"video0","max_outputs":1,"blob":false,"bus":"pci.0","addr":"0x2"}' \ +-device '{"driver":"virtio-gpu-pci","id":"video1","max_outputs":1,"blob":false,"bus":"pci.0","addr":"0x4"}' \ +-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x3"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/video-virtio-blob-off.xml b/tests/qemuxml2argvdata/video-virtio-blob-off.xml new file mode 100644 index 0000000000..78b7180b35 --- /dev/null +++ b/tests/qemuxml2argvdata/video-virtio-blob-off.xml @@ -0,0 +1,36 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' 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-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2' cache='none'/> + <source file='/var/lib/libvirt/images/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <controller type='usb' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <video> + <model type='virtio' heads='1' primary='yes' blob='off'/> + </video> + <video> + <model type='virtio' heads='1' primary='no' blob='off'/> + </video> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/video-virtio-blob-on.x86_64-latest.args b/tests/qemuxml2argvdata/video-virtio-blob-on.x86_64-latest.args new file mode 100644 index 0000000000..72f7b86017 --- /dev/null +++ b/tests/qemuxml2argvdata/video-virtio-blob-on.x86_64-latest.args @@ -0,0 +1,39 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram \ +-accel tcg \ +-cpu qemu64 \ +-m 1024 \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/QEMUGuest1","node-name":"libvirt-1-storage","cache":{"direct":true,"no-flush":false},"auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-1-format","read-only":false,"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":"libvirt-1-storage"}' \ +-device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-format","id":"ide0-0-0","bootindex":1,"write-cache":"on"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-device '{"driver":"virtio-vga","id":"video0","max_outputs":1,"blob":true,"bus":"pci.0","addr":"0x2"}' \ +-device '{"driver":"virtio-gpu-pci","id":"video1","max_outputs":1,"blob":true,"bus":"pci.0","addr":"0x4"}' \ +-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x3"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/video-virtio-blob-on.xml b/tests/qemuxml2argvdata/video-virtio-blob-on.xml new file mode 100644 index 0000000000..2b8a913f49 --- /dev/null +++ b/tests/qemuxml2argvdata/video-virtio-blob-on.xml @@ -0,0 +1,36 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' 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-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2' cache='none'/> + <source file='/var/lib/libvirt/images/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <controller type='usb' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <video> + <model type='virtio' heads='1' primary='yes' blob='on'/> + </video> + <video> + <model type='virtio' heads='1' primary='no' blob='on'/> + </video> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 3e58a73e41..2a8dc22025 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -2165,6 +2165,8 @@ mymain(void) DO_TEST("video-virtio-vga", QEMU_CAPS_DEVICE_VIRTIO_GPU, QEMU_CAPS_DEVICE_VIRTIO_VGA); + DO_TEST_CAPS_LATEST("video-virtio-blob-on"); + DO_TEST_CAPS_LATEST("video-virtio-blob-off"); DO_TEST_CAPS_LATEST("video-virtio-vga-gpu-gl"); DO_TEST_CAPS_LATEST("video-bochs-display-device"); DO_TEST_CAPS_LATEST("video-ramfb-display-device"); diff --git a/tests/qemuxml2xmloutdata/video-virtio-blob-off.x86_64-latest.xml b/tests/qemuxml2xmloutdata/video-virtio-blob-off.x86_64-latest.xml new file mode 100644 index 0000000000..d8de97a642 --- /dev/null +++ b/tests/qemuxml2xmloutdata/video-virtio-blob-off.x86_64-latest.xml @@ -0,0 +1,48 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2' cache='none'/> + <source file='/var/lib/libvirt/images/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <video> + <model type='virtio' heads='1' primary='yes' blob='off'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <video> + <model type='virtio' heads='1' blob='off'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </video> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/video-virtio-blob-on.x86_64-latest.xml b/tests/qemuxml2xmloutdata/video-virtio-blob-on.x86_64-latest.xml new file mode 100644 index 0000000000..410db67592 --- /dev/null +++ b/tests/qemuxml2xmloutdata/video-virtio-blob-on.x86_64-latest.xml @@ -0,0 +1,48 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2' cache='none'/> + <source file='/var/lib/libvirt/images/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <video> + <model type='virtio' heads='1' primary='yes' blob='on'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <video> + <model type='virtio' heads='1' blob='on'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </video> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 9ab49b822c..5a7d5ee521 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -1111,6 +1111,8 @@ mymain(void) QEMU_CAPS_DEVICE_VIRTIO_GPU_CCW); DO_TEST("video-none-device", QEMU_CAPS_VNC); DO_TEST_CAPS_LATEST("video-virtio-vga-gpu-gl"); + DO_TEST_CAPS_LATEST("video-virtio-blob-on"); + DO_TEST_CAPS_LATEST("video-virtio-blob-off"); DO_TEST_CAPS_LATEST("intel-iommu"); DO_TEST_CAPS_LATEST("intel-iommu-caching-mode"); -- 2.39.0
participants (2)
-
Jonathon Jongsma
-
Ján Tomko