From ea0ed35d6efcba9e79c76d7b57959f553b76224a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1n=20Tomko?= Date: Wed, 22 Jun 2016 16:28:22 +0200 Subject: [PATCH] Introduce device A device with an attribute 'model', with just one model so far: ... https://bugzilla.redhat.com/show_bug.cgi?id=1235580 --- docs/formatdomain.html.in | 26 ++++++ docs/schemas/domaincommon.rng | 11 +++ src/conf/domain_conf.c | 90 ++++++++++++++++++- src/conf/domain_conf.h | 16 ++++ src/libvirt_private.syms | 2 + src/qemu/qemu_driver.c | 6 ++ src/qemu/qemu_hotplug.c | 1 + .../qemuxml2argv-intel-iommu.xml | 37 ++++++++ .../qemuxml2xmlout-intel-iommu.xml | 37 ++++++++ tests/qemuxml2xmltest.c | 4 + 10 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-intel-iommu.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-intel-iommu.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index ee6d5e875f..59a8bb9229 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -6752,6 +6752,32 @@ qemu-kvm -net nic,model=? /dev/null +

IOMMU devices

+ +

+ The iommu element can be used to add an IOMMU device. + Since 2.1.0 +

+ +

+ Example: +

+
+  ...
+  <devices>
+    <iommu model='intel'/>
+  </devices>
+  ...
+
+
+
model
+
+

+ Currently only the intel model is supported. +

+
+
+

