[RFC PATCH 3/7] conf: introduce TrustDomain element in domain

Pavel Hrdina phrdina at redhat.com
Fri Jun 18 12:08:48 UTC 2021


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 at 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
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20210618/44b41a83/attachment-0001.sig>


More information about the libvir-list mailing list