[libvirt][PATCH v5 3/6] Support to query SGX capability

Haibin Huang haibin.huang at intel.com
Thu Jul 15 07:02:58 UTC 2021


1.Add SGX feature in domain capabilities
2.Get sgx capabilities by query-sgx-capabilities
3.Transfer the B to KB for epc_size
4.Delete sgx1 and sgx2

Signed-off-by: Haibin Huang <haibin.huang at intel.com>
---
 docs/schemas/domaincaps.rng    |  20 +++++
 src/conf/domain_capabilities.c |  29 +++++++
 src/conf/domain_capabilities.h |  13 +++
 src/libvirt_private.syms       |   1 +
 src/qemu/qemu_capabilities.c   | 139 +++++++++++++++++++++++++++++++++
 src/qemu/qemu_capabilities.h   |   6 ++
 src/qemu/qemu_monitor.c        |  10 +++
 src/qemu/qemu_monitor.h        |   3 +
 src/qemu/qemu_monitor_json.c   |  87 +++++++++++++++++++++
 src/qemu/qemu_monitor_json.h   |   3 +
 10 files changed, 311 insertions(+)

diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng
index 325581476d..0dc97b29bc 100644
--- a/docs/schemas/domaincaps.rng
+++ b/docs/schemas/domaincaps.rng
@@ -219,6 +219,9 @@
       <optional>
         <ref name='sev'/>
       </optional>
+      <optional>
+        <ref name='sgx'/>
+      </optional>
     </element>
   </define>
 
@@ -267,6 +270,23 @@
     </element>
   </define>
 
+  <define name='sgx'>
+    <element name='sgx'>
+      <ref name='supported'/>
+      <optional>
+        <element name='flc'>
+          <choice>
+            <value>yes</value>
+            <value>no</value>
+          </choice>
+        </element>
+        <element name='epc_size'>
+          <ref name='scaledInteger'/>
+        </element>
+      </optional>
+    </element>
+  </define>
+
   <define name='value'>
     <zeroOrMore>
       <element name='value'>
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index d61108e125..8024200951 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -91,6 +91,16 @@ virSEVCapabilitiesFree(virSEVCapability *cap)
 }
 
 
+void
+virSGXCapabilitiesFree(virSGXCapability *cap)
+{
+    if (!cap)
+        return;
+
+    VIR_FREE(cap);
+}
+
+
 static void
 virDomainCapsDispose(void *obj)
 {
@@ -101,6 +111,7 @@ virDomainCapsDispose(void *obj)
     virObjectUnref(caps->cpu.custom);
     virCPUDefFree(caps->cpu.hostModel);
     virSEVCapabilitiesFree(caps->sev);
+    virSGXCapabilitiesFree(caps->sgx);
 
     virDomainCapsStringValuesFree(&caps->os.loader.values);
 }
@@ -564,6 +575,23 @@ virDomainCapsFeatureSEVFormat(virBufferPtr buf,
     return;
 }
 
+static void
+virDomainCapsFeatureSGXFormat(virBufferPtr buf,
+                              virSGXCapabilityPtr const sgx)
+{
+    if (!sgx) {
+        virBufferAddLit(buf, "<sgx supported='no'/>\n");
+    } else {
+        virBufferAddLit(buf, "<sgx supported='yes'>\n");
+        virBufferAdjustIndent(buf, 2);
+        virBufferAsprintf(buf, "<flc>%s</flc>\n", sgx->flc ? "yes" : "no");
+        virBufferAsprintf(buf, "<epc_size unit='KiB'>%llu</epc_size>\n", sgx->epc_size);
+        virBufferAdjustIndent(buf, -2);
+        virBufferAddLit(buf, "</sgx>\n");
+    }
+
+    return;
+}
 
 static void
 virDomainCapsFormatFeatures(const virDomainCaps *caps,
@@ -584,6 +612,7 @@ virDomainCapsFormatFeatures(const virDomainCaps *caps,
     }
 
     virDomainCapsFeatureSEVFormat(&childBuf, caps->sev);
+    virDomainCapsFeatureSGXFormat(&childBuf, caps->sgx);
 
     virXMLFormatElement(buf, "features", NULL, &childBuf);
 }
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index 685d5e2a44..0b2447e81f 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -150,6 +150,13 @@ struct _virDomainCapsCPU {
     virDomainCapsCPUModelsPtr custom;
 };
 
+typedef struct _virSGXCapability virSGXCapability;
+typedef virSGXCapability *virSGXCapabilityPtr;
+struct _virSGXCapability {
+    bool flc;
+    unsigned long long epc_size;
+};
+
 typedef struct _virSEVCapability virSEVCapability;
 typedef virSEVCapability *virSEVCapabilityPtr;
 struct _virSEVCapability {
@@ -191,6 +198,7 @@ struct _virDomainCaps {
 
     virDomainCapsFeatureGIC gic;
     virSEVCapabilityPtr sev;
+    virSGXCapabilityPtr sgx;
     /* add new domain features here */
 
     virTristateBool features[VIR_DOMAIN_CAPS_FEATURE_LAST];
@@ -239,4 +247,9 @@ int virDomainCapsDeviceDefValidate(const virDomainCaps *caps,
 void
 virSEVCapabilitiesFree(virSEVCapability *capabilities);
 
+void
+virSGXCapabilitiesFree(virSGXCapability *capabilities);
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(virSEVCapability, virSEVCapabilitiesFree);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virSGXCapability, virSGXCapabilitiesFree);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 01c2e710cd..7b464f9592 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -215,6 +215,7 @@ virDomainCapsEnumSet;
 virDomainCapsFormat;
 virDomainCapsNew;
 virSEVCapabilitiesFree;
+virSGXCapabilitiesFree;
 
 
 # conf/domain_conf.h
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index ff6ba8c9e9..e2103c7975 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -597,6 +597,9 @@ VIR_ENUM_IMPL(virQEMUCaps,
               "spapr-tpm-proxy",
               "numa.hmat",
               "blockdev-hostdev-scsi",
+
+              /* 380 */
+              "sgx-epc",
     );
 
 
@@ -698,11 +701,14 @@ struct _virQEMUCaps {
 
     virSEVCapability *sevCapabilities;
 
+    virSGXCapability *sgxCapabilities;
+
     /* Capabilities which may differ depending on the accelerator. */
     virQEMUCapsAccel kvm;
     virQEMUCapsAccel tcg;
 };
 
+
 struct virQEMUCapsSearchData {
     virArch arch;
     const char *binaryFilter;
@@ -1323,6 +1329,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
     { "tcg-accel", QEMU_CAPS_TCG },
     { "pvscsi", QEMU_CAPS_SCSI_PVSCSI },
     { "spapr-tpm-proxy", QEMU_CAPS_DEVICE_SPAPR_TPM_PROXY },
+    { "sgx-epc", QEMU_CAPS_SGX_EPC },
 };
 
 
@@ -1870,6 +1877,20 @@ virQEMUCapsSEVInfoCopy(virSEVCapabilityPtr *dst,
 }
 
 
+static int
+virQEMUCapsSGXInfoCopy(virSGXCapabilityPtr *dst,
+                       virSGXCapabilityPtr src)
+{
+    virSGXCapability *tmp = g_new0(virSGXCapability, 1);
+
+    tmp->flc = src->flc;
+    tmp->epc_size = src->epc_size;
+
+    *dst = tmp;
+    return 0;
+}
+
+
 static void
 virQEMUCapsAccelCopyMachineTypes(virQEMUCapsAccelPtr dst,
                                  virQEMUCapsAccelPtr src)
@@ -1947,6 +1968,11 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
                                qemuCaps->sevCapabilities) < 0)
         goto error;
 
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SGX_EPC) &&
+        virQEMUCapsSGXInfoCopy(&ret->sgxCapabilities,
+                               qemuCaps->sgxCapabilities) < 0)
+        goto error;
+
     return ret;
 
  error:
@@ -1987,6 +2013,7 @@ void virQEMUCapsDispose(void *obj)
     VIR_FREE(qemuCaps->gicCapabilities);
 
     virSEVCapabilitiesFree(qemuCaps->sevCapabilities);
+    virSGXCapabilitiesFree(qemuCaps->sgxCapabilities);
 
     virQEMUCapsAccelClear(&qemuCaps->kvm);
     virQEMUCapsAccelClear(&qemuCaps->tcg);
@@ -2581,6 +2608,13 @@ virQEMUCapsGetSEVCapabilities(virQEMUCapsPtr qemuCaps)
 }
 
 
+virSGXCapabilityPtr
+virQEMUCapsGetSGXCapabilities(virQEMUCapsPtr qemuCaps)
+{
+    return qemuCaps->sgxCapabilities;
+}
+
+
 static int
 virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
                             qemuMonitorPtr mon)
@@ -3405,6 +3439,31 @@ virQEMUCapsProbeQMPSEVCapabilities(virQEMUCapsPtr qemuCaps,
 }
 
 
+static int
+virQEMUCapsProbeQMPSGXCapabilities(virQEMUCapsPtr qemuCaps,
+                                   qemuMonitorPtr mon)
+{
+    int rc = -1;
+    virSGXCapability *caps = NULL;
+
+    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SGX_EPC))
+        return 0;
+
+    if ((rc = qemuMonitorGetSGXCapabilities(mon, &caps)) < 0)
+        return -1;
+
+    /* SGX isn't actually supported */
+    if (rc == 0) {
+        virQEMUCapsClear(qemuCaps, QEMU_CAPS_SGX_EPC);
+        return 0;
+    }
+
+    virSGXCapabilitiesFree(qemuCaps->sgxCapabilities);
+    qemuCaps->sgxCapabilities = 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
@@ -4187,6 +4246,39 @@ virQEMUCapsParseSEVInfo(virQEMUCapsPtr qemuCaps, xmlXPathContextPtr ctxt)
     return 0;
 }
 
