From nobody Fri Sep 18 00:08:40 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 4hmCdj0Cxmz6sHls for ; Fri, 18 Sep 2026 00:08:41 +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 4hmCdh64HBz4bF3 for ; Fri, 18 Sep 2026 00:08:40 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789690120; 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=VqP/pihBC9FrDqzkkaBPR8HIETLUaCnwHHrKoeOKBp8=; b=D24PeQstJqn6AgljnhFPA6q3i71vYg1aJVBAOqEKWVBCZATc+Mt1XJjzX4QGXzPOjRv7IF QH4jy1WW+2f7ryiqmtn1bf0pn0RuCc5r3dfmiZpBxg2UWxjUGekWYav4LlrPIU92jhlFvY nNQmWtIKPOpRKsVctYk51MrrQ0BMkSp6itY7IMhKR5MgBA7murbgM6yPrAqreVoDkbT6bD NaCzKeD+iphLcrqXfRK2NLmvaNzMTehX4BtWSyhcyASUNFPyE25b2t9kSYkFw2E2xaIBDv Tb+t/e8BPm2QZNe3l2MnfeuLSYEPedbG3hzgWN6WTWvkZ30Eecb+NCefVC7vzA== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1789690120; b=IwPnostQ7Z74jk4+ptH8vXy4lECEYIQzmR1sbUV4xl2kI30OkXW0kjkDlmLDKsxHfgaWPv h+ZVnDUHq+ZsRi3LUJPA4Uuen29Rw4lgydPQfC7y2ZquTyzuDrrQAvN4fCtflzDABJ/ipf LWjvdCcir/QGo8jVma5m/lmTTUekQ1huEM9fDoccaEHqj/EuMULDcn+KQKmg6sgbKkAzHD KxU4uIUSOaBS9WDwRj0IYAM4XWJL3anZDyn/ckcOoh2IHFuuSlQ0tCUwn+y37opImB7gxN SJ/nvfzS9pV/QYV0kieKCysAfiTvXe1uMHFalG11MI2PQnQTPYvRNjaVOqHVpw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789690120; 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=VqP/pihBC9FrDqzkkaBPR8HIETLUaCnwHHrKoeOKBp8=; b=d04jlSMoRCBVV+jFkTrhYD58mrZ9wNToigG+YJIN/qHPqCYzEI2l2d+w8iGalqhDGJedH5 P8AZrYkXYwMiDJbDrEGnq4SJnbJsnkt3Sk+sotGAwn/Z5RdtkNbitZu/dmWGB1mcS15OXK xyRN6u1dp2OxRN3wW6zzxYA1ECnUT03o0bgX+M+9k96y6E77op6fDCs67NTiGRbHUFDRsd 4O53z0E+FiL9bHvZho+e1JNK6s4EZAcAlte9pCYf1SBSDccQ4C/6ZnzGxHZo0lW1AZtyMW RurP9+MXc+QvQ7f46McBRX63DhO7oCRIe3D69SQxUKUUhgN4kf9GkNwk8SvABw== 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 4hmCdh568Jzvvy for ; Fri, 18 Sep 2026 00:08:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 26ad0 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 18 Sep 2026 00:08:40 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kevin Bowling Subject: git: b89bacb6eec0 - stable/15 - tpm: Bound TPM 1.2 locality ownership 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: b89bacb6eec0c6f18243f5b709c7a3482936ea92 Auto-Submitted: auto-generated Date: Fri, 18 Sep 2026 00:08:40 +0000 Message-Id: <6aac8108.26ad0.e508a28@gitrepo.freebsd.org> The branch stable/15 has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=b89bacb6eec0c6f18243f5b709c7a3482936ea92 commit b89bacb6eec0c6f18243f5b709c7a3482936ea92 Author: Kevin Bowling AuthorDate: 2026-08-27 13:42:49 +0000 Commit: Kevin Bowling CommitDate: 2026-09-18 00:08:31 +0000 tpm: Bound TPM 1.2 locality ownership A TIS locality must remain active while a command is in flight, but should be relinquished once the command completes or is abandoned. The driver retained locality zero after probe, initialization, and resume, and several transaction error paths returned without releasing it. Closing the device after writing a command without reading its response had the same effect. Track locality ownership and whether a command is awaiting its response. Release locality after probe, initialization, and resume; retain it only across a successful command write and its matching response read. Abort and release on errors, replacement commands, close, and detach. Wait for locality during ISA probe instead of assuming an immediate grant, release locality acquired by the probe, and stop treating the command-style TPM_ACCESS register as restorable state. On a ThinkPad T440p with an STMicro TPM 1.2, the old driver left TPM_ACCESS at 0xa1 immediately after attach. The new driver left it at 0x81 after attach, completed PCR reads, and closing with an unread response. PCR reads also survived an unload and reload without TPM or locking diagnostics. Reviewed by: kevans Sponsored by: BBOX.io Differential Revision: https://reviews.freebsd.org/D59237 (cherry picked from commit 4e0f283fb97a7b0903adc7bc3ef2f6e07167c73e) --- sys/dev/tpm/tpm.c | 171 +++++++++++++++++++++++++++++++++++++++------------ sys/dev/tpm/tpmvar.h | 2 + 2 files changed, 134 insertions(+), 39 deletions(-) diff --git a/sys/dev/tpm/tpm.c b/sys/dev/tpm/tpm.c index 8c12abb39d1a..f37ce6955f17 100644 --- a/sys/dev/tpm/tpm.c +++ b/sys/dev/tpm/tpm.c @@ -194,7 +194,9 @@ 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 void tpm_tis12_abort(struct tpm_softc *); static int tpm_tis12_devid_index(uint32_t); +static void tpm_tis12_relinquish_locality(struct tpm_softc *); static int tpm_tis12_resume(struct tpm_softc *); @@ -225,6 +227,8 @@ tpm_attach(device_t dev) sc->sc_flags = 0; sc->sc_suspend = 0; sc->sc_dying = false; + sc->sc_locality = false; + sc->sc_command_pending = false; sc->mem_rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid, @@ -245,9 +249,6 @@ tpm_attach(device_t dev) else irq = IRQUNK; - /* In case PnP probe this may contain some initialization. */ - tpm_tis12_probe(sc->sc_bt, sc->sc_bh); - if (tpm_legacy_probe(sc->sc_bt, sc->sc_bh)) { sc->sc_init = tpm_legacy_init; sc->sc_start = tpm_legacy_start; @@ -315,6 +316,10 @@ tpm_detach(device_t dev) destroy_dev(sc->sc_cdev); sc->sc_cdev = NULL; } + sx_xlock(&sc->sc_lock); + if (sc->mem_res != NULL && sc->sc_init == tpm_tis12_init) + tpm_tis12_abort(sc); + sx_xunlock(&sc->sc_lock); if (sc->intr_cookie != NULL) { bus_teardown_intr(dev, sc->irq_res, sc->intr_cookie); sc->intr_cookie = NULL; @@ -341,7 +346,9 @@ int tpm_tis12_probe(bus_space_tag_t bt, bus_space_handle_t bh) { u_int32_t r; - u_int8_t save, reg; + u_int8_t reg; + bool acquired; + int to; r = bus_space_read_4(bt, bh, TPM_INTF_CAPABILITIES); if (r == 0xffffffff) @@ -358,15 +365,34 @@ tpm_tis12_probe(bus_space_tag_t bt, bus_space_handle_t bh) return 0; } - save = bus_space_read_1(bt, bh, TPM_ACCESS); - bus_space_write_1(bt, bh, TPM_ACCESS, TPM_ACCESS_REQUEST_USE); reg = bus_space_read_1(bt, bh, TPM_ACCESS); - if ((reg & TPM_ACCESS_VALID) && (reg & TPM_ACCESS_ACTIVE_LOCALITY) && - bus_space_read_4(bt, bh, TPM_ID) != 0xffffffff) - return 1; + acquired = false; + if ((reg & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) != + (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) { + bus_space_write_1(bt, bh, TPM_ACCESS, + TPM_ACCESS_REQUEST_USE); + to = TPM_ACCESS_TMO; /* Steps of one millisecond. */ + do { + reg = bus_space_read_1(bt, bh, TPM_ACCESS); + if ((reg & (TPM_ACCESS_VALID | + TPM_ACCESS_ACTIVE_LOCALITY)) == + (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) { + acquired = true; + break; + } + DELAY(1000); + } while (--to != 0); + } - bus_space_write_1(bt, bh, TPM_ACCESS, save); - return 0; + if ((reg & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) == + (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) + r = bus_space_read_4(bt, bh, TPM_ID); + else + r = UINT32_MAX; + if (acquired) + bus_space_write_1(bt, bh, TPM_ACCESS, + TPM_ACCESS_ACTIVE_LOCALITY); + return (r != UINT32_MAX); } /* @@ -427,7 +453,7 @@ int tpm_tis12_init(struct tpm_softc *sc, int irq, const char *name) { u_int32_t r; - int i; + int error, i; sx_assert(&sc->sc_lock, SA_XLOCKED); r = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INTF_CAPABILITIES); @@ -451,16 +477,22 @@ tpm_tis12_init(struct tpm_softc *sc, int irq, const char *name) else printf(": device 0x%08x rev 0x%x\n", sc->sc_devid, sc->sc_rev); - if (tpm_request_locality(sc, 0)) + error = tpm_request_locality(sc, 0); + if (error != 0) return 1; - if (tpm_tis12_irqinit(sc, irq, i)) - return 1; + error = tpm_tis12_irqinit(sc, irq, i); + if (error != 0) + goto out; /* Abort whatever it thought it was doing. */ bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, TPM_STS_CMD_READY); + error = tpm_waitfor(sc, TPM_STS_CMD_READY, TPM_READY_TMO, + sc->sc_write); - return 0; +out: + tpm_tis12_relinquish_locality(sc); + return (error != 0); } /* Restore TIS state which is not guaranteed to survive S3. */ @@ -489,13 +521,16 @@ tpm_tis12_resume(struct tpm_softc *sc) return (error); error = tpm_tis12_irqinit(sc, irq, i); if (error != 0) - return (error); + goto out; /* 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)); + error = tpm_waitfor(sc, TPM_STS_CMD_READY, TPM_READY_TMO, + sc->sc_write); +out: + tpm_tis12_relinquish_locality(sc); + return (error); } int @@ -507,11 +542,15 @@ tpm_request_locality(struct tpm_softc *sc, int l) sx_assert(&sc->sc_lock, SA_XLOCKED); if (l != 0) return EINVAL; + KASSERT(!sc->sc_locality, ("%s: locality already owned", __func__)); if ((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)) + (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) { + sc->sc_locality = true; return 0; + } + sc->sc_locality = false; bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS, TPM_ACCESS_REQUEST_USE); @@ -526,6 +565,14 @@ tpm_request_locality(struct tpm_softc *sc, int l) #ifdef TPM_DEBUG printf("tpm_request_locality: interrupted %d\n", rv); #endif + r = bus_space_read_1(sc->sc_bt, sc->sc_bh, + TPM_ACCESS); + if ((r & (TPM_ACCESS_VALID | + TPM_ACCESS_ACTIVE_LOCALITY)) == + (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) { + sc->sc_locality = true; + tpm_tis12_relinquish_locality(sc); + } return rv; } } @@ -538,9 +585,34 @@ tpm_request_locality(struct tpm_softc *sc, int l) return EBUSY; } + sc->sc_locality = true; return 0; } +static void +tpm_tis12_relinquish_locality(struct tpm_softc *sc) +{ + + sx_assert(&sc->sc_lock, SA_XLOCKED); + sc->sc_command_pending = false; + if (!sc->sc_locality) + return; + bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS, + TPM_ACCESS_ACTIVE_LOCALITY); + sc->sc_locality = false; +} + +static void +tpm_tis12_abort(struct tpm_softc *sc) +{ + + sx_assert(&sc->sc_lock, SA_XLOCKED); + if (sc->sc_locality) + bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, + TPM_STS_CMD_READY); + tpm_tis12_relinquish_locality(sc); +} + int tpm_getburst(struct tpm_softc *sc) { @@ -921,14 +993,23 @@ tpm_tis12_start(struct tpm_softc *sc, int flag) sx_assert(&sc->sc_lock, SA_XLOCKED); if (flag == UIO_READ) { + if (!sc->sc_locality || !sc->sc_command_pending) { + tpm_tis12_abort(sc); + return (EIO); + } rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID, TPM_READ_TMO, sc->sc_read); - return rv; + if (rv != 0) + tpm_tis12_abort(sc); + return (rv); } + /* Abort an incomplete command before starting another one. */ + tpm_tis12_abort(sc); + /* Own our (0th) locality. */ if ((rv = tpm_request_locality(sc, 0)) != 0) - return rv; + return (rv); sc->sc_stat = tpm_status(sc); if (sc->sc_stat & TPM_STS_CMD_READY) { @@ -950,7 +1031,8 @@ tpm_tis12_start(struct tpm_softc *sc, int flag) #ifdef TPM_DEBUG printf("tpm_tis12_start: UIO_WRITE readying failed %d\n", rv); #endif - return rv; + tpm_tis12_abort(sc); + return (rv); } #ifdef TPM_DEBUG @@ -1013,8 +1095,8 @@ tpm_tis12_write(struct tpm_softc *sc, void *buf, int len) #endif sx_assert(&sc->sc_lock, SA_XLOCKED); - if ((rv = tpm_request_locality(sc, 0)) != 0) - return rv; + if (!sc->sc_locality) + return (EIO); cnt = 0; while (cnt < len - 1) { @@ -1070,27 +1152,31 @@ tpm_tis12_end(struct tpm_softc *sc, int flag, int err) sx_assert(&sc->sc_lock, SA_XLOCKED); if (flag == UIO_READ) { - if ((rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, - sc->sc_read))) - return rv; + if (!sc->sc_locality) { + tpm_tis12_abort(sc); + return (err != 0 ? 0 : EIO); + } + if (err == 0) + rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, + sc->sc_read); /* Still more data? */ - sc->sc_stat = tpm_status(sc); - if (!err && ((sc->sc_stat & TPM_STS_DATA_AVAIL) == TPM_STS_DATA_AVAIL)) { + if (err == 0 && rv == 0) + sc->sc_stat = tpm_status(sc); + if (err == 0 && rv == 0 && + (sc->sc_stat & TPM_STS_DATA_AVAIL) != 0) { #ifdef TPM_DEBUG printf("tpm_tis12_end: read failed stat=%b\n", sc->sc_stat, TPM_STS_BITS); #endif rv = EIO; } - - bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, - TPM_STS_CMD_READY); - - /* Release our (0th) locality. */ - bus_space_write_1(sc->sc_bt, sc->sc_bh,TPM_ACCESS, - TPM_ACCESS_ACTIVE_LOCALITY); + tpm_tis12_abort(sc); } else { + if (!sc->sc_locality) { + tpm_tis12_abort(sc); + return (err != 0 ? 0 : EIO); + } /* Hungry for more? */ sc->sc_stat = tpm_status(sc); if (!err && (sc->sc_stat & TPM_STS_DATA_EXPECT)) { @@ -1101,8 +1187,13 @@ tpm_tis12_end(struct tpm_softc *sc, int flag, int err) rv = EIO; } - bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, - err ? TPM_STS_CMD_READY : TPM_STS_GO); + if (err != 0 || rv != 0) + tpm_tis12_abort(sc); + else { + bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS, + TPM_STS_GO); + sc->sc_command_pending = true; + } } return rv; @@ -1368,6 +1459,8 @@ tpmclose(struct cdev *dev, int flag, int mode, struct thread *td) if ((sc->sc_flags & TPM_OPEN) == 0) error = EINVAL; else { + if (sc->sc_init == tpm_tis12_init) + tpm_tis12_abort(sc); sc->sc_flags &= ~TPM_OPEN; error = 0; } diff --git a/sys/dev/tpm/tpmvar.h b/sys/dev/tpm/tpmvar.h index fc11d08fa4c1..61e5c17a8ffb 100644 --- a/sys/dev/tpm/tpmvar.h +++ b/sys/dev/tpm/tpmvar.h @@ -60,6 +60,8 @@ struct tpm_softc { struct mtx sc_intr_lock; struct cv sc_intr_cv; bool sc_dying; + bool sc_locality; + bool sc_command_pending; #endif #ifndef __FreeBSD__