mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Surendran Kanagaraj <surenkj@amazon.com>
To: Jarkko Sakkinen <jarkko@kernel.org>, Peter Huewe <peterhuewe@gmx.de>
Cc: Jason Gunthorpe <jgg@ziepe.ca>, <linux-integrity@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>, Jonathan Corbet <corbet@lwn.net>,
	<linux-doc@vger.kernel.org>, Jonathan McDowell <noodles@earth.li>,
	"Breno Leitao" <leitao@debian.org>, <nh-open-source@amazon.com>,
	Alexander Graf <graf@amazon.de>,
	Gunnar Kudrjavets <gunnarku@amazon.com>,
	Josh Levinson <joshlev@amazon.com>
Subject: [RFC PATCH v3 8/8] tpm_crb: Raise the limits for Amazon NitroTPM
Date: Thu, 12 Nov 2026 16:46:21 +0000	[thread overview]
Message-ID: <20261112164621.62645-1-surenkj@amazon.com> (raw)
In-Reply-To: <20261112163846.97654-1-surenkj@amazon.com>

In rare scenarios NitroTPM can enter a mode where it either sends
TPM2_RC_RETRY for longer than LONG duration or delays
command completion for longer than the TPM 2.0 durations allow.
When this happens during auth session start, the driver disables
the chip and every subsequent request fails:

    tpm tpm0: in retry loop
    tpm tpm0: tpm2_load_context: failed with a TPM error 0x0922

Add a quirk table to the CRB driver keyed by the vendor ID from the
interface ID register, and apply it from ->adjust_limits(). For
NitroTPM, raise the SHORT and MEDIUM durations to 30 s, which covers
the longest unavailability with some headroom, and LONG to 45 s. With
the back-off doubling from 20 ms, a 45 s LONG duration lets the driver
resubmit a command for about 40.9 s, so the retry loop covers the
entire unavailability window.

These are upper bounds, not expected waits. A command that completes
sooner ends the wait as soon as the poll sees it. Add TPM_VID_AMZN
next to the vendor ID list in tpm.h.

Tested on an EC2 instance with NitroTPM by inducing multiple
unavailability windows with no TPM errors, and in QEMU with swtpm by
holding the TPM in TPM2_RC_RETRY and stalling command completion for
longer than 2s.

Signed-off-by: Surendran Kanagaraj <surenkj@amazon.com>
---
 drivers/char/tpm/tpm_crb.c | 50 ++++++++++++++++++++++++++++++++++++++
 include/linux/tpm.h        |  1 +
 2 files changed, 51 insertions(+)

diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 7c1011eb855a..0e18f61cfddf 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -13,6 +13,7 @@
 
 #include <linux/acpi.h>
 #include <linux/highmem.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
 #include <linux/rculist.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -26,6 +27,14 @@
 #define ACPI_SIG_TPM2 "TPM2"
 #define TPM_CRB_MAX_RESOURCES 3
 
+/* TPM_CRB_INTF_ID_x vendor ID field, bits 47:32 of the 64-bit register */
+#define TPM_CRB_INTF_ID_VID(intf_id)	(((intf_id) >> 32) & 0xffff)
+
+/* Longest NitroTPM unavailability, with some headroom */
+#define TPM_CRB_AMZN_LIMIT_US		(30 * USEC_PER_SEC)
+/* LONG also bounds the retry loop: 45 s lets it resubmit for 40.9 s */
+#define TPM_CRB_AMZN_LONG_US		(45 * USEC_PER_SEC)
+
 static const guid_t crb_acpi_start_guid =
 	GUID_INIT(0x6BBF6CAB, 0x5463, 0x4714,
 		  0xB7, 0xCD, 0xF0, 0x20, 0x3C, 0x03, 0x68, 0xD4);
@@ -663,6 +672,46 @@ static bool crb_req_canceled(struct tpm_chip *chip, u8 status)
 	return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE;
 }
 
+/*
+ * Read the vendor ID from the interface ID register. Returns -ENODEV when
+ * the head registers are not mapped for this start method.
+ */
+static int crb_vendor_id(struct crb_priv *priv)
+{
+	u64 intf_id;
+
+	if (!priv->regs_h)
+		return -ENODEV;
+
+	intf_id = lo_hi_readq(&priv->regs_h->intf_id);
+
+	return TPM_CRB_INTF_ID_VID(intf_id);
+}
+
+/* Limits keyed by the vendor ID of the interface ID register */
+static const struct tpm_limits_quirk crb_limits_quirks[] = {
+	{
+		.id = TPM_VID_AMZN,
+		.time_us = {
+			[TPM_LIMIT_SHORT]	= TPM_CRB_AMZN_LIMIT_US,
+			[TPM_LIMIT_MEDIUM]	= TPM_CRB_AMZN_LIMIT_US,
+			[TPM_LIMIT_LONG]	= TPM_CRB_AMZN_LONG_US,
+		},
+	},
+};
+
+static void crb_adjust_limits(struct tpm_chip *chip, struct tpm_limits *p)
+{
+	struct crb_priv *priv = dev_get_drvdata(&chip->dev);
+	int vid = crb_vendor_id(priv);
+
+	if (vid < 0)
+		return;
+
+	tpm_limits_apply_quirks(p, crb_limits_quirks,
+				ARRAY_SIZE(crb_limits_quirks), vid);
+}
+
 static const struct tpm_class_ops tpm_crb = {
 	.flags = TPM_OPS_AUTO_STARTUP,
 	.status = crb_status,
@@ -674,6 +723,7 @@ static const struct tpm_class_ops tpm_crb = {
 	.cmd_ready = crb_cmd_ready,
 	.request_locality = crb_request_locality,
 	.relinquish_locality = crb_relinquish_locality,
+	.adjust_limits = crb_adjust_limits,
 	.req_complete_mask = CRB_DRV_STS_COMPLETE,
 	.req_complete_val = CRB_DRV_STS_COMPLETE,
 };
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index a4b7282d88b5..f557c1a32388 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -220,6 +220,7 @@ static inline enum tpm2_mso_type tpm2_handle_mso(u32 handle)
 #define TPM_VID_STM      0x104A
 #define TPM_VID_ATML     0x1114
 #define TPM_VID_IFX      0x15D1
+#define TPM_VID_AMZN     0x0EC2
 
 enum tpm_chip_flags {
 	TPM_CHIP_FLAG_BOOTSTRAPPED		= BIT(0),
-- 
2.47.3


      parent reply	other threads:[~2026-11-12 16:46 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-12 16:38 [RFC PATCH v3 0/8] tpm: Rework timeout and duration handling Surendran Kanagaraj
2026-11-12 16:38 ` [RFC PATCH v3 1/8] tpm: Add a single table for all TPM wait limits Surendran Kanagaraj
2026-11-12 16:38 ` [RFC PATCH v3 2/8] tpm: Wire the timing setup to the limits table Surendran Kanagaraj
2026-11-12 16:38 ` [RFC PATCH v3 3/8] tpm: Take command durations from " Surendran Kanagaraj
2026-11-12 16:38 ` [RFC PATCH v3 4/8] tpm: Bound core and CRB waits by " Surendran Kanagaraj
2026-11-12 16:42 ` [RFC PATCH v3 5/8] tpm: Drop the jiffies timing fields from struct tpm_chip Surendran Kanagaraj
2026-11-12 16:43 ` [RFC PATCH v3 6/8] tpm: Add the tpm.limits= parameter Surendran Kanagaraj
2026-11-12 16:45 ` [RFC PATCH v3 7/8] tpm: Show timeouts and durations for TPM 2.0 chips Surendran Kanagaraj
2026-11-12 16:46 ` Surendran Kanagaraj [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261112164621.62645-1-surenkj@amazon.com \
    --to=surenkj@amazon.com \
    --cc=corbet@lwn.net \
    --cc=graf@amazon.de \
    --cc=gunnarku@amazon.com \
    --cc=jarkko@kernel.org \
    --cc=jgg@ziepe.ca \
    --cc=joshlev@amazon.com \
    --cc=leitao@debian.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-integrity@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nh-open-source@amazon.com \
    --cc=noodles@earth.li \
    --cc=peterhuewe@gmx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®