[libvirt] [PATCH] conf: Parse virtio-crypto in the domain XML

Longpeng(Mike) longpeng2 at huawei.com
Mon Jan 9 02:15:25 UTC 2017


As virtio-crypto has been supported in QEMU 2.9 and
the frontend driver has been merged in linux 4.10,
so it's necessary to support virtio-crypto in domain
XML.

This patch parse the domain XML with virtio-crypto
support, the virtio-crypto XML looks like this:

    <crypto model='virtio'>
        <backend type='builtin' queues='2'/>
    </crypto>

Signed-off-by: Longpeng(Mike) <longpeng2 at huawei.com>
---
 src/conf/domain_conf.c         | 212 +++++++++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h         |  32 +++++++
 src/qemu/qemu_alias.c          |  20 ++++
 src/qemu/qemu_alias.h          |   4 +
 src/qemu/qemu_capabilities.c   |   4 +
 src/qemu/qemu_capabilities.h   |   2 +
 src/qemu/qemu_command.c        | 129 +++++++++++++++++++++++++
 src/qemu/qemu_command.h        |   4 +
 src/qemu/qemu_domain_address.c |  17 ++++
 src/qemu/qemu_driver.c         |   6 ++
 src/qemu/qemu_hotplug.c        |   1 +
 11 files changed, 431 insertions(+)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 9f7b906..fcfccd5 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -237,6 +237,7 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
               "memballoon",
               "nvram",
               "rng",
+              "crypto",
               "shmem",
               "tpm",
               "panic",
@@ -797,6 +798,14 @@ VIR_ENUM_IMPL(virDomainRNGBackend,
               "random",
               "egd");
 
+VIR_ENUM_IMPL(virDomainCryptoModel,
+              VIR_DOMAIN_CRYPTO_MODEL_LAST,
+              "virtio");
+
+VIR_ENUM_IMPL(virDomainCryptoBackend,
+              VIR_DOMAIN_CRYPTO_BACKEND_LAST,
+              "builtin");
+
 VIR_ENUM_IMPL(virDomainTPMModel, VIR_DOMAIN_TPM_MODEL_LAST,
               "tpm-tis")
 
@@ -2337,6 +2346,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
     case VIR_DOMAIN_DEVICE_RNG:
         virDomainRNGDefFree(def->data.rng);
         break;
+    case VIR_DOMAIN_DEVICE_CRYPTO:
+        virDomainCryptoDefFree(def->data.crypto);
+        break;
     case VIR_DOMAIN_DEVICE_CHR:
         virDomainChrDefFree(def->data.chr);
         break;
@@ -2600,6 +2612,10 @@ void virDomainDefFree(virDomainDefPtr def)
         virDomainRNGDefFree(def->rngs[i]);
     VIR_FREE(def->rngs);
 
+    for (i = 0; i < def->ncryptos; i++)
+        virDomainCryptoDefFree(def->cryptos[i]);
+    VIR_FREE(def->cryptos);
+
     for (i = 0; i < def->nmems; i++)
         virDomainMemoryDefFree(def->mems[i]);
     VIR_FREE(def->mems);
@@ -3169,6 +3185,8 @@ virDomainDeviceGetInfo(virDomainDeviceDefPtr device)
         return &device->data.shmem->info;
     case VIR_DOMAIN_DEVICE_RNG:
         return &device->data.rng->info;
+    case VIR_DOMAIN_DEVICE_CRYPTO:
+        return &device->data.crypto->info;
     case VIR_DOMAIN_DEVICE_TPM:
         return &device->data.tpm->info;
     case VIR_DOMAIN_DEVICE_PANIC:
@@ -3464,6 +3482,12 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
         if (cb(def, &device, &def->rngs[i]->info, opaque) < 0)
             return -1;
     }
+    device.type = VIR_DOMAIN_DEVICE_CRYPTO;
+    for (i = 0; i < def->ncryptos; i++) {
+        device.data.crypto = def->cryptos[i];
+        if (cb(def, &device, &def->cryptos[i]->info, opaque) < 0)
+            return -1;
+    }
     if (def->nvram) {
         device.type = VIR_DOMAIN_DEVICE_NVRAM;
         device.data.nvram = def->nvram;
@@ -3541,6 +3565,7 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
     case VIR_DOMAIN_DEVICE_PANIC:
     case VIR_DOMAIN_DEVICE_LAST:
     case VIR_DOMAIN_DEVICE_RNG:
+    case VIR_DOMAIN_DEVICE_CRYPTO:
     case VIR_DOMAIN_DEVICE_MEMORY:
         break;
     }
@@ -4599,6 +4624,7 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev,
     case VIR_DOMAIN_DEVICE_MEMBALLOON:
     case VIR_DOMAIN_DEVICE_NVRAM:
     case VIR_DOMAIN_DEVICE_RNG:
+    case VIR_DOMAIN_DEVICE_CRYPTO:
     case VIR_DOMAIN_DEVICE_SHMEM:
     case VIR_DOMAIN_DEVICE_TPM:
     case VIR_DOMAIN_DEVICE_PANIC:
@@ -12022,6 +12048,88 @@ virDomainRNGDefParseXML(xmlNodePtr node,
 }
 
 
+static virDomainCryptoDefPtr
+virDomainCryptoDefParseXML(xmlNodePtr node,
+                           xmlXPathContextPtr ctxt,
+                           unsigned int flags)
+{
+    char *model = NULL;
+    char *backend = NULL;
+    char *queues = NULL;
+    virDomainCryptoDefPtr def;
+    xmlNodePtr save = ctxt->node;
+    xmlNodePtr *backends = NULL;
+    int nbackends;
+
+    if (VIR_ALLOC(def) < 0)
+        return NULL;
+
+    if (!(model = virXMLPropString(node, "model"))) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("missing Crypto device model"));
+        goto error;
+    }
+
+    if ((def->model = virDomainCryptoModelTypeFromString(model)) < 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("unknown Crypto model '%s'"), model);
+        goto error;
+    }
+
+    ctxt->node = node;
+
+    if ((nbackends = virXPathNodeSet("./backend", ctxt, &backends)) < 0)
+        goto error;
+
+    if (nbackends != 1) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("only one Crypto backend is supported"));
+        goto error;
+    }
+
+    if (!(backend = virXMLPropString(backends[0], "type"))) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("missing Crypto device backend type"));
+        goto error;
+    }
+
+    if ((def->backend = virDomainCryptoBackendTypeFromString(backend)) < 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("unknown Crypto backend model '%s'"), backend);
+        goto error;
+    }
+
+    switch ((virDomainCryptoBackend) def->backend) {
+    case VIR_DOMAIN_CRYPTO_BACKEND_BUILTIN:
+        queues = virXMLPropString(backends[0], "queues");
+        if (queues && virStrToLong_ui(queues, NULL, 10, &def->queues) < 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                            _("Malformed 'queues' value '%s'"), queues);
+        }
+        break;
+
+    case VIR_DOMAIN_CRYPTO_BACKEND_LAST:
+        break;
+    }
+
+    if (virDomainDeviceInfoParseXML(node, NULL, &def->info, flags) < 0)
+        goto error;
+
+cleanup:
+    VIR_FREE(model);
+    VIR_FREE(backend);
+    VIR_FREE(queues);
+    VIR_FREE(backends);
+    ctxt->node = save;
+    return def;
+
+error:
+    virDomainCryptoDefFree(def);
+    def = NULL;
+    goto cleanup;
+}
+
+
 static virDomainMemballoonDefPtr
 virDomainMemballoonDefParseXML(xmlNodePtr node,
                                xmlXPathContextPtr ctxt,
@@ -13368,6 +13476,10 @@ virDomainDeviceDefParse(const char *xmlStr,
         if (!(dev->data.rng = virDomainRNGDefParseXML(node, ctxt, flags)))
             goto error;
         break;
+    case VIR_DOMAIN_DEVICE_CRYPTO:
+        if (!(dev->data.crypto = virDomainCryptoDefParseXML(node, ctxt, flags)))
+            goto error;
+        break;
     case VIR_DOMAIN_DEVICE_CHR:
         if (!(dev->data.chr = virDomainChrDefParseXML(ctxt,
                                                       node,
@@ -17073,6 +17185,22 @@ virDomainDefParseXML(xmlDocPtr xml,
     }
     VIR_FREE(nodes);
 
+    /* Parse the crypto devices */
+    if ((n = virXPathNodeSet("./devices/crypto", ctxt, &nodes)) < 0)
+        goto error;
+    if (n && VIR_ALLOC_N(def->cryptos, n) < 0)
+        goto error;
+    for (i = 0; i < n; i++) {
+        virDomainCryptoDefPtr crypto = virDomainCryptoDefParseXML(nodes[i],
+                                                         ctxt,
+                                                         flags);
+        if (!crypto)
+            goto error;
+
+        def->cryptos[def->ncryptos++] = crypto;
+    }
+    VIR_FREE(nodes);
+
     /* Parse the TPM devices */
     if ((n = virXPathNodeSet("./devices/tpm", ctxt, &nodes)) < 0)
         goto error;
@@ -18199,6 +18327,25 @@ virDomainRNGDefCheckABIStability(virDomainRNGDefPtr src,
 
 
 static bool
+virDomainCryptoDefCheckABIStability(virDomainCryptoDefPtr src,
+                                    virDomainCryptoDefPtr dst)
+{
+    if (src->model != dst->model) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Target Crypto model '%s' does not match source '%s'"),
+                       virDomainCryptoModelTypeToString(dst->model),
+                       virDomainCryptoModelTypeToString(src->model));
+        return false;
+    }
+
+    if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
+        return false;
+
+    return true;
+}
+
+
+static bool
 virDomainHubDefCheckABIStability(virDomainHubDefPtr src,
                                  virDomainHubDefPtr dst)
 {
@@ -18933,6 +19080,17 @@ virDomainDefCheckABIStability(virDomainDefPtr src,
         if (!virDomainRNGDefCheckABIStability(src->rngs[i], dst->rngs[i]))
             goto error;
 
+    if (src->ncryptos != dst->ncryptos) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Target domain crypto device count %zu "
+                         "does not match source %zu"), dst->ncryptos, src->ncryptos);
+        goto error;
+    }
+
+    for (i = 0; i < src->ncryptos; i++)
+        if (!virDomainCryptoDefCheckABIStability(src->cryptos[i], dst->cryptos[i]))
+            goto error;
+
     if (src->npanics != dst->npanics) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("Target domain panic device count %zu "
@@ -19007,6 +19165,7 @@ virDomainDefCheckABIStability(virDomainDefPtr src,
     case VIR_DOMAIN_DEVICE_NVRAM:
     case VIR_DOMAIN_DEVICE_LAST:
     case VIR_DOMAIN_DEVICE_RNG:
+    case VIR_DOMAIN_DEVICE_CRYPTO:
     case VIR_DOMAIN_DEVICE_TPM:
     case VIR_DOMAIN_DEVICE_PANIC:
     case VIR_DOMAIN_DEVICE_SHMEM:
@@ -21590,6 +21749,51 @@ virDomainRNGDefFree(virDomainRNGDefPtr def)
 
 
 static int
+virDomainCryptoDefFormat(virBufferPtr buf,
+                         virDomainCryptoDefPtr def,
+                         unsigned int flags)
+{
+    const char *model = virDomainCryptoModelTypeToString(def->model);
+    const char *backend = virDomainCryptoBackendTypeToString(def->backend);
+
+    virBufferAsprintf(buf, "<crypto model='%s'>\n", model);
+    virBufferAdjustIndent(buf, 2);
+    virBufferAsprintf(buf, "<backend type='%s'", backend);
+
+    switch ((virDomainCryptoBackend) def->backend) {
+    case VIR_DOMAIN_CRYPTO_BACKEND_BUILTIN:
+        if (def->queues)
+            virBufferAsprintf(buf, " queues='%u'", def->queues);
+
+        virBufferAddLit(buf, "/>\n");
+        break;
+
+    case VIR_DOMAIN_CRYPTO_BACKEND_LAST:
+        break;
+    }
+
+    if (virDomainDeviceInfoNeedsFormat(&def->info, flags)) {
+        if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0)
+            return -1;
+    }
+
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</crypto>\n");
+    return 0;
+}
+
+void
+virDomainCryptoDefFree(virDomainCryptoDefPtr def)
+{
+    if (!def)
+        return;
+
+    virDomainDeviceInfoClear(&def->info);
+    VIR_FREE(def);
+}
+
+
+static int
 virDomainMemorySourceDefFormat(virBufferPtr buf,
                                virDomainMemoryDefPtr def)
 {
@@ -23539,6 +23743,11 @@ virDomainDefFormatInternal(virDomainDefPtr def,
             goto error;
     }
 
+    for (n = 0; n < def->ncryptos; n++) {
+        if (virDomainCryptoDefFormat(buf, def->cryptos[n], flags))
+            goto error;
+    }
+
     if (def->nvram)
         virDomainNVRAMDefFormat(buf, def->nvram, flags);
 
@@ -24657,6 +24866,9 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src,
     case VIR_DOMAIN_DEVICE_RNG:
         rc = virDomainRNGDefFormat(&buf, src->data.rng, flags);
         break;
+    case VIR_DOMAIN_DEVICE_CRYPTO:
+        rc = virDomainCryptoDefFormat(&buf, src->data.crypto, flags);
+        break;
     case VIR_DOMAIN_DEVICE_CHR:
         rc = virDomainChrDefFormat(&buf, src->data.chr, flags);
         break;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index ba0ad5f..995ce8f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -127,6 +127,9 @@ typedef virDomainSnapshotObjList *virDomainSnapshotObjListPtr;
 typedef struct _virDomainRNGDef virDomainRNGDef;
 typedef virDomainRNGDef *virDomainRNGDefPtr;
 
+typedef struct _virDomainCryptoDef virDomainCryptoDef;
+typedef virDomainCryptoDef *virDomainCryptoDefPtr;
+
 typedef struct _virDomainIdMapEntry virDomainIdMapEntry;
 typedef virDomainIdMapEntry *virDomainIdMapEntryPtr;
 
@@ -172,6 +175,7 @@ typedef enum {
     VIR_DOMAIN_DEVICE_MEMBALLOON,
     VIR_DOMAIN_DEVICE_NVRAM,
     VIR_DOMAIN_DEVICE_RNG,
+    VIR_DOMAIN_DEVICE_CRYPTO,
     VIR_DOMAIN_DEVICE_SHMEM,
     VIR_DOMAIN_DEVICE_TPM,
     VIR_DOMAIN_DEVICE_PANIC,
@@ -203,6 +207,7 @@ struct _virDomainDeviceDef {
         virDomainMemballoonDefPtr memballoon;
         virDomainNVRAMDefPtr nvram;
         virDomainRNGDefPtr rng;
+        virDomainCryptoDefPtr crypto;
         virDomainShmemDefPtr shmem;
         virDomainTPMDefPtr tpm;
         virDomainPanicDefPtr panic;
@@ -1927,6 +1932,26 @@ struct _virDomainRNGDef {
 };
 
 typedef enum {
+    VIR_DOMAIN_CRYPTO_MODEL_VIRTIO,
+
+    VIR_DOMAIN_CRYPTO_MODEL_LAST
+} virDomainCryptoModel;
+
+typedef enum {
+    VIR_DOMAIN_CRYPTO_BACKEND_BUILTIN,
+
+    VIR_DOMAIN_CRYPTO_BACKEND_LAST
+} virDomainCryptoBackend;
+
+struct _virDomainCryptoDef {
+    int model;
+    int backend;
+    unsigned int queues; /* Multiqueue virtio-crypto */
+
+    virDomainDeviceInfo info;
+};
+
+typedef enum {
     VIR_DOMAIN_MEMORY_MODEL_NONE,
     VIR_DOMAIN_MEMORY_MODEL_DIMM, /* dimm hotpluggable memory device */
 
@@ -2218,6 +2243,9 @@ struct _virDomainDef {
     size_t nrngs;
     virDomainRNGDefPtr *rngs;
 
+    size_t ncryptos;
+    virDomainCryptoDefPtr *cryptos;
+
     size_t nshmems;
     virDomainShmemDefPtr *shmems;
 
@@ -2696,6 +2724,8 @@ int virDomainDefCompatibleDevice(virDomainDefPtr def,
 
 void virDomainRNGDefFree(virDomainRNGDefPtr def);
 
+void virDomainCryptoDefFree(virDomainCryptoDefPtr def);
+
 int virDomainDiskIndexByAddress(virDomainDefPtr def,
                                 virPCIDeviceAddressPtr pci_controller,
                                 unsigned int bus, unsigned int target,
@@ -2996,6 +3026,8 @@ VIR_ENUM_DECL(virDomainHyperv)
 VIR_ENUM_DECL(virDomainKVM)
 VIR_ENUM_DECL(virDomainRNGModel)
 VIR_ENUM_DECL(virDomainRNGBackend)
+VIR_ENUM_DECL(virDomainCryptoModel)
+VIR_ENUM_DECL(virDomainCryptoBackend)
 VIR_ENUM_DECL(virDomainTPMModel)
 VIR_ENUM_DECL(virDomainTPMBackend)
 VIR_ENUM_DECL(virDomainMemoryModel)
diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c
index d624071..25b87d2 100644
--- a/src/qemu/qemu_alias.c
+++ b/src/qemu/qemu_alias.c
@@ -331,6 +331,26 @@ qemuAssignDeviceRNGAlias(virDomainDefPtr def,
 
 
 int
+qemuAssignDeviceCryptoAlias(const virDomainDef *def,
+                            virDomainCryptoDefPtr crypto)
+{
+    size_t i;
+    int maxidx = 0;
+    int idx;
+
+    for (i = 0; i < def->ncryptos; i++) {
+        if ((idx = qemuDomainDeviceAliasIndex(&def->cryptos[i]->info, "crypto")) >= maxidx)
+            maxidx = idx + 1;
+    }
+
+    if (virAsprintf(&crypto->info.alias, "crypto%d", maxidx) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+int
 qemuAssignDeviceMemoryAlias(virDomainDefPtr def,
                             virDomainMemoryDefPtr mem)
 {
diff --git a/src/qemu/qemu_alias.h b/src/qemu/qemu_alias.h
index e328a9b..4ae1c92 100644
--- a/src/qemu/qemu_alias.h
+++ b/src/qemu/qemu_alias.h
@@ -57,6 +57,10 @@ int qemuAssignDeviceRedirdevAlias(virDomainDefPtr def,
 int qemuAssignDeviceRNGAlias(virDomainDefPtr def,
                              virDomainRNGDefPtr rng);
 
+int
+qemuAssignDeviceCryptoAlias(const virDomainDef *def,
+                            virDomainCryptoDefPtr crypto);
+
 int qemuAssignDeviceMemoryAlias(virDomainDefPtr def,
                                 virDomainMemoryDefPtr mems);
 
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 2c0b29d..b1b718b 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -337,6 +337,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
               "drive-detect-zeroes",
 
               "tls-creds-x509", /* 230 */
+              "cryptodev-backend-builtin",
+              "virtio-crypto",
     );
 
 
@@ -1565,6 +1567,8 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
     { "pxb", QEMU_CAPS_DEVICE_PXB },
     { "pxb-pcie", QEMU_CAPS_DEVICE_PXB_PCIE },
     { "tls-creds-x509", QEMU_CAPS_OBJECT_TLS_CREDS_X509 },
+    { "cryptodev-backend-builtin", QEMU_CAPS_OBJECT_CRYPTO_BUILTIN },
+    { "virtio-crypto-device", QEMU_CAPS_DEVICE_VIRTIO_CRYPTO },
 };
 
 static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBalloon[] = {
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index affb639..98cb817 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -370,6 +370,8 @@ typedef enum {
 
     /* 230 */
     QEMU_CAPS_OBJECT_TLS_CREDS_X509, /* -object tls-creds-x509 */
+    QEMU_CAPS_OBJECT_CRYPTO_BUILTIN,
+    QEMU_CAPS_DEVICE_VIRTIO_CRYPTO,
 
     QEMU_CAPS_LAST /* this must always be the last item */
 } virQEMUCapsFlags;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 3898ed7..8cf1258 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5451,6 +5451,132 @@ qemuBuildRNGCommandLine(virLogManagerPtr logManager,
 }
 
 
+static char *
+qemuBuildCryptoBackendStr(virDomainCryptoDefPtr crypto,
+                          virQEMUCapsPtr qemuCaps)
+{
+    const char *type = NULL;
+    char *alias = NULL;
+    char *queue = NULL;
+    char *ret = NULL;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    if (virAsprintf(&alias, "obj%s", crypto->info.alias) < 0)
+        goto cleanup;
+
+    if (crypto->queues > 1) {
+        if (virAsprintf(&queue, ",queues=%u", crypto->queues) < 0)
+            goto cleanup;
+    }
+
+    switch ((virDomainCryptoBackend)crypto->backend) {
+    case VIR_DOMAIN_CRYPTO_BACKEND_BUILTIN:
+        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_CRYPTO_BUILTIN)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("this qemu doesn't support the crypto-backend"
+                             "-builtin"));
+            goto cleanup;
+        }
+
+        type = "cryptodev-backend-builtin";
+        break;
+
+    case VIR_DOMAIN_CRYPTO_BACKEND_LAST:
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("unknown crypto backend"));
+        goto cleanup;
+    }
+
+    virBufferAsprintf(&buf, "%s,id=%s%s", type, alias, queue);
+
+    ret = virBufferContentAndReset(&buf);
+
+cleanup:
+    VIR_FREE(alias);
+    return ret;
+}
+
+
+char *
+qemuBuildCryptoDevStr(const virDomainDef *def,
+                      virDomainCryptoDefPtr dev,
+                      virQEMUCapsPtr qemuCaps)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    if (dev->model != VIR_DOMAIN_CRYPTO_MODEL_VIRTIO ||
+        !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_CRYPTO)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("this qemu doesn't support crypto device model '%s'"),
+                       virDomainRNGModelTypeToString(dev->model));
+        goto error;
+    }
+
+    if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("this qemu only support crypto device PCI address type"));
+        goto error;
+    }
+
+    virBufferAsprintf(&buf, "virtio-crypto-pci,cryptodev=obj%s,id=%s",
+                      dev->info.alias, dev->info.alias);
+
+    if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
+        goto error;
+
+    if (virBufferCheckError(&buf) < 0)
+        goto error;
+
+    return virBufferContentAndReset(&buf);
+
+error:
+    virBufferFreeAndReset(&buf);
+    return NULL;
+}
+
+
+static int
+qemuBuildCryptoCommandLine(virCommandPtr cmd,
+                           const virDomainDef *def,
+                           virQEMUCapsPtr qemuCaps)
+{
+    size_t i;
+
+    for (i = 0; i < def->ncryptos; i++) {
+        virDomainCryptoDefPtr crypto = def->cryptos[i];
+        char *tmp;
+
+        if (qemuAssignDeviceCryptoAlias(def, crypto)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("crypto device assign alias faile"));
+            return -1;
+        }
+
+        if (!crypto->info.alias) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("crypto device is missing alias"));
+            return -1;
+        }
+
+        /* add the Crypto backend */
+        if (!(tmp = qemuBuildCryptoBackendStr(crypto, qemuCaps)))
+            return -1;
+
+        virCommandAddArgList(cmd, "-object", tmp, NULL);
+        VIR_FREE(tmp);
+
+        /* add the device */
+        if (!(tmp = qemuBuildCryptoDevStr(def, crypto, qemuCaps)))
+            return -1;
+
+        virCommandAddArgList(cmd, "-device", tmp, NULL);
+        VIR_FREE(tmp);
+    }
+
+    return 0;
+}
+
+
 static char *qemuBuildSmbiosBiosStr(virSysinfoBIOSDefPtr def)
 {
     virBuffer buf = VIR_BUFFER_INITIALIZER;
@@ -9312,6 +9438,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
     if (qemuBuildRNGCommandLine(logManager, cmd, cfg, def, qemuCaps) < 0)
         goto error;
 
+    if (qemuBuildCryptoCommandLine(cmd, def, qemuCaps) < 0)
+        goto error;
+
     if (qemuBuildNVRAMCommandLine(cmd, def, qemuCaps) < 0)
         goto error;
 
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index c4d0567..ec9b3ac 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -143,6 +143,10 @@ int qemuBuildRNGBackendProps(virDomainRNGDefPtr rng,
                              const char **type,
                              virJSONValuePtr *props);
 
+char *qemuBuildCryptoDevStr(const virDomainDef *def,
+                            virDomainCryptoDefPtr dev,
+                            virQEMUCapsPtr qemuCaps);
+
 char *qemuBuildShmemDevStr(virDomainDefPtr def,
                            virDomainShmemDefPtr shmem,
                            virQEMUCapsPtr qemuCaps);
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index ee44d45..26e6caa 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -328,6 +328,12 @@ qemuDomainPrimeVirtioDeviceAddresses(virDomainDefPtr def,
             def->rngs[i]->info.type = type;
     }
 
+    for (i = 0; i < def->ncryptos; i++) {
+        if (def->cryptos[i]->model == VIR_DOMAIN_CRYPTO_MODEL_VIRTIO &&
+            def->cryptos[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+            def->cryptos[i]->info.type = type;
+    }
+
     if (type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
         for (i = 0; i < def->nfss; i++) {
             if (def->fss[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
@@ -1236,6 +1242,17 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def,
             goto error;
     }
 
+    /* VirtIO CRYPTO */
+    for (i = 0; i < def->ncryptos; i++) {
+        if (def->cryptos[i]->model != VIR_DOMAIN_CRYPTO_MODEL_VIRTIO ||
+            !virDeviceInfoPCIAddressWanted(&def->cryptos[i]->info))
+            continue;
+
+        if (virDomainPCIAddressReserveNextSlot(addrs,
+                                               &def->cryptos[i]->info, flags) < 0)
+            goto error;
+    }
+
     /* A watchdog - check if it is a PCI device */
     if (def->watchdog &&
         def->watchdog->model == VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB &&
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 2089359..a28a3c2 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7431,6 +7431,7 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
     case VIR_DOMAIN_DEVICE_SHMEM:
     case VIR_DOMAIN_DEVICE_TPM:
     case VIR_DOMAIN_DEVICE_PANIC:
+    case VIR_DOMAIN_DEVICE_CRYPTO:
     case VIR_DOMAIN_DEVICE_LAST:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("live attach of device '%s' is not supported"),
@@ -7522,6 +7523,7 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
     case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_TPM:
     case VIR_DOMAIN_DEVICE_PANIC:
+    case VIR_DOMAIN_DEVICE_CRYPTO:
     case VIR_DOMAIN_DEVICE_LAST:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("live detach of device '%s' is not supported"),
@@ -7637,6 +7639,7 @@ qemuDomainUpdateDeviceLive(virConnectPtr conn,
     case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_TPM:
     case VIR_DOMAIN_DEVICE_PANIC:
+    case VIR_DOMAIN_DEVICE_CRYPTO:
     case VIR_DOMAIN_DEVICE_LAST:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("live update of device '%s' is not supported"),
@@ -7800,6 +7803,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
     case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_TPM:
     case VIR_DOMAIN_DEVICE_PANIC:
+    case VIR_DOMAIN_DEVICE_CRYPTO:
     case VIR_DOMAIN_DEVICE_LAST:
          virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                         _("persistent attach of device '%s' is not supported"),
@@ -7954,6 +7958,7 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
     case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_TPM:
     case VIR_DOMAIN_DEVICE_PANIC:
+    case VIR_DOMAIN_DEVICE_CRYPTO:
     case VIR_DOMAIN_DEVICE_LAST:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("persistent detach of device '%s' is not supported"),
@@ -8052,6 +8057,7 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
     case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_TPM:
     case VIR_DOMAIN_DEVICE_PANIC:
+    case VIR_DOMAIN_DEVICE_CRYPTO:
     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 093aaf9..c1cfb76 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -3301,6 +3301,7 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver,
     case VIR_DOMAIN_DEVICE_TPM:
     case VIR_DOMAIN_DEVICE_PANIC:
     case VIR_DOMAIN_DEVICE_LAST:
+    case VIR_DOMAIN_DEVICE_CRYPTO:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("don't know how to remove a %s device"),
                        virDomainDeviceTypeToString(dev->type));
-- 
1.8.3.1





More information about the libvir-list mailing list