From 3f4f38e2f1f05b0484035f96e61ee0de130d3050 Mon Sep 17 00:00:00 2001 Message-ID: <3f4f38e2f1f05b0484035f96e61ee0de130d3050.1759835600.git.jdenemar@redhat.com> From: Zhenzhong Duan Date: Thu, 10 Jul 2025 03:21:09 -0400 Subject: [PATCH] conf: Add tdx as launch security type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When 'tdx' is used, the VM will be 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 are four optional child elements. Element policy is 64bit hex, bit 0 is set to enable TDX debug, bit 28 is set to enable sept-ve-disable, other bits are reserved currently. When policy isn't specified, QEMU will use its own default value 0x10000000. mrConfigId, mrOwner and mrOwnerConfig are base64 encoded SHA384 digest string. For example: 0x10000001 xxx xxx xxx Signed-off-by: Zhenzhong Duan Reviewed-by: Daniel P. Berrangé (cherry picked from commit e919a4dd374535511d962bee2cd64f22f1ac3fa1) Resolves: https://issues.redhat.com/browse/RHEL-111840 Signed-off-by: Paolo Bonzini RHEL: context --- src/conf/domain_conf.c | 49 +++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 11 +++++++ src/conf/domain_validate.c | 1 + src/conf/schemas/domaincommon.rng | 32 ++++++++++++++++++++ src/conf/virconftypes.h | 2 ++ src/qemu/qemu_cgroup.c | 1 + src/qemu/qemu_command.c | 3 ++ src/qemu/qemu_driver.c | 1 + src/qemu/qemu_firmware.c | 1 + src/qemu/qemu_namespace.c | 1 + src/qemu/qemu_process.c | 2 ++ src/qemu/qemu_validate.c | 1 + src/security/security_dac.c | 2 ++ 13 files changed, 107 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 286e59a4c7..92185080a9 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1538,6 +1538,7 @@ VIR_ENUM_IMPL(virDomainLaunchSecurity, "sev", "sev-snp", "s390-pv", + "tdx", ); VIR_ENUM_IMPL(virDomainPstoreBackend, @@ -3890,6 +3891,11 @@ virDomainSecDefFree(virDomainSecDef *def) g_free(def->data.sev_snp.id_auth); g_free(def->data.sev_snp.host_data); 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); + break; case VIR_DOMAIN_LAUNCH_SECURITY_PV: case VIR_DOMAIN_LAUNCH_SECURITY_NONE: case VIR_DOMAIN_LAUNCH_SECURITY_LAST: @@ -13905,6 +13911,29 @@ virDomainSEVSNPDefParseXML(virDomainSEVSNPDef *def, } +static int +virDomainTDXDefParseXML(virDomainTDXDef *def, + xmlXPathContextPtr ctxt) +{ + int rc; + + rc = virXPathULongLongBase("string(./policy)", ctxt, 16, &def->policy); + if (rc == 0) { + def->havePolicy = true; + } else if (rc == -2) { + 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); + + return 0; +} + + static virDomainSecDef * virDomainSecDefParseXML(xmlNodePtr lsecNode, xmlXPathContextPtr ctxt) @@ -13928,6 +13957,10 @@ virDomainSecDefParseXML(xmlNodePtr lsecNode, if (virDomainSEVSNPDefParseXML(&sec->data.sev_snp, 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: @@ -27219,6 +27252,18 @@ virDomainSEVSNPDefFormat(virBuffer *attrBuf, } +static void +virDomainTDXDefFormat(virBuffer *childBuf, virDomainTDXDef *def) +{ + if (def->havePolicy) + virBufferAsprintf(childBuf, "0x%llx\n", def->policy); + + virBufferEscapeString(childBuf, "%s\n", def->mrconfigid); + virBufferEscapeString(childBuf, "%s\n", def->mrowner); + virBufferEscapeString(childBuf, "%s\n", def->mrownerconfig); +} + + static void virDomainSecDefFormat(virBuffer *buf, virDomainSecDef *sec) { @@ -27240,6 +27285,10 @@ virDomainSecDefFormat(virBuffer *buf, virDomainSecDef *sec) virDomainSEVSNPDefFormat(&attrBuf, &childBuf, &sec->data.sev_snp); break; + case VIR_DOMAIN_LAUNCH_SECURITY_TDX: + virDomainTDXDefFormat(&childBuf, &sec->data.tdx); + break; + case VIR_DOMAIN_LAUNCH_SECURITY_PV: break; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index e59d2e6c5f..1238f2001f 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2924,6 +2924,7 @@ typedef enum { VIR_DOMAIN_LAUNCH_SECURITY_SEV, VIR_DOMAIN_LAUNCH_SECURITY_SEV_SNP, VIR_DOMAIN_LAUNCH_SECURITY_PV, + VIR_DOMAIN_LAUNCH_SECURITY_TDX, VIR_DOMAIN_LAUNCH_SECURITY_LAST, } virDomainLaunchSecurity; @@ -2958,11 +2959,21 @@ struct _virDomainSEVSNPDef { }; +struct _virDomainTDXDef { + bool havePolicy; + unsigned long long policy; + char *mrconfigid; + char *mrowner; + char *mrownerconfig; +}; + + struct _virDomainSecDef { virDomainLaunchSecurity sectype; union { virDomainSEVDef sev; virDomainSEVSNPDef sev_snp; + virDomainTDXDef tdx; } data; }; diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index 522fd0174f..2d4b79032b 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -1860,6 +1860,7 @@ virDomainDefLaunchSecurityValidate(const virDomainDef *def) case VIR_DOMAIN_LAUNCH_SECURITY_NONE: case VIR_DOMAIN_LAUNCH_SECURITY_SEV: case VIR_DOMAIN_LAUNCH_SECURITY_PV: + case VIR_DOMAIN_LAUNCH_SECURITY_TDX: case VIR_DOMAIN_LAUNCH_SECURITY_LAST: break; } diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 1b153acc48..552b2f4ced 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -528,6 +528,9 @@ s390-pv + + + @@ -623,6 +626,35 @@ + + + + tdx + + + + + + + + + + + + + + + + + + + + + + + + +