- Add ARM CCA support in domain capabilies XML schema.
[Capability example]
- Execution results of 'virsh domcapability" on qemu
<domaincapabilities>
...
<features>
...
</sgx>
<cca supported='yes'>
<enum name='measurement-algo'>
<value>sha256</value>
<value>sha512</value>
</enum>
</cca>
<hyperv supported='yes'>
...
</features>
</domaincapabilities>
Signed-off-by: Akio Kakuno <fj3333bs(a)fujitsu.com>
---
docs/formatdomaincaps.rst | 27 +++++++++-
src/conf/domain_capabilities.c | 48 +++++++++++++++++
src/conf/domain_capabilities.h | 6 +++
src/libvirt_private.syms | 1 +
src/qemu/qemu_capabilities.c | 28 ++++++++++
src/qemu/qemu_monitor.c | 10 ++++
src/qemu/qemu_monitor.h | 3 ++
src/qemu/qemu_monitor_json.c | 98 ++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 4 ++
9 files changed, 224 insertions(+), 1 deletion(-)
diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst
index ed95af4fee..fbf7db12e6 100644
--- a/docs/formatdomaincaps.rst
+++ b/docs/formatdomaincaps.rst
@@ -734,6 +734,12 @@ capabilities. All features occur as children of the main ``features``
element.
<section node='1' size='262144' unit='KiB'/>
</sections>
</sgx>
+ <cca supported='yes'>
+ <enum name='measurement-algo'>
+ <value>sha256</value>
+ <value>sha512</value>
+ </enum>
+ </cca>
<hyperv supported='yes'>
<enum name='features'>
<value>relaxed</value>
@@ -861,6 +867,24 @@ document store. In order to use SGX with libvirt have a look at `SGX
in domain X
``sections``
The sections of the SGX enclave page cache (called EPC).
+CCA capabilities
+^^^^^^^^^^^^^^^^
+
+Arm Confidential Compute Architecture (CCA) capabilities are exposed under the
+``cca`` element.
+
+Arm CCA is a system solution comprised of hardware and software components that
+maximizes the security of data on devices and in the cloud.
+CCA enhances the virtualization capabilities of the platform by separating the
+management of resources from access to those resources.
+
+For more details on the CCA feature, please follow resources in the CCA developer's
+document store. In order to use CCA with libvirt have a look at `CCA in domain
+XML <formatdomain.html#launch-security>`__
+
+``measurement-algo``
+ Options for the ``measurement-algo`` used to describe blob hashes.
+
Hyper-V Enlightenments
^^^^^^^^^^^^^^^^^^^^^^
@@ -882,4 +906,5 @@ The ``sectype`` enum corresponds to ``type`` attribute of
``<launchSecurity/>``
element as documented in `Launch Security
<formatdomain.html#launch-security>`__. :since:`(Since 10.5.0)` For additional
information on individual types, see sections above: `s390-pv capability`_ for
-S390 PV, `SEV capabilities`_ for AMD SEV and/or AMD SEV-SNP.
+S390 PV, `SEV capabilities`_ for AMD SEV and/or AMD SEV-SNP, `CCA capabilities`_
+for Arm CCA.
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index ab715b19d8..cae6730061 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -90,6 +90,25 @@ virSGXCapabilitiesFree(virSGXCapability *cap)
}
+void
+virCCACapabilitiesFree(virCCACapability *cap)
+{
+ size_t i;
+
+ if (!cap)
+ return;
+
+ if (cap->nCcaMeasurementAlgo)
+ for (i = 0; i < cap->nCcaMeasurementAlgo; i++)
+ g_free(cap->ccaMeasurementAlgo[i]);
+
+ if (cap->ccaMeasurementAlgo)
+ g_free(cap->ccaMeasurementAlgo);
+
+ g_free(cap);
+}
+
+
static void
virDomainCapsDispose(void *obj)
{
@@ -103,6 +122,7 @@ virDomainCapsDispose(void *obj)
virCPUDefFree(caps->cpu.hostModel);
virSEVCapabilitiesFree(caps->sev);
virSGXCapabilitiesFree(caps->sgx);
+ virCCACapabilitiesFree(caps->cca);
g_free(caps->hyperv);
values = &caps->os.loader.values;
@@ -774,6 +794,33 @@ virDomainCapsFeatureSGXFormat(virBuffer *buf,
virBufferAddLit(buf, "</sgx>\n");
}
+static void
+virDomainCapsFeatureCCAFormat(virBuffer *buf,
+ const virCCACapability *cca)
+{
+ size_t i;
+
+ if (!cca) {
+ virBufferAddLit(buf, "<cca supported='no'/>\n");
+ return;
+ }
+
+ virBufferAddLit(buf, "<cca supported='yes'>\n");
+ virBufferAdjustIndent(buf, 2);
+
+ virBufferAddLit(buf, "<enum name='measurement-algo'>\n");
+ virBufferAdjustIndent(buf, 2);
+ for (i = 0; i < cca->nCcaMeasurementAlgo; i++) {
+ virBufferAsprintf(buf, "<value>%s</value>\n",
+ cca->ccaMeasurementAlgo[i]);
+ }
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</enum>\n");
+
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</cca>\n");
+}
+
static void
virDomainCapsFeatureHypervFormat(virBuffer *buf,
const virDomainCapsFeatureHyperv *hyperv)
@@ -821,6 +868,7 @@ virDomainCapsFormatFeatures(const virDomainCaps *caps,
virDomainCapsFeatureSEVFormat(&childBuf, caps->sev);
virDomainCapsFeatureSGXFormat(&childBuf, caps->sgx);
+ virDomainCapsFeatureCCAFormat(&childBuf, caps->cca);
virDomainCapsFeatureHypervFormat(&childBuf, caps->hyperv);
virDomainCapsLaunchSecurityFormat(&childBuf, &caps->launchSecurity);
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index 93e2cc2931..b55f860e7b 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -315,6 +315,7 @@ struct _virDomainCaps {
virDomainCapsFeatureGIC gic;
virSEVCapability *sev;
virSGXCapability *sgx;
+ virCCACapability *cca;
virDomainCapsFeatureHyperv *hyperv;
virDomainCapsLaunchSecurity launchSecurity;
/* add new domain features here */
@@ -375,3 +376,8 @@ void
virSGXCapabilitiesFree(virSGXCapability *capabilities);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virSGXCapability, virSGXCapabilitiesFree);
+
+void
+virCCACapabilitiesFree(virCCACapability *capabilities);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCCACapability, virCCACapabilitiesFree);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 33b93cbd3e..bf525c50d9 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -208,6 +208,7 @@ virDomainAuditVcpu;
# conf/domain_capabilities.h
+virCCACapabilitiesFree;
virDomainCapsCPUModelsAdd;
virDomainCapsCPUModelsCopy;
virDomainCapsCPUModelsGet;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index b0283c0119..4534f18a24 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -3651,6 +3651,32 @@ virQEMUCapsProbeQMPSGXCapabilities(virQEMUCaps *qemuCaps,
}
+static int
+virQEMUCapsProbeQMPCCACapabilities(virQEMUCaps *qemuCaps,
+ qemuMonitor *mon)
+{
+ int rc = -1;
+ virCCACapability *caps = NULL;
+
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CCA_GUEST))
+ return 0;
+
+ if ((rc = qemuMonitorGetCCACapabilities(mon, &caps)) < 0)
+ return -1;
+
+ /* CCA isn't actually supported */
+ if (rc == 0) {
+ virQEMUCapsClear(qemuCaps, QEMU_CAPS_CCA_GUEST);
+ return 0;
+ }
+
+ virCCACapabilitiesFree(qemuCaps->ccaCapabilities);
+ qemuCaps->ccaCapabilities = caps;
+ return 0;
+}
+
+
+
/*
* Filter for features which should never be passed to QEMU. Either because
* QEMU never supported them or they were dropped as they never did anything
@@ -5757,6 +5783,8 @@ virQEMUCapsInitQMPMonitor(virQEMUCaps *qemuCaps,
return -1;
if (virQEMUCapsProbeQMPSGXCapabilities(qemuCaps, mon) < 0)
return -1;
+ if (virQEMUCapsProbeQMPCCACapabilities(qemuCaps, mon) < 0)
+ return -1;
virQEMUCapsInitProcessCaps(qemuCaps);
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index ec2f166785..53908d8bf8 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3483,6 +3483,16 @@ qemuMonitorGetSGXCapabilities(qemuMonitor *mon,
}
+int
+qemuMonitorGetCCACapabilities(qemuMonitor *mon,
+ virCCACapability **capabilities)
+{
+ QEMU_CHECK_MONITOR(mon);
+
+ return qemuMonitorJSONGetCCACapabilities(mon, capabilities);
+}
+
+
int
qemuMonitorNBDServerStart(qemuMonitor *mon,
const virStorageNetHostDef *server,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index c74892c4dc..8a37376f97 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -846,6 +846,9 @@ int qemuMonitorGetSEVCapabilities(qemuMonitor *mon,
int qemuMonitorGetSGXCapabilities(qemuMonitor *mon,
virSGXCapability **capabilities);
+int qemuMonitorGetCCACapabilities(qemuMonitor *mon,
+ virCCACapability **capabilities);
+
typedef enum {
QEMU_MONITOR_MIGRATE_RESUME = 1 << 0, /* resume failed post-copy
migration */
QEMU_MONITOR_MIGRATION_FLAGS_LAST
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 9f417d27c6..ebe5f87d36 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -6213,6 +6213,104 @@ qemuMonitorJSONGetSGXCapabilities(qemuMonitor *mon,
}
+static int
+qemuMonitorJSONGetCCAMeasurementAlgo(qemuMonitor *mon,
+ size_t *numalgo,
+ char ***malgo)
+{
+ g_autoptr(virJSONValue) cmd = NULL;
+ g_autoptr(virJSONValue) reply = NULL;
+ virJSONValue *caps;
+ virJSONValue *malgolist = NULL;
+ g_auto(GStrv) list = NULL;
+ size_t i;
+ size_t n = 0;
+
+ if (!(cmd = qemuMonitorJSONMakeCommand("query-cca-capabilities",
+ NULL)))
+ return -1;
+
+ if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+ return -1;
+
+ /* If the 'query-cca-capabilities' QMP command was not available
+ * we simply successfully return zero capabilities.
+ * This is the current QEMU (=9.1.91) and all non-ARM architectures */
+ if (qemuMonitorJSONHasError(reply, "CommandNotFound"))
+ return 0;
+
+ if (qemuMonitorJSONCheckError(cmd, reply) < 0)
+ return -1;
+
+ caps = virJSONValueObjectGetObject(reply, "return");
+
+ if (!(caps = qemuMonitorJSONGetReply(cmd, reply, VIR_JSON_TYPE_OBJECT)))
+ return -1;
+
+ if ((malgolist = virJSONValueObjectGetArray(caps, "sections"))) {
+ n = virJSONValueArraySize(malgolist);
+
+ /* If the received array is empty, an error is returned. */
+ if (n == 0)
+ return -1;
+
+ list = g_new0(char *, n + 1);
+
+ for (i = 0; i < n; i++) {
+ virJSONValue *cap = virJSONValueArrayGet(malgolist, i);
+ const char *measurement_algo = NULL;
+
+ if (!cap || virJSONValueGetType(cap) != VIR_JSON_TYPE_OBJECT) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing entry in CCA capabilities list"));
+ return -1;
+ }
+
+ if (!(measurement_algo = virJSONValueObjectGetString(cap,
"measurement-algo"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("query-cca-capabilities reply was missing
'measurement-algo' field"));
+ return -1;
+ }
+
+ list[i] = g_strdup(measurement_algo);
+ }
+ }
+
+ *numalgo = n;
+ *malgo = g_steal_pointer(&list);
+ return 1;
+}
+
+
+/**
+ * qemuMonitorJSONGetCCACapabilities:
+ * @mon: qemu monitor object
+ * @capabilities: pointer to pointer to a CCA capability structure to be filled
+ *
+ * Returns -1 on error, 0 if CCA is not supported, and 1 if CCA is supported on
+ * the platform.
+ */
+int
+qemuMonitorJSONGetCCACapabilities(qemuMonitor *mon,
+ virCCACapability **capabilities)
+{
+ g_autoptr(virCCACapability) capability = NULL;
+ int ret = 0;
+
+ *capabilities = NULL;
+ capability = g_new0(virCCACapability, 1);
+
+ ret = qemuMonitorJSONGetCCAMeasurementAlgo(mon,
+ &capability->nCcaMeasurementAlgo,
+ &capability->ccaMeasurementAlgo);
+
+ if (ret > 0)
+ *capabilities = g_steal_pointer(&capability);
+
+ return ret;
+}
+
+
static virJSONValue *
qemuMonitorJSONBuildInetSocketAddress(const char *host,
const char *port)
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 2f5a021f56..d422e84e88 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -168,6 +168,10 @@ int
qemuMonitorJSONGetSEVCapabilities(qemuMonitor *mon,
virSEVCapability **capabilities);
+int
+qemuMonitorJSONGetCCACapabilities(qemuMonitor *mon,
+ virCCACapability **capabilities);
+
int
qemuMonitorJSONMigrate(qemuMonitor *mon,
unsigned int flags,
--
2.34.1