From nobody Tue Sep 01 18:24:25 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 4hZDls5gZsz6rGh0 for ; Tue, 01 Sep 2026 18:24:25 +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 4hZDls4Htvz3XxS for ; Tue, 01 Sep 2026 18:24:25 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788287065; 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=dNxyZlRh65DLy68EaOvJV7Y06P1sARjba8kp0w9LM+A=; b=t+QkS+5ufHiRVIt9Y4iOppaBnUQ6tw7uW9F7/tWof94lU07ezTnIJoIWTS/+7huTAnmH96 UcHUdYe5eZKNSD1it5c0uzyMZFgpgBGn4f0CHYsMb8qeu7jDMmXmmyBv3K1hUZip7RapsJ 9PbxFcE07uzm3faua1mYn2uoF7wQwsTNwFKfkKA0Kh/e+/5xs9HEhZHnUiNr4NRKqrmxL2 9Bv7golT8B/onIeBwCPkHI4CiNgUdS5SK9W0r/k7AdSp+VM4O/UyVEK886gVhW5D04Ybrt usyk91yoXWofUFwXTObRHC0PJeuzU1kBXwuuyoBtIwOkTNh3+8346vdwuXd6eQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1788287065; a=rsa-sha256; cv=none; b=jyqEecc3Kilkp1oGeHL5De76knEfV79r2o5oPLHq9yOMTX6DOEBAjBZhoD901oCOuL+qQ6 WFXV3EIlAB0SBKMR4oeoLYhUvtmu3+ayI863I5vKiEwgZqZBEkaYqtfBv3GXSm3TENabA0 dqRAdnt6rsuICuR6gRBG+qkaqh+GreXqXjvScBf8KR91/GuYUejhQyIikvqYtfXVWFStWp 2+KnF/xrkye6cTczd400cx42mqtwos0HzYDFnW4QXOcyRlGACCohcarqwL3lup0qFrzKlj M7QZ/yFO+5l9CPc2dX2CLlVYj4Dtknutv66ZxrYHaOXUuZoYAayp14+NqgJ5Lg== 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=1788287065; 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=dNxyZlRh65DLy68EaOvJV7Y06P1sARjba8kp0w9LM+A=; b=U6VD6VqfLG8TD6+zS4K/+pzjGa48cQtU+eXrKhxa3DD96HKuzPMMj8ocymXyL8oZTXAYbk 3jjrqvh3TxYLHNWG40/+dJzN5Low24asZ3Kr4OFoc8idGsBUqv5GFRvLSjYbTnoUm+toDQ dgZvQp3pohb/D1Y1D77kpH/8izo35lwu+drzGjOUnHrtoocbpx1Nw05MB9r9D5a2F78aU8 3WXe5ISfGtPN2PUjvybe5z1Ck8T0kbZ+gnMjF90ppYp/nSZXNaFKboo+ZBUVg26hCF4SP1 7is+5FkE1+Ck6laWIilci7xmyDZ8HcUqulAWNbh8oUO44olrJh6ypWtJ+YpgYg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hZDls34Nfz1860 for ; Tue, 01 Sep 2026 18:24:25 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3f05c by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 01 Sep 2026 18:24:25 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: 4e0f283fb97a - main - tpm: Bound TPM 1.2 locality ownership 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: 4e0f283fb97a7b0903adc7bc3ef2f6e07167c73e Auto-Submitted: auto-generated Date: Tue, 01 Sep 2026 18:24:25 +0000 Message-Id: <6a971859.3f05c.10c5fdd8@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=4e0f283fb97a7b0903adc7bc3ef2f6e07167c73e commit 4e0f283fb97a7b0903adc7bc3ef2f6e07167c73e Author: Kevin Bowling AuthorDate: 2026-08-27 13:42:49 +0000 Commit: Kevin Bowling CommitDate: 2026-09-01 18:23:36 +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: kevants MFC after: 2 weeks Sponsored by: BBOX.io Differential Revision: https://reviews.freebsd.org/D59237 --- 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__