Intel Trust Domain Extensions (TDX) lets you run a whole virtual machine whose memory and CPU state the cloud host cannot read or tamper with, and lets a remote party check, cryptographically, exactly what software booted inside it. For AI workloads that is the difference between trusting a provider's promise and checking a signed measurement before you hand over model weights or patient data.

Service-level design lives in confidential computing for LLMs and GPU bring-up in confidential compute for LLM serving. This article goes one layer down: the TDX module, private and shared memory, guest kernel changes, measurements and quotes, and what each costs a model server, ending with a worked key-release flow.

Advertisement

What TDX protects, and from whom

In an ordinary VM the hypervisor, the host kernel, the operator's admins and anyone with a DIMM interposer can, in principle, read guest memory. TDX removes the hypervisor and host software from the trusted computing base. What remains trusted is the CPU package, Intel-signed firmware running in a special mode (the TDX module), and your guest software.

Gaps remain. The host controls scheduling, so it can deny service. It sees every byte sent through shared memory, including disk and network I/O you do not encrypt, and it can observe access patterns and timing. Attacks on the CPU package and many side channels are out of scope. TDX gives confidentiality and integrity of private memory and registers, plus attestation; availability and traffic analysis are your problem.

SEAM mode and the TDX module

TDX adds a CPU mode called Secure Arbitration Mode (SEAM). A region of physical memory, the SEAM range, is reserved by the BIOS and locked by range registers; code there runs with VMX-root privileges that the normal hypervisor cannot touch. Intel's signed TDX module is loaded into that range through an authenticated loader, and from then on it is the only software that can create, enter or inspect a trust domain (TD).

The host VMM still does all the housekeeping, but only by asking. It calls the module with SEAMCALL leaf functions to create a TD, add pages, create virtual CPUs and enter the guest. The module checks each request against its own page-ownership metadata and refuses anything that would break isolation. Inside the guest, software talks to the module with TDCALL, for example to read a report or extend a measurement register. When the TD exits for an interrupt or a request for host service, the module saves and scrubs CPU state before returning control to the VMM, so registers never leak.

Trust domain (TD)guest kernel + model serverLegacy VMordinary guestQuoting enclave (SGX)signs quotes on the hostIntel TDX module (SEAM VMX root)signed by Intel; owns TD state, Secure EPTHost VMM (KVM, Hyper-V)untrusted: schedules, allocates, does I/OTDCALLSEAMCALLSEAMRETVM entryPrivate memoryTME-MK, TD-private key IDShared memoryshared GPA bit set; host-visibleSecure EPTshared EPTCPU: SEAM range registers, memory encryption engine, measurement registers MRTD and RTMR0-3
The TDX trust boundary. The TDX module runs in Secure Arbitration Mode and mediates every transition between the untrusted host VMM and a trust domain. Private TD memory is encrypted under a key the host cannot use; only pages the guest marks shared are visible to the host for I/O.

Unlike SGX, which protects a region inside a process, TDX protects a full VM, so an unmodified inference server runs inside it; the changes are in guest kernel and firmware. Upstream KVM host support landed in Linux 6.16, and clouds offer TDX VMs such as Azure DCesv5/ECesv5 and Google Cloud C3 confidential VMs; check your provider for newer series.

Advertisement

Private memory, shared memory and Secure EPT

Every TD gets its own memory encryption key, held inside the CPU's multi-key total memory encryption engine (TME-MK) and selected by a key ID that the host cannot assign to anything else. Lines leaving the CPU for DRAM are encrypted with that key, so a DIMM snapshot or a host read through a different key ID yields ciphertext. TDX also tracks ownership of each line, so a host write through another key is detected on the next TD read; depending on platform configuration this integrity check is logical (an ownership bit) or cryptographic (a MAC).

Translation is split in two. The guest physical address space has a shared bit near the top. Addresses with the bit clear are private and are translated by a Secure EPT that lives in TD-private memory and is edited only by the TDX module. Addresses with the bit set are shared and go through an ordinary EPT that the host manages. The host can still decide which physical page backs a private address, but only by asking the module, which checks the page is free and records the mapping. A guest must accept each private page (TDG.MEM.PAGE.ACCEPT) before first use, which stops the host from silently swapping a page underneath it.

For AI software the consequence is concrete: anything a device reads or writes by DMA (virtio queues, network buffers, NVMe blocks and, without device-side TEE support, GPU transfers) must sit in shared memory. Linux copies data through a pool of shared bounce buffers (SWIOTLB). Weights in private RAM are protected, but loading them from disk or pushing them to a GPU passes through host-visible memory, so that payload must already be encrypted.

Why the guest kernel changes: #VE and TDVMCALL

