[libvirt][PATCH v17 1/9] domain_capabilities: Define SGX capabilities structs

From: Haibin Huang <haibin.huang@intel.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> Signed-off-by: Haibin Huang <haibin.huang@intel.com> --- src/conf/domain_capabilities.c | 11 +++++++++++ src/conf/domain_capabilities.h | 22 ++++++++++++++++++++++ src/libvirt_private.syms | 1 + 3 files changed, 34 insertions(+) diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index a7f256e4ec..daeaee3c5c 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -76,6 +76,17 @@ virSEVCapabilitiesFree(virSEVCapability *cap) } +void +virSGXCapabilitiesFree(virSGXCapability *cap) +{ + if (!cap) + return; + + g_free(cap->sgxSections); + g_free(cap); +} + + static void virDomainCapsDispose(void *obj) { diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index e0cfa75531..1d504a3506 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -208,6 +208,22 @@ struct _virSEVCapability { unsigned int max_es_guests; }; +typedef struct _virSGXSection virSGXSection; +struct _virSGXSection { + unsigned long long size; + unsigned int node; +}; + +typedef struct _virSGXCapability virSGXCapability; +struct _virSGXCapability { + bool flc; + bool sgx1; + bool sgx2; + unsigned long long section_size; + size_t nSgxSections; + virSGXSection *sgxSections; +}; + typedef enum { VIR_DOMAIN_CAPS_FEATURE_IOTHREADS = 0, VIR_DOMAIN_CAPS_FEATURE_VMCOREINFO, @@ -246,6 +262,7 @@ struct _virDomainCaps { virDomainCapsFeatureGIC gic; virSEVCapability *sev; + virSGXCapability *sgx; /* add new domain features here */ virTristateBool features[VIR_DOMAIN_CAPS_FEATURE_LAST]; @@ -296,3 +313,8 @@ void virSEVCapabilitiesFree(virSEVCapability *capabilities); G_DEFINE_AUTOPTR_CLEANUP_FUNC(virSEVCapability, virSEVCapabilitiesFree); + +void +virSGXCapabilitiesFree(virSGXCapability *capabilities); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virSGXCapability, virSGXCapabilitiesFree); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 97ff2a43e4..ebd7bc61a8 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -218,6 +218,7 @@ virDomainCapsEnumSet; virDomainCapsFormat; virDomainCapsNew; virSEVCapabilitiesFree; +virSGXCapabilitiesFree; # conf/domain_conf.h -- 2.25.1

From: Haibin Huang <haibin.huang@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@intel.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.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 cd9f43071e..8ada16154c 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 62f1bc1299..c690fc3655 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -823,6 +823,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 74967afb24..fa44e07c2b 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6025,6 +6025,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 4c65838b7e..93789480c5 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -160,6 +160,10 @@ int qemuMonitorJSONGetGICCapabilities(qemuMonitor *mon, virGICCapability **capabilities); +int +qemuMonitorJSONGetSGXCapabilities(qemuMonitor *mon, + virSGXCapability **capabilities); + int qemuMonitorJSONGetSEVCapabilities(qemuMonitor *mon, virSEVCapability **capabilities); -- 2.25.1

From: Haibin Huang <haibin.huang@intel.com> the QMP capabilities: {"return": { "sgx": true, "section-size": 1024, "flc": true } } the domain capabilities: <sgx> <flc>yes</flc> <epc_size>1</epc_size> </sgx> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Haibin Huang <haibin.huang@intel.com> --- src/qemu/qemu_capabilities.c | 204 ++++++++++++++++++ src/qemu/qemu_capabilities.h | 4 + .../caps_6.2.0.x86_64.replies | 21 +- .../caps_7.0.0.x86_64.replies | 34 ++- .../caps_7.0.0.x86_64.xml | 11 + .../caps_7.1.0.x86_64.replies | 21 +- .../caps_7.2.0.x86_64.replies | 21 +- 7 files changed, 300 insertions(+), 16 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index a2031e9aaa..7c9d7ed885 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -677,6 +677,7 @@ VIR_ENUM_IMPL(virQEMUCaps, /* 435 */ "query-stats", /* QEMU_CAPS_QUERY_STATS */ "query-stats-schemas", /* QEMU_CAPS_QUERY_STATS_SCHEMAS */ + "sgx-epc", /* QEMU_CAPS_SGX_EPC */ ); @@ -758,6 +759,8 @@ struct _virQEMUCaps { virSEVCapability *sevCapabilities; + virSGXCapability *sgxCapabilities; + /* Capabilities which may differ depending on the accelerator. */ virQEMUCapsAccel kvm; virQEMUCapsAccel hvf; @@ -1380,6 +1383,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "s390-pv-guest", QEMU_CAPS_S390_PV_GUEST }, { "virtio-mem-pci", QEMU_CAPS_DEVICE_VIRTIO_MEM_PCI }, { "virtio-iommu-pci", QEMU_CAPS_DEVICE_VIRTIO_IOMMU_PCI }, + { "sgx-epc", QEMU_CAPS_SGX_EPC }, }; @@ -1891,6 +1895,36 @@ virQEMUCapsSEVInfoCopy(virSEVCapability **dst, } +static int +virQEMUCapsSGXInfoCopy(virSGXCapability **dst, + virSGXCapability *src) +{ + g_autoptr(virSGXCapability) tmp = NULL; + + if (!src) { + *dst = NULL; + return 0; + } + + tmp = g_new0(virSGXCapability, 1); + + tmp->flc = src->flc; + tmp->sgx1 = src->sgx1; + tmp->sgx2 = src->sgx2; + tmp->section_size = src->section_size; + + if (src->nSgxSections > 0) { + tmp->sgxSections = g_new0(virSGXSection, src->nSgxSections); + memcpy(tmp->sgxSections, src->sgxSections, + src->nSgxSections * sizeof(*tmp->sgxSections)); + tmp->nSgxSections = src->nSgxSections; + } + + *dst = g_steal_pointer(&tmp); + return 0; +} + + static void virQEMUCapsAccelCopyMachineTypes(virQEMUCapsAccel *dst, virQEMUCapsAccel *src) @@ -1972,6 +2006,12 @@ virQEMUCaps *virQEMUCapsNewCopy(virQEMUCaps *qemuCaps) qemuCaps->sevCapabilities) < 0) return NULL; + + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SGX_EPC) && + virQEMUCapsSGXInfoCopy(&ret->sgxCapabilities, + qemuCaps->sgxCapabilities) < 0) + return NULL; + return g_steal_pointer(&ret); } @@ -2010,6 +2050,7 @@ void virQEMUCapsDispose(void *obj) virCPUDataFree(qemuCaps->cpuData); virSEVCapabilitiesFree(qemuCaps->sevCapabilities); + virSGXCapabilitiesFree(qemuCaps->sgxCapabilities); virQEMUCapsAccelClear(&qemuCaps->kvm); virQEMUCapsAccelClear(&qemuCaps->hvf); @@ -2541,6 +2582,13 @@ virQEMUCapsGetSEVCapabilities(virQEMUCaps *qemuCaps) } +virSGXCapability * +virQEMUCapsGetSGXCapabilities(virQEMUCaps *qemuCaps) +{ + return qemuCaps->sgxCapabilities; +} + + static int virQEMUCapsProbeQMPCommands(virQEMUCaps *qemuCaps, qemuMonitor *mon) @@ -3373,6 +3421,31 @@ virQEMUCapsProbeQMPSEVCapabilities(virQEMUCaps *qemuCaps, } +static int +virQEMUCapsProbeQMPSGXCapabilities(virQEMUCaps *qemuCaps, + qemuMonitor *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 @@ -4167,6 +4240,97 @@ virQEMUCapsParseSEVInfo(virQEMUCaps *qemuCaps, xmlXPathContextPtr ctxt) } +static int +virQEMUCapsParseSGXInfo(virQEMUCaps *qemuCaps, + xmlXPathContextPtr ctxt) +{ + g_autoptr(virSGXCapability) sgx = NULL; + xmlNodePtr sgxSections = NULL; + g_autofree char *flc = NULL; + g_autofree char *sgx1 = NULL; + g_autofree char *sgx2 = NULL; + + 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; + } + + sgx = g_new0(virSGXCapability, 1); + + if ((!(flc = virXPathString("string(./sgx/flc)", ctxt))) || + virStringParseYesNo(flc, &sgx->flc) < 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing or invalid SGX platform flc in QEMU capabilities cache")); + return -1; + } + + if ((!(sgx1 = virXPathString("string(./sgx/sgx1)", ctxt))) || + virStringParseYesNo(sgx1, &sgx->sgx1) < 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing or invalid SGX platform sgx1 in QEMU capabilities cache")); + return -1; + } + + if ((!(sgx2 = virXPathString("string(./sgx/sgx2)", ctxt))) || + virStringParseYesNo(sgx2, &sgx->sgx2) < 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing or invalid SGX platform sgx2 in QEMU capabilities cache")); + return -1; + } + + if (virXPathULongLong("string(./sgx/section_size)", ctxt, + &sgx->section_size) < 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing or malformed SGX platform section_size in QEMU capabilities cache")); + return -1; + } + + if ((sgxSections = virXPathNode("./sgx/sections", ctxt))) { + g_autofree xmlNodePtr *sectionNodes = NULL; + int nSgxSections = 0; + size_t i; + VIR_XPATH_NODE_AUTORESTORE(ctxt); + + ctxt->node = sgxSections; + nSgxSections = virXPathNodeSet("./section", ctxt, §ionNodes); + + if (nSgxSections < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to parse SGX sections in QEMU capabilities cache")); + return -1; + } + + sgx->nSgxSections = nSgxSections; + sgx->sgxSections = g_new0(virSGXSection, nSgxSections); + + for (i = 0; i < nSgxSections; i++) { + if (virXMLPropUInt(sectionNodes[i], "node", 10, + VIR_XML_PROP_REQUIRED, + &(sgx->sgxSections[i].node)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing node name in QEMU capabilities cache")); + return -1; + } + + if (virXMLPropULongLong(sectionNodes[i], "size", 10, + VIR_XML_PROP_REQUIRED, + &(sgx->sgxSections[i].size)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing size name in QEMU capabilities cache")); + return -1; + } + } + } + + qemuCaps->sgxCapabilities = g_steal_pointer(&sgx); + return 0; +} + + static int virQEMUCapsParseFlags(virQEMUCaps *qemuCaps, xmlXPathContextPtr ctxt) { @@ -4455,6 +4619,9 @@ virQEMUCapsLoadCache(virArch hostArch, if (virQEMUCapsParseSEVInfo(qemuCaps, ctxt) < 0) return -1; + if (virQEMUCapsParseSGXInfo(qemuCaps, ctxt) < 0) + return -1; + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM)) virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_KVM); if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_HVF)) @@ -4643,6 +4810,38 @@ virQEMUCapsFormatSEVInfo(virQEMUCaps *qemuCaps, virBuffer *buf) } +static void +virQEMUCapsFormatSGXInfo(virQEMUCaps *qemuCaps, + virBuffer *buf) +{ + virSGXCapability *sgx = virQEMUCapsGetSGXCapabilities(qemuCaps); + + virBufferAddLit(buf, "<sgx supported='yes'>\n"); + virBufferAdjustIndent(buf, 2); + virBufferAsprintf(buf, "<flc>%s</flc>\n", sgx->flc ? "yes" : "no"); + virBufferAsprintf(buf, "<sgx1>%s</sgx1>\n", sgx->sgx1 ? "yes" : "no"); + virBufferAsprintf(buf, "<sgx2>%s</sgx2>\n", sgx->sgx2 ? "yes" : "no"); + virBufferAsprintf(buf, "<section_size unit='KiB'>%llu</section_size>\n", sgx->section_size); + + if (sgx->nSgxSections > 0) { + size_t i; + virBufferAddLit(buf, "<sections>\n"); + + for (i = 0; i < sgx->nSgxSections; i++) { + virBufferAdjustIndent(buf, 2); + virBufferAsprintf(buf, "<section node='%u' ", sgx->sgxSections[i].node); + virBufferAsprintf(buf, "size='%llu' ", sgx->sgxSections[i].size); + virBufferAddLit(buf, "unit='KiB'/>\n"); + virBufferAdjustIndent(buf, -2); + } + virBufferAddLit(buf, "</sections>\n"); + } + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</sgx>\n"); +} + + char * virQEMUCapsFormatCache(virQEMUCaps *qemuCaps) { @@ -4724,6 +4923,9 @@ virQEMUCapsFormatCache(virQEMUCaps *qemuCaps) if (qemuCaps->sevCapabilities) virQEMUCapsFormatSEVInfo(qemuCaps, &buf); + if (qemuCaps->sgxCapabilities) + virQEMUCapsFormatSGXInfo(qemuCaps, &buf); + if (qemuCaps->kvmSupportsNesting) virBufferAddLit(&buf, "<kvmSupportsNesting/>\n"); @@ -5353,6 +5555,8 @@ virQEMUCapsInitQMPMonitor(virQEMUCaps *qemuCaps, return -1; if (virQEMUCapsProbeQMPSEVCapabilities(qemuCaps, mon) < 0) return -1; + if (virQEMUCapsProbeQMPSGXCapabilities(qemuCaps, mon) < 0) + return -1; virQEMUCapsInitProcessCaps(qemuCaps); diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index c79bc7cd24..dfa3d8cd9b 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -656,6 +656,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ /* 435 */ QEMU_CAPS_QUERY_STATS, /* accepts query-stats */ QEMU_CAPS_QUERY_STATS_SCHEMAS, /* accepts query-stats-schemas */ + QEMU_CAPS_SGX_EPC, /* -object sgx-epc,... */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; @@ -859,6 +860,9 @@ virQEMUCapsCPUFeatureFromQEMUInPlace(virArch arch, virSEVCapability * virQEMUCapsGetSEVCapabilities(virQEMUCaps *qemuCaps); +virSGXCapability * +virQEMUCapsGetSGXCapabilities(virQEMUCaps *qemuCaps); + bool virQEMUCapsGetKVMSupportsSecureGuest(virQEMUCaps *qemuCaps) G_NO_INLINE; diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies index b4b853eb51..fb32cb7a03 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies @@ -32419,6 +32419,19 @@ } } +{ + "execute": "query-sgx-capabilities", + "id": "libvirt-48" +} + +{ + "id": "libvirt-48", + "error": { + "class": "GenericError", + "desc": "SGX is not enabled in KVM" + } +} + { "execute": "query-cpu-model-expansion", "arguments": { @@ -32427,7 +32440,7 @@ "name": "host" } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -32760,7 +32773,7 @@ } } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -32774,7 +32787,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -33107,7 +33120,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { diff --git a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.replies index 0590294255..a331006289 100644 --- a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.replies @@ -33029,6 +33029,32 @@ } } +{ + "execute": "query-sgx-capabilities", + "id": "libvirt-48" +} + +{ + "return": { + "sgx": true, + "flc": false, + "sgx1": true, + "sgx2": false, + "section-size": 536870912, + "sections": [ + { + "node": 0, + "size": 268435456 + }, + { + "node": 1, + "size": 268435456 + } + ] + }, + "id": "libvirt-48" +} + { "execute": "query-cpu-model-expansion", "arguments": { @@ -33037,7 +33063,7 @@ "name": "host" } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -33374,7 +33400,7 @@ } } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -33388,7 +33414,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -33725,7 +33751,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { diff --git a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml index 12980ffcf6..d26d0c727a 100644 --- a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml @@ -195,6 +195,7 @@ <flag name='display-dbus'/> <flag name='usb-host.guest-resets-all'/> <flag name='migration.blocked-reasons'/> + <flag name='sgx-epc'/> <version>7000000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100243</microcodeVersion> @@ -3723,4 +3724,14 @@ <machine type='tcg' name='pc-q35-2.5' hotplugCpus='yes' maxCpus='255' defaultCPU='qemu64-x86_64-cpu' numaMemSupported='yes' defaultRAMid='pc.ram'/> <machine type='tcg' name='pc-i440fx-3.0' hotplugCpus='yes' maxCpus='255' defaultCPU='qemu64-x86_64-cpu' numaMemSupported='yes' defaultRAMid='pc.ram'/> <machine type='tcg' name='pc-q35-2.11' hotplugCpus='yes' maxCpus='288' defaultCPU='qemu64-x86_64-cpu' numaMemSupported='yes' defaultRAMid='pc.ram'/> + <sgx supported='yes'> + <flc>no</flc> + <sgx1>yes</sgx1> + <sgx2>no</sgx2> + <section_size unit='KiB'>524288</section_size> + <sections> + <section node='0' size='262144' unit='KiB'/> + <section node='1' size='262144' unit='KiB'/> + </sections> + </sgx> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_7.1.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_7.1.0.x86_64.replies index 126c76301e..9eb851694f 100644 --- a/tests/qemucapabilitiesdata/caps_7.1.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_7.1.0.x86_64.replies @@ -33722,6 +33722,19 @@ } } +{ + "execute": "query-sgx-capabilities", + "id": "libvirt-48" +} + +{ + "id": "libvirt-48", + "error": { + "class": "GenericError", + "desc": "SGX is not enabled in KVM" + } +} + { "execute": "query-cpu-model-expansion", "arguments": { @@ -33730,7 +33743,7 @@ "name": "host" } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -34068,7 +34081,7 @@ } } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -34082,7 +34095,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -34420,7 +34433,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { diff --git a/tests/qemucapabilitiesdata/caps_7.2.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_7.2.0.x86_64.replies index 8e4479dc92..b7eb0356c4 100644 --- a/tests/qemucapabilitiesdata/caps_7.2.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_7.2.0.x86_64.replies @@ -34635,6 +34635,19 @@ } } +{ + "execute": "query-sgx-capabilities", + "id": "libvirt-48" +} + +{ + "id": "libvirt-48", + "error": { + "class": "GenericError", + "desc": "SGX is not enabled in KVM" + } +} + { "execute": "query-cpu-model-expansion", "arguments": { @@ -34643,7 +34656,7 @@ "name": "host" } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -34981,7 +34994,7 @@ } } }, - "id": "libvirt-48" + "id": "libvirt-49" } { @@ -34995,7 +35008,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { @@ -35333,7 +35346,7 @@ } } }, - "id": "libvirt-49" + "id": "libvirt-50" } { -- 2.25.1

From: Haibin Huang <haibin.huang@intel.com> Extend hypervisor capabilities to include sgx feature. When available, the hypervisor supports launching an VM with SGX on Intel platfrom. The SGX feature tag privides additional details like section size and sgx1 or sgx2. Signed-off-by: Haibin Huang <haibin.huang@intel.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- docs/formatdomaincaps.rst | 40 +++++++++++++++++ src/conf/domain_capabilities.c | 36 ++++++++++++++++ src/conf/schemas/domaincaps.rng | 43 +++++++++++++++++++ src/qemu/qemu_capabilities.c | 16 +++++++ tests/domaincapsdata/bhyve_basic.x86_64.xml | 1 + tests/domaincapsdata/bhyve_fbuf.x86_64.xml | 1 + tests/domaincapsdata/bhyve_uefi.x86_64.xml | 1 + tests/domaincapsdata/empty.xml | 1 + tests/domaincapsdata/libxl-xenfv.xml | 1 + tests/domaincapsdata/libxl-xenpv.xml | 1 + .../domaincapsdata/qemu_4.2.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_4.2.0-tcg.x86_64.xml | 1 + .../qemu_4.2.0-virt.aarch64.xml | 1 + tests/domaincapsdata/qemu_4.2.0.aarch64.xml | 1 + tests/domaincapsdata/qemu_4.2.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_4.2.0.s390x.xml | 1 + tests/domaincapsdata/qemu_4.2.0.x86_64.xml | 1 + .../domaincapsdata/qemu_5.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_5.0.0-tcg.x86_64.xml | 1 + .../qemu_5.0.0-virt.aarch64.xml | 1 + tests/domaincapsdata/qemu_5.0.0.aarch64.xml | 1 + tests/domaincapsdata/qemu_5.0.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_5.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_5.1.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_5.1.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_5.1.0.sparc.xml | 1 + tests/domaincapsdata/qemu_5.1.0.x86_64.xml | 1 + .../domaincapsdata/qemu_5.2.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_5.2.0-tcg.x86_64.xml | 1 + .../qemu_5.2.0-virt.aarch64.xml | 1 + tests/domaincapsdata/qemu_5.2.0.aarch64.xml | 1 + tests/domaincapsdata/qemu_5.2.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_5.2.0.s390x.xml | 1 + tests/domaincapsdata/qemu_5.2.0.x86_64.xml | 1 + .../domaincapsdata/qemu_6.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_6.0.0-tcg.x86_64.xml | 1 + .../qemu_6.0.0-virt.aarch64.xml | 1 + tests/domaincapsdata/qemu_6.0.0.aarch64.xml | 1 + tests/domaincapsdata/qemu_6.0.0.s390x.xml | 1 + tests/domaincapsdata/qemu_6.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_6.1.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_6.1.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_6.1.0.x86_64.xml | 1 + .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 1 + .../qemu_6.2.0-virt.aarch64.xml | 1 + tests/domaincapsdata/qemu_6.2.0.aarch64.xml | 1 + tests/domaincapsdata/qemu_6.2.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 1 + .../domaincapsdata/qemu_7.0.0-q35.x86_64.xml | 10 +++++ .../domaincapsdata/qemu_7.0.0-tcg.x86_64.xml | 10 +++++ .../qemu_7.0.0-virt.aarch64.xml | 1 + tests/domaincapsdata/qemu_7.0.0.aarch64.xml | 1 + tests/domaincapsdata/qemu_7.0.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_7.0.0.x86_64.xml | 10 +++++ .../domaincapsdata/qemu_7.1.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_7.1.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_7.1.0.ppc64.xml | 1 + tests/domaincapsdata/qemu_7.1.0.x86_64.xml | 1 + .../domaincapsdata/qemu_7.2.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_7.2.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_7.2.0.x86_64.xml | 1 + 62 files changed, 220 insertions(+) diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst index f95d3a7083..532fea0f60 100644 --- a/docs/formatdomaincaps.rst +++ b/docs/formatdomaincaps.rst @@ -614,6 +614,16 @@ capabilities. All features occur as children of the main ``features`` element. <cbitpos>47</cbitpos> <reduced-phys-bits>1</reduced-phys-bits> </sev> + <sgx supported='yes'> + <flc>no</flc> + <sgx1>yes</sgx1> + <sgx2>no</sgx2> + <section_size unit='KiB'>524288</section_size> + <sections> + <section node='0' size='262144' unit='KiB'/> + <section node='1' size='262144' unit='KiB'/> + </sections> + </sgx> </features> </domainCapabilities> @@ -693,3 +703,33 @@ in domain XML <formatdomain.html#launch-security>`__ ``maxESGuests`` The maximum number of SEV-ES guests that can be launched on the host. This value may be configurable in the firmware for some hosts. + +SGX capabilities +^^^^^^^^^^^^^^^^ + +Intel Software Guard Extensions (Intel SGX) capabilities are exposed under the +``sgx`` element. + +Intel SGX helps protect data in use via unique application isolation technology. +Protect selected code and data from modification using hardened enclaves with +Intel SGX. + +For more details on the SGX feature, please follow resources in the SGX developer's +document store. In order to use SGX with libvirt have a look at `SGX in domain XML +<formatdomain.html#memory-devices>`__ + +``flc`` + FLC (Flexible Launch Control), not strictly part of SGX2, but was not part of + original SGX hardware either. + +``sgx1`` + the sgx version 1. + +``sgx2`` + The sgx version 2. + +``section_size`` + The size of the SGX enclave page cache (called EPC). + +``sections`` + The sections of the SGX enclave page cache (called EPC). diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index daeaee3c5c..247cfa49de 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -99,6 +99,7 @@ virDomainCapsDispose(void *obj) virObjectUnref(caps->cpu.custom); virCPUDefFree(caps->cpu.hostModel); virSEVCapabilitiesFree(caps->sev); + virSGXCapabilitiesFree(caps->sgx); values = &caps->os.loader.values; for (i = 0; i < values->nvalues; i++) @@ -648,6 +649,40 @@ virDomainCapsFeatureSEVFormat(virBuffer *buf, virBufferAddLit(buf, "</sev>\n"); } +static void +virDomainCapsFeatureSGXFormat(virBuffer *buf, + const virSGXCapability *sgx) +{ + if (!sgx) { + virBufferAddLit(buf, "<sgx supported='no'/>\n"); + return; + } + + virBufferAddLit(buf, "<sgx supported='yes'>\n"); + virBufferAdjustIndent(buf, 2); + virBufferAsprintf(buf, "<flc>%s</flc>\n", sgx->flc ? "yes" : "no"); + virBufferAsprintf(buf, "<sgx1>%s</sgx1>\n", sgx->sgx1 ? "yes" : "no"); + virBufferAsprintf(buf, "<sgx2>%s</sgx2>\n", sgx->sgx2 ? "yes" : "no"); + virBufferAsprintf(buf, "<section_size unit='KiB'>%llu</section_size>\n", sgx->section_size); + + if (sgx->nSgxSections > 0) { + size_t i; + + virBufferAddLit(buf, "<sections>\n"); + + for (i = 0; i < sgx->nSgxSections; i++) { + virBufferAdjustIndent(buf, 2); + virBufferAsprintf(buf, "<section node='%d' ", sgx->sgxSections[i].node); + virBufferAsprintf(buf, "size='%llu' ", sgx->sgxSections[i].size); + virBufferAddLit(buf, "unit='KiB'/>\n"); + virBufferAdjustIndent(buf, -2); + } + virBufferAddLit(buf, "</sections>\n"); + } + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</sgx>\n"); +} static void virDomainCapsFormatFeatures(const virDomainCaps *caps, @@ -668,6 +703,7 @@ virDomainCapsFormatFeatures(const virDomainCaps *caps, } virDomainCapsFeatureSEVFormat(&childBuf, caps->sev); + virDomainCapsFeatureSGXFormat(&childBuf, caps->sgx); virXMLFormatElement(buf, "features", NULL, &childBuf); } diff --git a/src/conf/schemas/domaincaps.rng b/src/conf/schemas/domaincaps.rng index a6747b20ef..b6408bca88 100644 --- a/src/conf/schemas/domaincaps.rng +++ b/src/conf/schemas/domaincaps.rng @@ -293,6 +293,9 @@ <optional> <ref name="sev"/> </optional> + <optional> + <ref name="sgx"/> + </optional> </element> </define> @@ -353,6 +356,46 @@ </element> </define> + <define name="sgx"> + <element name="sgx"> + <ref name="supported"/> + <optional> + <element name="flc"> + <ref name="virYesNo"/> + </element> + <element name="sgx1"> + <ref name="virYesNo"/> + </element> + <element name="sgx2"> + <ref name="virYesNo"/> + </element> + <element name="section_size"> + <attribute name="unit"> + <value>KiB</value> + </attribute> + <data type="unsignedLong"/> + </element> + <optional> + <element name="sections"> + <zeroOrMore> + <element name="section"> + <attribute name="node"> + <data type="unsignedInt"/> + </attribute> + <attribute name="size"> + <data type="unsignedLong"/> + </attribute> + <attribute name="unit"> + <value>KiB</value> + </attribute> + </element> + </zeroOrMore> + </element> + </optional> + </optional> + </element> + </define> + <define name="value"> <zeroOrMore> <element name="value"> diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 7c9d7ed885..d3ba8c85c9 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -6633,6 +6633,21 @@ virQEMUCapsFillDomainFeatureS390PVCaps(virQEMUCaps *qemuCaps, } } +/** + * virQEMUCapsFillDomainFeatureSGXCaps: + * @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(virQEMUCaps *qemuCaps, + virDomainCaps *domCaps) +{ + virQEMUCapsSGXInfoCopy(&domCaps->sgx, qemuCaps->sgxCapabilities); +} int virQEMUCapsFillDomainCaps(virQEMUCaps *qemuCaps, @@ -6689,6 +6704,7 @@ virQEMUCapsFillDomainCaps(virQEMUCaps *qemuCaps, virQEMUCapsFillDomainFeatureGICCaps(qemuCaps, domCaps); virQEMUCapsFillDomainFeatureSEVCaps(qemuCaps, domCaps); virQEMUCapsFillDomainFeatureS390PVCaps(qemuCaps, domCaps); + virQEMUCapsFillDomainFeatureSGXCaps(qemuCaps, domCaps); return 0; } diff --git a/tests/domaincapsdata/bhyve_basic.x86_64.xml b/tests/domaincapsdata/bhyve_basic.x86_64.xml index 745f325531..dd054577c0 100644 --- a/tests/domaincapsdata/bhyve_basic.x86_64.xml +++ b/tests/domaincapsdata/bhyve_basic.x86_64.xml @@ -33,5 +33,6 @@ <vmcoreinfo supported='no'/> <genid supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/bhyve_fbuf.x86_64.xml b/tests/domaincapsdata/bhyve_fbuf.x86_64.xml index bb11c02ae9..0b1d9c17d7 100644 --- a/tests/domaincapsdata/bhyve_fbuf.x86_64.xml +++ b/tests/domaincapsdata/bhyve_fbuf.x86_64.xml @@ -50,5 +50,6 @@ <vmcoreinfo supported='no'/> <genid supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/bhyve_uefi.x86_64.xml b/tests/domaincapsdata/bhyve_uefi.x86_64.xml index dfd2360d74..69fff197a7 100644 --- a/tests/domaincapsdata/bhyve_uefi.x86_64.xml +++ b/tests/domaincapsdata/bhyve_uefi.x86_64.xml @@ -42,5 +42,6 @@ <vmcoreinfo supported='no'/> <genid supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/empty.xml b/tests/domaincapsdata/empty.xml index d3e2d89b60..97752ca04a 100644 --- a/tests/domaincapsdata/empty.xml +++ b/tests/domaincapsdata/empty.xml @@ -13,5 +13,6 @@ </devices> <features> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/libxl-xenfv.xml b/tests/domaincapsdata/libxl-xenfv.xml index cc5b3847e2..c71d759517 100644 --- a/tests/domaincapsdata/libxl-xenfv.xml +++ b/tests/domaincapsdata/libxl-xenfv.xml @@ -76,5 +76,6 @@ <vmcoreinfo supported='no'/> <genid supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/libxl-xenpv.xml b/tests/domaincapsdata/libxl-xenpv.xml index 325f1e50b3..8ae2370b7e 100644 --- a/tests/domaincapsdata/libxl-xenpv.xml +++ b/tests/domaincapsdata/libxl-xenpv.xml @@ -66,5 +66,6 @@ <vmcoreinfo supported='no'/> <genid supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml index def80fe8cd..9375fc9457 100644 --- a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml @@ -236,5 +236,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_4.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_4.2.0-tcg.x86_64.xml index 9e920d1ccb..860ffd1047 100644 --- a/tests/domaincapsdata/qemu_4.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_4.2.0-tcg.x86_64.xml @@ -251,5 +251,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_4.2.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_4.2.0-virt.aarch64.xml index 776173e60e..02aca3e448 100644 --- a/tests/domaincapsdata/qemu_4.2.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_4.2.0-virt.aarch64.xml @@ -184,5 +184,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_4.2.0.aarch64.xml b/tests/domaincapsdata/qemu_4.2.0.aarch64.xml index b6711fc3a4..676e1b0739 100644 --- a/tests/domaincapsdata/qemu_4.2.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_4.2.0.aarch64.xml @@ -178,5 +178,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_4.2.0.ppc64.xml b/tests/domaincapsdata/qemu_4.2.0.ppc64.xml index 88790451b0..bcc415d7de 100644 --- a/tests/domaincapsdata/qemu_4.2.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_4.2.0.ppc64.xml @@ -151,5 +151,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_4.2.0.s390x.xml b/tests/domaincapsdata/qemu_4.2.0.s390x.xml index fa416af038..4f176e2d37 100644 --- a/tests/domaincapsdata/qemu_4.2.0.s390x.xml +++ b/tests/domaincapsdata/qemu_4.2.0.s390x.xml @@ -258,5 +258,6 @@ <backup supported='no'/> <s390-pv supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_4.2.0.x86_64.xml b/tests/domaincapsdata/qemu_4.2.0.x86_64.xml index ed9de89dfa..0187584e6b 100644 --- a/tests/domaincapsdata/qemu_4.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_4.2.0.x86_64.xml @@ -236,5 +236,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_5.0.0-q35.x86_64.xml index af0335eb3a..3f534b77a2 100644 --- a/tests/domaincapsdata/qemu_5.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_5.0.0-q35.x86_64.xml @@ -238,5 +238,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_5.0.0-tcg.x86_64.xml index fc09e9ff28..2826ce58e1 100644 --- a/tests/domaincapsdata/qemu_5.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_5.0.0-tcg.x86_64.xml @@ -253,5 +253,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.0.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_5.0.0-virt.aarch64.xml index 88bc77f50b..1ae7dfdc01 100644 --- a/tests/domaincapsdata/qemu_5.0.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_5.0.0-virt.aarch64.xml @@ -196,5 +196,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.0.0.aarch64.xml b/tests/domaincapsdata/qemu_5.0.0.aarch64.xml index 5e030047d1..74db0a2561 100644 --- a/tests/domaincapsdata/qemu_5.0.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_5.0.0.aarch64.xml @@ -190,5 +190,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.0.0.ppc64.xml b/tests/domaincapsdata/qemu_5.0.0.ppc64.xml index 0c5aaade40..804172d013 100644 --- a/tests/domaincapsdata/qemu_5.0.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_5.0.0.ppc64.xml @@ -157,5 +157,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.0.0.x86_64.xml b/tests/domaincapsdata/qemu_5.0.0.x86_64.xml index 5b2a0bc83d..a83e942ca5 100644 --- a/tests/domaincapsdata/qemu_5.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_5.0.0.x86_64.xml @@ -238,5 +238,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_5.1.0-q35.x86_64.xml index fb9f69bb9a..f10a106d9a 100644 --- a/tests/domaincapsdata/qemu_5.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_5.1.0-q35.x86_64.xml @@ -239,5 +239,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.1.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_5.1.0-tcg.x86_64.xml index ea31348ab1..a2a3b501cc 100644 --- a/tests/domaincapsdata/qemu_5.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_5.1.0-tcg.x86_64.xml @@ -253,5 +253,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.1.0.sparc.xml b/tests/domaincapsdata/qemu_5.1.0.sparc.xml index 5bbf4720dc..cde31462bc 100644 --- a/tests/domaincapsdata/qemu_5.1.0.sparc.xml +++ b/tests/domaincapsdata/qemu_5.1.0.sparc.xml @@ -125,5 +125,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.1.0.x86_64.xml b/tests/domaincapsdata/qemu_5.1.0.x86_64.xml index 584dad5a89..926ac6c231 100644 --- a/tests/domaincapsdata/qemu_5.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_5.1.0.x86_64.xml @@ -239,5 +239,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_5.2.0-q35.x86_64.xml index f1d20991e9..31ff03f9f0 100644 --- a/tests/domaincapsdata/qemu_5.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_5.2.0-q35.x86_64.xml @@ -239,5 +239,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_5.2.0-tcg.x86_64.xml index cec260f56d..fdaa0ae5bc 100644 --- a/tests/domaincapsdata/qemu_5.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_5.2.0-tcg.x86_64.xml @@ -253,5 +253,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.2.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_5.2.0-virt.aarch64.xml index be7262211c..762fbe2f50 100644 --- a/tests/domaincapsdata/qemu_5.2.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_5.2.0-virt.aarch64.xml @@ -196,5 +196,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.2.0.aarch64.xml b/tests/domaincapsdata/qemu_5.2.0.aarch64.xml index 5e030047d1..74db0a2561 100644 --- a/tests/domaincapsdata/qemu_5.2.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_5.2.0.aarch64.xml @@ -190,5 +190,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.2.0.ppc64.xml b/tests/domaincapsdata/qemu_5.2.0.ppc64.xml index 9367738157..02e038d445 100644 --- a/tests/domaincapsdata/qemu_5.2.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_5.2.0.ppc64.xml @@ -157,5 +157,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.2.0.s390x.xml b/tests/domaincapsdata/qemu_5.2.0.s390x.xml index adc197648f..760f514d7b 100644 --- a/tests/domaincapsdata/qemu_5.2.0.s390x.xml +++ b/tests/domaincapsdata/qemu_5.2.0.s390x.xml @@ -260,5 +260,6 @@ <backup supported='no'/> <s390-pv supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_5.2.0.x86_64.xml b/tests/domaincapsdata/qemu_5.2.0.x86_64.xml index a3707e6804..cfd6ff1d84 100644 --- a/tests/domaincapsdata/qemu_5.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_5.2.0.x86_64.xml @@ -239,5 +239,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml index 7edb84e9bc..048c47e9f6 100644 --- a/tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml @@ -246,5 +246,6 @@ <maxGuests>59</maxGuests> <maxESGuests>450</maxESGuests> </sev> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml index a7b5d3047a..75bf330a79 100644 --- a/tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml @@ -261,5 +261,6 @@ <maxGuests>59</maxGuests> <maxESGuests>450</maxESGuests> </sev> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.0.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_6.0.0-virt.aarch64.xml index db9b45d74e..30446b75f7 100644 --- a/tests/domaincapsdata/qemu_6.0.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_6.0.0-virt.aarch64.xml @@ -198,5 +198,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.0.0.aarch64.xml b/tests/domaincapsdata/qemu_6.0.0.aarch64.xml index 1a65156544..6c30318d34 100644 --- a/tests/domaincapsdata/qemu_6.0.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_6.0.0.aarch64.xml @@ -192,5 +192,6 @@ <backingStoreInput supported='yes'/> <backup supported='no'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.0.0.s390x.xml b/tests/domaincapsdata/qemu_6.0.0.s390x.xml index 56d87f7a2f..b1968668db 100644 --- a/tests/domaincapsdata/qemu_6.0.0.s390x.xml +++ b/tests/domaincapsdata/qemu_6.0.0.s390x.xml @@ -261,5 +261,6 @@ <backup supported='no'/> <s390-pv supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.0.0.x86_64.xml b/tests/domaincapsdata/qemu_6.0.0.x86_64.xml index 3afab2f4c2..8b9e910fdc 100644 --- a/tests/domaincapsdata/qemu_6.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.0.0.x86_64.xml @@ -246,5 +246,6 @@ <maxGuests>59</maxGuests> <maxESGuests>450</maxESGuests> </sev> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_6.1.0-q35.x86_64.xml index d0dbadd6d3..bc4912bc62 100644 --- a/tests/domaincapsdata/qemu_6.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.1.0-q35.x86_64.xml @@ -242,5 +242,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.1.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_6.1.0-tcg.x86_64.xml index 6354573c61..6cbdb1d6ae 100644 --- a/tests/domaincapsdata/qemu_6.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.1.0-tcg.x86_64.xml @@ -256,5 +256,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.1.0.x86_64.xml b/tests/domaincapsdata/qemu_6.1.0.x86_64.xml index 17c30b394d..5efb7b595c 100644 --- a/tests/domaincapsdata/qemu_6.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.1.0.x86_64.xml @@ -242,5 +242,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml index c185ae4510..1281dc5ff8 100644 --- a/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml @@ -242,5 +242,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml index 8a009ee070..2fcff7a96f 100644 --- a/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml @@ -258,5 +258,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.2.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_6.2.0-virt.aarch64.xml index 3d79cd7486..5aa8820612 100644 --- a/tests/domaincapsdata/qemu_6.2.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-virt.aarch64.xml @@ -205,5 +205,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.2.0.aarch64.xml b/tests/domaincapsdata/qemu_6.2.0.aarch64.xml index 4ccffb3695..96c426cd4f 100644 --- a/tests/domaincapsdata/qemu_6.2.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_6.2.0.aarch64.xml @@ -199,5 +199,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.2.0.ppc64.xml b/tests/domaincapsdata/qemu_6.2.0.ppc64.xml index ba7bc17a98..350c55e2c0 100644 --- a/tests/domaincapsdata/qemu_6.2.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_6.2.0.ppc64.xml @@ -156,5 +156,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_6.2.0.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0.x86_64.xml index ba40728489..ae789c3a9b 100644 --- a/tests/domaincapsdata/qemu_6.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0.x86_64.xml @@ -242,5 +242,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml index 94c6f3d712..59b2988de0 100644 --- a/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml @@ -243,5 +243,15 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='yes'> + <flc>no</flc> + <sgx1>yes</sgx1> + <sgx2>no</sgx2> + <section_size unit='KiB'>524288</section_size> + <sections> + <section node='0' size='262144' unit='KiB'/> + <section node='1' size='262144' unit='KiB'/> + </sections> + </sgx> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml index 945ad91c66..58d8bdee3f 100644 --- a/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml @@ -259,5 +259,15 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='yes'> + <flc>no</flc> + <sgx1>yes</sgx1> + <sgx2>no</sgx2> + <section_size unit='KiB'>524288</section_size> + <sections> + <section node='0' size='262144' unit='KiB'/> + <section node='1' size='262144' unit='KiB'/> + </sections> + </sgx> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_7.0.0-virt.aarch64.xml b/tests/domaincapsdata/qemu_7.0.0-virt.aarch64.xml index 3addb1fc57..4ec23a8b85 100644 --- a/tests/domaincapsdata/qemu_7.0.0-virt.aarch64.xml +++ b/tests/domaincapsdata/qemu_7.0.0-virt.aarch64.xml @@ -204,5 +204,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_7.0.0.aarch64.xml b/tests/domaincapsdata/qemu_7.0.0.aarch64.xml index 9f07a10a90..d3f90db5a8 100644 --- a/tests/domaincapsdata/qemu_7.0.0.aarch64.xml +++ b/tests/domaincapsdata/qemu_7.0.0.aarch64.xml @@ -198,5 +198,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_7.0.0.ppc64.xml b/tests/domaincapsdata/qemu_7.0.0.ppc64.xml index ed6c74aac1..e9322a02e2 100644 --- a/tests/domaincapsdata/qemu_7.0.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_7.0.0.ppc64.xml @@ -161,5 +161,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_7.0.0.x86_64.xml b/tests/domaincapsdata/qemu_7.0.0.x86_64.xml index 5913f44937..368c359dcf 100644 --- a/tests/domaincapsdata/qemu_7.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.0.0.x86_64.xml @@ -243,5 +243,15 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='yes'> + <flc>no</flc> + <sgx1>yes</sgx1> + <sgx2>no</sgx2> + <section_size unit='KiB'>524288</section_size> + <sections> + <section node='0' size='262144' unit='KiB'/> + <section node='1' size='262144' unit='KiB'/> + </sections> + </sgx> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml index 2d76581915..831ef667e9 100644 --- a/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml @@ -242,5 +242,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml index f4933e435f..e5d5768b40 100644 --- a/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml @@ -257,5 +257,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_7.1.0.ppc64.xml b/tests/domaincapsdata/qemu_7.1.0.ppc64.xml index a5c2d8e598..73c2cb84e4 100644 --- a/tests/domaincapsdata/qemu_7.1.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_7.1.0.ppc64.xml @@ -154,5 +154,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_7.1.0.x86_64.xml b/tests/domaincapsdata/qemu_7.1.0.x86_64.xml index a419005ee3..0e2aa77a7d 100644 --- a/tests/domaincapsdata/qemu_7.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.1.0.x86_64.xml @@ -242,5 +242,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml index 2d0d0ad8e3..8c6399a7b6 100644 --- a/tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.2.0-q35.x86_64.xml @@ -247,5 +247,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml index 5f22698400..b04beaa9d6 100644 --- a/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.2.0-tcg.x86_64.xml @@ -246,5 +246,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> diff --git a/tests/domaincapsdata/qemu_7.2.0.x86_64.xml b/tests/domaincapsdata/qemu_7.2.0.x86_64.xml index 234d2f3672..86385dacbd 100644 --- a/tests/domaincapsdata/qemu_7.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.2.0.x86_64.xml @@ -247,5 +247,6 @@ <backingStoreInput supported='yes'/> <backup supported='yes'/> <sev supported='no'/> + <sgx supported='no'/> </features> </domainCapabilities> -- 2.25.1

<devices> ... <memory model='sgx-epc'> <source> <nodemask>0-1</nodemask> </source> <target> <size unit='KiB'>512</size> <node>0</node> </target> </memory> ... </devices> Signed-off-by: Lin Yang <lin.a.yang@intel.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Haibin Huang <haibin.huang@intel.com> --- docs/formatdomain.rst | 25 ++++++- src/conf/domain_conf.c | 30 +++++++++ src/conf/domain_conf.h | 1 + src/conf/domain_postparse.c | 1 + src/conf/domain_validate.c | 9 +++ src/conf/schemas/domaincommon.rng | 1 + src/qemu/qemu_alias.c | 3 + src/qemu/qemu_command.c | 1 + src/qemu/qemu_domain.c | 28 ++++++-- src/qemu/qemu_domain_address.c | 6 ++ src/qemu/qemu_driver.c | 1 + src/qemu/qemu_process.c | 2 + src/qemu/qemu_validate.c | 8 +++ src/security/security_apparmor.c | 1 + src/security/security_dac.c | 2 + src/security/security_selinux.c | 2 + tests/qemuxml2argvdata/sgx-epc.xml | 65 +++++++++++++++++++ .../sgx-epc.x86_64-7.0.0.xml | 65 +++++++++++++++++++ tests/qemuxml2xmltest.c | 2 + 19 files changed, 248 insertions(+), 5 deletions(-) create mode 100644 tests/qemuxml2argvdata/sgx-epc.xml create mode 100644 tests/qemuxml2xmloutdata/sgx-epc.x86_64-7.0.0.xml diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 488b6be862..d7fffc6e0b 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -8002,6 +8002,20 @@ Example: usage of the memory devices <current unit='KiB'>524288</current> </target> </memory> + <memory model='sgx-epc'> + <source> + <nodemask>0-1</nodemask> + </source> + <target> + <size unit='KiB'>16384</size> + <node>0</node> + </target> + </memory> + <memory model='sgx-epc'> + <target> + <size unit='KiB'>16384</size> + </target> + </memory> </devices> ... @@ -8010,7 +8024,9 @@ Example: usage of the memory devices 1.2.14` Provide ``nvdimm`` model that adds a Non-Volatile DIMM module. :since:`Since 3.2.0` Provide ``virtio-pmem`` model to add a paravirtualized persistent memory device. :since:`Since 7.1.0` Provide ``virtio-mem`` model - to add paravirtualized memory device. :since:`Since 7.9.0` + to add paravirtualized memory device. :since:`Since 7.9.0` Provide + ``sgx-epc`` model to add a SGX enclave page cache (EPC) memory to the guest. + :since:`Since 8.10.0 and QEMU 7.0.0` ``access`` An optional attribute ``access`` ( :since:`since 3.2.0` ) that provides @@ -8070,6 +8086,13 @@ Example: usage of the memory devices Represents a path in the host that backs the virtio memory module in the guest. It is mandatory. + For model ``sgx-epc`` this element is optional. The following optional + elements may be used: + + ``nodemask`` + This element can be used to override the default set of NUMA nodes where + the memory would be allocated. :since:`Since 8.10.0 and QEMU 7.0.0` + ``target`` The mandatory ``target`` element configures the placement and sizing of the added memory from the perspective of the guest. diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index cbc08064c4..622f83590f 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1444,6 +1444,7 @@ VIR_ENUM_IMPL(virDomainMemoryModel, "nvdimm", "virtio-pmem", "virtio-mem", + "sgx-epc", ); VIR_ENUM_IMPL(virDomainShmemModel, @@ -13054,6 +13055,20 @@ virDomainMemorySourceDefParseXML(xmlNodePtr node, def->nvdimmPath = virXPathString("string(./path)", ctxt); break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + if ((nodemask = virXPathString("string(./nodemask)", ctxt))) { + if (virBitmapParse(nodemask, &def->sourceNodes, + VIR_DOMAIN_CPUMASK_LEN) < 0) + return -1; + + if (virBitmapIsAllClear(def->sourceNodes)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Invalid value of 'nodemask': %s"), nodemask); + return -1; + } + } + break; + case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -13122,6 +13137,7 @@ virDomainMemoryTargetDefParseXML(xmlNodePtr node, case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; } @@ -14918,6 +14934,11 @@ virDomainMemoryFindByDefInternal(virDomainDef *def, continue; break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + if (!virBitmapEqual(tmp->sourceNodes, mem->sourceNodes)) + continue; + break; + case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -24535,6 +24556,15 @@ virDomainMemorySourceDefFormat(virBuffer *buf, virBufferEscapeString(&childBuf, "<path>%s</path>\n", def->nvdimmPath); break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + if (def->sourceNodes) { + if (!(bitmap = virBitmapFormat(def->sourceNodes))) + return -1; + + virBufferAsprintf(&childBuf, "<nodemask>%s</nodemask>\n", bitmap); + } + break; + case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index a076471808..e16558988d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2585,6 +2585,7 @@ typedef enum { VIR_DOMAIN_MEMORY_MODEL_NVDIMM, /* nvdimm memory device */ VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM, /* virtio-pmem memory device */ VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM, /* virtio-mem memory device */ + VIR_DOMAIN_MEMORY_MODEL_SGX_EPC, /* SGX enclave page cache */ VIR_DOMAIN_MEMORY_MODEL_LAST } virDomainMemoryModel; diff --git a/src/conf/domain_postparse.c b/src/conf/domain_postparse.c index df59de2d0d..9a3e8f494c 100644 --- a/src/conf/domain_postparse.c +++ b/src/conf/domain_postparse.c @@ -645,6 +645,7 @@ virDomainMemoryDefPostParse(virDomainMemoryDef *mem, break; case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index 81f6d5dbd5..5bc7ea10aa 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -2360,6 +2360,15 @@ virDomainMemoryDefValidate(const virDomainMemoryDef *mem, case VIR_DOMAIN_MEMORY_MODEL_DIMM: break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + if (mem->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("memory device address is not supported for model '%s'"), + virDomainMemoryModelTypeToString(mem->model)); + return -1; + } + break; + case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: default: diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 03703148df..8bc627d114 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -6909,6 +6909,7 @@ <value>nvdimm</value> <value>virtio-pmem</value> <value>virtio-mem</value> + <value>sgx-epc</value> </choice> </attribute> <optional> diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index 835401dc07..6061dd3f02 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -513,6 +513,9 @@ qemuAssignDeviceMemoryAlias(virDomainDef *def, case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: prefix = "virtiomem"; break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + prefix = "epc"; + break; case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: default: diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 18a36495b9..4ef979e278 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3562,6 +3562,7 @@ qemuBuildMemoryDeviceProps(virQEMUDriverConfig *cfg, return NULL; break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: default: diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 3435da5bdc..0d579bfc9b 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -8383,6 +8383,7 @@ qemuDomainUpdateMemoryDeviceInfo(virDomainObj *vm, break; case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -9064,6 +9065,12 @@ qemuDomainDefValidateMemoryHotplugDevice(const virDomainMemoryDef *mem, } break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("hotplug is not supported for the %s device"), + virDomainMemoryModelTypeToString(mem->model)); + return -1; + case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: return -1; @@ -9148,10 +9155,23 @@ qemuDomainDefValidateMemoryHotplug(const virDomainDef *def, for (i = 0; i < def->nmems; i++) { hotplugMemory += def->mems[i]->size; - /* already existing devices don't need to be checked on hotplug */ - if (!mem && - qemuDomainDefValidateMemoryHotplugDevice(def->mems[i], def) < 0) - return -1; + switch (def->mems[i]->model) { + case VIR_DOMAIN_MEMORY_MODEL_DIMM: + case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + /* already existing devices don't need to be checked on hotplug */ + if (!mem && + qemuDomainDefValidateMemoryHotplugDevice(def->mems[i], def) < 0) + return -1; + break; + + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + /* sgx epc memory does not support hotplug, skip this check */ + case VIR_DOMAIN_MEMORY_MODEL_LAST: + case VIR_DOMAIN_MEMORY_MODEL_NONE: + break; + } } if (hotplugMemory > hotplugSpace) { diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index d8ec6ec71c..b8d1969fbe 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -389,6 +389,7 @@ qemuDomainPrimeVirtioDeviceAddresses(virDomainDef *def, case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; } @@ -1038,6 +1039,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev, case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: return 0; } @@ -2420,6 +2422,7 @@ qemuDomainAssignDevicePCISlots(virDomainDef *def, case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; } @@ -3080,6 +3083,7 @@ qemuDomainAssignMemoryDeviceSlot(virDomainObj *vm, return qemuDomainEnsurePCIAddress(vm, &dev); break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -3106,6 +3110,7 @@ qemuDomainReleaseMemoryDeviceSlot(virDomainObj *vm, qemuDomainReleaseDeviceAddress(vm, &mem->info); break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -3139,6 +3144,7 @@ qemuDomainAssignMemorySlots(virDomainDef *def) case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: /* handled in qemuDomainAssignPCIAddresses() */ break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c7c966503e..ff5a743716 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6831,6 +6831,7 @@ qemuDomainChangeMemoryLiveValidateChange(const virDomainMemoryDef *oldDef, case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("cannot modify memory of model '%s'"), diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 5a72e35308..4b26c384cf 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3871,6 +3871,7 @@ qemuProcessDomainMemoryDefNeedHugepagesPath(const virDomainMemoryDef *mem, case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: /* None of these can be backed by hugepages. */ return false; @@ -3955,6 +3956,7 @@ qemuProcessNeedMemoryBackingPath(virDomainDef *def, case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: /* Backed by user provided path. Not stored in memory * backing dir anyway. */ diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 4a01fe4d14..3b44c5e139 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -5025,6 +5025,14 @@ qemuValidateDomainDeviceDefMemory(virDomainMemoryDef *mem, } break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SGX_EPC)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("sgx epc isn't supported by this QEMU binary")); + return -1; + } + break; + case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c index 008384dee8..36e8ce42b5 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -687,6 +687,7 @@ AppArmorSetMemoryLabel(virSecurityManager *mgr, case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; } diff --git a/src/security/security_dac.c b/src/security/security_dac.c index 21cebae694..d94995c9cf 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1853,6 +1853,7 @@ virSecurityDACRestoreMemoryLabel(virSecurityManager *mgr, case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: case VIR_DOMAIN_MEMORY_MODEL_NONE: ret = 0; @@ -2040,6 +2041,7 @@ virSecurityDACSetMemoryLabel(virSecurityManager *mgr, case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: case VIR_DOMAIN_MEMORY_MODEL_NONE: ret = 0; diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index a296cb7613..1f72f61cac 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -1580,6 +1580,7 @@ virSecuritySELinuxSetMemoryLabel(virSecurityManager *mgr, case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; } @@ -1608,6 +1609,7 @@ virSecuritySELinuxRestoreMemoryLabel(virSecurityManager *mgr, case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: ret = 0; diff --git a/tests/qemuxml2argvdata/sgx-epc.xml b/tests/qemuxml2argvdata/sgx-epc.xml new file mode 100644 index 0000000000..f6cbc67a51 --- /dev/null +++ b/tests/qemuxml2argvdata/sgx-epc.xml @@ -0,0 +1,65 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <maxMemory slots='16' unit='KiB'>1130496</maxMemory> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='pc-q35-7.0'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + <numa> + <cell id='0' cpus='0' memory='524288' unit='KiB'/> + <cell id='1' cpus='1' memory='524288' unit='KiB'/> + </numa> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='pci' index='0' model='pcie-root'/> + <controller type='pci' index='1' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='1' port='0x8'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/> + </controller> + <controller type='pci' index='2' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='2' port='0x9'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='usb' index='0' model='none'/> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </memballoon> + <memory model='sgx-epc'> + <source> + <nodemask>0-1</nodemask> + </source> + <target> + <size unit='KiB'>65536</size> + <node>0</node> + </target> + </memory> + <memory model='sgx-epc'> + <source> + <nodemask>0-1</nodemask> + </source> + <target> + <size unit='KiB'>16384</size> + <node>1</node> + </target> + </memory> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/sgx-epc.x86_64-7.0.0.xml b/tests/qemuxml2xmloutdata/sgx-epc.x86_64-7.0.0.xml new file mode 100644 index 0000000000..f6cbc67a51 --- /dev/null +++ b/tests/qemuxml2xmloutdata/sgx-epc.x86_64-7.0.0.xml @@ -0,0 +1,65 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <maxMemory slots='16' unit='KiB'>1130496</maxMemory> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='pc-q35-7.0'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + <numa> + <cell id='0' cpus='0' memory='524288' unit='KiB'/> + <cell id='1' cpus='1' memory='524288' unit='KiB'/> + </numa> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='pci' index='0' model='pcie-root'/> + <controller type='pci' index='1' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='1' port='0x8'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/> + </controller> + <controller type='pci' index='2' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='2' port='0x9'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='usb' index='0' model='none'/> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </memballoon> + <memory model='sgx-epc'> + <source> + <nodemask>0-1</nodemask> + </source> + <target> + <size unit='KiB'>65536</size> + <node>0</node> + </target> + </memory> + <memory model='sgx-epc'> + <source> + <nodemask>0-1</nodemask> + </source> + <target> + <size unit='KiB'>16384</size> + <node>1</node> + </target> + </memory> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 1b74a81f26..e13da8bd2c 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -1295,6 +1295,8 @@ mymain(void) DO_TEST_CAPS_LATEST("channel-qemu-vdagent"); DO_TEST_CAPS_LATEST("channel-qemu-vdagent-features"); + DO_TEST_CAPS_VER("sgx-epc", "7.0.0"); + cleanup: if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) virFileDeleteTree(fakerootdir); -- 2.25.1

From: Michal Privoznik <mprivozn@redhat.com> SGX memory backend needs to access /dev/sgx_vepc (which allows userspace to allocate "raw" EPC without an associated enclave) and /dev/sgx_provision (which allows creating provisioning enclaves). Allow these two devices in CGroups if a domain is configured so. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Haibin Huang <haibin.huang@intel.com> --- src/qemu/qemu_cgroup.c | 78 +++++++++++++++++++++++++++++++++++------- src/qemu/qemu_domain.h | 2 ++ 2 files changed, 68 insertions(+), 12 deletions(-) diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index d6f27a5a4d..9cd4bf8b98 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -120,6 +120,28 @@ qemuCgroupDenyDevicePath(virDomainObj *vm, } +static int +qemuCgroupDenyDevicesPaths(virDomainObj *vm, + const char *const *paths, + int perms, + bool ignoreEacces) +{ + size_t i; + + for (i = 0; paths[i] != NULL; i++) { + if (!virFileExists(paths[i])) { + VIR_DEBUG("Ignoring non-existent device %s", paths[i]); + continue; + } + + if (qemuCgroupDenyDevicePath(vm, paths[i], perms, ignoreEacces) < 0) + return -1; + } + + return 0; +} + + static int qemuSetupImagePathCgroup(virDomainObj *vm, const char *path, @@ -520,16 +542,32 @@ qemuSetupMemoryDevicesCgroup(virDomainObj *vm, virDomainMemoryDef *mem) { qemuDomainObjPrivate *priv = vm->privateData; - - if (mem->model != VIR_DOMAIN_MEMORY_MODEL_NVDIMM && - mem->model != VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM) - return 0; + const char *const sgxPaths[] = { QEMU_DEV_SGX_VEPVC, + QEMU_DEV_SGX_PROVISION, NULL }; if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) return 0; - return qemuCgroupAllowDevicePath(vm, mem->nvdimmPath, - VIR_CGROUP_DEVICE_RW, false); + switch (mem->model) { + case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: + if (qemuCgroupAllowDevicePath(vm, mem->nvdimmPath, + VIR_CGROUP_DEVICE_RW, false) < 0) + return -1; + break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + if (qemuCgroupAllowDevicesPaths(vm, sgxPaths, + VIR_CGROUP_DEVICE_RW, false) < 0) + return -1; + break; + case VIR_DOMAIN_MEMORY_MODEL_NONE: + case VIR_DOMAIN_MEMORY_MODEL_DIMM: + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_LAST: + break; + } + + return 0; } @@ -538,16 +576,32 @@ qemuTeardownMemoryDevicesCgroup(virDomainObj *vm, virDomainMemoryDef *mem) { qemuDomainObjPrivate *priv = vm->privateData; - - if (mem->model != VIR_DOMAIN_MEMORY_MODEL_NVDIMM && - mem->model != VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM) - return 0; + const char *const sgxPaths[] = { QEMU_DEV_SGX_VEPVC, + QEMU_DEV_SGX_PROVISION, NULL }; if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) return 0; - return qemuCgroupDenyDevicePath(vm, mem->nvdimmPath, - VIR_CGROUP_DEVICE_RWM, false); + switch (mem->model) { + case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: + if (qemuCgroupDenyDevicePath(vm, mem->nvdimmPath, + VIR_CGROUP_DEVICE_RWM, false) < 0) + return -1; + break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + if (qemuCgroupDenyDevicesPaths(vm, sgxPaths, + VIR_CGROUP_DEVICE_RW, false) < 0) + return -1; + break; + case VIR_DOMAIN_MEMORY_MODEL_NONE: + case VIR_DOMAIN_MEMORY_MODEL_DIMM: + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_LAST: + break; + } + + return 0; } diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 7950c4c2da..d5f4fbad12 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -81,6 +81,8 @@ struct _qemuDomainUnpluggingDevice { #define QEMU_DEVPREFIX "/dev/" #define QEMU_DEV_VFIO "/dev/vfio/vfio" #define QEMU_DEV_SEV "/dev/sev" +#define QEMU_DEV_SGX_VEPVC "/dev/sgx_vepc" +#define QEMU_DEV_SGX_PROVISION "/dev/sgx_provision" #define QEMU_DEVICE_MAPPER_CONTROL_PATH "/dev/mapper/control" -- 2.25.1

From: Michal Privoznik <mprivozn@redhat.com> This is similar to the previous commit. SGX memory backend needs to access /dev/sgx_vepc and /dev/sgx_provision. Create these nodes in domain's private /dev when required by domain's config. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Haibin Huang <haibin.huang@intel.com> --- src/qemu/qemu_namespace.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c index 8189cc37ba..90c0b90024 100644 --- a/src/qemu/qemu_namespace.c +++ b/src/qemu/qemu_namespace.c @@ -370,11 +370,23 @@ static int qemuDomainSetupMemory(virDomainMemoryDef *mem, GSList **paths) { - if (mem->model != VIR_DOMAIN_MEMORY_MODEL_NVDIMM && - mem->model != VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM) - return 0; + switch (mem->model) { + case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: + *paths = g_slist_prepend(*paths, g_strdup(mem->nvdimmPath)); + break; + + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + *paths = g_slist_prepend(*paths, g_strdup(QEMU_DEV_SGX_VEPVC)); + *paths = g_slist_prepend(*paths, g_strdup(QEMU_DEV_SGX_PROVISION)); + break; - *paths = g_slist_prepend(*paths, g_strdup(mem->nvdimmPath)); + case VIR_DOMAIN_MEMORY_MODEL_NONE: + case VIR_DOMAIN_MEMORY_MODEL_DIMM: + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_LAST: + break; + } return 0; } -- 2.25.1

From: Michal Privoznik <mprivozn@redhat.com> As advertised in previous commits, QEMU needs to access /dev/sgx_vepc and /dev/sgx_provision files when SGX memory backend is configured. And if it weren't for QEMU's namespaces, we wouldn't dare to relabel them, because they are system wide files. But if namespaces are used, then we can set label on domain's private copies, just like we do for /dev/sev. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Haibin Huang <haibin.huang@intel.com> --- src/security/security_dac.c | 46 ++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/src/security/security_dac.c b/src/security/security_dac.c index d94995c9cf..5ca63e30f4 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -48,6 +48,8 @@ VIR_LOG_INIT("security.security_dac"); #define SECURITY_DAC_NAME "dac" #define DEV_SEV "/dev/sev" +#define DEV_SGX_VEPC "/dev/sgx_vepc" +#define DEV_SGX_PROVISION "/dev/sgx_provision" typedef struct _virSecurityDACData virSecurityDACData; struct _virSecurityDACData { @@ -1843,24 +1845,24 @@ virSecurityDACRestoreMemoryLabel(virSecurityManager *mgr, virDomainDef *def G_GNUC_UNUSED, virDomainMemoryDef *mem) { - int ret = -1; - switch (mem->model) { case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: - ret = virSecurityDACRestoreFileLabel(mgr, mem->nvdimmPath); + return virSecurityDACRestoreFileLabel(mgr, mem->nvdimmPath); + + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + /* We set label on SGX /dev nodes iff running with namespaces, so we + * don't need to restore anything. */ break; case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: - case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: case VIR_DOMAIN_MEMORY_MODEL_NONE: - ret = 0; break; } - return ret; + return 0; } @@ -2020,35 +2022,43 @@ virSecurityDACSetMemoryLabel(virSecurityManager *mgr, { virSecurityDACData *priv = virSecurityManagerGetPrivateData(mgr); virSecurityLabelDef *seclabel; - int ret = -1; uid_t user; gid_t group; + seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME); + if (seclabel && !seclabel->relabel) + return 0; + + if (virSecurityDACGetIds(seclabel, priv, &user, &group, NULL, NULL) < 0) + return -1; + switch (mem->model) { case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: - seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME); - if (seclabel && !seclabel->relabel) - return 0; + return virSecurityDACSetOwnership(mgr, NULL, + mem->nvdimmPath, + user, group, true); - if (virSecurityDACGetIds(seclabel, priv, &user, &group, NULL, NULL) < 0) + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + /* Skip chowning SGX if namespaces are disabled. */ + if (priv->mountNamespace && + (virSecurityDACSetOwnership(mgr, NULL, + DEV_SGX_VEPC, + user, group, true) < 0 || + virSecurityDACSetOwnership(mgr, NULL, + DEV_SGX_PROVISION, + user, group, true) < 0)) return -1; - - ret = virSecurityDACSetOwnership(mgr, NULL, - mem->nvdimmPath, - user, group, true); break; case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: - case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: case VIR_DOMAIN_MEMORY_MODEL_NONE: - ret = 0; break; } - return ret; + return 0; } -- 2.25.1

According to the result parsing from xml, add the argument of SGX EPC memory backend into QEMU command line. $ qemu-system-x86_64 \ ...... \ -object '{"qom-type":"memory-backend-epc","id":"memepc0","prealloc":true,"size":67108864,"host-nodes":[0,1],"policy":"bind"}' \ -object '{"qom-type":"memory-backend-epc","id":"memepc1","prealloc":true,"size":16777216,"host-nodes":[2,3],"policy":"bind"}' \ -machine sgx-epc.0.memdev=memepc0,sgx-epc.0.node=0,sgx-epc.1.memdev=memepc1,sgx-epc.1.node=1 Signed-off-by: Lin Yang <lin.a.yang@intel.com> Signed-off-by: Haibin Huang <haibin.huang@intel.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_alias.c | 3 +- src/qemu/qemu_command.c | 65 ++++++++++++++++--- src/qemu/qemu_monitor_json.c | 41 ++++++++++-- src/qemu/qemu_validate.c | 32 +++++++++ .../sgx-epc.x86_64-7.0.0.args | 40 ++++++++++++ tests/qemuxml2argvtest.c | 2 + 6 files changed, 167 insertions(+), 16 deletions(-) create mode 100644 tests/qemuxml2argvdata/sgx-epc.x86_64-7.0.0.args diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index 6061dd3f02..ef8e87ab58 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -464,7 +464,8 @@ qemuDeviceMemoryGetAliasID(virDomainDef *def, * valid */ if (!oldAlias && mem->model != VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM && - mem->model != VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM) + mem->model != VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM && + mem->model != VIR_DOMAIN_MEMORY_MODEL_SGX_EPC) return mem->info.addr.dimm.slot; for (i = 0; i < def->nmems; i++) { diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4ef979e278..41b9f7cb52 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3307,7 +3307,11 @@ qemuBuildMemoryBackendProps(virJSONValue **backendProps, props = virJSONValueNewObject(); - if (!mem->nvdimmPath && + if (mem->model == VIR_DOMAIN_MEMORY_MODEL_SGX_EPC) { + backendType = "memory-backend-epc"; + if (!priv->memPrealloc) + prealloc = true; + } else if (!mem->nvdimmPath && def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_MEMFD) { backendType = "memory-backend-memfd"; @@ -3322,7 +3326,6 @@ qemuBuildMemoryBackendProps(virJSONValue **backendProps, if (systemMemory) disableCanonicalPath = true; - } else if (useHugepage || mem->nvdimmPath || memAccess || def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_FILE) { @@ -6600,6 +6603,8 @@ qemuAppendDomainMemoryMachineParams(virBuffer *buf, virQEMUCaps *qemuCaps) { virTristateSwitch dump = def->mem.dump_core; + bool nvdimmAdded = false; + int epcNum = 0; size_t i; if (dump == VIR_TRISTATE_SWITCH_ABSENT) @@ -6611,8 +6616,36 @@ qemuAppendDomainMemoryMachineParams(virBuffer *buf, virBufferAddLit(buf, ",mem-merge=off"); for (i = 0; i < def->nmems; i++) { - if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM) { - virBufferAddLit(buf, ",nvdimm=on"); + int targetNode = def->mems[i]->targetNode; + + switch (def->mems[i]->model) { + case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + if (!nvdimmAdded) { + virBufferAddLit(buf, ",nvdimm=on"); + nvdimmAdded = true; + } + break; + + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + /* add sgx epc memory to -machine parameter */ + + if (targetNode < 0) { + /* set NUMA target node to 0 by default if user doesn't + * specify it. */ + targetNode = 0; + } + + virBufferAsprintf(buf, ",sgx-epc.%d.memdev=mem%s,sgx-epc.%d.node=%d", + epcNum, def->mems[i]->info.alias, epcNum, targetNode); + + epcNum++; + break; + + case VIR_DOMAIN_MEMORY_MODEL_DIMM: + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_NONE: + case VIR_DOMAIN_MEMORY_MODEL_LAST: break; } } @@ -7322,11 +7355,27 @@ qemuBuildMemoryDeviceCommandLine(virCommand *cmd, if (qemuBuildMemoryDimmBackendStr(cmd, def->mems[i], def, cfg, priv) < 0) return -1; - if (!(props = qemuBuildMemoryDeviceProps(cfg, priv, def, def->mems[i]))) - return -1; + switch (def->mems[i]->model) { + case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + case VIR_DOMAIN_MEMORY_MODEL_DIMM: + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + if (!(props = qemuBuildMemoryDeviceProps(cfg, priv, def, def->mems[i]))) + return -1; - if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, priv->qemuCaps) < 0) - return -1; + if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, priv->qemuCaps) < 0) + return -1; + + break; + + /* sgx epc memory will be added to -machine parameter, so skip here */ + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + break; + + case VIR_DOMAIN_MEMORY_MODEL_NONE: + case VIR_DOMAIN_MEMORY_MODEL_LAST: + break; + } } return 0; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index fa44e07c2b..f4e942a32f 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -7208,13 +7208,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); @@ -7258,6 +7270,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_validate.c b/src/qemu/qemu_validate.c index 3b44c5e139..bd040c7ff8 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -4984,6 +4984,9 @@ static int qemuValidateDomainDeviceDefMemory(virDomainMemoryDef *mem, virQEMUCaps *qemuCaps) { + virSGXCapability *sgxCaps; + ssize_t node = -1; + switch (mem->model) { case VIR_DOMAIN_MEMORY_MODEL_DIMM: if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PC_DIMM)) { @@ -5031,6 +5034,35 @@ qemuValidateDomainDeviceDefMemory(virDomainMemoryDef *mem, _("sgx epc isn't supported by this QEMU binary")); return -1; } + + sgxCaps = virQEMUCapsGetSGXCapabilities(qemuCaps); + + if (sgxCaps->nSgxSections == 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("this QEMU version didn't provide SGX EPC NUMA info")); + return -1; + } + + if (mem->sourceNodes) { + while ((node = virBitmapNextSetBit(mem->sourceNodes, node)) >= 0) { + if (mem->size > sgxCaps->sgxSections[node].size) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("sgx epc size %lld on host node %ld is less than requested size %lld"), + sgxCaps->sgxSections[node].size, node, mem->size); + return -1; + } + } + } else { + /* allocate epc from host node 0 by default if user doesn't + * specify it. */ + if (mem->size > sgxCaps->sgxSections[0].size) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("sgx epc size %lld on host node %d is less than requested size %lld"), + sgxCaps->sgxSections[0].size, 0, mem->size); + return -1; + } + } + break; case VIR_DOMAIN_MEMORY_MODEL_NONE: diff --git a/tests/qemuxml2argvdata/sgx-epc.x86_64-7.0.0.args b/tests/qemuxml2argvdata/sgx-epc.x86_64-7.0.0.args new file mode 100644 index 0000000000..e5d29afabd --- /dev/null +++ b/tests/qemuxml2argvdata/sgx-epc.x86_64-7.0.0.args @@ -0,0 +1,40 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc-q35-7.0,usb=off,dump-guest-core=off,sgx-epc.0.memdev=memepc0,sgx-epc.0.node=0,sgx-epc.1.memdev=memepc1,sgx-epc.1.node=1 \ +-accel tcg \ +-cpu qemu64 \ +-m size=1048576k,slots=16,maxmem=1130496k \ +-overcommit mem-lock=off \ +-smp 2,sockets=2,cores=1,threads=1 \ +-object '{"qom-type":"memory-backend-ram","id":"ram-node0","size":536870912}' \ +-numa node,nodeid=0,cpus=0,memdev=ram-node0 \ +-object '{"qom-type":"memory-backend-ram","id":"ram-node1","size":536870912}' \ +-numa node,nodeid=1,cpus=1,memdev=ram-node1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot strict=on \ +-device '{"driver":"pcie-root-port","port":8,"chassis":1,"id":"pci.1","bus":"pcie.0","multifunction":true,"addr":"0x1"}' \ +-device '{"driver":"pcie-root-port","port":9,"chassis":2,"id":"pci.2","bus":"pcie.0","addr":"0x1.0x1"}' \ +-object '{"qom-type":"memory-backend-epc","id":"memepc0","prealloc":true,"size":67108864,"host-nodes":[0,1],"policy":"bind"}' \ +-object '{"qom-type":"memory-backend-epc","id":"memepc1","prealloc":true,"size":16777216,"host-nodes":[0,1],"policy":"bind"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.1","addr":"0x0"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 3b25c99639..4d563d3a09 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -2967,6 +2967,8 @@ mymain(void) DO_TEST_PARSE_ERROR("cpu-phys-bits-emulate3", QEMU_CAPS_KVM); DO_TEST_PARSE_ERROR("cpu-phys-bits-passthrough2", QEMU_CAPS_KVM); + DO_TEST_CAPS_VER("sgx-epc", "7.0.0"); + if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) virFileDeleteTree(fakerootdir); -- 2.25.1
participants (1)
-
Lin Yang