[libvirt] [PATCH v2 3/4] qemu: Implement support for 'builtin' backend for virtio-crypto

Longpeng(Mike) longpeng2 at huawei.com
Wed Jan 11 08:28:25 UTC 2017


This patch implements support for the virtio-crypto-pci device
and the builtin backend in qemu.

Two capabilities bits are added to track support for those:

QEMU_CAPS_DEVICE_VIRTIO_CRYPTO - for the device support and
QEMU_CAPS_OBJECT_CRYPTO_BUILTIN - for the backend support.

qemu is invoked with these additional parameters if the device
id enabled:

(to add the backend)
-object cryptodev-backend-builtin,id=objcrypto0,queues=1
(to add the device)
-device virtio-crypto-pci,cryptodev=objcrypto0,id=crypto0

Signed-off-by: Longpeng(Mike) <longpeng2 at huawei.com>
---
 src/conf/domain_conf.c         |   4 +-
 src/qemu/qemu_alias.c          |  20 +++++++
 src/qemu/qemu_alias.h          |   3 +
 src/qemu/qemu_capabilities.c   |   4 ++
 src/qemu/qemu_capabilities.h   |   2 +
 src/qemu/qemu_command.c        | 132 +++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_command.h        |   3 +
 src/qemu/qemu_domain_address.c |  26 +++++++-
 8 files changed, 191 insertions(+), 3 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index ef44930..cf77af5 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -12595,7 +12595,7 @@ virDomainCryptoDefParseXML(xmlNodePtr node,
     if (virDomainDeviceInfoParseXML(node, NULL, &def->info, flags) < 0)
         goto error;
 
-cleanup:
+ cleanup:
     VIR_FREE(model);
     VIR_FREE(backend);
     VIR_FREE(queues);
@@ -12603,7 +12603,7 @@ cleanup:
     ctxt->node = save;
     return def;
 
-error:
+ error:
     virDomainCryptoDefFree(def);
     def = NULL;
     goto cleanup;
diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c
index 8521a44..00e5521 100644
--- a/src/qemu/qemu_alias.c
+++ b/src/qemu/qemu_alias.c
@@ -332,6 +332,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;
+}
+
+
 /**
  * qemuAssignDeviceMemoryAlias:
  * @def: domain definition. Necessary only if @oldAlias is true.
diff --git a/src/qemu/qemu_alias.h b/src/qemu/qemu_alias.h
index dea05cf..8588ed1 100644
--- a/src/qemu/qemu_alias.h
+++ b/src/qemu/qemu_alias.h
@@ -57,6 +57,9 @@ int qemuAssignDeviceRedirdevAlias(virDomainDefPtr def,
 int qemuAssignDeviceRNGAlias(virDomainDefPtr def,
                              virDomainRNGDefPtr rng);
 
+int qemuAssignDeviceCryptoAlias(const virDomainDef *def,
+                                virDomainCryptoDefPtr crypto);
+
 int qemuAssignDeviceMemoryAlias(virDomainDefPtr def,
                                 virDomainMemoryDefPtr mems,
                                 bool oldAlias);
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 2512e48..880c4e2 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -356,6 +356,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
               "drive-iotune-group",
 
               "query-cpu-model-expansion", /* 245 */
+              "cryptodev-backend-builtin",
+              "virtio-crypto",
     );
 
 
@@ -1623,6 +1625,8 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
     { "ivshmem-plain", QEMU_CAPS_DEVICE_IVSHMEM_PLAIN },
     { "ivshmem-doorbell", QEMU_CAPS_DEVICE_IVSHMEM_DOORBELL },
     { "vhost-scsi", QEMU_CAPS_DEVICE_VHOST_SCSI },
+    { "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 b5ad95e..81deb2b 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -392,6 +392,8 @@ typedef enum {
 
     /* 245 */
     QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION, /* qmp query-cpu-model-expansion */
+    QEMU_CAPS_OBJECT_CRYPTO_BUILTIN, /* -object cryptodev-backend-builtin */
+    QEMU_CAPS_DEVICE_VIRTIO_CRYPTO, /* -device virtio-crypto-pci */
 
     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 d459f8e..afebe69 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5787,6 +5787,135 @@ 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 > 0) {
+        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 builtin backend"));
+            goto cleanup;
+        }
+
+        type = "cryptodev-backend-builtin";
+        break;
+
+    case VIR_DOMAIN_CRYPTO_BACKEND_LAST:
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("unknown crypto backend"));
+        goto cleanup;
+    }
+
+    if (queue)
+        virBufferAsprintf(&buf, "%s,id=%s,%s", type, alias, queue);
+    else
+        virBufferAsprintf(&buf, "%s,id=%s", type, alias);
+
+    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,
+                       _("unsupported address type %s for virtio crypto device"),
+                       virDomainDeviceAddressTypeToString(dev->info.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;
@@ -9793,6 +9922,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 3bcfdc6..9b49ccd 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -201,6 +201,9 @@ char *qemuBuildShmemDevStr(virDomainDefPtr def,
                            virQEMUCapsPtr qemuCaps)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
 
+char *qemuBuildCryptoDevStr(const virDomainDef *def,
+                            virDomainCryptoDefPtr dev,
+                            virQEMUCapsPtr qemuCaps);
 
 
 #endif /* __QEMU_COMMAND_H__*/
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index e17476a..62bbd1c 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -331,6 +331,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)
@@ -727,6 +733,15 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev,
             return 0;
         }
 
+    case VIR_DOMAIN_DEVICE_CRYPTO:
+        switch ((virDomainCryptoModel) dev->data.crypto->model) {
+        case VIR_DOMAIN_CRYPTO_MODEL_VIRTIO:
+            return virtioFlags;
+
+        case VIR_DOMAIN_RNG_MODEL_LAST:
+            return 0;
+        }
+
     case VIR_DOMAIN_DEVICE_VIDEO:
         switch ((virDomainVideoType) dev->data.video->type) {
         case VIR_DOMAIN_VIDEO_TYPE_VIRTIO:
@@ -784,7 +799,6 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev,
     case VIR_DOMAIN_DEVICE_LEASE:
     case VIR_DOMAIN_DEVICE_GRAPHICS:
     case VIR_DOMAIN_DEVICE_IOMMU:
-    case VIR_DOMAIN_DEVICE_CRYPTO:
     case VIR_DOMAIN_DEVICE_LAST:
     case VIR_DOMAIN_DEVICE_NONE:
         return 0;
@@ -1770,6 +1784,16 @@ 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 (qemuDomainPCIAddressReserveNextSlot(addrs, &def->cryptos[i]->info) < 0)
+            goto error;
+    }
+
     /* A watchdog - check if it is a PCI device */
     if (def->watchdog &&
         def->watchdog->model == VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB &&
-- 
1.8.3.1





More information about the libvir-list mailing list