From 746b760f69f8a1ddf9bb7b7bf1844759e70de78a Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 29 May 2026 20:26:11 -0700 Subject: [PATCH] tpm: remove spurious TPM-establishment check at startup Emulator::new() refused to start the VMM unless the TPM Establishment bit (TPM_LOC_STATE.tpmEstablished, bit 0) was already set, aborting with "TPM not in established state" otherwise. That gate is not justified by the TCG PC Client Platform TPM Profile (PTP) specification: * tpmEstablished == 0 is the defined default state after a cold reset of the TPM. * The bit transitions to 1 only after a TPM2_Startup is issued from Locality 3 or 4 -- something the guest firmware/OS may or may not ever do, and which has not happened by the time the VMM is wiring up the device. So the check was rejecting the spec-defined normal case. It also had inverted internal naming (the boolean called "established_flag" was true when the bit was 0), which is what made the conditional read as if it were testing the opposite of what it actually tested. In practice the check happened to pass on KVM and fail on MSHV (issue socket, but the bug is independent of the backend: the VMM has no business gating startup on tpmEstablished at all. Drop the check. The bit is still surfaced to the guest from Tpm::read() when CRB_LOC_STATE is read, which is the only place the PTP spec requires it to be visible. Assisted-by: Copilot:GPT-5.5 Signed-off-by: Wei Liu --- tpm/src/emulator.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tpm/src/emulator.rs b/tpm/src/emulator.rs index 42b210a58..cf6f6013c 100644 --- a/tpm/src/emulator.rs +++ b/tpm/src/emulator.rs @@ -116,11 +116,12 @@ impl Emulator { ))); } - if !emulator.get_established_flag() { - return Err(Error::InitializeEmulator(anyhow!( - "TPM not in established state" - ))); - } + // Note: The TPM establishment flag can only be queried after the TPM + // has been initialized via CMD_INIT. swtpm rejects most control + // commands (returning PTM_BAD_ORDINAL = 0x0A) before initialization, + // so we defer the establishment-flag check to `get_established_flag()` + // which is invoked later (e.g. on guest reads of CRB_LOC_STATE) after + // `Tpm::reset()` has issued CMD_INIT. Ok(emulator) }