On 7/1/22 21:14, Lin Yang wrote:
From: Haibin Huang <haibin.huang(a)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: Michal Privoznik <mprivozn(a)redhat.com>
Signed-off-by: Haibin Huang <haibin.huang(a)intel.com>
---
docs/formatdomaincaps.rst | 40 ++++++++++++++++
src/conf/domain_capabilities.c | 48 +++++++++++++++++++
src/conf/schemas/domaincaps.rng | 42 ++++++++++++++++
src/qemu/qemu_capabilities.c | 28 +++++++++++
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_2.11.0-q35.x86_64.xml | 1 +
.../domaincapsdata/qemu_2.11.0-tcg.x86_64.xml | 1 +
tests/domaincapsdata/qemu_2.11.0.s390x.xml | 1 +
tests/domaincapsdata/qemu_2.11.0.x86_64.xml | 1 +
.../domaincapsdata/qemu_2.12.0-q35.x86_64.xml | 1 +
.../domaincapsdata/qemu_2.12.0-tcg.x86_64.xml | 1 +
.../qemu_2.12.0-virt.aarch64.xml | 1 +
tests/domaincapsdata/qemu_2.12.0.aarch64.xml | 1 +
tests/domaincapsdata/qemu_2.12.0.ppc64.xml | 1 +
tests/domaincapsdata/qemu_2.12.0.s390x.xml | 1 +
tests/domaincapsdata/qemu_2.12.0.x86_64.xml | 1 +
.../domaincapsdata/qemu_3.0.0-q35.x86_64.xml | 1 +
.../domaincapsdata/qemu_3.0.0-tcg.x86_64.xml | 1 +
tests/domaincapsdata/qemu_3.0.0.ppc64.xml | 1 +
tests/domaincapsdata/qemu_3.0.0.s390x.xml | 1 +
tests/domaincapsdata/qemu_3.0.0.x86_64.xml | 1 +
.../domaincapsdata/qemu_3.1.0-q35.x86_64.xml | 1 +
.../domaincapsdata/qemu_3.1.0-tcg.x86_64.xml | 1 +
tests/domaincapsdata/qemu_3.1.0.ppc64.xml | 1 +
tests/domaincapsdata/qemu_3.1.0.x86_64.xml | 1 +
.../domaincapsdata/qemu_4.0.0-q35.x86_64.xml | 1 +
.../domaincapsdata/qemu_4.0.0-tcg.x86_64.xml | 1 +
.../qemu_4.0.0-virt.aarch64.xml | 1 +
tests/domaincapsdata/qemu_4.0.0.aarch64.xml | 1 +
tests/domaincapsdata/qemu_4.0.0.ppc64.xml | 1 +
tests/domaincapsdata/qemu_4.0.0.s390x.xml | 1 +
tests/domaincapsdata/qemu_4.0.0.x86_64.xml | 1 +
.../domaincapsdata/qemu_4.1.0-q35.x86_64.xml | 1 +
.../domaincapsdata/qemu_4.1.0-tcg.x86_64.xml | 1 +
tests/domaincapsdata/qemu_4.1.0.x86_64.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 | 6 +++
.../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 6 +++
.../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 | 6 +++
.../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 | 10 ++++
.../domaincapsdata/qemu_7.1.0-tcg.x86_64.xml | 10 ++++
tests/domaincapsdata/qemu_7.1.0.x86_64.xml | 10 ++++
88 files changed, 311 insertions(+)
diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst
index 933469b2a2..d3bdee28d4 100644
--- a/docs/formatdomaincaps.rst
+++ b/docs/formatdomaincaps.rst
@@ -519,6 +519,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>2</section_size>
+ <sections>
+ <section node='0' size='1'/>
+ <section node='1' size='1'/>
+ </sections>
+ </sgx>
</features>
</domainCapabilities>
@@ -598,3 +608,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 formatdomain.rst
+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 27f3fb8d36..fa29f69807 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -98,6 +98,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++)
@@ -620,6 +621,52 @@ virDomainCapsFeatureSEVFormat(virBuffer *buf,
return;
}
+static void
+virDomainCapsFeatureSGXFormat(virBuffer *buf,
+ const virSGXCapability *sgx)
+{
+ size_t i;
+
+ if (!sgx) {
+ virBufferAddLit(buf, "<sgx supported='no'/>\n");
+ } else {
+ virBufferAddLit(buf, "<sgx supported='yes'>\n");
+ virBufferAdjustIndent(buf, 2);
+ if (sgx->flc) {
+ virBufferAsprintf(buf, "<flc>%s</flc>\n",
"yes");
+ } else {
+ virBufferAsprintf(buf, "<flc>%s</flc>\n",
"no");
+ }
Same comment here as in the previous patch.
+ if (sgx->sgx1) {
+ virBufferAsprintf(buf, "<sgx1>%s</sgx1>\n",
"yes");
+ } else {
+ virBufferAsprintf(buf, "<sgx1>%s</sgx1>\n",
"no");
+ }
+ if (sgx->sgx2) {
+ virBufferAsprintf(buf, "<sgx2>%s</sgx2>\n",
"yes");
+ } else {
+ virBufferAsprintf(buf, "<sgx2>%s</sgx2>\n",
"no");
+ }
+ virBufferAsprintf(buf, "<section_size
unit='KiB'>%llu</section_size>\n", sgx->section_size);
+
+ if (sgx->nSections > 0) {
+ virBufferAddLit(buf, "<sections>\n");
+
+ for (i = 0; i < sgx->nSections; i++) {
+ virBufferAdjustIndent(buf, 2);
+ virBufferAsprintf(buf, "<section node='%u' ",
sgx->pSections[i].node);
+ virBufferAsprintf(buf, "size='%llu'/>\n",
sgx->pSections[i].size);
+ virBufferAdjustIndent(buf, -2);
+ }
+ virBufferAddLit(buf, "</sections>\n");
+ }
+
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</sgx>\n");
+ }
+
+ return;
+}
static void
virDomainCapsFormatFeatures(const virDomainCaps *caps,
@@ -640,6 +687,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 9cbc2467ab..6975ebacb9 100644
--- a/src/conf/schemas/domaincaps.rng
+++ b/src/conf/schemas/domaincaps.rng
@@ -270,6 +270,9 @@
<optional>
<ref name="sev"/>
</optional>
+ <optional>
+ <ref name="sgx"/>
+ </optional>
</element>
</define>
@@ -330,6 +333,45 @@
</element>
</define>
+ <define name="sgx">
+ <element name="sgx">
+ <ref name="supported"/>
+ <optional>
+ <element name="flc">
+ <data type="string"/>
Or, since we know we are formatting yes/no, we can use virYesNo instead
of too generic string type.
+ </element>
+ <element name="sgx1">
+ <data type="string"/>
+ </element>
+ <element name="sgx2">
+ <data type="string"/>
+ </element>
+ <element name="section_size">
+ <attribute name="unit">
+ <value>KiB</value>
+ </attribute>
+ <data type="unsignedInt"/>
+ </element>
+ <optional>
+ <element name="sections">
+ <interleave>
I think the order is well defined and thus we don't really need
<interleave/> here. The domain capabilities XML is not provided by user,
it's generated by libvirt, in virDomainCapsFormat() where the order is
well defined.
+ <zeroOrMore>
+ <element name="section">
+ <attribute name="node">
+ <data type="string"/>
This is an integer ..
+ </attribute>
+ <attribute name="size">
+ <data type="string"/>
.. and so is this.
+ </attribute>
+ </element>
+ </zeroOrMore>
+ </interleave>
+ </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 57b5acb150..598c694738 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -6744,6 +6744,33 @@ virQEMUCapsFillDomainFeatureS390PVCaps(virQEMUCaps *qemuCaps,
}
}
+/**
+ * virQEMUCapsFillDomainFeatureiSGXCaps:
+ * @qemuCaps: QEMU capabilities
+ * @domCaps: domain capabilities
+ *
+ * Take the information about SGX capabilities that has been obtained
+ * using the 'query-sgx-capabilities' QMP command and stored in @qemuCaps
+ * and convert it to a form suitable for @domCaps.
+ */
+static void
+virQEMUCapsFillDomainFeatureSGXCaps(virQEMUCaps *qemuCaps,
+ virDomainCaps *domCaps)
+{
+ virSGXCapability *cap = qemuCaps->sgxCapabilities;
+
+ if (!cap)
+ return;
+
+ domCaps->sgx = g_new0(virSGXCapability, 1);
+
+ domCaps->sgx->flc = cap->flc;
+ domCaps->sgx->sgx1 = cap->sgx1;
+ domCaps->sgx->sgx2 = cap->sgx2;
+ domCaps->sgx->section_size = cap->section_size;
+ domCaps->sgx->nSections = cap->nSections;
+ domCaps->sgx->pSections = cap->pSections;
This is a verbatim copy of virQEMUCapsSGXInfoCopy(), any reason for not
just call the function?
+}
Michal