From: Surendran Kanagaraj <surenkj@amazon.com>
To: Jarkko Sakkinen <jarkko@kernel.org>, Peter Huewe <peterhuewe@gmx.de>
Cc: Jason Gunthorpe <jgg@ziepe.ca>, <linux-integrity@vger.kernel.org>,
<linux-kernel@vger.kernel.org>, Jonathan Corbet <corbet@lwn.net>,
<linux-doc@vger.kernel.org>, Jonathan McDowell <noodles@earth.li>,
"Breno Leitao" <leitao@debian.org>, <nh-open-source@amazon.com>,
Alexander Graf <graf@amazon.de>,
Gunnar Kudrjavets <gunnarku@amazon.com>,
Josh Levinson <joshlev@amazon.com>
Subject: [RFC PATCH v3 0/8] tpm: Rework timeout and duration handling
Date: Thu, 12 Nov 2026 16:38:38 +0000 [thread overview]
Message-ID: <20261112163846.97654-1-surenkj@amazon.com> (raw)
Review of v2 [1] asked to redesign how the timeouts and durations are
handled across TPM families and drivers. This series is my attempt
at it. Sorry for the slow progress.
- Interface timeouts live in four fields, TPM1.x duration in an array
which uses duration class and TPM2.0 in a different map with raw time
values and other duration macros. Move interface timeouts and duration
classes to a new struct called struct tpm_limits embedded in struct
tpm_chip so that core and most drivers read them from one place.
- Currently it's left up to the driver to initialize the timeout values.
During probe, core/driver runs tpm_get_timeouts() which on TPM1.x
queries the TPM for timeout values. The transmit function used for this
request uses these timeouts for the state changes which can be zero at
this time. I found a case with xen-tpmfront where it calls tpm get
capability with TIMEOUT_C at zero. Hence the limit table is initialized
with default value which is highest among both TPM1.x and TPM2. This
makes sure driver is not missing to initialize during probe.
- Add module param option for all duration and timeouts. This gives an
option of passing these values via kernel command line.
Current flow:
tpm_chip_alloc() Each driver sets its own default timeouts
or none
tpm1_get_timeouts() reported values, ->update_timeouts()
and ->update_durations(), into
jiffies fields and chip->duration[]
tpm2_get_timeouts() fixed TPM2_TIMEOUT_A..D, no driver hook
tpm_calc_ordinal_duration() chip->duration[] on TPM 1.x, a fixed
per-ordinal map on TPM 2.0
tpm_transmit() resubmits on TPM2_RC_RETRY until the
delay passes TPM2_DURATION_LONG
The limit table is built in fixed order starting with family
defaults, reported by TPM chip, ->adjust_limits, tpm.limits= parameter
and finally the validation that checks the bounds. This also adds
a visibility to the source which sets the limit eg: default, TPM,
driver, param etc.
The flow after this series:
tpm_chip_alloc()
tpm_limits_init() larger of the TPM 1.x and 2.0 defaults,
tpm.limits= and bounds check
tpm1_get_timeouts(), tpm2_get_timeouts()
tpm_limits_update() family defaults
reported values (TPM 1.x)
->adjust_limits()
tpm.limits=
bounds check
readers of chip->limits
tpm_try_transmit() polls for completion up to the command's
duration class
tpm_transmit() resubmits on TPM2_RC_RETRY up to the
LONG duration
drivers tpm_poll_timeout(), or the limit in
jiffies where a driver counts jiffies
sysfs timeouts and durations, on TPM 2.0 too
This changes some of the existing behaviour:
- TPM2_VerifySignature waits DEFAULT 120 s instead of 30 s.
- Completion polling first sleeps at most 100 us instead of 1 ms.
- Until the timing query runs, tpm_crb waits up to 750 ms for
TIMEOUT_C instead of 200 ms, xen-tpmfront 750 ms instead of 0, and
st33zp24, tpm_i2c_infineon and tpm_i2c_nuvoton up to 4 s for
TIMEOUT_B instead of 2 s.
- On TPM 1.x, an ordinal with no class waits DEFAULT, which is never
shorter than LONG, so a chip that reports LONG above two minutes
waits longer than the old fixed two minutes.
- The timeouts and durations sysfs files now print exact
microseconds, and their "[adjusted]" marker also covers a value
changed by validation. TPM 2.0 chips now get both files too, in
/sys/class/tpm/tpmX/. tpm.limits= is documented in
kernel-parameters.txt.
I ran each patch in QEMU with swtpm, on TPM 2.0 over CRB and TIS and
on TPM 1.2 over TIS. Every boot answered commands and the TPM 1.2
sysfs output stays the same across the series. I also fed tpm.limits=
values below the floor, above the ceiling and malformed, and with a
local test hook held the TPM in TPM2_RC_RETRY and stalled completions
to see each wait end where the table says.
On an EC2 instance with Amazon NitroTPM, I ran a GetCapability and hwrng
loop through repeated periods of TPM unavailability. Kernel without
these changes logged "tpm2_load_context: failed with a TPM error 0x0922"
and every later TPM command failed. With this series applied, no command
failed.
The idea for this series is mine. An LLM coding assistant helped draft
the code and I reviewed every patch myself.
[1] https://lore.kernel.org/linux-integrity/atLD-d1v1B8ARv7x@kernel.org/
Surendran
V2 -> V3:
- Replace the TPM 2.0 duration override with one limits table for both
TPM families, built in a fixed order and validated
- Replace ->update_timeouts() and ->update_durations() with
->adjust_limits()
- Bound the tpm_transmit() retry loop by the LONG duration instead of
TPM2_DURATION_LONG
- Add tpm.limits=, and show the timeouts and durations files for
TPM 2.0 chips
- Move the NitroTPM values to a tpm_crb quirk table, raise its SHORT
and MEDIUM durations to 30 s and its LONG duration to 45 s
V1 -> V2:
- Drop chip->busy_timeout_ms. TPM2 durations and the TPM2_RC_RETRY
budget now come from chip->duration.
- Map TPM2_CC_SELF_TEST and TPM2_CC_VERIFY_SIGNATURE to TPM_LONG with
floors of 3s and 30s since their durations do not fit SHORT, MEDIUM,
LONG durations.
- Keep the TPM2 defaults for commands sent before tpm2_get_timeouts()
has run such as the one in tpm2_probe() and keep the 2s retry
budget for TPM 1.x chips.
- Keep the first TPM2_RC_RETRY wait at TPM2_DURATION_SHORT instead of
chip->duration[TPM_SHORT]. No TPM2 command maps to TPM_SHORT today
and a driver that raises TPM_SHORT for its commands should not also
lengthen the first retry wait.
- Return early from tpm_tis_update_durations() for TPM2 chips, since
its overrides are for TPM 1.x.
- Raise TPM_SHORT, TPM_MEDIUM and TPM_LONG to 30s for NitroTPM.
- Replace the vendor quirk table in tpm_crb with a plain vendor ID
check.
- Use the TPM_CRB_ prefix for the new tpm_crb macros.
- Rename the patches from "tpm: Add per-chip timeout for transient
unavailability" and "tpm_crb: Raise timeouts for Amazon NitroTPM".
v2: https://lore.kernel.org/linux-integrity/20261016043733.30589-1-surenkj@amazon.com/
v1: https://lore.kernel.org/linux-integrity/20260923142834.16786-1-surenkj@amazon.com/
Surendran Kanagaraj (8):
tpm: Add a single table for all TPM wait limits
tpm: Wire the timing setup to the limits table
tpm: Take command durations from the limits table
tpm: Bound core and CRB waits by the limits table
tpm: Drop the jiffies timing fields from struct tpm_chip
tpm: Add the tpm.limits= parameter
tpm: Show timeouts and durations for TPM 2.0 chips
tpm_crb: Raise the limits for Amazon NitroTPM
Documentation/ABI/stable/sysfs-class-tpm | 12 +-
.../admin-guide/kernel-parameters.txt | 13 +
drivers/char/tpm/Makefile | 1 +
drivers/char/tpm/st33zp24/st33zp24.c | 28 +-
drivers/char/tpm/tpm-chip.c | 1 +
drivers/char/tpm/tpm-interface.c | 72 +-
drivers/char/tpm/tpm-limits.c | 481 +++++++++++++
drivers/char/tpm/tpm-sysfs.c | 29 +-
drivers/char/tpm/tpm.h | 25 +-
drivers/char/tpm/tpm1-cmd.c | 669 +++++++++---------
drivers/char/tpm/tpm2-cmd.c | 80 ++-
drivers/char/tpm/tpm_crb.c | 120 +++-
drivers/char/tpm/tpm_i2c_atmel.c | 9 -
drivers/char/tpm/tpm_i2c_infineon.c | 25 +-
drivers/char/tpm/tpm_i2c_nuvoton.c | 32 +-
drivers/char/tpm/tpm_tis_core.c | 174 ++---
drivers/char/tpm/tpm_tis_i2c_cr50.c | 15 +-
drivers/char/tpm/xen-tpmfront.c | 10 +-
include/linux/tpm.h | 72 +-
include/linux/tpm_ptp.h | 9 -
20 files changed, 1188 insertions(+), 689 deletions(-)
create mode 100644 drivers/char/tpm/tpm-limits.c
base-commit: ca61ec17cf17a774a11c565c2167619eea32ebfb
--
2.47.3
next reply other threads:[~2026-11-12 16:38 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-12 16:38 Surendran Kanagaraj [this message]
2026-11-12 16:38 ` [RFC PATCH v3 1/8] tpm: Add a single table for all TPM wait limits Surendran Kanagaraj
2026-11-12 16:38 ` [RFC PATCH v3 2/8] tpm: Wire the timing setup to the limits table Surendran Kanagaraj
2026-11-12 16:38 ` [RFC PATCH v3 3/8] tpm: Take command durations from " Surendran Kanagaraj
2026-11-12 16:38 ` [RFC PATCH v3 4/8] tpm: Bound core and CRB waits by " Surendran Kanagaraj
2026-11-12 16:42 ` [RFC PATCH v3 5/8] tpm: Drop the jiffies timing fields from struct tpm_chip Surendran Kanagaraj
2026-11-12 16:43 ` [RFC PATCH v3 6/8] tpm: Add the tpm.limits= parameter Surendran Kanagaraj
2026-11-12 16:45 ` [RFC PATCH v3 7/8] tpm: Show timeouts and durations for TPM 2.0 chips Surendran Kanagaraj
2026-11-12 16:46 ` [RFC PATCH v3 8/8] tpm_crb: Raise the limits for Amazon NitroTPM Surendran Kanagaraj
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261112163846.97654-1-surenkj@amazon.com \
--to=surenkj@amazon.com \
--cc=corbet@lwn.net \
--cc=graf@amazon.de \
--cc=gunnarku@amazon.com \
--cc=jarkko@kernel.org \
--cc=jgg@ziepe.ca \
--cc=joshlev@amazon.com \
--cc=leitao@debian.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-integrity@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=nh-open-source@amazon.com \
--cc=noodles@earth.li \
--cc=peterhuewe@gmx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox