[libvirt][PATCH v16 2/9] qemu: Get SGX capabilities form QMP

Lin Yang lin.a.yang at intel.com
Sat Oct 8 04:00:26 UTC 2022


From: Haibin Huang <haibin.huang at intel.com>

Generate the QMP command for query-sgx-capabilities and the command
return SGX capabilities from QMP.

{"execute":"query-sgx-capabilities"}

the right reply:
  {"return":
    {
      "sgx": true,
      "section-size": 197132288,
      "flc": true
    }
  }

the error reply:
  {"error":
    {"class": "GenericError", "desc": "SGX is not enabled in KVM"}
  }

Signed-off-by: Haibin Huang <haibin.huang at intel.com>
Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
Signed-off-by: Haibin Huang <haibin.huang at intel.com>
---
 src/qemu/qemu_monitor.c      |  10 ++++
 src/qemu/qemu_monitor.h      |   3 +
 src/qemu/qemu_monitor_json.c | 113 +++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor_json.h |   4 ++
 4 files changed, 130 insertions(+)

diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index c2808c75a3..9068865972 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3418,6 +3418,16 @@ qemuMonitorGetSEVCapabilities(qemuMonitor *mon,
 }
 
 
+int
+qemuMonitorGetSGXCapabilities(qemuMonitor *mon,
+                              virSGXCapability **capabilities)
+{
+    QEMU_CHECK_MONITOR(mon);
+
+    return qemuMonitorJSONGetSGXCapabilities(mon, capabilities);
+}
+
+
 int
 qemuMonitorNBDServerStart(qemuMonitor *mon,
                           const virStorageNetHostDef *server,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 4d770486be..be65fdcfed 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -824,6 +824,9 @@ int qemuMonitorGetGICCapabilities(qemuMonitor *mon,
 int qemuMonitorGetSEVCapabilities(qemuMonitor *mon,
                                   virSEVCapability **capabilities);
 
+int qemuMonitorGetSGXCapabilities(qemuMonitor *mon,
+                                  virSGXCapability **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 b63400354b..32e0c2ff17 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -6027,6 +6027,119 @@ qemuMonitorJSONGetSEVCapabilities(qemuMonitor *mon,
     return 1;
 }
 
+
+/**
+ * qemuMonitorJSONGetSGXCapabilities:
+ * @mon: qemu monitor object
+ * @capabilities: pointer to pointer to a SGX capability structure to be filled
+ *
+ * This function queries and fills in INTEL's SGX platform-specific data.
+ * Note that from QEMU's POV both -object sgx-epc and query-sgx-capabilities
+ * can be present even if SGX is not available, which basically leaves us with
+ * checking for JSON "GenericError" in order to differentiate between compiled-in
+ * support and actual SGX support on the platform.
+ *
+ * Returns: -1 on error,
+ *           0 if SGX is not supported, and
+ *           1 if SGX is supported on the platform.
+ */
+int
+qemuMonitorJSONGetSGXCapabilities(qemuMonitor *mon,
+                                  virSGXCapability **capabilities)
+{
+    g_autoptr(virJSONValue) cmd = NULL;
+    g_autoptr(virJSONValue) reply = NULL;
+    g_autoptr(virSGXCapability) capability = NULL;
+    unsigned long long section_size_sum = 0;
+    virJSONValue *sgxSections = NULL;
+    virJSONValue *caps;
+    size_t i;
+
+    *capabilities = NULL;
+    capability = g_new0(virSGXCapability, 1);
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("query-sgx-capabilities", NULL)))
+        return -1;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        return -1;
+
+    /* QEMU has only compiled-in support of SGX */
+    if (qemuMonitorJSONHasError(reply, "GenericError"))
+        return 0;
+
+    if (qemuMonitorJSONCheckError(cmd, reply) < 0)
+        return -1;
+
+    caps = virJSONValueObjectGetObject(reply, "return");
+
+    if (virJSONValueObjectGetBoolean(caps, "flc", &capability->flc) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("query-sgx-capabilities reply was missing 'flc' field"));
+        return -1;
+    }
+
+    if (virJSONValueObjectGetBoolean(caps, "sgx1", &capability->sgx1) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("query-sgx-capabilities reply was missing 'sgx1' field"));
+        return -1;
+    }
+
+    if (virJSONValueObjectGetBoolean(caps, "sgx2", &capability->sgx2) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("query-sgx-capabilities reply was missing 'sgx2' field"));
+        return -1;
+    }
+
+    if ((sgxSections = virJSONValueObjectGetArray(caps, "sections"))) {
+        /* SGX EPC sections info was added since QEMU 7.0.0 */
+        unsigned long long size;
+
+        capability->nSgxSections = virJSONValueArraySize(sgxSections);
+        capability->sgxSections = g_new0(virSGXSection, capability->nSgxSections);
+
+        for (i = 0; i < capability->nSgxSections; i++) {
+            virJSONValue *elem = virJSONValueArrayGet(sgxSections, i);
+
+            if (virJSONValueObjectGetNumberUlong(elem, "size", &size) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("query-sgx-capabilities reply was missing 'size' field"));
+                return -1;
+            }
+            capability->sgxSections[i].size = size / 1024;
+            section_size_sum += capability->sgxSections[i].size;
+
+            if (virJSONValueObjectGetNumberUint(elem, "node",
+                                               &capability->sgxSections[i].node) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("query-sgx-capabilities reply was missing 'node' field"));
+                return -1;
+            }
+        }
+    } else {
+        /* no support for QEMU version older than 7.0.0 */
+        return 0;
+    }
+
+    if (virJSONValueObjectHasKey(caps, "section-size")) {
+        unsigned long long section_size = 0;
+
+        if (virJSONValueObjectGetNumberUlong(caps, "section-size", &section_size) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("query-sgx-capabilities reply was missing 'section-size' field"));
+            return -1;
+        }
+        capability->section_size = section_size / 1024;
+    } else {
+        /* QEMU no longer reports deprecated attribute. */
+        capability->section_size = section_size_sum;
+    }
+
+    *capabilities = g_steal_pointer(&capability);
+    return 1;
+}
+
+
 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 a53e6423df..09e770f531 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -161,6 +161,10 @@ int
 qemuMonitorJSONGetGICCapabilities(qemuMonitor *mon,
                                   virGICCapability **capabilities);
 
+int
+qemuMonitorJSONGetSGXCapabilities(qemuMonitor *mon,
+                                  virSGXCapability **capabilities);
+
 int
 qemuMonitorJSONGetSEVCapabilities(qemuMonitor *mon,
                                   virSEVCapability **capabilities);
-- 
2.25.1



More information about the libvir-list mailing list