[PATCH] libvirt: configure TPM device in the XML

Srihari Parimi via Devel posted 1 patch 3 weeks, 5 days ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/libvirt tags/patchew/20260417061517.46477-1-sparimi@redhat.com
There is a newer version of this series
src/vmx/vmx.c              | 50 ++++++++++++++++++++++++++++++++++++++
tests/vmx2xmldata/vtpm.vmx | 22 +++++++++++++++++
tests/vmx2xmldata/vtpm.xml | 32 ++++++++++++++++++++++++
tests/vmx2xmltest.c        |  2 ++
4 files changed, 106 insertions(+)
create mode 100644 tests/vmx2xmldata/vtpm.vmx
create mode 100644 tests/vmx2xmldata/vtpm.xml
[PATCH] libvirt: configure TPM device in the XML
Posted by Srihari Parimi via Devel 3 weeks, 5 days ago
Parses vtpm.present from VMX files and converts to libvirt TPM
device with CRB model and emulator backend. VMware vTPM uses
TPM 2.0 with the CRB

Signed-off-by: Srihari Parimi <sparimi@redhat.com>
---
 src/vmx/vmx.c              | 50 ++++++++++++++++++++++++++++++++++++++
 tests/vmx2xmldata/vtpm.vmx | 22 +++++++++++++++++
 tests/vmx2xmldata/vtpm.xml | 32 ++++++++++++++++++++++++
 tests/vmx2xmltest.c        |  2 ++
 4 files changed, 106 insertions(+)
 create mode 100644 tests/vmx2xmldata/vtpm.vmx
 create mode 100644 tests/vmx2xmldata/vtpm.xml

diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c
index 57dfd57cfc..9231968175 100644
--- a/src/vmx/vmx.c
+++ b/src/vmx/vmx.c
@@ -599,6 +599,7 @@ static int virVMXParseSerial(virVMXContext *ctx, virConf *conf, int port,
 static int virVMXParseParallel(virVMXContext *ctx, virConf *conf, int port,
                                virDomainChrDef **def);
 static int virVMXParseSVGA(virConf *conf, virDomainVideoDef **def);
+static int virVMXParseTPM(virConf *conf, virDomainTPMDef **def);
 
 static int virVMXFormatVNC(virDomainGraphicsDef *def, virBuffer *buffer);
 static int virVMXFormatDisk(virVMXContext *ctx, virDomainDiskDef *def,
@@ -1403,6 +1404,7 @@ virVMXParseConfig(virVMXContext *ctx,
     char *guestOS = NULL;
     bool smbios_reflecthost = false;
     bool uefi_secureboot = false;
+    bool vtpm_present = false;
     int controller;
     int bus;
     int port;
@@ -1938,6 +1940,16 @@ virVMXParseConfig(virVMXContext *ctx,
 
     def->nvideos = 1;
 
+    /* def:tpms */
+    {
+        virDomainTPMDef *tpm = NULL;
+        if (virVMXParseTPM(conf, &tpm) < 0)
+            goto cleanup;
+
+        if (tpm)
+            VIR_APPEND_ELEMENT(def->tpms, def->ntpms, tpm);
+    }
+
     /* def:sounds */
     /* FIXME */
 
@@ -2001,6 +2013,18 @@ virVMXParseConfig(virVMXContext *ctx,
         }
     }
 
+    /* vmx: vtpm.present (optional) */
+    if (virVMXGetConfigBoolean(conf, "vtpm.present",
+        &vtpm_present, false, true) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("Unable to parse vtpm.present"));
+        goto cleanup;
+    }
+    if (vtpm_present) {
+        VIR_DEBUG("Processing vtpm_present: %s",
+            (vtpm_present == true) ? "yes" : "no");
+    }
+
     /* vmx:uefi.secureBoot.enabled */
     if (virVMXGetConfigBoolean(conf, "uefi.secureBoot.enabled",
                                &uefi_secureboot, false, true) < 0) {
@@ -3367,6 +3391,32 @@ virVMXParseSVGA(virConf *conf, virDomainVideoDef **def)
     return result;
 }
 
+static int
+virVMXParseTPM(virConf *conf, virDomainTPMDef **def)
+{
+    bool vtpm_present = false;
+
+    if (def == NULL || *def != NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+        return -1;
+    }
+
+    /* vmx:vtpm.present */
+    if (virVMXGetConfigBoolean(conf, "vtpm.present", &vtpm_present,
+                               false, true) < 0) {
+        return -1;
+    }
+
+    if (!vtpm_present)
+        return 0;
+
+    *def = g_new0(virDomainTPMDef, 1);
+    (*def)->type = VIR_DOMAIN_TPM_TYPE_EMULATOR;
+    (*def)->model = VIR_DOMAIN_TPM_MODEL_CRB;
+    (*def)->data.emulator.version = VIR_DOMAIN_TPM_VERSION_2_0;
+
+    return 0;
+}
 
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
diff --git a/tests/vmx2xmldata/vtpm.vmx b/tests/vmx2xmldata/vtpm.vmx
new file mode 100644
index 0000000000..6e2fd725b7
--- /dev/null
+++ b/tests/vmx2xmldata/vtpm.vmx
@@ -0,0 +1,22 @@
+config.version = "8"
+virtualHW.version = "19"
+displayName = "test-vtpm"
+memsize = "4096"
+numvcpus = "2"
+guestOS = "windows9-64"
+
+# Disk Configuration
+scsi0.present = "TRUE"
+scsi0.virtualDev = "lsisas1068"
+scsi0:0.present = "TRUE"
+scsi0:0.deviceType = "scsi-hardDisk"
+scsi0:0.fileName = "test_disk.vmdk"
+
+# vTPM configuration
+vtpm.present = "TRUE"
+
+# Network Configuration
+ethernet0.present = "TRUE"
+ethernet0.connectionType = "nat"
+ethernet0.virtualDev = "e1000e"
+ethernet0.addressType = "generated"
diff --git a/tests/vmx2xmldata/vtpm.xml b/tests/vmx2xmldata/vtpm.xml
new file mode 100644
index 0000000000..cbb23ce673
--- /dev/null
+++ b/tests/vmx2xmldata/vtpm.xml
@@ -0,0 +1,32 @@
+<domain type='vmware'>
+  <name>test-vtpm</name>
+  <uuid>00000000-0000-0000-0000-000000000000</uuid>
+  <memory unit='KiB'>4194304</memory>
+  <currentMemory unit='KiB'>4194304</currentMemory>
+  <vcpu placement='static'>2</vcpu>
+  <os>
+    <type arch='x86_64'>hvm</type>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <disk type='file' device='disk'>
+      <source file='[datastore] directory/test_disk.vmdk'/>
+      <target dev='sda' bus='scsi'/>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='scsi' index='0' model='lsisas1068'/>
+    <interface type='user'>
+      <mac address='00:00:00:00:00:00' type='generated'/>
+      <model type='e1000e'/>
+    </interface>
+    <tpm model='tpm-crb'>
+      <backend type='emulator' version='2.0'/>
+    </tpm>
+    <video>
+      <model type='vmvga' vram='4096' primary='yes'/>
+    </video>
+  </devices>
+</domain>
diff --git a/tests/vmx2xmltest.c b/tests/vmx2xmltest.c
index fcca765bed..3ffc04fda4 100644
--- a/tests/vmx2xmltest.c
+++ b/tests/vmx2xmltest.c
@@ -243,6 +243,8 @@ mymain(void)
 
     DO_TEST("firmware-efi");
 
+    DO_TEST("vtpm");
+
     ctx.datacenterPath = "folder1/folder2/datacenter1";
 
     DO_TEST("datacenterpath");
-- 
2.53.0
Re: [PATCH] libvirt: configure TPM device in the XML
Posted by Peter Krempa via Devel 3 weeks, 5 days ago
In summary of the commit mention 'vmx' as the driver instead of the
obvious 'libvirt'


On Fri, Apr 17, 2026 at 11:45:15 +0530, Srihari Parimi via Devel wrote:
> Parses vtpm.present from VMX files and converts to libvirt TPM
> device with CRB model and emulator backend. VMware vTPM uses
> TPM 2.0 with the CRB

Do you know of any docs to point to for which version of TPM is used?


> 
> Signed-off-by: Srihari Parimi <sparimi@redhat.com>
> ---
>  src/vmx/vmx.c              | 50 ++++++++++++++++++++++++++++++++++++++
>  tests/vmx2xmldata/vtpm.vmx | 22 +++++++++++++++++
>  tests/vmx2xmldata/vtpm.xml | 32 ++++++++++++++++++++++++
>  tests/vmx2xmltest.c        |  2 ++
>  4 files changed, 106 insertions(+)
>  create mode 100644 tests/vmx2xmldata/vtpm.vmx
>  create mode 100644 tests/vmx2xmldata/vtpm.xml
> 
> diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c
> index 57dfd57cfc..9231968175 100644
> --- a/src/vmx/vmx.c
> +++ b/src/vmx/vmx.c
> @@ -599,6 +599,7 @@ static int virVMXParseSerial(virVMXContext *ctx, virConf *conf, int port,
>  static int virVMXParseParallel(virVMXContext *ctx, virConf *conf, int port,
>                                 virDomainChrDef **def);
>  static int virVMXParseSVGA(virConf *conf, virDomainVideoDef **def);
> +static int virVMXParseTPM(virConf *conf, virDomainTPMDef **def);
>  
>  static int virVMXFormatVNC(virDomainGraphicsDef *def, virBuffer *buffer);
>  static int virVMXFormatDisk(virVMXContext *ctx, virDomainDiskDef *def,
> @@ -1403,6 +1404,7 @@ virVMXParseConfig(virVMXContext *ctx,
>      char *guestOS = NULL;
>      bool smbios_reflecthost = false;
>      bool uefi_secureboot = false;
> +    bool vtpm_present = false;
>      int controller;
>      int bus;
>      int port;
> @@ -1938,6 +1940,16 @@ virVMXParseConfig(virVMXContext *ctx,
>  
>      def->nvideos = 1;
>  
> +    /* def:tpms */
> +    {
> +        virDomainTPMDef *tpm = NULL;
> +        if (virVMXParseTPM(conf, &tpm) < 0)
> +            goto cleanup;

So this parses 'vtpm.present'


> +
> +        if (tpm)
> +            VIR_APPEND_ELEMENT(def->tpms, def->ntpms, tpm);
> +    }
> +
>      /* def:sounds */
>      /* FIXME */
>  
> @@ -2001,6 +2013,18 @@ virVMXParseConfig(virVMXContext *ctx,
>          }
>      }
>  
> +    /* vmx: vtpm.present (optional) */

And inside the same function ...

> +    if (virVMXGetConfigBoolean(conf, "vtpm.present",
> +        &vtpm_present, false, true) < 0) {

You parse it again ...

> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                        _("Unable to parse vtpm.present"));
> +        goto cleanup;
> +    }
> +    if (vtpm_present) {
> +        VIR_DEBUG("Processing vtpm_present: %s",
> +            (vtpm_present == true) ? "yes" : "no");

just to add a debug statement? Can you explain this please?

> +    }
> +
>      /* vmx:uefi.secureBoot.enabled */
>      if (virVMXGetConfigBoolean(conf, "uefi.secureBoot.enabled",
>                                 &uefi_secureboot, false, true) < 0) {
> @@ -3367,6 +3391,32 @@ virVMXParseSVGA(virConf *conf, virDomainVideoDef **def)
>      return result;
>  }
>  
> +static int
> +virVMXParseTPM(virConf *conf, virDomainTPMDef **def)
> +{
> +    bool vtpm_present = false;
> +
> +    if (def == NULL || *def != NULL) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
> +        return -1;
> +    }

The only caller always passes these, so this check isn't needed.

> +
> +    /* vmx:vtpm.present */
> +    if (virVMXGetConfigBoolean(conf, "vtpm.present", &vtpm_present,
> +                               false, true) < 0) {
> +        return -1;
> +    }
> +
> +    if (!vtpm_present)
> +        return 0;
> +
> +    *def = g_new0(virDomainTPMDef, 1);
> +    (*def)->type = VIR_DOMAIN_TPM_TYPE_EMULATOR;
> +    (*def)->model = VIR_DOMAIN_TPM_MODEL_CRB;
> +    (*def)->data.emulator.version = VIR_DOMAIN_TPM_VERSION_2_0;
> +
> +    return 0;
> +}
>  
>  
>  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Re: [PATCH] libvirt: configure TPM device in the XML
Posted by Srihari Parimi via Devel 3 weeks, 2 days ago
On Fri, Apr 17, 2026 at 3:45 PM Peter Krempa <pkrempa@redhat.com> wrote:

>
> In summary of the commit mention 'vmx' as the driver instead of the
> obvious 'libvirt'
>
>
> On Fri, Apr 17, 2026 at 11:45:15 +0530, Srihari Parimi via Devel wrote:
> > Parses vtpm.present from VMX files and converts to libvirt TPM
> > device with CRB model and emulator backend. VMware vTPM uses
> > TPM 2.0 with the CRB
>
> Do you know of any docs to point to for which version of TPM is used?
>

Google search general suggestions
1. TIS supports TPM 1.2, TPM 2.0
2. CRB strictly supports TPM 2.0
3. CRB is generally recommended for Windows 11 or for UEFI based systems
which requires TPM 2.0


>
>
> >
> > Signed-off-by: Srihari Parimi <sparimi@redhat.com>
> > ---
> >  src/vmx/vmx.c              | 50 ++++++++++++++++++++++++++++++++++++++
> >  tests/vmx2xmldata/vtpm.vmx | 22 +++++++++++++++++
> >  tests/vmx2xmldata/vtpm.xml | 32 ++++++++++++++++++++++++
> >  tests/vmx2xmltest.c        |  2 ++
> >  4 files changed, 106 insertions(+)
> >  create mode 100644 tests/vmx2xmldata/vtpm.vmx
> >  create mode 100644 tests/vmx2xmldata/vtpm.xml
> >
> > diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c
> > index 57dfd57cfc..9231968175 100644
> > --- a/src/vmx/vmx.c
> > +++ b/src/vmx/vmx.c
> > @@ -599,6 +599,7 @@ static int virVMXParseSerial(virVMXContext *ctx,
> virConf *conf, int port,
> >  static int virVMXParseParallel(virVMXContext *ctx, virConf *conf, int
> port,
> >                                 virDomainChrDef **def);
> >  static int virVMXParseSVGA(virConf *conf, virDomainVideoDef **def);
> > +static int virVMXParseTPM(virConf *conf, virDomainTPMDef **def);
> >
> >  static int virVMXFormatVNC(virDomainGraphicsDef *def, virBuffer
> *buffer);
> >  static int virVMXFormatDisk(virVMXContext *ctx, virDomainDiskDef *def,
> > @@ -1403,6 +1404,7 @@ virVMXParseConfig(virVMXContext *ctx,
> >      char *guestOS = NULL;
> >      bool smbios_reflecthost = false;
> >      bool uefi_secureboot = false;
> > +    bool vtpm_present = false;
> >      int controller;
> >      int bus;
> >      int port;
> > @@ -1938,6 +1940,16 @@ virVMXParseConfig(virVMXContext *ctx,
> >
> >      def->nvideos = 1;
> >
> > +    /* def:tpms */
> > +    {
> > +        virDomainTPMDef *tpm = NULL;
> > +        if (virVMXParseTPM(conf, &tpm) < 0)
> > +            goto cleanup;
>
> So this parses 'vtpm.present'
>
>
> > +
> > +        if (tpm)
> > +            VIR_APPEND_ELEMENT(def->tpms, def->ntpms, tpm);
> > +    }
> > +
> >      /* def:sounds */
> >      /* FIXME */
> >
> > @@ -2001,6 +2013,18 @@ virVMXParseConfig(virVMXContext *ctx,
> >          }
> >      }
> >
> > +    /* vmx: vtpm.present (optional) */
>
> And inside the same function ...
>
> > +    if (virVMXGetConfigBoolean(conf, "vtpm.present",
> > +        &vtpm_present, false, true) < 0) {
>
> You parse it again ...
>
> > +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> > +                        _("Unable to parse vtpm.present"));
> > +        goto cleanup;
> > +    }
> > +    if (vtpm_present) {
> > +        VIR_DEBUG("Processing vtpm_present: %s",
> > +            (vtpm_present == true) ? "yes" : "no");
>
> just to add a debug statement? Can you explain this please?
>

Agree - this is not needed. Mistake on my part when I moved the code into
the function *virVMXParseTPM*, this should have been removed. I need to
review the patch before posting it.


>
> > +    }
> > +
> >      /* vmx:uefi.secureBoot.enabled */
> >      if (virVMXGetConfigBoolean(conf, "uefi.secureBoot.enabled",
> >                                 &uefi_secureboot, false, true) < 0) {
> > @@ -3367,6 +3391,32 @@ virVMXParseSVGA(virConf *conf, virDomainVideoDef
> **def)
> >      return result;
> >  }
> >
> > +static int
> > +virVMXParseTPM(virConf *conf, virDomainTPMDef **def)
> > +{
> > +    bool vtpm_present = false;
> > +
> > +    if (def == NULL || *def != NULL) {
> > +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid
> argument"));
> > +        return -1;
> > +    }
>
> The only caller always passes these, so this check isn't needed.
>

Agree. I have removed the checks. Was wondering if we need to be more
defensive ?

>
> > +
> > +    /* vmx:vtpm.present */
> > +    if (virVMXGetConfigBoolean(conf, "vtpm.present", &vtpm_present,
> > +                               false, true) < 0) {
> > +        return -1;
> > +    }
> > +
> > +    if (!vtpm_present)
> > +        return 0;
> > +
> > +    *def = g_new0(virDomainTPMDef, 1);
> > +    (*def)->type = VIR_DOMAIN_TPM_TYPE_EMULATOR;
> > +    (*def)->model = VIR_DOMAIN_TPM_MODEL_CRB;
> > +    (*def)->data.emulator.version = VIR_DOMAIN_TPM_VERSION_2_0;
> > +
> > +    return 0;
> > +}
> >
> >
> >  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
> * * * *
>
>
Re: [PATCH] libvirt: configure TPM device in the XML
Posted by Cole Robinson via Devel 3 weeks, 4 days ago
On 4/17/26 6:15 AM, Peter Krempa via Devel wrote:
> 
> In summary of the commit mention 'vmx' as the driver instead of the
> obvious 'libvirt'
> 
> 
> On Fri, Apr 17, 2026 at 11:45:15 +0530, Srihari Parimi via Devel wrote:
>> Parses vtpm.present from VMX files and converts to libvirt TPM
>> device with CRB model and emulator backend. VMware vTPM uses
>> TPM 2.0 with the CRB
> 
> Do you know of any docs to point to for which version of TPM is used?
> 

I wrote the original RFE so I'll provide this piece. Docs:

https://techdocs.broadcom.com/us/en/vmware-cis/vsphere/vsphere/8-0/vsphere-security/securing-virtual-machines-with-virtual-trusted-platform-module/vtpm-overview.html

Has this quote: "A virtual Trusted Platform Module (vTPM) is a
software-based   representation of a physical Trusted Platform Module
2.0 chip."

So, emulated version 2.0. Can't find anything about CRB vs TIS but I
believe CRB is default for TPM 2.0 devices in general so I took that to
be implied. I lack a setup to confirm at the moment but I can scrounge
one up if you'd like

Thanks,
Cole