+static int
+virQEMUCapsParseSGXInfo(virQEMUCapsPtr qemuCaps, xmlXPathContextPtr ctxt)
+{
+    virSGXCapability *sgx = g_new0(virSGXCapability, 1);
+
+    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SGX_EPC))
+        return 0;
+
+    if (virXPathBoolean("boolean(./sgx)", ctxt) == 0) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("missing SGX platform data in QEMU "
+                       "capabilities cache"));
+        return -1;
+    }
+
+    if (virXPathBoolean("boolean(./sgx/flc)", ctxt) == 0) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("missing SGX platform flc data in QEMU "
+                       "capabilities cache"));
+        return -1;
+    }
+
+    if (virXPathULongLong("string(./sgx/epc_size)", ctxt, &sgx->epc_size) < 0) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("missing or malformed SGX platform epc_size information "
+                       "in QEMU capabilities cache"));
+        return -1;
+    }
+
+    qemuCaps->sgxCapabilities = g_steal_pointer(&sgx);
+    return 0;
+}
+
 
 /*
  * Parsing a doc that looks like
@@ -4425,6 +4517,9 @@ virQEMUCapsLoadCache(virArch hostArch,
     if (virQEMUCapsParseSEVInfo(qemuCaps, ctxt) < 0)
         goto cleanup;
 
+    if (virQEMUCapsParseSGXInfo(qemuCaps, ctxt) < 0)
+        goto cleanup;
+
     virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_KVM);
     virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_QEMU);
 
@@ -4601,6 +4696,19 @@ virQEMUCapsFormatSEVInfo(virQEMUCapsPtr qemuCaps, virBufferPtr buf)
     virBufferAddLit(buf, "</sev>\n");
 }
 
+static void
+virQEMUCapsFormatSGXInfo(virQEMUCapsPtr qemuCaps, virBufferPtr buf)
+{
+    virSGXCapabilityPtr sgx = virQEMUCapsGetSGXCapabilities(qemuCaps);
+
+    virBufferAddLit(buf, "<sgx>\n");
+    virBufferAdjustIndent(buf, 2);
+    virBufferAsprintf(buf, "<flc>%s</flc>\n", sgx->flc ? "yes" : "no");
+    virBufferAsprintf(buf, "<epc_size>%llu</epc_size>\n", sgx->epc_size);
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</sgx>\n");
+}
+
 
 char *
 virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps)
@@ -4671,6 +4779,9 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps)
     if (qemuCaps->sevCapabilities)
         virQEMUCapsFormatSEVInfo(qemuCaps, &buf);
 
+    if (qemuCaps->sgxCapabilities)
+        virQEMUCapsFormatSGXInfo(qemuCaps, &buf);
+
     if (qemuCaps->kvmSupportsNesting)
         virBufferAddLit(&buf, "<kvmSupportsNesting/>\n");
 
@@ -5323,6 +5434,8 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
         return -1;
     if (virQEMUCapsProbeQMPSEVCapabilities(qemuCaps, mon) < 0)
         return -1;
+    if (virQEMUCapsProbeQMPSGXCapabilities(qemuCaps, mon) < 0)
+        return -1;
 
     virQEMUCapsInitProcessCaps(qemuCaps);
 
@@ -6245,6 +6358,31 @@ virQEMUCapsFillDomainFeatureGICCaps(virQEMUCapsPtr qemuCaps,
 }
 
 
+/**
+ * virQEMUCapsFillDomainFeatureiSGXCaps:
+ * @qemuCaps: QEMU capabilities
+ * @domCaps: domain capabilities
+ *
+ * Take the information about SGX capabilities that has been obtained
+ * using the 'query-sgx-capabilities' QMP command and stored in @qemuCaps
+ * and convert it to a form suitable for @domCaps.
+ */
+static void
+virQEMUCapsFillDomainFeatureSGXCaps(virQEMUCapsPtr qemuCaps,
+                                    virDomainCapsPtr domCaps)
+{
+    virSGXCapability *cap = qemuCaps->sgxCapabilities;
+
+    if (!cap)
+        return;
+
+    domCaps->sgx = g_new0(virSGXCapability, 1);
+
+    domCaps->sgx->flc = cap->flc;
+    domCaps->sgx->epc_size = cap->epc_size;
+}
+
+
 /**
  * virQEMUCapsFillDomainFeatureSEVCaps:
  * @qemuCaps: QEMU capabilities
@@ -6316,6 +6454,7 @@ virQEMUCapsFillDomainCaps(virQEMUCapsPtr qemuCaps,
     virQEMUCapsFillDomainDeviceRNGCaps(qemuCaps, rng);
     virQEMUCapsFillDomainFeatureGICCaps(qemuCaps, domCaps);
     virQEMUCapsFillDomainFeatureSEVCaps(qemuCaps, domCaps);
+    virQEMUCapsFillDomainFeatureSGXCaps(qemuCaps, domCaps);
 
     return 0;
 }
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 5d08941538..0e3af622a7 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -578,6 +578,9 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
     QEMU_CAPS_NUMA_HMAT, /* -numa hmat */
     QEMU_CAPS_BLOCKDEV_HOSTDEV_SCSI, /* -blockdev used for (i)SCSI hostdevs */
 
+    /* 380 */
+    QEMU_CAPS_SGX_EPC, /* -object sgx-epc,... */
+
     QEMU_CAPS_LAST /* this must always be the last item */
 } virQEMUCapsFlags;
 
