git: 943686575d81 - main - tpm: Do not use timed tsleep() while polling during cold boot
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 27 Sep 2026 16:45:01 UTC
The branch main has been updated by jrm:
URL: https://cgit.FreeBSD.org/src/commit/?id=943686575d818c5cd3aaf2dfb912fabfb7dd7872
commit 943686575d818c5cd3aaf2dfb912fabfb7dd7872
Author: Joseph Mingrone <jrm@FreeBSD.org>
AuthorDate: 2026-09-26 19:12:47 +0000
Commit: Joseph Mingrone <jrm@FreeBSD.org>
CommitDate: 2026-09-27 16:20:34 +0000
tpm: Do not use timed tsleep() while polling during cold boot
Commit 4e0f283fb97a made tpm_tis12_init() wait for TPM_STS_CMD_READY
after aborting any command. The wait is implemented by the driver's
existing tpm_waitfor_poll() loop, which sleeps with a one-tick tsleep()
between status reads. Until now, that loop only ran from the resume and
command paths after boot. From tpm_attach() it can panic with "timed
sleep before timers are working" when the TPM is attached from ACPI
during cold boot and the chip does not report ready on the first status
read.
Before 4e0f283fb97a, tpm_tis12_init() wrote TPM_STS_CMD_READY and
returned without waiting, so the polling loops only ran after boot.
tpm_request_locality() had the same latent hazard but its fast path
returns before sleeping whenever locality is already active.
Nothing calls wakeup() on the channels used by these polling loops, so
the sleeps are pure delays. Use pause_sig(), which falls back to
DELAY() while the kernel is cold and returns EWOULDBLOCK, a value these
loops already tolerate.
The c argument to tpm_waitfor_poll() is now unused. It is left in place
to keep this change minimal for MFC and can be removed in a follow-up.
Reviewed by: kbowling
Fixes: 4e0f283fb97a ("tpm: Bound TPM 1.2 locality ownership")
MFC after: 1 week
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D60050
---
sys/dev/tpm/tpm.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/sys/dev/tpm/tpm.c b/sys/dev/tpm/tpm.c
index ee886e6ae7f8..109d01af220e 100644
--- a/sys/dev/tpm/tpm.c
+++ b/sys/dev/tpm/tpm.c
@@ -561,7 +561,7 @@ tpm_request_locality(struct tpm_softc *sc, int l)
while ((r = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
(TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
(TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && to--) {
- rv = tsleep(sc->sc_init, PRIBIO | PCATCH, "tpm_locality", 1);
+ rv = pause_sig("tpm_locality", 1);
if (rv && rv != EWOULDBLOCK) {
#ifdef TPM_DEBUG
printf("tpm_request_locality: interrupted %d\n", rv);
@@ -638,7 +638,7 @@ tpm_getburst(struct tpm_softc *sc)
if (burst)
return burst;
- rv = tsleep(sc, PRIBIO | PCATCH, "tpm_getburst", 1);
+ rv = pause_sig("tpm_getburst", 1);
if (rv && rv != EWOULDBLOCK) {
return 0;
}
@@ -807,7 +807,7 @@ tpm_waitfor_poll(struct tpm_softc *sc, u_int8_t mask, int tmo, void *c)
* met.
*/
while (((sc->sc_stat = tpm_status(sc)) & mask) != mask && tmo--) {
- rv = tsleep(c, PRIBIO | PCATCH, "tpm_poll", 1);
+ rv = pause_sig("tpm_poll", 1);
if (rv && rv != EWOULDBLOCK) {
#ifdef TPM_DEBUG
printf("tpm_waitfor_poll: interrupted %d\n", rv);