mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [RFC PATCH v3 0/8] tpm: Rework timeout and duration handling
@ 2026-11-12 16:38 Surendran Kanagaraj
  2026-11-12 16:38 ` [RFC PATCH v3 1/8] tpm: Add a single table for all TPM wait limits Surendran Kanagaraj
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Surendran Kanagaraj @ 2026-11-12 16:38 UTC (permalink / raw)
  To: Jarkko Sakkinen, Peter Huewe
  Cc: Jason Gunthorpe, linux-integrity, linux-kernel, Jonathan Corbet,
	linux-doc, Jonathan McDowell, Breno Leitao, nh-open-source,
	Alexander Graf, Gunnar Kudrjavets, Josh Levinson

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


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-11-12 16:46 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-12 16:38 [RFC PATCH v3 0/8] tpm: Rework timeout and duration handling Surendran Kanagaraj
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®