Because the host cannot see guest registers, it cannot emulate instructions the way a normal hypervisor does. Instead, when the guest executes something that needs host help (certain CPUID leaves, some MSR accesses, port I/O, MMIO to emulated devices, HLT), the TDX module injects a virtualization exception (#VE) into the guest. The guest kernel's #VE handler decides what to disclose and issues TDG.VP.VMCALL, a TDCALL that passes only the selected registers to the host, following the Guest-Host Communication Interface (GHCI) specification.

So the guest kernel must be TDX-enlightened: handle #VE, convert pages between private and shared with TDG.VP.VMCALL<MapGPA>, route DMA through SWIOTLB, and treat every host-returned value as hostile. Drivers were written for a trusted hypervisor, so a malicious virtio device can feed malformed descriptors; keep the device set minimal and kernels current.

Measurement: MRTD and the runtime registers

Attestation is only as useful as what was measured. TDX keeps two kinds of measurement register per TD, each a SHA-384 digest. MRTD is built by the TDX module while the host adds initial pages to the TD (TDH.MEM.PAGE.ADD and TDH.MR.EXTEND), and it is finalised before the TD first runs. In practice it measures the virtual firmware image, typically TDVF (OVMF built for TDX). Four runtime measurement registers, RTMR0 to RTMR3, start at zero and can only be extended, never set: new value = SHA-384(old value || digest).

By TDVF convention the firmware extends RTMR0 with its configuration (including the ACPI tables and boot variables), RTMR1 with the OS loader and kernel, and RTMR2 with the kernel command line and initrd, roughly mirroring TPM PCRs 1 and 7, 2 to 6, and 8 to 15. RTMR3 is left for the workload. Each extension is also logged (the CCEL ACPI table) so a verifier can replay the log and see which component produced which digest. Checking MRTD alone verifies only the firmware; match MRTD plus RTMR0 to RTMR2 against values computed from your own image build.

From TDREPORT to a verifiable quote

Inside the TD, TDG.MR.REPORT returns a TDREPORT: the measurement registers, TD attributes (for example whether debug is enabled), the TCB security versions of the module and CPU, and 64 bytes of caller-chosen report data, all protected by a MAC with a key that only this CPU knows. That MAC can be checked only on the same machine, so a TDREPORT proves nothing to a remote party. It has to be turned into a quote.

The quote comes from Intel's Data Center Attestation Primitives (DCAP) stack on the host. An SGX Quoting Enclave (QE) on the same platform verifies the TDREPORT's MAC locally, then signs its contents with an ECDSA attestation key. The QE's own report, which binds the hash of that attestation key, is signed by the platform's Provisioning Certification Key (PCK), and the PCK certificate chains to Intel's root CA. A verifier therefore checks: the PCK chain and revocation lists; the QE report signature and the QE's identity; the quote signature under the attestation key; the TCB status against Intel's published TCB info; and finally your policy on MRTD, the RTMRs, the attributes and the report data.

On Linux, a guest fetches a quote through the configfs TSM interface. You create a report directory, write report data, and read the quote back; the kernel forwards the request to the host's quote-generation service.

R=/sys/kernel/config/tsm/report/req1
mkdir -p "$R"
cat "$R/provider"                       # expect: tdx_guest
# 64 bytes of report data: here SHA-512 of the ephemeral public key plus verifier nonce
cat ephemeral_pub.der nonce.bin | openssl dgst -sha512 -binary > "$R/inblob"
cat "$R/outblob" > quote.bin            # signed TD quote
cat "$R/generation"                     # bumps on every write; detects racing writers

Without a key bound into the report data, a quote proves a good TD exists somewhere, not that your session terminates inside it.

Worked example: releasing model-weight keys to a TD

The key AI pattern: release a model-weight decryption key only to a TD running your exact serving image. Weights are encrypted with a data key held by a key broker. At boot the TD generates an ephemeral key pair, gets a quote whose report data commits to the public key and a broker nonce, and sends both; the broker verifies and wraps the data key to that public key.

# Key broker: runs outside the TD, holds the wrapping key (in an HSM or KMS).
ALLOWED = load_policy("serving-image-2026-10.json")  # MRTD and RTMR0-2 from your reproducible build

def release_weights_key(quote: bytes, pubkey_der: bytes, nonce: bytes) -> bytes:
    q = parse_td_quote(quote)                       # header, TD body, signature data
    collateral = fetch_dcap_collateral(q.fmspc)     # TCB info, QE identity, CRLs from PCCS
    verify_pck_chain(q.pck_chain, collateral.crls, intel_root_ca)
    verify_qe_report(q.qe_report, q.qe_report_sig, q.pck_chain.leaf)
    verify_ecdsa(q.attest_pub, q.signed_bytes, q.signature)
    if q.qe_report.report_data[:32] != sha256(q.attest_pub + q.qe_auth_data):
        raise Deny("attestation key not bound to QE")
    if tcb_status(q, collateral) not in ALLOWED.tcb_ok:  # e.g. UpToDate only, or plus SWHardeningNeeded
        raise Deny("platform TCB out of date")
    if q.td.attributes.debug:
        raise Deny("debug TD")
    if (q.td.mrtd, q.td.rtmr[0], q.td.rtmr[1], q.td.rtmr[2]) not in ALLOWED.measurements:
        raise Deny("unknown image")
    if q.td.report_data != sha512(pubkey_der + nonce):
        raise Deny("quote not bound to this key")
    consume_nonce(nonce)                             # single use, short TTL
    return hpke_seal(pubkey_der, unwrap(WEIGHTS_DATA_KEY))

In production, Intel's DCAP verification library, Intel Trust Authority or your cloud's attestation service does the cryptographic checks; keep the policy lines in your own code, because a genuine quote is not necessarily your image. The same flow gates TLS keys and fine-tuning dataset keys.

What TDX costs a model server

Instructions run natively and memory encryption adds modest latency on cache misses; the noticeable costs are elsewhere:

WhereWhyWhat to do
Exits and #VEEach host interaction goes through the module and the #VE path, more expensive than a normal VM exitPrefer virtio with batching; avoid emulated devices and chatty MMIO
Bounce buffersEvery DMA is a copy between private and shared memorySize SWIOTLB for peak I/O; measure disk and network throughput, not just tokens per second
GPU transfersWithout device-side TEE, host-to-device copies go through shared memory and must be encrypted by softwareUse GPUs with confidential-computing mode, which encrypt the bounce path; budget the copy cost for large prompts and KV cache offload
Boot and page acceptPrivate pages must be accepted before useLazy accept in recent kernels and firmware; keep a warm pool of TDs rather than cold-starting per request
Attestation round tripQuote generation and collateral fetch take network callsCache collateral with a local PCCS; attest once per TD lifetime, not per request

Intel's TDX Connect extends TDX to devices through the PCIe TDISP standard so a GPU can DMA into private memory; check vendor and cloud availability before planning around it, and treat bounce-buffer cost as today's baseline.

Failure modes

These are the failures we see most:

  • Measuring only the firmware. Policy pins MRTD but not RTMR1 and RTMR2, so any kernel and command line passes. Pin all three and rebuild the allow-list in CI from the image.
  • Unbound quotes. Static report data lets another VM replay a quote. Commit to an ephemeral key and fresh nonce.
  • Debug TDs in production. The debug attribute lets the host read TD state. Reject it.
  • Stale TCB accepted forever. Microcode and module updates change TCB status; alert when the fleet drifts.
  • Plaintext through shared memory. Disks, model files and traffic leave unencrypted. Use broker-keyed disk encryption and TLS terminating inside the TD.
  • Fragile allow-lists. Non-reproducible builds change measurements every rebuild, and teams loosen policy. Make images reproducible.

Trade-offs

AMD SEV-SNP offers the same VM-level model with a different reporting chain; choose by where your capacity and GPUs are. SGX has a smaller TCB but forces application partitioning, which rarely fits a Python serving stack. Cryptographic approaches in secure inference avoid trusting hardware vendors but are far slower for transformers. With TDX you trust Intel and its firmware and pay in I/O copies and measurement work; in return the cloud operator leaves your trust base. Pair it with encryption in use for data that leaves the TD.

What to do next

  1. Write down your threat model: which party you are removing from trust, and which risks (availability, traffic analysis, side channels) you accept.
  2. Boot a TDX VM on your provider and confirm dmesg reports a TDX guest and that /sys/kernel/config/tsm/report exists.
  3. Build your serving image reproducibly and compute expected MRTD and RTMR0 to RTMR2 from the build, not by copying from a running VM.
  4. Stand up a verifier using DCAP libraries or an attestation service, and put image policy, TCB policy and debug rejection in your own code.
  5. Bind every quote to an ephemeral key and nonce, and release weight and disk keys only through that check.
  6. Encrypt everything that crosses shared memory: disk, network, and GPU transfers.
  7. Benchmark I/O-heavy paths (model load, long prompts, KV cache offload) inside and outside a TD before committing capacity.
  8. Automate re-attestation and alerting when TCB status or your allow-list changes.
Key takeaway: TDX moves the hypervisor and cloud operator out of your trust base by running a whole VM under an Intel-signed module that owns its memory mappings and CPU state. Private memory is encrypted per TD, while all device I/O goes through host-visible shared buffers, so encrypt what crosses them. The security you actually get comes from attestation: pin MRTD and the runtime registers to your own reproducible image, bind each quote to a fresh key, reject debug TDs and stale TCBs, and release model keys only after those checks pass.