Enable x2APIC mode. Useful for higher number of guest CPUs.
:since:`Since 11.5.0` (QEMU/KVM and ``amd`` model only)
+ ``pciBus``
+ The ``pciBus`` attribute notes the index of the controller that an
+ IOMMU device is attached to. (QEMU/KVM and ``smmuv3`` model only)
+
The ``virtio`` IOMMU devices can further have ``address`` element as described
in `Device addresses`_ (address has to by type of ``pci``).
iommu = g_new0(virDomainIOMMUDef, 1);
+ iommu->pci_bus = -1;
+
return g_steal_pointer(&iommu);
}
if (virXMLPropTristateSwitch(driver, "passthrough", VIR_XML_PROP_NONE,
&iommu->pt) < 0)
return NULL;
+
+ if (virXMLPropInt(driver, "pciBus", 10, VIR_XML_PROP_NONE,
+ &iommu->pci_bus, -1) < 0)
+ return NULL;
}
if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt,
dst->aw_bits, src->aw_bits);
return false;
}
+ if (src->pci_bus != dst->pci_bus) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target domain IOMMU device pci_bus value '%1$d' does not match source '%2$d'"),
+ dst->pci_bus, src->pci_bus);
+ return false;
+ }
if (src->dma_translation != dst->dma_translation) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Target domain IOMMU device dma translation '%1$s' does not match source '%2$s'"),
virBufferAsprintf(&driverAttrBuf, " xtsup='%s'",
virTristateSwitchTypeToString(iommu->xtsup));
}
+ if (iommu->pci_bus >= 0) {
+ virBufferAsprintf(&driverAttrBuf, " pciBus='%d'",
+ iommu->pci_bus);
+ }
virXMLFormatElement(&childBuf, "driver", &driverAttrBuf, NULL);
virTristateSwitch eim;
virTristateSwitch iotlb;
unsigned int aw_bits;
+ int pci_bus;
virDomainDeviceInfo info;
virTristateSwitch dma_translation;
virTristateSwitch xtsup;
_("IOMMU model smmuv3 must be specified for multiple IOMMU definitions"));
}
+ if (def->niommus > 1 && iommu->pci_bus < 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("device-pluggable IOMMU with pciBus attribute must be specified for multiple IOMMU definitions"));
+ }
+
if (iommu->intremap == VIR_TRISTATE_SWITCH_ON &&
def->features[VIR_DOMAIN_FEATURE_IOAPIC] != VIR_DOMAIN_IOAPIC_QEMU) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
{
switch (iommu->model) {
case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
+ if (iommu->intremap != VIR_TRISTATE_SWITCH_ABSENT ||
+ iommu->caching_mode != VIR_TRISTATE_SWITCH_ABSENT ||
+ iommu->eim != VIR_TRISTATE_SWITCH_ABSENT ||
+ iommu->iotlb != VIR_TRISTATE_SWITCH_ABSENT ||
+ iommu->aw_bits != 0 ||
+ iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT ||
+ iommu->xtsup != VIR_TRISTATE_SWITCH_ABSENT ||
+ iommu->pt != VIR_TRISTATE_SWITCH_ABSENT) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("iommu model '%1$s' doesn't support some additional attributes"),
+ virDomainIOMMUModelTypeToString(iommu->model));
+ return -1;
+ }
+ break;
case VIR_DOMAIN_IOMMU_MODEL_VIRTIO:
if (iommu->intremap != VIR_TRISTATE_SWITCH_ABSENT ||
iommu->caching_mode != VIR_TRISTATE_SWITCH_ABSENT ||
iommu->eim != VIR_TRISTATE_SWITCH_ABSENT ||
iommu->iotlb != VIR_TRISTATE_SWITCH_ABSENT ||
iommu->aw_bits != 0 ||
- iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT) {
+ iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT ||
+ iommu->pci_bus >= 0) {
virReportError(VIR_ERR_XML_ERROR,
_("iommu model '%1$s' doesn't support additional attributes"),
virDomainIOMMUModelTypeToString(iommu->model));
if (iommu->caching_mode != VIR_TRISTATE_SWITCH_ABSENT ||
iommu->eim != VIR_TRISTATE_SWITCH_ABSENT ||
iommu->aw_bits != 0 ||
- iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT) {
+ iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT ||
+ iommu->pci_bus >= 0) {
virReportError(VIR_ERR_XML_ERROR,
_("iommu model '%1$s' doesn't support some additional attributes"),
virDomainIOMMUModelTypeToString(iommu->model));
case VIR_DOMAIN_IOMMU_MODEL_INTEL:
if (iommu->pt != VIR_TRISTATE_SWITCH_ABSENT ||
- iommu->xtsup != VIR_TRISTATE_SWITCH_ABSENT) {
+ iommu->xtsup != VIR_TRISTATE_SWITCH_ABSENT ||
+ iommu->pci_bus >= 0) {
virReportError(VIR_ERR_XML_ERROR,
_("iommu model '%1$s' doesn't support some additional attributes"),
virDomainIOMMUModelTypeToString(iommu->model));
<ref name="virOnOff"/>
</attribute>
</optional>
+ <optional>
+ <attribute name="pciBus">
+ <data type="unsignedInt"/>
+ </attribute>
+ </optional>
</element>
</optional>
<optional>
}
+static virJSONValue *
+qemuBuildPCINestedSmmuv3DevProps(const virDomainDef *def,
+ const virDomainIOMMUDef *iommu)
+{
+ g_autoptr(virJSONValue) props = NULL;
+ g_autofree char *bus = NULL;
+ virPCIDeviceAddress addr = { .bus = iommu->pci_bus };
+
+ bus = qemuBuildDeviceAddressPCIGetBus(def, &addr);
+
+ if (!bus) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not find a suitable controller for smmuv3"));
+ return NULL;
+ }
+
+ if (virJSONValueObjectAdd(&props,
+ "s:driver", "arm-smmuv3",
+ "s:primary-bus", bus,
+ "s:id", iommu->info.alias,
+ NULL) < 0)
+ return NULL;
+
+ return g_steal_pointer(&props);
+}
+
+
static int
qemuBuildIOMMUCommandLine(virCommand *cmd,
const virDomainDef *def,
return -1;
break;
+
case VIR_DOMAIN_IOMMU_MODEL_VIRTIO:
if (virJSONValueObjectAdd(&props,
"s:driver", "virtio-iommu",
return -1;
break;
- case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
- /* There is no -device for SMMUv3, so nothing to be done here */
- break;
case VIR_DOMAIN_IOMMU_MODEL_AMD:
if (virJSONValueObjectAdd(&wrapperProps,
break;
+ case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
+ if (iommu->pci_bus >= 0) {
+ if (!(props = qemuBuildPCINestedSmmuv3DevProps(def, iommu)))
+ return -1;
+ if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCaps) < 0)
+ return -1;
+ }
+ break;
+
case VIR_DOMAIN_IOMMU_MODEL_LAST:
default:
virReportEnumRangeError(virDomainIOMMUModel, iommu->model);