On Mon, Nov 27, 2023 at 04:55:14PM +0800, Zhenzhong Duan wrote:
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' and four optional element for tdx type.
In 'policy', bit 0 is set to enable TDX debug, bit 28 set to enable
sept-ve-disable, other bits are reserved currently. mrConfigId, mrOwner
and mrOwnerConfig are hex string of 48 * 2 length each.
Quote-Generation-Service is string to specify Quote Generation Service(QGS)
in qemu socket address format. The examples of the supported format are
"vsock:2:1234", "unix:/run/qgs", "localhost:1234".
For example:
<launchSecurity type='tdx'>
<policy>0x1</policy>
<mrConfigId>xxx...xxx</mrConfigId>
<mrOwner>xxx...xxx</mrOwner>
<mrOwnerConfig>xxx...xxx</mrOwnerConfig>
<Quote-Generation-Service>xxx</Quote-Generation-Service>
</launchSecurity>
On the QEMU side, the quote generateo sevice is defined as
'*quote-generation-socket': 'SocketAddress'
we need to model 'SocktetAddress' in the XML properly, not
just as an opaque string.
Also given the naming for the rest of the elements, this
should also use caps, eg <quoteGenerationService>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan(a)intel.com>
---
src/conf/domain_conf.c | 46 +++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 10 +++++++
src/conf/schemas/domaincommon.rng | 34 +++++++++++++++++++++++
src/conf/virconftypes.h | 2 ++
src/qemu/qemu_command.c | 2 ++
src/qemu/qemu_firmware.c | 1 +
src/qemu/qemu_namespace.c | 1 +
src/qemu/qemu_process.c | 1 +
src/qemu/qemu_validate.c | 1 +
Schema additions need something added to docs/formatdomain.rst to
document them, as well as example XML added under tests/ to validate
the parsing and formatting logic, and the QEMU command line args
generation.
9 files changed, 98 insertions(+)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 80f467ae7a..08e82c5380 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1513,6 +1513,7 @@ VIR_ENUM_IMPL(virDomainLaunchSecurity,
"",
"sev",
"s390-pv",
+ "tdx",
);
typedef enum {
@@ -3808,6 +3809,11 @@ virDomainSecDefFree(virDomainSecDef *def)
g_free(def->data.sev.dh_cert);
g_free(def->data.sev.session);
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
+ g_free(def->data.tdx.mrconfigid);
+ g_free(def->data.tdx.mrowner);
+ g_free(def->data.tdx.mrownerconfig);
+ g_free(def->data.tdx.QGS);
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
@@ -13452,6 +13458,25 @@ virDomainSEVDefParseXML(virDomainSEVDef *def,
}
+static int
+virDomainTDXDefParseXML(virDomainTDXDef *def,
+ xmlXPathContextPtr ctxt)
+{
+ if (virXPathUIntBase("string(./policy)", ctxt, 16, &def->policy)
< 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("failed to get launch security policy for launch security
type TDX"));
+ return -1;
+ }
+
+ def->mrconfigid = virXPathString("string(./mrConfigId)", ctxt);
+ def->mrowner = virXPathString("string(./mrOwner)", ctxt);
+ def->mrownerconfig = virXPathString("string(./mrOwnerConfig)", ctxt);
+ def->QGS = virXPathString("string(./Quote-Generation-Service)", ctxt);
+
+ return 0;
+}
+
+
static virDomainSecDef *
virDomainSecDefParseXML(xmlNodePtr lsecNode,
xmlXPathContextPtr ctxt)
@@ -13471,6 +13496,10 @@ virDomainSecDefParseXML(xmlNodePtr lsecNode,
if (virDomainSEVDefParseXML(&sec->data.sev, ctxt) < 0)
return NULL;
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
+ if (virDomainTDXDefParseXML(&sec->data.tdx, ctxt) < 0)
+ return NULL;
+ break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
break;
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
@@ -26468,6 +26497,23 @@ virDomainSecDefFormat(virBuffer *buf, virDomainSecDef *sec)
break;
}
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX: {
+ virDomainTDXDef *tdx = &sec->data.tdx;
+
+ virBufferAsprintf(&childBuf,
"<policy>0x%04x</policy>\n", tdx->policy);
+
+ if (tdx->mrconfigid)
+ virBufferEscapeString(&childBuf,
"<mrConfigId>%s</mrConfigId>\n", tdx->mrconfigid);
+ if (tdx->mrowner)
+ virBufferEscapeString(&childBuf,
"<mrOwner>%s</mrOwner>\n", tdx->mrowner);
+ if (tdx->mrownerconfig)
+ virBufferEscapeString(&childBuf,
"<mrOwnerConfig>%s</mrOwnerConfig>\n", tdx->mrownerconfig);
+ if (tdx->QGS)
+ virBufferEscapeString(&childBuf,
"<Quote-Generation-Service>%s</Quote-Generation-Service>\n",
tdx->QGS);
+
+ break;
+ }
+
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
break;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 98f99721f0..3b01850eb4 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2833,6 +2833,7 @@ typedef enum {
VIR_DOMAIN_LAUNCH_SECURITY_NONE,
VIR_DOMAIN_LAUNCH_SECURITY_SEV,
VIR_DOMAIN_LAUNCH_SECURITY_PV,
+ VIR_DOMAIN_LAUNCH_SECURITY_TDX,
VIR_DOMAIN_LAUNCH_SECURITY_LAST,
} virDomainLaunchSecurity;
@@ -2849,10 +2850,19 @@ struct _virDomainSEVDef {
virTristateBool kernel_hashes;
};
+struct _virDomainTDXDef {
+ unsigned int policy;
+ char *mrconfigid;
+ char *mrowner;
+ char *mrownerconfig;
+ char *QGS;
+};
+
struct _virDomainSecDef {
virDomainLaunchSecurity sectype;
union {
virDomainSEVDef sev;
+ virDomainTDXDef tdx;
} data;
};
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index a26986b5ce..bf3667d727 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -520,6 +520,9 @@
<value>s390-pv</value>
</attribute>
</group>
+ <group>
+ <ref name="launchSecurityTDX"/>
+ </group>
</choice>
</element>
</define>
@@ -565,6 +568,37 @@
</interleave>
</define>
+ <define name="launchSecurityTDX">
+ <attribute name="type">
+ <value>tdx</value>
+ </attribute>
+ <interleave>
+ <element name="policy">
+ <ref name="hexuint"/>
+ </element>
+ <optional>
+ <element name="mrConfigId">
+ <data type="string"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="mrOwner">
+ <data type="string"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="mrOwnerConfig">
+ <data type="string"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="Quote-Generation-Service">
+ <data type="string"/>
+ </element>
+ </optional>
+ </interleave>
+ </define>
+
<!--
Enable or disable perf events for the domain. For each
of the events the following rules apply:
diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h
index 26cb966194..5516165bcc 100644
--- a/src/conf/virconftypes.h
+++ b/src/conf/virconftypes.h
@@ -210,6 +210,8 @@ typedef struct _virDomainResourceDef virDomainResourceDef;
typedef struct _virDomainSEVDef virDomainSEVDef;
+typedef struct _virDomainTDXDef virDomainTDXDef;
+
typedef struct _virDomainSecDef virDomainSecDef;
typedef struct _virDomainShmemDef virDomainShmemDef;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index fd0f12f304..89905378e4 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7001,6 +7001,7 @@ qemuBuildMachineCommandLine(virCommand *cmd,
}
break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
virBufferAddLit(&buf, ",confidential-guest-support=lsec0");
break;
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
@@ -9658,6 +9659,7 @@ qemuBuildSecCommandLine(virDomainObj *vm, virCommand *cmd,
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
return qemuBuildPVCommandLine(vm, cmd);
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
virReportEnumRangeError(virDomainLaunchSecurity, sec->sectype);
diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index d39e61d071..b073a38bfc 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1374,6 +1374,7 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
}
break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
break;
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c
index 915d44310f..ac8a4b5c07 100644
--- a/src/qemu/qemu_namespace.c
+++ b/src/qemu/qemu_namespace.c
@@ -660,6 +660,7 @@ qemuDomainSetupLaunchSecurity(virDomainObj *vm,
VIR_DEBUG("Set up launch security for SEV");
break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
break;
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 1ef032dbd2..f27f6653f5 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -6744,6 +6744,7 @@ qemuProcessPrepareLaunchSecurityGuestInput(virDomainObj *vm)
case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
return qemuProcessPrepareSEVGuestInput(vm);
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
return 0;
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 93df9e4c8e..af630796cd 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -1322,6 +1322,7 @@ qemuValidateDomainDef(const virDomainDef *def,
return -1;
}
break;
+ case VIR_DOMAIN_LAUNCH_SECURITY_TDX:
case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
virReportEnumRangeError(virDomainLaunchSecurity, def->sec->sectype);
--
2.34.1
With regards,
Daniel
--
|:
https://berrange.com -o-
https://www.flickr.com/photos/dberrange :|
|:
https://libvirt.org -o-
https://fstop138.berrange.com :|
|:
https://entangle-photo.org -o-
https://www.instagram.com/dberrange :|