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> --- src/conf/domain_capabilities.h | 8 +++ src/qemu/qemu_monitor.c | 10 ++++ src/qemu/qemu_monitor.h | 3 + src/qemu/qemu_monitor_json.c | 104 ++++++++++++++++++++++++++++++--- src/qemu/qemu_monitor_json.h | 9 +++ 5 files changed, 127 insertions(+), 7 deletions(-) diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index f2eed80b15..21736ad1ac 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -192,6 +192,13 @@ struct _virSEVCapability { unsigned int max_es_guests; }; +typedef struct _virSGXCapability virSGXCapability; +typedef virSGXCapability *virSGXCapabilityPtr; +struct _virSGXCapability { + bool flc; + unsigned int epc_size; +}; + typedef enum { VIR_DOMAIN_CAPS_FEATURE_IOTHREADS = 0, VIR_DOMAIN_CAPS_FEATURE_VMCOREINFO, @@ -228,6 +235,7 @@ struct _virDomainCaps { virDomainCapsFeatureGIC gic; virSEVCapability *sev; + virSGXCapability *sgx; /* add new domain features here */ virTristateBool features[VIR_DOMAIN_CAPS_FEATURE_LAST]; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index d44c7f0c60..6b82e8c853 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3648,6 +3648,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 b1484fdff8..ed87185e5d 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -900,6 +900,9 @@ int qemuMonitorGetGICCapabilities(qemuMonitor *mon, int qemuMonitorGetSEVCapabilities(qemuMonitor *mon, virSEVCapability **capabilities); +int qemuMonitorGetSGXCapabilities(qemuMonitor *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 a092bf420f..38c3d018f3 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6433,6 +6433,69 @@ 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; + virJSONValue *caps; + bool flc = false; + unsigned int 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 -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", &flc) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("query-sgx-capabilities reply was missing 'flc' field")); + return -1; + } + + if (virJSONValueObjectGetNumberUint(caps, "section-size", §ion_size) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("query-sgx-capabilities reply was missing 'section-size' field")); + return -1; + } + + capability = g_new0(virSGXCapability, 1); + capability->flc = flc; + capability->epc_size = section_size/1024; + + *capabilities = g_steal_pointer(&capability); + return 1; +} + static virJSONValue * qemuMonitorJSONBuildInetSocketAddress(const char *host, const char *port) @@ -7469,13 +7532,25 @@ qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitor *mon, return -1; } - /* While 'id' attribute is marked as optional in QEMU's QAPI - * specification, Libvirt always sets it. Thus we can fail if not - * present. */ - if (!(devalias = virJSONValueObjectGetString(dimminfo, "id"))) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("dimm memory info data is missing 'id'")); - return -1; + if (STREQ(type, "dimm") || STREQ(type, "nvdimm") || STREQ(type, "virtio-mem")) { + /* While 'id' attribute is marked as optional in QEMU's QAPI + * specification, Libvirt always sets it. Thus we can fail if not + * present. */ + if (!(devalias = virJSONValueObjectGetString(dimminfo, "id"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("dimm memory info data is missing 'id'")); + return -1; + } + } else if (STREQ(type, "sgx-epc")) { + if (!(devalias = virJSONValueObjectGetString(dimminfo, "memdev"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("sgx-epc memory info data is missing 'memdev'")); + return -1; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("%s memory device info is not handled yet"), type); + return -1; } meminfo = g_new0(qemuMonitorMemoryDeviceInfo, 1); @@ -7519,6 +7594,21 @@ qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitor *mon, _("malformed/missing size in virtio memory info")); return -1; } + } else if (STREQ(type, "sgx-epc")) { + /* sgx-epc memory devices */ + if (virJSONValueObjectGetNumberUlong(dimminfo, "memaddr", + &meminfo->address) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed/missing memaddr in sgx-epc memory info")); + return -1; + } + + if (virJSONValueObjectGetNumberUlong(dimminfo, "size", + &meminfo->size) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed/missing size in sgx-epc memory info")); + return -1; + } } else { /* type not handled yet */ continue; diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 3c442d669f..dbe772c3f7 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -255,6 +255,15 @@ qemuMonitorJSONAddFileHandleToSet(qemuMonitor *mon, int fdset, const char *opaque); +int qemuMonitorJSONGetSGXCapabilities(qemuMonitor *mon, + virSGXCapability **capabilities); + +int qemuMonitorJSONMigrate(qemuMonitor *mon, + unsigned int flags, + const char *uri); +int qemuMonitorJSONGetSpiceMigrationStatus(qemuMonitor *mon, + bool *spice_migrated); + int qemuMonitorJSONRemoveFdset(qemuMonitor *mon, unsigned int fdset); -- 2.25.1