From nobody Fri Sep 18 00:07:54 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hmCcq1VfZz6sHMt for ; Fri, 18 Sep 2026 00:07:55 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hmCcq0vyHz4Zh0 for ; Fri, 18 Sep 2026 00:07:55 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789690075; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=FvgzLbNGk123f88y7GEctbpOSwjolaApQwg94hSe1Cc=; b=wWqFcXBNEKsRj5Z3o59+keCCjpC2hlTw4cVsR0ThrQpEhTO62/hcN+Yz31kFVgJRsYhLzc VW1xOERQ8YGDEvX65epwUC2K+2ZQ6J4Ujw6T046XSqHtkEcptsUuTnvv/1NIj4D5KBUpo0 2FnlvwpsnlRce35mbrOrH7mAMGLAIXTMnRe3sARStucZSRJvHBPXihS4MdZJycWErEij16 g1N8kfRwufw6iJuSpDG/DprH3zfrL4MhauM+9tbrgraDkPxrPwZ0AQ7kwrWkFOJUi3AihB Dz/qMsmzMaRO0mHe9oDEsZwh0Pff5YrxsQXWFBzm2LKuKecbycjQdpYcmwNUgQ== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1789690075; b=oMyNZL2YqDFI9HkUo4CHqUbiegFX9KJTel5g8qfyq3wd1LKp1DK0C0PUI89jzpxMRBzmiS JpvlsA1ZwjnZOEo36YOxMi/wy9kCFde6KN62AJNleSLo6tm7eDXRr7z70CxSz4JWqgtqTq OdtDUUBgpYJEM5dFbxumw74iI4+F8XcmbsSdVuxi4DXawVFgm+5T0ellEbievWJoyNCufS si8/NXmGaxK+CuHByiFlQLT833MzII3Kz2qmaio0Y+NhEgkEY8cyuDCnxt61jb0Oa8OZOL hQ9TNiJS/R283WSvFkvKQiDUXZxt0+hgUDvzIv9ZlcrqJt3T8R79Fy7oJdN22w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789690075; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=FvgzLbNGk123f88y7GEctbpOSwjolaApQwg94hSe1Cc=; b=GsVkEncw2f5PVB1T+atrjOKGdIAn4H7hJT+2t18wAHSzqIo1Lr35R60e5waMSrNUdVNExN 0RmV3pGJJnQxhDMnOdLDF8pWhkjOnFRRwsgkPZG8JdgB94+n/egFYzZYuyCrxGVWfn6Vdk 6HIdgD/ZiPwAyjxvg0hpBG5F4y0lAK4nAzuI3lSjs6M025gsnnYd4U92xlR43KlDMfkUFG +CJkEmMyfPSgy4f95YbZ3MskUmwiVGTh10xDQu6zsG6jXb9lJirzTAK4ff+o8B74Lf0bwj 20NXTU4WWlGf+XS6g9HGE4xporlCUW965SIrNDT7kf2oL7Q3SiJKxPkQ9v56hQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hmCcp73dKzv9X for ; Fri, 18 Sep 2026 00:07:54 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 25976 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 18 Sep 2026 00:07:54 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kevin Bowling Subject: git: 74f94f11dd69 - stable/15 - tpm: Restore TPM 1.2 TIS state after resume List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kbowling X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: 74f94f11dd6915b1d23d64bf92aaf037c4b31fc9 Auto-Submitted: auto-generated Date: Fri, 18 Sep 2026 00:07:54 +0000 Message-Id: <6aac80da.25976.14060801@gitrepo.freebsd.org> The branch stable/15 has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=74f94f11dd6915b1d23d64bf92aaf037c4b31fc9 commit 74f94f11dd6915b1d23d64bf92aaf037c4b31fc9 Author: Kevin Bowling AuthorDate: 2026-08-26 10:33:38 +0000 Commit: Kevin Bowling CommitDate: 2026-09-18 00:07:45 +0000 tpm: Restore TPM 1.2 TIS state after resume Firmware restores the state saved by TPM_ORD_SaveState, but the TIS interrupt, locality, and command FIFO state are not guaranteed to survive S3. The legacy driver previously treated resume as a no-op. Revalidate the interface and device identity, disable and acknowledge stale interrupts, restore the configured interrupt vector, reacquire locality zero, and return the FIFO to command-ready state. Also disable TIS interrupts during initial setup when the device uses polling so firmware settings cannot leave an unhandled interrupt enabled. TIS 1.3 Table 22 makes the interrupt control registers locality protected. Acquire locality before disabling or programming them during initial setup and resume rather than relying on probe retaining locality. Keep TPM self-test outside the resume critical path. It can take minutes on some TPM 1.2 devices and is not required to restore the transport state. The two-commit suspend and resume series completed two consecutive S3 cycles on a ThinkPad T440p with its STMicro TPM 1.2 Security Chip enabled. PCR 0 was readable with the same value before and after each cycle, and no SaveState or TIS restoration errors were logged. The locality ordering completed another two consecutive S3 cycles on a ThinkPad T430 with the same STMicro TPM in polling mode. PCR 0 again remained stable, and TPM access recovered without errors after each resume. PR: 291067 Reviewed by: kevans Sponsored by: BBOX.io Differential Revision: https://reviews.freebsd.org/D59193 (cherry picked from commit 96ed6005082fc63d633408ba3ad697e8757e80f9) --- sys/dev/tpm/tpm.c | 91 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 70 insertions(+), 21 deletions(-) diff --git a/sys/dev/tpm/tpm.c b/sys/dev/tpm/tpm.c index 855dad8eee85..c877f617fdad 100644 --- a/sys/dev/tpm/tpm.c +++ b/sys/dev/tpm/tpm.c @@ -195,6 +195,8 @@ int tpm_legacy_write(struct tpm_softc *, void *, int); int tpm_legacy_end(struct tpm_softc *, int, int); static int tpm_transmit_header(struct tpm_softc *, uint32_t, uint32_t *); +static int tpm_tis12_devid_index(uint32_t); +static int tpm_tis12_resume(struct tpm_softc *); /* @@ -329,19 +331,14 @@ tpm_tis12_probe(bus_space_tag_t bt, bus_space_handle_t bh) } /* - * Setup interrupt vector if one is provided and interrupts are know to - * work on that particular chip. + * Setup the interrupt vector if one is provided and interrupts are known + * to work on that particular chip. The caller must hold locality zero. */ int tpm_tis12_irqinit(struct tpm_softc *sc, int irq, int idx) { u_int32_t r; - if ((irq == IRQUNK) || (tpm_devs[idx].flags & TPM_DEV_NOINTS)) { - sc->sc_vector = IRQUNK; - return 0; - } - /* Ack and disable all interrupts. */ bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE, bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INTERRUPT_ENABLE) & @@ -349,6 +346,11 @@ tpm_tis12_irqinit(struct tpm_softc *sc, int irq, int idx) bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS, bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS)); + if ((irq == IRQUNK) || (tpm_devs[idx].flags & TPM_DEV_NOINTS)) { + sc->sc_vector = IRQUNK; + return 0; + } + /* Program interrupt vector. */ bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_INT_VECTOR, irq); sc->sc_vector = irq; @@ -365,6 +367,17 @@ tpm_tis12_irqinit(struct tpm_softc *sc, int irq, int idx) return 0; } +static int +tpm_tis12_devid_index(uint32_t devid) +{ + int i; + + for (i = 0; tpm_devs[i].devid != 0; i++) + if (tpm_devs[i].devid == devid) + break; + return (i); +} + /* Setup TPM using TIS 1.2 interface. */ int tpm_tis12_init(struct tpm_softc *sc, int irq, const char *name) @@ -386,19 +399,17 @@ tpm_tis12_init(struct tpm_softc *sc, int irq, const char *name) sc->sc_devid = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_ID); sc->sc_rev = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_REV); - for (i = 0; tpm_devs[i].devid; i++) - if (tpm_devs[i].devid == sc->sc_devid) - break; + i = tpm_tis12_devid_index(sc->sc_devid); if (tpm_devs[i].devid) printf(": %s rev 0x%x\n", tpm_devs[i].name, sc->sc_rev); else printf(": device 0x%08x rev 0x%x\n", sc->sc_devid, sc->sc_rev); - if (tpm_tis12_irqinit(sc, irq, i)) + if (tpm_request_locality(sc, 0)) return 1; - if (tpm_request_locality(sc, 0)) + if (tpm_tis12_irqinit(sc, irq, i)) return 1; /* Abort whatever it thought it was doing. */ @@ -407,6 +418,40 @@ tpm_tis12_init(struct tpm_softc *sc, int irq, const char *name) return 0; } +/* Restore TIS state which is not guaranteed to survive S3. */ +static int +tpm_tis12_resume(struct tpm_softc *sc) +{ + uint32_t capabilities, devid; + int error, i, irq; + + capabilities = bus_space_read_4(sc->sc_bt, sc->sc_bh, + TPM_INTF_CAPABILITIES); + if ((capabilities & TPM_CAPSREQ) != TPM_CAPSREQ || + (capabilities & (TPM_INTF_INT_EDGE_RISING | + TPM_INTF_INT_LEVEL_LOW)) == 0) + return (ENXIO); + devid = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_ID); + if (devid == UINT32_MAX || devid != sc->sc_devid) + return (ENXIO); + + sc->sc_capabilities = capabilities; + i = tpm_tis12_devid_index(devid); + irq = sc->sc_vector; + error = tpm_request_locality(sc, 0); + if (error != 0) + return (error); + error = tpm_tis12_irqinit(sc, irq, i); + if (error != 0) + return (error); + + /* Abort firmware residue and leave the command FIFO ready. */ + bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, + TPM_STS_CMD_READY); + return (tpm_waitfor(sc, TPM_STS_CMD_READY, TPM_READY_TMO, + sc->sc_write)); +} + int tpm_request_locality(struct tpm_softc *sc, int l) { @@ -584,21 +629,25 @@ tpm_suspend(device_t dev) return (0); } -/* - * Handle resume event. Actually nothing to do as the BIOS is supposed - * to restore the previously saved state. - */ +/* Handle resume after firmware has restored the saved TPM state. */ int tpm_resume(device_t dev) { - struct tpm_softc *sc = device_get_softc(dev); - int why = 0; + struct tpm_softc *sc; + int error; + + sc = device_get_softc(dev); + error = 0; + if (sc->sc_init == tpm_tis12_init) + error = tpm_tis12_resume(sc); #ifdef TPM_DEBUG - printf("tpm_resume: resume: %d -> %d\n", sc->sc_suspend, why); + device_printf(dev, "resume: %d -> 0\n", sc->sc_suspend); #endif - sc->sc_suspend = why; + sc->sc_suspend = 0; + if (error != 0) + device_printf(dev, "failed to restore TIS state: %d\n", error); - return 0; + return (error); } /* Dispatch suspend and resume events. */