From nobody Tue Sep 01 18:20:34 2026 X-Original-To: dev-commits-src-main@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 4hZDgQ43mlz6rGHj for ; Tue, 01 Sep 2026 18:20:34 +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 4hZDgQ2z8Mz3X8T for ; Tue, 01 Sep 2026 18:20:34 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788286834; 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=4ZBHbyTaW49UpB2hUKfz0THkOvZi1DmOoOHzS6V90ec=; b=AGAFUOMnZw6cOcTpklCXPJFgNLkieTPRSl9Z9PVZpwPN816FxZtFGcSGrWTbL2L6gxb4be LkzRZsIg3qhpf9w5YVd97zej7Li2Nzi2jf8CBD1DQ8gq/gL/fMnVdMjkR4heXUJa1GmMt7 6YZOLPfe9tNS0RXYNALyAO9Xmdq9s8iw/Mk+o2zKfpABTv5PCpJecJu1lPL6jCmakuf9Wt jvDQ2h4kUs6dUyko1//CLhMVnJcDtS7GnPWMoE1PZB4l+OWRPhOkBCy0SdOpQ6QhMGMs0B R4zCX2N3Du9/fYzvDROv61OVwpr6DUVx8ON+c83dmOPFIAcuMyMz8eouCvNlWA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1788286834; a=rsa-sha256; cv=none; b=jBT/XWQEGQ2vmX8h/r6YU4Ex387QMZtBl0WNnTMu1scUQFMj/3wVdToheHonTdQBOax82D 5z3BIkNiquuEm/LxIXfoJN9W4rT6IJYC7XcMXRaTgU3cGugD1hSfesUP3HuMFgJWpfXuVM fLl12uYWLZ8LXs22ZAM4/wnW7+8UKkMUsofqgD6d0fWxMhO0kVCRwhskO8njY6IOTREUzk G9c7li8H05/N5Z6Ej7AgIkIpmiFGt1Kq0ZqGFcjraTZB2SOT2HpRa799S2aXXckXtvjh+e BNnH9uB7WyGX7AnZ0Hitkwqfe25mBpu/HMJP0DTMWZXcTgihPrWfmmbB69StWg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788286834; 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=4ZBHbyTaW49UpB2hUKfz0THkOvZi1DmOoOHzS6V90ec=; b=PT8Km7BYYJ22d9/9JNjZSYuDjWlAFIxd71U0eE9kcI23Sa4FsAmHDV6qwS4OKF1BaY1w/k 1Gx+iFRgjDq+aGoC6YSIfa1wq1rA8cjXzlazmeGXr1BXRlMeQjYyWkgghvK717szdvj11p GaDtIzsmDQOL9Rem6oxeboFqFXydLZg2nB4/A7OdDyNzK7UgRbSWQmDTM56HUrwQHI+/x0 tY44KgDFvc1cO0RPc2C8PKB33zDfIcQlBV9o/oYIVeGOsZLlqSgdjBEOovpOEYOerU8PcO YT6Niywdg37XM1NabCDmn4gWoE7tAifQjfykk8m0qsESdk3vm28fpAp5ge7lUQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hZDgQ1GRqz17nk for ; Tue, 01 Sep 2026 18:20:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 4108a by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 01 Sep 2026 18:20:34 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: 96ed6005082f - main - tpm: Restore TPM 1.2 TIS state after resume List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@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/main X-Git-Reftype: branch X-Git-Commit: 96ed6005082fc63d633408ba3ad697e8757e80f9 Auto-Submitted: auto-generated Date: Tue, 01 Sep 2026 18:20:34 +0000 Message-Id: <6a971772.4108a.6a0a8b73@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=96ed6005082fc63d633408ba3ad697e8757e80f9 commit 96ed6005082fc63d633408ba3ad697e8757e80f9 Author: Kevin Bowling AuthorDate: 2026-08-26 10:33:38 +0000 Commit: Kevin Bowling CommitDate: 2026-09-01 18:19:50 +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 MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D59193 --- 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. */