From bb593e3743d8aa0ecd7385eb6be83f1fa355c8a4 Mon Sep 17 00:00:00 2001 From: Rayhan Faizel Date: Fri, 12 Apr 2024 01:42:43 +0530 Subject: [PATCH] conf: Introduce support for virtio-sound devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds parsing of the virtio sound model, along with parsing of virtio options and PCI/virtio-mmio address assignment. A new 'streams' attribute is added for configuring number of PCM streams (default is 2) in virtio sound devices. QEMU additionally has jacks and chmaps parameters but these are currently stubbed, hence they are excluded in this patch series. Signed-off-by: Rayhan Faizel Reviewed-by: Ján Tomko --- docs/formatdomain.rst | 11 +++++++++-- src/conf/domain_conf.c | 25 +++++++++++++++++++++++++ src/conf/domain_conf.h | 4 ++++ src/conf/domain_postparse.c | 13 ++++++++++++- src/conf/schemas/domaincommon.rng | 11 +++++++++++ src/libxl/libxl_domain.c | 1 + src/qemu/qemu_command.c | 1 + src/qemu/qemu_domain_address.c | 9 +++++++++ src/qemu/qemu_validate.c | 8 ++++++++ 9 files changed, 80 insertions(+), 3 deletions(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 89e634e16a..00f861e385 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -7405,8 +7405,9 @@ A virtual sound card can be attached to the host via the ``sound`` element. what real sound device is emulated. Valid values are specific to the underlying hypervisor, though typical choices are ``sb16``, ``es1370``, ``pcspk``, ``ac97`` (:since:`Since 0.6.0`), ``ich6`` (:since:`Since 0.8.8`), - ``ich9`` (:since:`Since 1.1.3`), ``usb`` (:since:`Since 1.2.8`) and ``ich7`` - (:since:`Since 6.7.0`, bhyve only). + ``ich9`` (:since:`Since 1.1.3`), ``usb`` (:since:`Since 1.2.8`), ``ich7`` + (:since:`Since 6.7.0`, bhyve only) and ``virtio`` + (:since:`Since 10.4.0 and QEMU 8.2.0`). :since:`Since 0.9.13`, a sound element with ``ich6`` or ``ich9`` models can have optional sub-elements ```` to attach various audio codecs to the audio @@ -7434,6 +7435,12 @@ multi-channel mode by using the ``multichannel`` attribute:: +:since:`Since 10.4.0 and QEMU 8.2.0` the number of PCM streams in a ``virtio`` +sound device can be configured by using the ``streams`` attribute, which +defaults to ``2`` if left unspecified:: + + + Each ``sound`` element has an optional sub-element ``
`` which can tie the device to a particular PCI slot. See `Device Addresses`_. diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 9eaec76b07..fde594f811 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -779,6 +779,7 @@ VIR_ENUM_IMPL(virDomainSoundModel, "ich9", "usb", "ich7", + "virtio", ); VIR_ENUM_IMPL(virDomainAudioType, @@ -3212,6 +3213,7 @@ void virDomainSoundDefFree(virDomainSoundDef *def) virDomainSoundCodecDefFree(def->codecs[i]); g_free(def->codecs); + g_free(def->virtio); g_free(def); } @@ -11887,6 +11889,13 @@ virDomainSoundDefParseXML(virDomainXMLOption *xmlopt, return NULL; } + if (def->model == VIR_DOMAIN_SOUND_MODEL_VIRTIO) { + if (virXMLPropUInt(node, "streams", 10, + VIR_XML_PROP_NONZERO, + &def->streams) < 0) + return NULL; + } + audioNode = virXPathNode("./audio", ctxt); if (audioNode) { if (virXMLPropUInt(audioNode, "id", 10, @@ -11898,6 +11907,10 @@ virDomainSoundDefParseXML(virDomainXMLOption *xmlopt, if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) < 0) return NULL; + if (virDomainVirtioOptionsParseXML(virXPathNode("./driver", ctxt), + &def->virtio) < 0) + return NULL; + return g_steal_pointer(&def); } @@ -11922,6 +11935,9 @@ virDomainSoundDefEquals(const virDomainSoundDef *a, if (a->multichannel != b->multichannel) return false; + if (a->streams != b->streams) + return false; + if (a->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && !virDomainDeviceInfoAddressIsEqual(&a->info, &b->info)) return false; @@ -24848,6 +24864,7 @@ virDomainSoundDefFormat(virBuffer *buf, const char *model = virDomainSoundModelTypeToString(def->model); g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER; size_t i; if (!model) { @@ -24872,6 +24889,14 @@ virDomainSoundDefFormat(virBuffer *buf, virTristateBoolTypeToString(def->multichannel)); } + if (def->model == VIR_DOMAIN_SOUND_MODEL_VIRTIO) { + virBufferAsprintf(&attrBuf, " streams='%d'", def->streams); + + virDomainVirtioOptionsFormat(&driverAttrBuf, def->virtio); + + virXMLFormatElement(&childBuf, "driver", &driverAttrBuf, NULL); + } + virXMLFormatElement(buf, "sound", &attrBuf, &childBuf); return 0; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index c2abdb9f52..a06f015444 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1568,6 +1568,7 @@ typedef enum { VIR_DOMAIN_SOUND_MODEL_ICH9, VIR_DOMAIN_SOUND_MODEL_USB, VIR_DOMAIN_SOUND_MODEL_ICH7, + VIR_DOMAIN_SOUND_MODEL_VIRTIO, VIR_DOMAIN_SOUND_MODEL_LAST } virDomainSoundModel; @@ -1589,6 +1590,9 @@ struct _virDomainSoundDef { virTristateBool multichannel; unsigned int audioId; + + unsigned int streams; + virDomainVirtioOptions *virtio; }; typedef enum { diff --git a/src/conf/domain_postparse.c b/src/conf/domain_postparse.c index cafa2d235d..112795ea65 100644 --- a/src/conf/domain_postparse.c +++ b/src/conf/domain_postparse.c @@ -677,6 +677,13 @@ virDomainInputDefPostParse(virDomainInputDef *input, } } +static void +virDomainSoundDefPostParse(virDomainSoundDef *sound) +{ + if (sound->model == VIR_DOMAIN_SOUND_MODEL_VIRTIO && sound->streams == 0) + sound->streams = 2; +} + static int virDomainDeviceDefPostParseCommon(virDomainDeviceDef *dev, const virDomainDef *def, @@ -730,9 +737,13 @@ virDomainDeviceDefPostParseCommon(virDomainDeviceDef *dev, ret = 0; break; + case VIR_DOMAIN_DEVICE_SOUND: + virDomainSoundDefPostParse(dev->data.sound); + ret = 0; + break; + case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_NET: - case VIR_DOMAIN_DEVICE_SOUND: case VIR_DOMAIN_DEVICE_WATCHDOG: case VIR_DOMAIN_DEVICE_GRAPHICS: case VIR_DOMAIN_DEVICE_HUB: diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 86d9e391d8..a46a824f88 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -5062,6 +5062,7 @@ ich7 ich9 usb + virtio @@ -5069,6 +5070,11 @@ + + + + + @@ -5089,6 +5095,11 @@ + + + + + diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 16c2ab973b..0f129ec69c 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -344,6 +344,7 @@ libxlDomainDefValidate(const virDomainDef *def, case VIR_DOMAIN_SOUND_MODEL_ICH7: case VIR_DOMAIN_SOUND_MODEL_USB: case VIR_DOMAIN_SOUND_MODEL_ICH9: + case VIR_DOMAIN_SOUND_MODEL_VIRTIO: case VIR_DOMAIN_SOUND_MODEL_LAST: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported audio model %1$s"), diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 807f013713..c32f577339 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4482,6 +4482,7 @@ qemuBuildSoundDevCmd(virCommand *cmd, case VIR_DOMAIN_SOUND_MODEL_SB16: model = "sb16"; break; + case VIR_DOMAIN_SOUND_MODEL_VIRTIO: case VIR_DOMAIN_SOUND_MODEL_PCSPK: /* pc-speaker is handled separately */ case VIR_DOMAIN_SOUND_MODEL_ICH7: case VIR_DOMAIN_SOUND_MODEL_LAST: diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 7690021ca7..251f5b7e1a 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -324,6 +324,12 @@ qemuDomainPrimeVirtioDeviceAddresses(virDomainDef *def, if (def->cryptos[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) def->cryptos[i]->info.type = type; } + + for (i = 0; i < def->nsounds; i++) { + if (def->sounds[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && + def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_VIRTIO) + def->sounds[i]->info.type = type; + } } @@ -694,6 +700,9 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev, case VIR_DOMAIN_SOUND_MODEL_ICH9: return pciFlags; + case VIR_DOMAIN_SOUND_MODEL_VIRTIO: + return virtioFlags; + case VIR_DOMAIN_SOUND_MODEL_SB16: case VIR_DOMAIN_SOUND_MODEL_PCSPK: case VIR_DOMAIN_SOUND_MODEL_USB: diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index d4ac721c06..ac1940cb31 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -4675,6 +4675,14 @@ qemuValidateDomainDeviceDefSound(virDomainSoundDef *sound, } break; + case VIR_DOMAIN_SOUND_MODEL_VIRTIO: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_SOUND)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("virtio-sound controller is not supported in this QEMU binary")); + return -1; + } + break; + case VIR_DOMAIN_SOUND_MODEL_ES1370: case VIR_DOMAIN_SOUND_MODEL_AC97: case VIR_DOMAIN_SOUND_MODEL_ICH6: