]> xenbits.xensource.com Git - libvirt.git/commitdiff
conf: Introduce support for virtio-sound devices
authorRayhan Faizel <rayhan.faizel@gmail.com>
Thu, 11 Apr 2024 20:12:43 +0000 (01:42 +0530)
committerJán Tomko <jtomko@redhat.com>
Thu, 2 May 2024 13:38:32 +0000 (15:38 +0200)
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 <rayhan.faizel@gmail.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
docs/formatdomain.rst
src/conf/domain_conf.c
src/conf/domain_conf.h
src/conf/domain_postparse.c
src/conf/schemas/domaincommon.rng
src/libxl/libxl_domain.c
src/qemu/qemu_command.c
src/qemu/qemu_domain_address.c
src/qemu/qemu_validate.c

index 89e634e16a91167c612f9b4cc4c4a35c6f3f8f54..00f861e38590a9126e7f6f5d325d3c5c2c35ca6c 100644 (file)
@@ -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 ``<codec>`` to attach various audio codecs to the audio
@@ -7434,6 +7435,12 @@ multi-channel mode by using the ``multichannel`` attribute::
 
   <sound model='usb' multichannel='yes'/>
 
+: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::
+
+  <sound model='virtio' streams='2'/>
+
 Each ``sound`` element has an optional sub-element ``<address>`` which can tie
 the device to a particular PCI slot. See `Device Addresses`_.
 
index 9eaec76b079ea44aecc813d67297e39a9193fc9f..fde594f81156ef61e2718751f7879bc00ec39c67 100644 (file)
@@ -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;
index c2abdb9f524ed46d0c66c5973e35a960686990ce..a06f01544415775831320363d4310e9a0f4464e7 100644 (file)
@@ -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 {
index cafa2d235d80fe06c47af198d6b25deeb1095f07..112795ea65992fdc188bafd0421da5a671b354ab 100644 (file)
@@ -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:
index 86d9e391d81bde0397be538b71f8308d635605e2..a46a824f88b5b6ba0770f04c6fcbea7ef9565c8a 100644 (file)
           <value>ich7</value>
           <value>ich9</value>
           <value>usb</value>
+          <value>virtio</value>
         </choice>
       </attribute>
       <optional>
           <ref name="virYesNo"/>
         </attribute>
       </optional>
+      <optional>
+        <attribute name="streams">
+          <ref name="uint32"/>
+        </attribute>
+      </optional>
       <interleave>
         <optional>
           <ref name="alias"/>
         <zeroOrMore>
           <ref name="codec"/>
         </zeroOrMore>
+        <optional>
+          <element name="driver">
+            <ref name="virtioOptions"/>
+          </element>
+        </optional>
       </interleave>
     </element>
   </define>
index 16c2ab973b5ec016bace862a4df3ab55bf7b3cdf..0f129ec69cf1eea2fedeb3cdc0330380d44111e1 100644 (file)
@@ -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"),
index 807f013713b00e8777d03481c5e138572249e80a..c32f5773397e909403cd14f6c9a8fb4fd8654a3d 100644 (file)
@@ -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:
index 7690021ca7cc4b50bc7114b8df40137f1718ffef..251f5b7e1aa1b17ed458f43ea7ca7061b046be53 100644 (file)
@@ -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:
index d4ac721c0662cf25f712a7bcb535e7fb15db6c1c..ac1940cb31ad17be4233033e9ac80f85f1adc844 100644 (file)
@@ -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: