From nobody Wed Sep 09 09:01:12 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 4hfvtJ5kv3z6rkk3 for ; Wed, 09 Sep 2026 09:01:12 +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 4hfvtJ5Bjfz4RYC for ; Wed, 09 Sep 2026 09:01:12 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788944472; 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=O+MHxK2oUAUlDCmsCfzjPrv6ymwEEmVtsk5+2BCJKKE=; b=hNIlz/A86bdZ9pD+U8ri32u3Vkk7pr2jDpwaKwnWjeiiyBj1sqoTkfqkf7s1eGpSl3i4AS qTmOT/UMM00v1dJpqdHH1rbquak+LkWAe4s/de1K0IRJ0RKdT2pFY4AzEgniC8tM4PQ22c dMLmd0Dq0N6BwcA5LddGgtT08bNJMZWkWMepNX97ByO2BUf/I55ebQMix4WXmFVNUpXYfw vzcmbGBTV6MI7Tu/40L862XxX1bMgnjvqF6MGpBhg2i1DeiWCrH/n/tFbsIOaL070Hs9I3 qh5fpo3R2BdWfrgJ6rLc50/xQ/pP2UYfkE5L4E21MwtVmMQPRYA6ogC0EerseA== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1788944472; b=TBUTQs86oWnnFAwsb8FSmZeL1K+uLqrWkA8tl8ANoup+CKiXghAJKus3iDOBviR+Enuxcu X816viUYz5/0ASbCZ/BUMSj9ANwCp1J2FJqvNLVjcKNVukKiiNWcptBoBDg9VEuP4MWR0Y 2PUp23TSxyVB+ZFuvJNGqpw8iTrktWm7bPcOF65UYi4I91isS9UCxV9uyMVOtwtDXTdmou lNgHE9xNGMQoq/e5S3K33tZtAMHKcTOAV27XtpjzC0lSR1XOUp4i40M7cX7tsxLOyomwv5 Wx5mKDpJTX0aQFU+zNCw5M7uB7oHMZLT294yR1MISZiISlIaM+ay+aN3FPaLUQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788944472; 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=O+MHxK2oUAUlDCmsCfzjPrv6ymwEEmVtsk5+2BCJKKE=; b=FI5SLVkmHALa6g78omFq2rbDzQnNxbkgawdPA+vR8lkIF9RhWhchNxy8ZmsfROqKOhZ15v xCHY3ny16CjHgLPzjR3D5FxJZ2G330cHvWyM2vHZ6Quw9VaWdE8WMHXgrdAxncJOBraz/Y jZl9TA5JPWtMgUo2E0qNDkKy1TNOvBu/HjPpF0ygBA0FXBIurtvbMw1bF2dKPsAF6bOx5R /DTpghQVjjiFKQbpV2FCh4i5CAWtcPlI3cbd9gvOAZn0dgan5WrZ1PW8CDSeYQvjSx6iWc licAhIIT0s/X8ZbIIGDMYuIsTYaed6KucxQMEMrMevmv5JTzTpKBPaB7Mk5JHg== 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 4hfvtJ4FqRzqg4 for ; Wed, 09 Sep 2026 09:01:12 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1e92e by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 09 Sep 2026 09:01:12 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kyle Evans Subject: git: 6af3031c9516 - main - tpm: crb: make the Pluton startmethod more resilient 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: kevans X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 6af3031c951614f2a42dfd67ce2c3a48ee8314ae Auto-Submitted: auto-generated Date: Wed, 09 Sep 2026 09:01:12 +0000 Message-Id: <6aa12058.1e92e.1cb96b2@gitrepo.freebsd.org> The branch main has been updated by kevans: URL: https://cgit.FreeBSD.org/src/commit/?id=6af3031c951614f2a42dfd67ce2c3a48ee8314ae commit 6af3031c951614f2a42dfd67ce2c3a48ee8314ae Author: Kyle Evans AuthorDate: 2026-09-09 09:00:28 +0000 Commit: Kyle Evans CommitDate: 2026-09-09 09:00:28 +0000 tpm: crb: make the Pluton startmethod more resilient The original implementation assumed that the start/reply doorbells lived within the device _CRS space, but that isn't always the case. On my AMD Ryzen 7640U-based frame.work laptop, device memory runs from 0xc0500000-0xc0500fff while the doorbells are up around 0xc0508000. Stop sanity checking the addresses and just map them in to work reliably whether they're within the device range or not. pluton_wait_reply is cribbed from tpm_wait_for_u32, but rewritten slightly to read in just one place and to read one last time before giving up at the end of the timeout, just in case. Reviewed by: kbowling Differential Revision: https://reviews.freebsd.org/D59327 --- sys/dev/tpm/tpm_crb.c | 115 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 87 insertions(+), 28 deletions(-) diff --git a/sys/dev/tpm/tpm_crb.c b/sys/dev/tpm/tpm_crb.c index 3e567e215313..e5bbec5d46da 100644 --- a/sys/dev/tpm/tpm_crb.c +++ b/sys/dev/tpm/tpm_crb.c @@ -76,18 +76,21 @@ #define TPM_CRB_INT_ENABLE_BIT BIT(31) struct tpmcrb_sc; -/* Attach */ +/* Attach/detach callbacks */ typedef bool (sm_attach_t)(struct tpmcrb_sc *, void *, size_t); +typedef void (sm_detach_t)(struct tpmcrb_sc *); /* State change notification (timeout == 0 for 'no timeout') */ typedef bool (sm_statechange_t)(struct tpmcrb_sc *, int); struct tpmcrb_sm_cfg { sm_attach_t *sm_attach; + sm_detach_t *sm_detach; sm_statechange_t *sm_statechange; sm_statechange_t *sm_cmdready; }; static sm_attach_t pluton_attach; +static sm_detach_t pluton_detach; static sm_statechange_t pluton_doorbell; static const struct tpmcrb_sm_cfg_map { @@ -105,6 +108,7 @@ static const struct tpmcrb_sm_cfg_map { .desc = "Trusted Platform Module 2.0, CRB mode (Pluton)", .sm_cfg = { .sm_attach = &pluton_attach, + .sm_detach = &pluton_detach, .sm_statechange = &pluton_doorbell, .sm_cmdready = &pluton_doorbell, }, @@ -115,10 +119,15 @@ struct tpmcrb_sc { struct tpm_sc base; const struct tpmcrb_sm_cfg *sm_cfg; union { - /* StartMethod data */ + /* + * StartMethod data. The Pluton start/reply mailbox + * registers may live outside of the _CRS window, so they get + * their own bus_space mapping. + */ struct { - uint64_t start_reg; - uint64_t reply_reg; + bus_space_tag_t bst; + bus_space_handle_t start_bsh; + bus_space_handle_t reply_bsh; } pluton; }; bus_size_t cmd_off; @@ -333,11 +342,16 @@ tpmcrb_attach(device_t dev) static int tpmcrb_detach(device_t dev) { + struct tpmcrb_sc *crb_sc; struct tpm_sc *sc; - sc = device_get_softc(dev); + crb_sc = device_get_softc(dev); + sc = &crb_sc->base; tpm20_release(sc); + if (crb_sc->sm_cfg != NULL && crb_sc->sm_cfg->sm_detach != NULL) + (*crb_sc->sm_cfg->sm_detach)(crb_sc); + if (sc->mem_res != NULL) bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem_res); @@ -618,7 +632,7 @@ pluton_attach(struct tpmcrb_sc *crb_sc, void *smdataregion, size_t datasz) { struct tpmcrb_startmethod_pluton *smdata; struct tpm_sc *sc; - rman_res_t base_addr, end_addr; + bus_space_tag_t bst; if (datasz < sizeof(*smdata)) return (false); @@ -626,38 +640,83 @@ pluton_attach(struct tpmcrb_sc *crb_sc, void *smdataregion, size_t datasz) smdata = smdataregion; sc = &crb_sc->base; - base_addr = rman_get_start(sc->mem_res); - end_addr = rman_get_end(sc->mem_res); - /* Sanity check */ - if (smdata->sm_startaddr < base_addr || - smdata->sm_startaddr > end_addr || - smdata->sm_replyaddr < base_addr || - smdata->sm_replyaddr > end_addr) + /* + * The start/reply mailbox registers are not necessarily part of + * the CRB register window described by _CRS, so we map them + * independently. + */ + bst = rman_get_bustag(sc->mem_res); + if (bus_space_map(bst, smdata->sm_startaddr, sizeof(uint32_t), 0, + &crb_sc->pluton.start_bsh) != 0) { + device_printf(sc->dev, + "Failed to map Pluton start register at %#jx\n", + (uintmax_t)smdata->sm_startaddr); + return (false); + } + + if (bus_space_map(bst, smdata->sm_replyaddr, sizeof(uint32_t), 0, + &crb_sc->pluton.reply_bsh) != 0) { + device_printf(sc->dev, + "Failed to map Pluton reply register at %#jx\n", + (uintmax_t)smdata->sm_replyaddr); + bus_space_unmap(bst, crb_sc->pluton.start_bsh, + sizeof(uint32_t)); return (false); + } - crb_sc->pluton.start_reg = smdata->sm_startaddr - base_addr; - crb_sc->pluton.reply_reg = smdata->sm_replyaddr - base_addr; + crb_sc->pluton.bst = bst; return (true); } -static bool -pluton_doorbell(struct tpmcrb_sc *crb_sc, int timeout) +static void +pluton_detach(struct tpmcrb_sc *crb_sc) { - struct tpm_sc *sc; - device_t dev; - sc = &crb_sc->base; - dev = sc->dev; - TPM_WRITE_4(dev, crb_sc->pluton.start_reg, 1); - TPM_WRITE_BARRIER(dev, crb_sc->pluton.start_reg, 4); + if (crb_sc->pluton.bst == 0) + return; - if (timeout > 0) { - if (!tpm_wait_for_u32(sc, crb_sc->pluton.reply_reg, ~0U, 1, - timeout)) - return (false); + bus_space_unmap(crb_sc->pluton.bst, crb_sc->pluton.start_bsh, + sizeof(uint32_t)); + bus_space_unmap(crb_sc->pluton.bst, crb_sc->pluton.reply_bsh, + sizeof(uint32_t)); +} + +static bool +pluton_wait_reply(struct tpmcrb_sc *crb_sc, int32_t timeout) +{ + for (;;) { + /* + * Always read at least once, and try one more time after we hit + * the timeout. + */ + if (bus_space_read_4(crb_sc->pluton.bst, + crb_sc->pluton.reply_bsh, 0) == 1) + return (true); + else if (timeout <= 0) + break; + + pause("TPM in polling mode", 1); + timeout -= tick; } - return (true); + return (false); +} + +static bool +pluton_doorbell(struct tpmcrb_sc *crb_sc, int timeout) +{ + bus_space_write_4(crb_sc->pluton.bst, crb_sc->pluton.start_bsh, 0, 1); + bus_space_barrier(crb_sc->pluton.bst, crb_sc->pluton.start_bsh, 0, + sizeof(uint32_t), BUS_SPACE_BARRIER_WRITE); + + /* + * We assume at timeout == 0 that they're not really interested in a + * reply immediately. Otherwise, we poll for a reply at least once, + * even with low timeouts. + */ + if (timeout <= 0) + return (true); + return (pluton_wait_reply(crb_sc, timeout)); } /* ACPI Driver */