From: Haibin Huang <haibin.huang@xxxxxxxxx> 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@xxxxxxxxx> Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> Signed-off-by: Haibin Huang <haibin.huang@xxxxxxxxx> --- 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", §ion_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