@@ -759,5 +762,8 @@ virQEMUCapsCPUFeatureFromQEMU(virQEMUCapsPtr qemuCaps,
 virSEVCapabilityPtr
 virQEMUCapsGetSEVCapabilities(virQEMUCapsPtr qemuCaps);
 
+virSGXCapabilityPtr
+virQEMUCapsGetSGXCapabilities(virQEMUCapsPtr qemuCaps);
+
 virArch virQEMUCapsArchFromString(const char *arch);
 const char *virQEMUCapsArchToString(virArch arch);
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 637361d24d..1e377ee8dc 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3870,6 +3870,16 @@ qemuMonitorGetSEVCapabilities(qemuMonitorPtr mon,
 }
 
 
+int
+qemuMonitorGetSGXCapabilities(qemuMonitorPtr mon,
+                              virSGXCapability **capabilities)
+{
+    QEMU_CHECK_MONITOR(mon);
+
+    return qemuMonitorJSONGetSGXCapabilities(mon, capabilities);
+}
+
+
 int
 qemuMonitorNBDServerStart(qemuMonitorPtr mon,
                           const virStorageNetHostDef *server,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index d20a15c202..76b3cd54c7 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -836,6 +836,9 @@ int qemuMonitorGetGICCapabilities(qemuMonitorPtr mon,
 int qemuMonitorGetSEVCapabilities(qemuMonitorPtr mon,
                                   virSEVCapability **capabilities);
 
+int qemuMonitorGetSGXCapabilities(qemuMonitorPtr mon,
+                                  virSGXCapability **capabilities);
+
 typedef enum {
   QEMU_MONITOR_MIGRATE_BACKGROUND       = 1 << 0,
   QEMU_MONITOR_MIGRATE_NON_SHARED_DISK  = 1 << 1, /* migration with non-shared storage with full disk copy */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 9cdf6c0f7f..69a6a31aee 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -44,6 +44,7 @@
 # include "libvirt_qemu_probes.h"
 #endif
 
+#define KB 1024
 #define VIR_FROM_THIS VIR_FROM_QEMU
 
 VIR_LOG_INIT("qemu.qemu_monitor_json");
@@ -7056,6 +7057,92 @@ qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon,
 }
 
 
+/**
+ * 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(qemuMonitorPtr mon,
+                                  virSGXCapability **capabilities)
+{
+    int ret = -1;
+    g_autoptr(virJSONValue) cmd = NULL;
+    g_autoptr(virJSONValue) reply = NULL;
+    virJSONValuePtr caps;
+    bool sgx = false;
+    bool flc = false;
+    unsigned long long section_size = 0;
+    g_autoptr(virSGXCapability) capability = NULL;
+
+    *capabilities = NULL;
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("query-sgx-capabilities", NULL)))
+        return -1;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        return ret;
+
+    /* QEMU has only compiled-in support of SGX */
+    if (qemuMonitorJSONHasError(reply, "GenericError")) {
+        ret = 0;
+        return ret;
+    }
+
+    if (qemuMonitorJSONCheckError(cmd, reply) < 0)
+        return ret;
+
+    caps = virJSONValueObjectGetObject(reply, "return");
+
+    if (virJSONValueObjectGetBoolean(caps, "sgx", &sgx) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("query-sgx reply was missing"
+                         " 'sgx' field"));
+        return ret;
+    }
+    if (!sgx) {
+        VIR_WARN("sgx is not support %d\n", sgx);
+        ret = 0;
+        return ret;
+    }
+
+    if (virJSONValueObjectGetBoolean(caps, "flc", &flc) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("query-sgx-capabilities reply was missing"
+                         " 'flc' field"));
+        return ret;
+    }
+
+    if (virJSONValueObjectGetNumberUlong(caps, "section-size", &section_size) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("query-sgx-capabilities reply was missing"
+                         " 'section-size' field"));
+        return ret;
+    }
+
+
+    if (VIR_ALLOC(capability) < 0)
+        return ret;
+
+    capability->flc = flc;
+
+    capability->epc_size = section_size/(KB);
+    *capabilities = g_steal_pointer(&capability);
+    ret = 1;
+
+    return ret;
+}
+
+
 /**
  * qemuMonitorJSONGetSEVCapabilities:
  * @mon: qemu monitor object
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 098ab857be..b0c23e57ac 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -159,6 +159,9 @@ int qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon,
 int qemuMonitorJSONGetSEVCapabilities(qemuMonitorPtr mon,
                                       virSEVCapability **capabilities);
 
+int qemuMonitorJSONGetSGXCapabilities(qemuMonitorPtr mon,
+                                      virSGXCapability **capabilities);
+
 int qemuMonitorJSONMigrate(qemuMonitorPtr mon,
                            unsigned int flags,
                            const char *uri);
-- 
2.17.1




More information about the libvir-list mailing list