Security label

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index cba2d1223e..348dbfe6b1 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3718,6 +3718,14 @@ + + + + intel + + + + @@ -4187,6 +4195,9 @@ + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 4c232e0f84..16e0736e09 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -240,7 +240,8 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST, "shmem", "tpm", "panic", - "memory") + "memory", + "iommu") VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST, "none", @@ -803,6 +804,9 @@ VIR_ENUM_IMPL(virDomainTPMModel, VIR_DOMAIN_TPM_MODEL_LAST, VIR_ENUM_IMPL(virDomainTPMBackend, VIR_DOMAIN_TPM_TYPE_LAST, "passthrough") +VIR_ENUM_IMPL(virDomainIOMMUModel, VIR_DOMAIN_IOMMU_MODEL_LAST, + "intel") + VIR_ENUM_IMPL(virDomainDiskDiscard, VIR_DOMAIN_DISK_DISCARD_LAST, "default", "unmap", @@ -2394,6 +2398,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def) case VIR_DOMAIN_DEVICE_MEMORY: virDomainMemoryDefFree(def->data.memory); break; + case VIR_DOMAIN_DEVICE_IOMMU: + VIR_FREE(def->data.iommu); + break; case VIR_DOMAIN_DEVICE_LAST: case VIR_DOMAIN_DEVICE_NONE: break; @@ -2640,6 +2647,8 @@ void virDomainDefFree(virDomainDefPtr def) virDomainPanicDefFree(def->panics[i]); VIR_FREE(def->panics); + VIR_FREE(def->iommu); + VIR_FREE(def->idmap.uidmap); VIR_FREE(def->idmap.gidmap); @@ -3180,6 +3189,7 @@ virDomainDeviceGetInfo(virDomainDeviceDefPtr device) /* The following devices do not contain virDomainDeviceInfo */ case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_GRAPHICS: + case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_LAST: case VIR_DOMAIN_DEVICE_NONE: break; @@ -3543,6 +3553,7 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def, case VIR_DOMAIN_DEVICE_LAST: case VIR_DOMAIN_DEVICE_RNG: case VIR_DOMAIN_DEVICE_MEMORY: + case VIR_DOMAIN_DEVICE_IOMMU: break; } #endif @@ -4604,6 +4615,7 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_MEMORY: + case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_LAST: break; @@ -13266,6 +13278,39 @@ virDomainMemoryDefParseXML(xmlNodePtr memdevNode, } +static virDomainIOMMUDefPtr +virDomainIOMMUDefParseXML(xmlNodePtr node) +{ + virDomainIOMMUDefPtr iommu = NULL, ret = NULL; + char *tmp = NULL; + int val; + + if (VIR_ALLOC(iommu) < 0) + goto cleanup; + + if (!(tmp = virXMLPropString(node, "model"))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing model for IOMMU device")); + goto cleanup; + } + + if ((val = virDomainIOMMUModelTypeFromString(tmp)) < 0) { + virReportError(VIR_ERR_XML_ERROR, _("unknown IOMMU model: %s"), tmp); + goto cleanup; + } + + iommu->model = val; + + ret = iommu; + iommu = NULL; + + cleanup: + VIR_FREE(iommu); + VIR_FREE(tmp); + return ret; +} + + virDomainDeviceDefPtr virDomainDeviceDefParse(const char *xmlStr, const virDomainDef *def, @@ -13407,6 +13452,10 @@ virDomainDeviceDefParse(const char *xmlStr, if (!(dev->data.memory = virDomainMemoryDefParseXML(node, ctxt, flags))) goto error; break; + case VIR_DOMAIN_DEVICE_IOMMU: + if (!(dev->data.iommu = virDomainIOMMUDefParseXML(node))) + goto error; + break; case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_LAST: break; @@ -17215,6 +17264,21 @@ virDomainDefParseXML(xmlDocPtr xml, } VIR_FREE(nodes); + if ((n = virXPathNodeSet("./devices/iommu", ctxt, &nodes)) < 0) + goto error; + + if (n > 1) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("only a single IOMMU device is supported")); + goto error; + } + + if (n > 0) { + if (!(def->iommu = virDomainIOMMUDefParseXML(nodes[0]))) + goto error; + } + VIR_FREE(nodes); + /* analysis of the user namespace mapping */ if ((n = virXPathNodeSet("./idmap/uid", ctxt, &nodes)) < 0) goto error; @@ -18981,6 +19045,23 @@ virDomainDefCheckABIStability(virDomainDefPtr src, goto error; } + if (!!src->iommu != !!dst->iommu) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Target domain IOMMU device count " + "does not match source")); + goto error; + } + + if (src->iommu && + src->iommu->model != dst->iommu->model) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target domain IOMMU device model '%s' " + "does not match source '%s'"), + virDomainIOMMUModelTypeToString(dst->iommu->model), + virDomainIOMMUModelTypeToString(src->iommu->model)); + goto error; + } + /* Coverity is not very happy with this - all dead_error_condition */ #if !STATIC_ANALYSIS /* This switch statement is here to trigger compiler warning when adding @@ -19013,6 +19094,7 @@ virDomainDefCheckABIStability(virDomainDefPtr src, case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_SHMEM: case VIR_DOMAIN_DEVICE_MEMORY: + case VIR_DOMAIN_DEVICE_IOMMU: break; } #endif @@ -23576,6 +23658,11 @@ virDomainDefFormatInternal(virDomainDefPtr def, goto error; } + if (def->iommu) { + virBufferAsprintf(buf, "\n", + virDomainIOMMUModelTypeToString(def->iommu->model)); + } + virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "\n"); @@ -24693,6 +24780,7 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src, case VIR_DOMAIN_DEVICE_MEMBALLOON: case VIR_DOMAIN_DEVICE_NVRAM: case VIR_DOMAIN_DEVICE_SHMEM: + case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_INTERNAL_ERROR, _("Copying definition of '%d' type " diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index c34fc50340..db3f9e889a 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -151,6 +151,9 @@ typedef virDomainShmemDef *virDomainShmemDefPtr; typedef struct _virDomainTPMDef virDomainTPMDef; typedef virDomainTPMDef *virDomainTPMDefPtr; +typedef struct _virDomainIOMMUDef virDomainIOMMUDef; +typedef virDomainIOMMUDef *virDomainIOMMUDefPtr; + /* Flags for the 'type' field in virDomainDeviceDef */ typedef enum { VIR_DOMAIN_DEVICE_NONE = 0, @@ -176,6 +179,7 @@ typedef enum { VIR_DOMAIN_DEVICE_TPM, VIR_DOMAIN_DEVICE_PANIC, VIR_DOMAIN_DEVICE_MEMORY, + VIR_DOMAIN_DEVICE_IOMMU, VIR_DOMAIN_DEVICE_LAST } virDomainDeviceType; @@ -207,6 +211,7 @@ struct _virDomainDeviceDef { virDomainTPMDefPtr tpm; virDomainPanicDefPtr panic; virDomainMemoryDefPtr memory; + virDomainIOMMUDefPtr iommu; } data; }; @@ -2100,6 +2105,15 @@ struct _virDomainKeyWrapDef { int dea; /* enum virTristateSwitch */ }; +typedef enum { + VIR_DOMAIN_IOMMU_MODEL_INTEL, + + VIR_DOMAIN_IOMMU_MODEL_LAST +} virDomainIOMMUModel; + +struct _virDomainIOMMUDef { + virDomainIOMMUModel model; +}; /* * Guest VM main configuration * @@ -2237,6 +2251,7 @@ struct _virDomainDef { virCPUDefPtr cpu; virSysinfoDefPtr sysinfo; virDomainRedirFilterDefPtr redirfilter; + virDomainIOMMUDefPtr iommu; void *namespaceData; virDomainXMLNamespace ns; @@ -3001,6 +3016,7 @@ VIR_ENUM_DECL(virDomainTPMModel) VIR_ENUM_DECL(virDomainTPMBackend) VIR_ENUM_DECL(virDomainMemoryModel) VIR_ENUM_DECL(virDomainMemoryBackingModel) +VIR_ENUM_DECL(virDomainIOMMUModel) /* from libvirt.h */ VIR_ENUM_DECL(virDomainState) VIR_ENUM_DECL(virDomainNostateReason) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 597ce5f3e8..ba718b8de0 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -341,6 +341,8 @@ virDomainHubTypeToString; virDomainHypervTypeFromString; virDomainHypervTypeToString; virDomainInputDefFree; +virDomainIOMMUModelTypeFromString; +virDomainIOMMUModelTypeToString; virDomainIOThreadIDAdd; virDomainIOThreadIDDefFree; virDomainIOThreadIDDel; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 28ef5aa60f..f8d9afe25e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7425,6 +7425,7 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_SHMEM: case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: + case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("live attach of device '%s' is not supported"), @@ -7516,6 +7517,7 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: + case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("live detach of device '%s' is not supported"), @@ -7631,6 +7633,7 @@ qemuDomainUpdateDeviceLive(virConnectPtr conn, case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: + case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("live update of device '%s' is not supported"), @@ -7794,6 +7797,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef, case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: + case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("persistent attach of device '%s' is not supported"), @@ -7948,6 +7952,7 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: + case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("persistent detach of device '%s' is not supported"), @@ -8046,6 +8051,7 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef, case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: + case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("persistent update of device '%s' is not supported"), diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 093aaf928d..04e11b4d79 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -3300,6 +3300,7 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver, case VIR_DOMAIN_DEVICE_SHMEM: case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: + case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("don't know how to remove a %s device"), diff --git a/tests/qemuxml2argvdata/qemuxml2argv-intel-iommu.xml b/tests/qemuxml2argvdata/qemuxml2argv-intel-iommu.xml new file mode 100644 index 0000000000..b5b2b5158a --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-intel-iommu.xml @@ -0,0 +1,37 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219100 + 219100 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +

+ + + + +
+ + +
+ + + + +
+ + + + diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-intel-iommu.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-intel-iommu.xml new file mode 100644 index 0000000000..b5b2b5158a --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-intel-iommu.xml @@ -0,0 +1,37 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219100 + 219100 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + +
+ + +
+ + + + +
+ + + + diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index eb810e3ce4..c81465a5d5 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -886,6 +886,10 @@ mymain(void) DO_TEST("video-qxl-heads"); DO_TEST("video-qxl-noheads"); + DO_TEST_FULL("intel-iommu", WHEN_ACTIVE, GIC_NONE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE); + qemuTestDriverFree(&driver); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;