Confidential Computing with Intel Trust Domain Extensions (TDX)

Intel TDX is a Confidential Computing technology. It deploys hardware-isolated Virtual Machines (VMs) called Trust Domains (TDs), and protects them from a broad range of software attacks by isolating them from the Virtual Machine Manager (VMM), hypervisor, and other non-TD software on the host platform. This enhances a platform user’s control of data security and IP protection. It also enhances a Cloud Service Providers’ (CSP) ability to provide managed cloud services without exposing tenant data to adversaries.

Ubuntu supports Intel TDX for both host and guest operating systems. Guest support is available from Ubuntu 24.04 LTS onwards, while host support begins with Ubuntu 25.10.

Supported hardware

This table lists Intel Xeon processors that support Intel TDX:

Processor

Code Name

TDX Module Version

4th Gen Intel Xeon Scalable Processors (select SKUs with Intel TDX)

Sapphire Rapids

1.5.x

5th Gen Intel Xeon Scalable Processors

Emerald Rapids

1.5.x

Intel Xeon 6 Processors with E-Cores

Sierra Forest

1.5.x

Intel Xeon 6 Processors with P-Cores

Granite Rapids

2.0.x

Configure host

To enable Intel TDX on the host, BIOS and host OS configurations are required. First, enable Intel TDX settings in the BIOS.

Note

The following is a sample BIOS configuration. The necessary BIOS settings or menus may differ based on the platform used. Reach out to your OEM/ODM or independent BIOS vendor for platform-specific instructions.

Navigate to Socket Configuration ‣ Processor Configuration ‣ TME, TME-MT, TDX and configure:

  • Set Memory Encryption (TME) to Enable

  • Set Total Memory Encryption Bypass to Enable (optional setting for best host OS and regular VM performance)

  • Set Total Memory Encryption Multi-Tenant (TME-MT) to Enable

  • Set TME-MT memory integrity to Disable

  • Set Trust Domain Extension (TDX) to Enable

  • Set TDX Secure Arbitration Mode Loader (SEAM Loader) to Enable (allows loading Intel TDX Loader and Intel TDX Module from the ESP or BIOS)

  • Set TME-MT/TDX key split to a non-zero value

Navigate to Socket Configuration ‣ Processor Configuration ‣ Software Guard Extension (SGX) and configure:

  • Set SW Guard Extensions (SGX) to Enable

Save the BIOS settings and reboot.

Now, add the nohibernate kvm_intel.tdx=1 kernel parameters to GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub, run sudo update-grub, and then reboot again. After rebooting, verify that the parameters have been applied:

cat /proc/cmdline 

You should see something like:

BOOT_IMAGE=/boot/vmlinuz-6.19.0-3-generic root=UUID=f6ce4201-d6d1-4505-bdf5-019ee4fe842e ro nohibernate kvm_intel.tdx=1

Next, confirm that Intel TDX has been successfully enabled:

sudo dmesg | grep -i tdx

Which produces output like this:

[    1.824045] virt/tdx: BIOS enabled: private KeyID range [32, 64)
[    1.824049] virt/tdx: Disable ACPI S3. Turn off Intel TDX in the BIOS to use ACPI S3.
[   24.195089] virt/tdx: 1050644 KB allocated for PAMT
[   24.195098] virt/tdx: module initialized

The message virt/tdx: module initialized tells us that TDX has indeed been enabled.

Install virtualization stack

The next step is to install the virtualization components required to run TDs.

sudo apt update
sudo apt install \
  qemu-system-x86 \
  ovmf-inteltdx \
  libvirt-daemon-system \
  libvirt-clients

This installs:

  • qemu-system-x86 - QEMU emulator for x86_64 with Intel TDX support

  • ovmf-inteltdx - EDK II UEFI firmware with Intel TDX-capable OVMF builds

  • libvirt-daemon-system - Libvirt daemon for managing VMs

  • libvirt-clients - Command-line tools for libvirt (virsh, etc.)

After installation, verify the Intel TDX-capable OVMF firmware is available:

$ ls -l /usr/share/ovmf/OVMF.inteltdx.ms.fd

-rw-r--r-- 1 root root 4194304 Jan 15 12:00 /usr/share/ovmf/OVMF.inteltdx.ms.fd

Create a guest image

Download a cloud image (Ubuntu 26.04 LTS in this example):

wget https://cloud-images.ubuntu.com/resolute/current/resolute-server-cloudimg-amd64.img

Next, install the required tool:

sudo apt install cloud-image-utils

Create a cloud-init configuration file:

cat > user-data.yaml << 'EOF'
#cloud-config
chpasswd:
  list: |
    root:root
  expire: False
ssh_pwauth: True
disable_root: false
EOF

From that, create a cloud-init ISO:

cloud-localds user-data.img user-data.yaml

The user-data.img will be attached to the VM to apply the configuration.

Note

For production use, set a strong password and configure SSH key-based authentication instead of password authentication.

Launch a TD guest using QEMU

Using QEMU, we can now launch a TD with the prepared image:

qemu-system-x86_64 \
  -accel kvm \
  -smp 32 \
  -m 16G \
  -cpu host \
  -object '{"qom-type":"tdx-guest","id":"tdx","quote-generation-socket":{"type": "vsock", "cid":"2","port":"4050"}}' \
  -object memory-backend-ram,id=mem0,size=16G \
  -machine q35,kernel_irqchip=split,confidential-guest-support=tdx,memory-backend=mem0 \
  -bios /usr/share/ovmf/OVMF.inteltdx.ms.fd \
  -nographic \
  -nodefaults \
  -vga none \
  -drive file=resolute-server-cloudimg-amd64.img,if=none,id=virtio-disk0 \
  -device virtio-blk-pci,drive=virtio-disk0 \
  -drive file=user-data.img,if=none,id=cloud-init,format=raw \
  -device virtio-blk-pci,drive=cloud-init \
  -serial stdio

Key Intel TDX-specific parameters:

  • -object '{"qom-type":"tdx-guest","id":"tdx",...}': Creates the TDX guest object that enables confidential computing capabilities. The quote-generation-socket configures the vsock channel (CID 2, port 4050) for remote attestation quote generation.

  • -machine q35,kernel_irqchip=split,confidential-guest-support=tdx,memory-backend=mem0:

    • kernel_irqchip=split: Required for Intel TDX to properly isolate interrupt handling between host and guest

    • confidential-guest-support=tdx: Links the machine to the Intel TDX guest object

    • memory-backend=mem0: Associates the machine with the Intel TDX-protected memory backend

  • -object memory-backend-ram,id=mem0,size=16G: Defines the memory backend that will be encrypted by Intel TDX

  • -bios /usr/share/ovmf/OVMF.inteltdx.ms.fd: Specifies the Intel TDX-capable UEFI firmware with Microsoft Secure Boot keys

  • -cpu host: Uses the host CPU model to expose Intel TDX capabilities to the guest

For more details about these parameters, refer to the QEMU documentation.

Verify Intel TDX enablement in the guest

Once the TD is launched, verify that Intel TDX is enabled by checking the kernel logs:

sudo dmesg | grep tdx

You should see something like:

[    0.000000] tdx: Guest detected
[   11.162378] systemd[1]: Detected confidential virtualization tdx.

You can also check the Intel TDX guest device:

$ ls -l /dev/tdx_guest

crw------- 1 root root 10, 125 Jan  1 00:00 /dev/tdx_guest

Launch a TDX VM with libvirt

Intel TDX VM can be managed by libvirt. For this, the domain definition must be modified to contain certain necessary information about the confidential VM. Here is a domain definition sample for Intel TDX VM:

cat > tdx-vm.xml << 'EOF'
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
  <name>tdx-guest</name>
  <memory unit='GiB'>16</memory>
  <memoryBacking>
    <source type="anonymous"/>
    <access mode="private"/>
  </memoryBacking>
  <vcpu placement="static">16</vcpu>
  <os>
    <type arch='x86_64' machine='q35'>hvm</type>
    <loader type='rom' readonly='yes'>/usr/share/ovmf/OVMF.inteltdx.ms.fd</loader>
    <boot dev='hd'/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <ioapic driver='qemu'/>
  </features>
  <clock offset='utc'>
    <timer name='hpet' present='no'/>
  </clock>
  <cpu mode='host-passthrough'>
    <topology sockets='1' cores='16' threads='1'/>
  </cpu>
  <devices>
    <emulator>/usr/bin/qemu-system-x86_64</emulator>
    <disk type="file" device="disk">
      <driver name="qemu" type="qcow2"/>
      <source file="/var/lib/libvirt/images/resolute-server-cloudimg-amd64.img"/>
      <target dev="vda" bus="virtio"/>
    </disk>
    <console type='pty'>
      <target type='virtio' port='1'/>
    </console>
  </devices>
  <launchSecurity type='tdx'>
    <policy>0x10000000</policy>
    <quoteGenerationService>
      <SocketAddress type='vsock' cid='2' port='4050'/>
    </quoteGenerationService>
  </launchSecurity>
</domain>
EOF

Next, define the VM:

sudo virsh define tdx-vm.xml

Start the VM:

sudo virsh start tdx-guest

Connect to the console:

sudo virsh console tdx-guest

Key libvirt configuration elements for TDX:

  • <launchSecurity type='tdx'>: Enables TDX confidential computing for the VM

  • <policy>0x10000001</policy>: TDX policy controlling debug and other TD features

  • <quote-generation-service>: Configures the vsock channel for remote attestation

  • <memoryBacking>: Uses shared memory with memfd backend required for TDX

  • <loader>: Specifies the TDX-capable OVMF firmware

Manage the VM

List all VMs:

sudo virsh list --all

Stop the VM:

sudo virsh shutdown tdx-guest

Force stop the VM:

sudo virsh destroy tdx-guest

Remove the VM definition:

sudo virsh undefine tdx-guest

Troubleshooting Intel TDX

Intel TDX is not enabled on the host

Ensure BIOS settings are correct and kernel parameters are enabled. Confirm the following MSR checks.

  • Install the MSR tools package:

    sudo apt install msr-tools
    
  • Verify that Multi-Key Total Memory Encryption (MK-TME) is enabled by checking bit 1 of MSR 0x982:

    sudo rdmsr 0x982 -f 1:1 1
    

    Expected value of 1 indicates MK-TME is enabled in BIOS.

  • Verify Intel TDX support by checking bit 11 of MSR 0x1401 (enable bit for SEAMRRSEAM Range Registers):

    sudo rdmsr 0x1401 -f 11:11 1
    

    Expected value of 1 indicates SEAMRR is enabled.

  • Verify the number of private keys allocated to TDs by checking bits 63:32 of IA32_TME_CAPABILITY MSR:

    echo $((0x$(sudo rdmsr 0x87 -f 63:32)))
    

    This shows the number of private keys available for Trust Domains (NUM_TDX_PRIV_KEYS) in decimal format. A non-zero value indicates keys are allocated for Intel TDX.

  • Verify the number of private keys allocated to TDs by checking bits 63:32 of IA32_TME_CAPABILITY MSR:

    echo $((0x$(sudo rdmsr 0x87 -f 63:32)))
    

    This shows the number of private keys available for Trust Domains (NUM_TDX_PRIV_KEYS) in decimal format. A non-zero value indicates keys are allocated for Intel TDX.

  • Verify the Intel SGX and MCHECK status.

    sudo rdmsr 0xa0
    

    Expected value of 1 indicates it is enabled. A value of 1861 indicates SGX registration UEFI variables maybe corrupt. Boot into the BIOS and set SGX Factory Reset to Enable. This will result in two new keys.

sudo dmesg | grep -i tdx shows virt/tdx: module initialization failed (-5)

You may have an old and unsupported Intel TDX Module. Try updating to the latest Intel TDX Module.

Note

If you chose to “Update Intel TDX Module via Binary Deployment”, make sure you’re using the correct Intel TDX Module version for your hardware. See the Supported hardware table.

I rebooted my TD, but it shuts down instead

Legacy (non-TDX) guests support reboot by resetting vCPU context. However, TD guests do not allow it for security reasons. You must power it down and boot it up again.