[RFC PATCH v2 2/6] src: Add ARM CCA support in domain capabilities command

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



- 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@xxxxxxxxxxx>
---
 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



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux