On Fri, Jun 18, 2021 at 04:50:48PM +0800, Zhenzhong Duan wrote:
The TrustDomain element can be used to define the security model to
use when launching a domain. Only type 'tdx' is supported currently.
When 'tdx' is used, the VM will launched with Intel TDX feature enabled.
TDX feature supports running encrypted VM (Trust Domain, TD) under the
control of KVM. A TD runs in a CPU model which protects the
confidentiality of its memory and its CPU state from other software
There is a child element 'policy' in TrustDomain. In 'policy', bit 0
is used to enable TDX debug, other bits are reserved currently.
For example:
<TrustDomain type='tdx'>
<policy>0x0001</policy>
</TrustDomain>
Any reason why you are adding a new element that basically copies
exactly what <launchSecurity> is doing?
In libvirt it will essentially use `confidential-guest-support` which is
used for launchSecurity so there is no need to duplicate the code and
the XML element.
It could look like this:
<launchSecurity type='tdx'>
<policy>0x0001</policy>
</launchSecurity>
We would have to reorganize the <launchSecurity> documentation a little
bit but otherwise there is nothing blocking us to have single element to
specify different type of encrypted/confidential/secure/... VMs.
We already have patches for similar feature for s390 which will also
reuse this element and in the future any other CPU architecture can
reuse it.
Pavel
Signed-off-by: Zhenzhong Duan <zhenzhong.duan(a)intel.com>
---
docs/schemas/domaincommon.rng | 16 ++++
src/conf/domain_conf.c | 84 +++++++++++++++++++
src/conf/domain_conf.h | 15 ++++
src/conf/virconftypes.h | 2 +
src/qemu/qemu_validate.c | 8 ++
.../genericxml2xmlindata/trust-domain-tdx.xml | 21 +++++
tests/genericxml2xmltest.c | 1 +
7 files changed, 147 insertions(+)
create mode 100644 tests/genericxml2xmlindata/trust-domain-tdx.xml
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 5ea14b6dbf..2b39a01e84 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -89,6 +89,9 @@
<optional>
<ref name="launchSecurity"/>
</optional>
+ <optional>
+ <ref name="TrustDomain"/>
+ </optional>
<optional>
<ref name="bhyvecmdline"/>
</optional>
@@ -518,6 +521,19 @@
</element>
</define>
+ <define name="TrustDomain">
+ <element name="TrustDomain">
+ <attribute name="type">
+ <value>tdx</value>
+ </attribute>
+ <interleave>
+ <element name="policy">
+ <ref name="hexuint"/>
+ </element>
+ </interleave>
+ </element>
+ </define>
+
<!--
Enable or disable perf events for the domain. For each
of the events the following rules apply:
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 139cdfc0a7..a51db088c1 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1403,6 +1403,12 @@ VIR_ENUM_IMPL(virDomainLaunchSecurity,
"sev",
);
+VIR_ENUM_IMPL(virDomainTrustDomain,
+ VIR_DOMAIN_TRUST_DOMAIN_LAST,
+ "",
+ "tdx",
+);
+
static virClass *virDomainObjClass;
static virClass *virDomainXMLOptionClass;
static void virDomainObjDispose(void *obj);
@@ -3502,6 +3508,16 @@ virDomainSEVDefFree(virDomainSEVDef *def)
g_free(def);
}
+
+static void
+virDomainTDXDefFree(virDomainTDXDef *def)
+{
+ if (!def)
+ return;
+
+ g_free(def);
+}
+
static void
virDomainOSDefClear(virDomainOSDef *os)
{
@@ -3704,6 +3720,7 @@ void virDomainDefFree(virDomainDef *def)
(def->ns.free)(def->namespaceData);
virDomainSEVDefFree(def->sev);
+ virDomainTDXDefFree(def->tdx);
xmlFreeNode(def->metadata);
@@ -14793,6 +14810,53 @@ virDomainSEVDefParseXML(xmlNodePtr sevNode,
return NULL;
}
+static virDomainTDXDef *
+virDomainTDXDefParseXML(xmlNodePtr tdxNode,
+ xmlXPathContextPtr ctxt)
+{
+ VIR_XPATH_NODE_AUTORESTORE(ctxt)
+ virDomainTDXDef *def;
+ unsigned long policy;
+ g_autofree char *type = NULL;
+
+ def = g_new0(virDomainTDXDef, 1);
+
+ ctxt->node = tdxNode;
+
+ if (!(type = virXMLPropString(tdxNode, "type"))) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing trust domain type"));
+ goto error;
+ }
+
+ def->sectype = virDomainTrustDomainTypeFromString(type);
+ switch ((virDomainTrustDomain) def->sectype) {
+ case VIR_DOMAIN_TRUST_DOMAIN_TDX:
+ break;
+ case VIR_DOMAIN_TRUST_DOMAIN_NONE:
+ case VIR_DOMAIN_TRUST_DOMAIN_LAST:
+ default:
+ virReportError(VIR_ERR_XML_ERROR,
+ _("unsupported trust domain type '%s'"),
+ type);
+ goto error;
+ }
+
+ if (virXPathULongHex("string(./policy)", ctxt, &policy) < 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("failed to get trust domain policy"));
+ goto error;
+ }
+
+ def->policy = policy;
+
+ return def;
+
+ error:
+ virDomainTDXDefFree(def);
+ return NULL;
+}
+
static virDomainMemoryDef *
virDomainMemoryDefParseXML(virDomainXMLOption *xmlopt,
@@ -20117,6 +20181,13 @@ virDomainDefParseXML(xmlDocPtr xml,
goto error;
}
+ /* Check for TDX feature */
+ if ((node = virXPathNode("./TrustDomain", ctxt)) != NULL) {
+ def->tdx = virDomainTDXDefParseXML(node, ctxt);
+ if (!def->tdx)
+ goto error;
+ }
+
/* analysis of memory devices */
if ((n = virXPathNodeSet("./devices/memory", ctxt, &nodes)) < 0)
goto error;
@@ -26870,6 +26941,18 @@ virDomainSEVDefFormat(virBuffer *buf, virDomainSEVDef *sev)
virBufferAddLit(buf, "</launchSecurity>\n");
}
+static void
+virDomainTDXDefFormat(virBuffer *buf, virDomainTDXDef *tdx)
+{
+ if (!tdx)
+ return;
+
+ virBufferAsprintf(buf, "<TrustDomain type='tdx'>\n");
+ virBufferAdjustIndent(buf, 2);
+ virBufferAsprintf(buf, "<policy>0x%04x</policy>\n",
tdx->policy);
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</TrustDomain>\n");
+}
static void
virDomainPerfDefFormat(virBuffer *buf, virDomainPerfDef *perf)
@@ -28277,6 +28360,7 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def,
virDomainKeyWrapDefFormat(buf, def->keywrap);
virDomainSEVDefFormat(buf, def->sev);
+ virDomainTDXDefFormat(buf, def->tdx);
if (def->namespaceData && def->ns.format) {
if ((def->ns.format)(buf, def->namespaceData) < 0)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index f706c498ff..7cb5061c8c 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2661,6 +2661,17 @@ struct _virDomainSEVDef {
unsigned int reduced_phys_bits;
};
+typedef enum {
+ VIR_DOMAIN_TRUST_DOMAIN_NONE,
+ VIR_DOMAIN_TRUST_DOMAIN_TDX,
+
+ VIR_DOMAIN_TRUST_DOMAIN_LAST,
+} virDomainTrustDomain;
+
+struct _virDomainTDXDef {
+ int sectype; /* enum virDomainTrustDomain */
+ unsigned int policy; /* bit 0 set hint debug enabled, other bit reserved */
+};
typedef enum {
VIR_DOMAIN_IOMMU_MODEL_INTEL,
@@ -2874,6 +2885,9 @@ struct _virDomainDef {
/* SEV-specific domain */
virDomainSEVDef *sev;
+ /* TDX-specific domain */
+ virDomainTDXDef *tdx;
+
/* Application-specific custom metadata */
xmlNodePtr metadata;
@@ -3888,6 +3902,7 @@ VIR_ENUM_DECL(virDomainVsockModel);
VIR_ENUM_DECL(virDomainShmemModel);
VIR_ENUM_DECL(virDomainShmemRole);
VIR_ENUM_DECL(virDomainLaunchSecurity);
+VIR_ENUM_DECL(virDomainTrustDomain);
/* from libvirt.h */
VIR_ENUM_DECL(virDomainState);
VIR_ENUM_DECL(virDomainNostateReason);
diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h
index b21068486e..dbd2eb984c 100644
--- a/src/conf/virconftypes.h
+++ b/src/conf/virconftypes.h
@@ -202,6 +202,8 @@ typedef struct _virDomainResourceDef virDomainResourceDef;
typedef struct _virDomainSEVDef virDomainSEVDef;
+typedef struct _virDomainTDXDef virDomainTDXDef;
+
typedef struct _virDomainShmemDef virDomainShmemDef;
typedef struct _virDomainSmartcardDef virDomainSmartcardDef;
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 382473d03b..2efd011cc0 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -1222,6 +1222,14 @@ qemuValidateDomainDef(const virDomainDef *def,
return -1;
}
+ if (def->tdx &&
+ !virQEMUCapsGet(qemuCaps, QEMU_CAPS_TDX_GUEST)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("TDX trust domain is not supported with "
+ "this QEMU binary"));
+ return -1;
+ }
+
if (def->naudios > 1 &&
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_AUDIODEV)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
diff --git a/tests/genericxml2xmlindata/trust-domain-tdx.xml
b/tests/genericxml2xmlindata/trust-domain-tdx.xml
new file mode 100644
index 0000000000..7a56cf0e92
--- /dev/null
+++ b/tests/genericxml2xmlindata/trust-domain-tdx.xml
@@ -0,0 +1,21 @@
+<domain type='kvm'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc-1.0'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ </devices>
+ <TrustDomain type='tdx'>
+ <policy>0x0001</policy>
+ </TrustDomain>
+</domain>
+
diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c
index ac89422a32..0bd7717953 100644
--- a/tests/genericxml2xmltest.c
+++ b/tests/genericxml2xmltest.c
@@ -233,6 +233,7 @@ mymain(void)
DO_TEST("tseg");
DO_TEST("launch-security-sev");
+ DO_TEST("trust-domain-tdx");
DO_TEST_DIFFERENT("cputune");
DO_TEST("device-backenddomain");
--
2.25.1