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(a)huawei.com>
---
src/qemu/qemu_alias.c | 20 +++++++
src/qemu/qemu_alias.h | 3 +
src/qemu/qemu_capabilities.c | 6 ++
src/qemu/qemu_capabilities.h | 4 ++
src/qemu/qemu_command.c | 126 +++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_command.h | 3 +
src/qemu/qemu_domain_address.c | 26 ++++++++-
7 files changed, 187 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c
index 914b2b9..2b6e049 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 300fd4d..fe59928 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 61c9a10..01005d5 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -430,6 +430,10 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
"virtio.iommu_platform",
"virtio.ats",
"loadparm",
+ "cryptodev-backend-builtin",
+
+ /* 265 */
+ "virtio-crypto",
);
@@ -1679,6 +1683,8 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
{ "nvdimm", QEMU_CAPS_DEVICE_NVDIMM },
{ "pcie-root-port", QEMU_CAPS_DEVICE_PCIE_ROOT_PORT },
{ "qemu-xhci", QEMU_CAPS_DEVICE_QEMU_XHCI },
+ { "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 6e95876..50bb7a5 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -416,6 +416,10 @@ typedef enum {
QEMU_CAPS_VIRTIO_PCI_IOMMU_PLATFORM, /* virtio-*-pci.iommu_platform */
QEMU_CAPS_VIRTIO_PCI_ATS, /* virtio-*-pci.ats */
QEMU_CAPS_LOADPARM, /* -machine loadparm */
+ QEMU_CAPS_OBJECT_CRYPTO_BUILTIN, /* -object cryptodev-backend-builtin */
+
+ /* 265 */
+ 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 c53ab97..5278edc 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5992,6 +5992,129 @@ qemuBuildRNGCommandLine(virLogManagerPtr logManager,
static char *
+qemuBuildCryptoBackendStr(virDomainCryptoDefPtr crypto,
+ virQEMUCapsPtr qemuCaps)
+{
+ const char *type = NULL;
+ char *alias = NULL;
+ char *queue = NULL;
+ char *backstr = NULL;
+
+ 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)
+ ignore_value(virAsprintf(&backstr, "%s,id=%s,%s", type, alias,
queue));
+ else
+ ignore_value(virAsprintf(&backstr, "%s,id=%s", type, alias));
+
+ cleanup:
+ VIR_FREE(alias);
+ return backstr;
+}
+
+
+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;
+
+ 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;
@@ -10220,6 +10343,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
chardevStdioLogd) < 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 f5e3e5f..996840d 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -204,6 +204,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 5209fbe..9bd064b 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)
@@ -738,6 +744,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:
@@ -796,7 +811,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;
@@ -1775,6 +1789,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 (qemuDomainPCIAddressReserveNextAddr(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