<interface type='user'> <mac address='52:54:56:5a:5c:5e'/> <model type='virtio'/> <driver iommu='on' ats='on'/> </interface> https://bugzilla.redhat.com/show_bug.cgi?id=1283251 --- docs/formatdomain.html.in | 19 ++++ docs/schemas/domaincommon.rng | 12 ++ src/conf/domain_conf.c | 121 +++++++++++++++++++++ src/conf/domain_conf.h | 10 ++ .../qemuxml2argv-virtio-options.xml | 1 + 5 files changed, 163 insertions(+) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index fa0edd1..e9ff73b 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3451,6 +3451,19 @@ </dd> </dl> + <h4><a name="elementsVirtio">Virtio-related options</a></h4> + + <p> + QEMU's virtio devices have some attributes related to the virtio transport under + the <code>driver</code> element: + The <code>iommu</code> attribute enables the use of emulated IOMMU + by the device. The attribute <code>ats</code> controls the Address + Translation Service support for PCIe devices. This is needed to make use + of IOTLB support (see <a href="#elementsIommu">IOMMU device</a>). + Possible values are <code>on</code> or <code>off</code>. + <span class="since">Since 3.5.0</span> + </p> + <h4><a name="elementsControllers">Controllers</a></h4> <p> @@ -5142,6 +5155,12 @@ qemu-kvm -net nic,model=? /dev/null <b>In general you should leave this option alone, unless you are very certain you know what you are doing.</b> </dd> + <dt>virtio options</dt> + <dd> + For virtio interfaces, + <a href="#elementsVirtio">Virtio-specific options</a> can also be + set. (<span class="since">Since 3.5.0</span>) + </dd> </dl> <p> Offloading options for the host and guest can be configured using diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 5c542c7..15fd72f 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2686,6 +2686,7 @@ </optional> </group> </choice> + <ref name="virtioOptions"/> <interleave> <optional> <element name='host'> @@ -5006,6 +5007,17 @@ </element> </define> + <define name="virtioOptions"> + <optional> + <attribute name="iommu"> + <ref name="virOnOff"/> + </attribute> + <attribute name="ats"> + <ref name="virOnOff"/> + </attribute> + </optional> + </define> + <define name="usbmaster"> <element name="master"> <attribute name="startport"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 710048c..22b8653 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1112,6 +1112,46 @@ virDomainXMLOptionGetNamespace(virDomainXMLOptionPtr xmlopt) return &xmlopt->ns; } +static int +virDomainVirtioOptionsParseXML(xmlXPathContextPtr ctxt, + virDomainVirtioOptionsPtr *virtio) +{ + char *str = NULL; + int ret = -1; + int val; + virDomainVirtioOptionsPtr res; + + if (VIR_ALLOC(*virtio) < 0) + return -1; + + res = *virtio; + + if ((str = virXPathString("string(./driver/@iommu)", ctxt))) { + if ((val = virTristateSwitchTypeFromString(str)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("invalid iommu value")); + goto cleanup; + } + res->iommu = val; + } + VIR_FREE(str); + + if ((str = virXPathString("string(./driver/@ats)", ctxt))) { + if ((val = virTristateSwitchTypeFromString(str)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("invalid ats value")); + goto cleanup; + } + res->ats = val; + } + + ret = 0; + + cleanup: + VIR_FREE(str); + return ret; +} + virSaveCookieCallbacksPtr virDomainXMLOptionGetSaveCookie(virDomainXMLOptionPtr xmlopt) @@ -1966,6 +2006,7 @@ virDomainNetDefClear(virDomainNetDefPtr def) VIR_FREE(def->ifname); VIR_FREE(def->ifname_guest); VIR_FREE(def->ifname_guest_actual); + VIR_FREE(def->virtio); virNetDevIPInfoClear(&def->guestIP); virNetDevIPInfoClear(&def->hostIP); @@ -4340,6 +4381,28 @@ virDomainHostdevDefPostParse(virDomainHostdevDefPtr dev, static int +virDomainCheckVirtioOptions(virDomainVirtioOptionsPtr virtio) +{ + if (!virtio) + return 0; + + if (virtio->iommu != VIR_TRISTATE_SWITCH_ABSENT) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("iommu driver option is only supported " + "for virtio devices")); + return -1; + } + if (virtio->ats != VIR_TRISTATE_SWITCH_ABSENT) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("ats driver option is only supported " + "for virtio devices")); + return -1; + } + return 0; +} + + +static int virDomainDeviceDefPostParseInternal(virDomainDeviceDefPtr dev, const virDomainDef *def, virCapsPtr caps ATTRIBUTE_UNUSED, @@ -4437,6 +4500,13 @@ virDomainDeviceDefPostParseInternal(virDomainDeviceDefPtr dev, } } + if (dev->type == VIR_DOMAIN_DEVICE_NET) { + virDomainNetDefPtr net = dev->data.net; + if (STRNEQ_NULLABLE(net->model, "virtio") && + virDomainCheckVirtioOptions(net->virtio) < 0) + return -1; + } + return 0; } @@ -5235,6 +5305,24 @@ virDomainDefValidate(virDomainDefPtr def, } +static void +virDomainVirtioOptionsFormat(virBufferPtr buf, + virDomainVirtioOptionsPtr virtio) +{ + if (!virtio) + return; + + if (virtio->iommu != VIR_TRISTATE_SWITCH_ABSENT) { + virBufferAsprintf(buf, " iommu='%s'", + virTristateSwitchTypeToString(virtio->iommu)); + } + if (virtio->ats != VIR_TRISTATE_SWITCH_ABSENT) { + virBufferAsprintf(buf, " ats='%s'", + virTristateSwitchTypeToString(virtio->ats)); + } +} + + /* Generate a string representation of a device address * @info address Device address to stringify */ @@ -10381,6 +10469,9 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, goto error; } + if (virDomainVirtioOptionsParseXML(ctxt, &def->virtio) < 0) + goto error; + cleanup: ctxt->node = oldnode; VIR_FREE(macaddr); @@ -19005,6 +19096,30 @@ virDomainDeviceInfoCheckABIStability(virDomainDeviceInfoPtr src, static bool +virDomainVirtioOptionsCheckABIStability(virDomainVirtioOptionsPtr src, + virDomainVirtioOptionsPtr dst) +{ + if (src->iommu != dst->iommu) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target device iommu option '%s' does not " + "match source '%s'"), + virTristateSwitchTypeToString(dst->iommu), + virTristateSwitchTypeToString(src->iommu)); + return false; + } + if (src->ats != dst->ats) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target device ats option '%s' does not " + "match source '%s'"), + virTristateSwitchTypeToString(dst->ats), + virTristateSwitchTypeToString(src->ats)); + return false; + } + return true; +} + + +static bool virDomainDiskDefCheckABIStability(virDomainDiskDefPtr src, virDomainDiskDefPtr dst) { @@ -19163,6 +19278,10 @@ virDomainNetDefCheckABIStability(virDomainNetDefPtr src, return false; } + if (src->virtio && dst->virtio && + !virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio)) + return false; + if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info)) return false; @@ -22118,6 +22237,8 @@ virDomainVirtioNetDriverFormat(char **outstr, virBufferAsprintf(&buf, " rx_queue_size='%u'", def->driver.virtio.rx_queue_size); + virDomainVirtioOptionsFormat(&buf, def->virtio); + if (virBufferCheckError(&buf) < 0) return -1; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 597fb22..b3e607b 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -156,6 +156,9 @@ typedef virDomainTPMDef *virDomainTPMDefPtr; typedef struct _virDomainIOMMUDef virDomainIOMMUDef; typedef virDomainIOMMUDef *virDomainIOMMUDefPtr; +typedef struct _virDomainVirtioOptions virDomainVirtioOptions; +typedef virDomainVirtioOptions *virDomainVirtioOptionsPtr; + /* Flags for the 'type' field in virDomainDeviceDef */ typedef enum { VIR_DOMAIN_DEVICE_NONE = 0, @@ -1040,6 +1043,7 @@ struct _virDomainNetDef { int linkstate; unsigned int mtu; virNetDevCoalescePtr coalesce; + virDomainVirtioOptionsPtr virtio; }; typedef enum { @@ -2215,6 +2219,12 @@ struct _virDomainIOMMUDef { virTristateSwitch eim; virTristateSwitch iotlb; }; + +struct _virDomainVirtioOptions { + virTristateSwitch iommu; + virTristateSwitch ats; +}; + /* * Guest VM main configuration * diff --git a/tests/qemuxml2argvdata/qemuxml2argv-virtio-options.xml b/tests/qemuxml2argvdata/qemuxml2argv-virtio-options.xml index c88cf64..3357bc6 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-virtio-options.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-virtio-options.xml @@ -47,6 +47,7 @@ <interface type='user'> <mac address='52:54:56:58:5a:5c'/> <model type='virtio'/> + <driver iommu='on' ats='on'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> </interface> <input type='mouse' bus='virtio'> -- 2.10.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list