mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] tpm: crb: handle ACPI NVS memory region overlap
@ 2026-08-27  3:55 microfish
  2026-08-28  2:04 ` Jarkko Sakkinen
  0 siblings, 1 reply; 3+ messages in thread
From: microfish @ 2026-08-27  3:55 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Peter Huewe, Jason Gunthorpe, linux-integrity, linux-kernel,
	stable, microfish, microfish

On certain Lenovo/AMD systems, the BIOS declares an ACPI NVS region
that covers a large memory range (e.g. 0xccc40000-0xccd3efff) which
includes the TPM CRB MMIO area (0xccd35000-0xccd38fff). The E820
subsystem registers this NVS region with IORESOURCE_BUSY in the
iomem_resource tree.

When tpm_crb probes, it calls devm_ioremap_resource() to map the CRB
registers, which internally calls devm_request_mem_region(). This fails
with -EBUSY because the NVS region already claims that address range.

Fix this by adding a crb_try_nvs_fallback() helper that detects the
ACPI NVS overlap using region_intersects() and falls back to
devm_memremap() when the resource falls inside ACPI NVS.
devm_memremap() does not require exclusive resource reservation,
making it safe to use on NVS-overlapping regions. This approach is
identical to the one used by the WDAT watchdog driver (wdat_wdt_map_mem).

The NVS fallback is applied in both code paths of crb_map_res():
1. When iores is NULL (no ACPI resource encompasses the target address)
2. When iores is non-NULL but devm_ioremap_resource() fails with EBUSY

Before this patch:
  tpm_crb MSFT0101:00: error -EBUSY: can't request region for resource
  [mem 0xccd35000-0xccd38fff]
  tpm_crb MSFT0101:00: probe with driver tpm_crb failed with error -16

After this patch:
  tpm_crb MSFT0101:00: [mem 0xccd35000-0xccd38fff] is inside ACPI NVS,
  mapping without reservation
  tpm_crb MSFT0101:00: of device registration complete, result 0: 0

Signed-off-by: microfish <microfish@kernel.org>
Signed-off-by: microfish <f13208471983@163.com>
---
 drivers/char/tpm/tpm_crb.c | 50 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 48 insertions(+), 2 deletions(-)

diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index ceb4100ba..c4e8b925c 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/mm.h>
 #include <linux/rculist.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -557,6 +558,39 @@ static int crb_check_resource(struct acpi_resource *ares, void *data)
 	return 1;
 }
 
+/*
+ * Try to map a resource region. If devm_ioremap_resource() fails with
+ * -EBUSY because the region falls inside an ACPI NVS area (common on
+ * certain Lenovo/AMD firmware), fall back to devm_memremap() which
+ * does not require exclusive resource reservation. This is analogous
+ * to the approach used by the WDAT watchdog driver (wdat_wdt_map_mem).
+ */
+static void __iomem *crb_try_nvs_fallback(struct device *dev, u64 start,
+					   u32 size)
+{
+	struct resource res = {
+		.start	= start,
+		.end	= start + size - 1,
+		.flags	= IORESOURCE_MEM,
+	};
+	void *addr;
+
+	if (region_intersects(res.start, resource_size(&res), IORESOURCE_MEM,
+			     IORES_DESC_ACPI_NV_STORAGE) !=
+			     REGION_INTERSECTS)
+		return NULL;
+
+	dev_warn(dev,
+		 "%pR is inside ACPI NVS, mapping without reservation\n",
+		 &res);
+
+	addr = devm_memremap(dev, res.start, resource_size(&res), MEMREMAP_WB);
+	if (IS_ERR(addr))
+		return IOMEM_ERR_PTR(PTR_ERR(addr));
+
+	return (void __iomem __force *)addr;
+}
+
 static void __iomem *crb_map_res(struct device *dev, struct resource *iores,
 				 void __iomem **iobase_ptr, u64 start, u32 size)
 {
@@ -565,18 +599,30 @@ static void __iomem *crb_map_res(struct device *dev, struct resource *iores,
 		.end	= start + size - 1,
 		.flags	= IORESOURCE_MEM,
 	};
+	void __iomem *p;
 
 	/* Detect a 64 bit address on a 32 bit system */
 	if (start != new_res.start)
 		return IOMEM_ERR_PTR(-EINVAL);
 
-	if (!iores)
+	if (!iores) {
+		p = crb_try_nvs_fallback(dev, start, size);
+		if (p)
+			return p;
 		return devm_ioremap_resource(dev, &new_res);
+	}
 
 	if (!*iobase_ptr) {
 		*iobase_ptr = devm_ioremap_resource(dev, iores);
-		if (IS_ERR(*iobase_ptr))
+		if (IS_ERR(*iobase_ptr)) {
+			p = crb_try_nvs_fallback(dev, iores->start,
+						 resource_size(iores));
+			if (p) {
+				*iobase_ptr = p;
+				return p + (new_res.start - iores->start);
+			}
 			return *iobase_ptr;
+		}
 	}
 
 	return *iobase_ptr + (new_res.start - iores->start);
-- 
2.47.3


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] tpm: crb: handle ACPI NVS memory region overlap
  2026-08-27  3:55 [PATCH] tpm: crb: handle ACPI NVS memory region overlap microfish
@ 2026-08-28  2:04 ` Jarkko Sakkinen
  2026-08-28 11:11   ` MicroFish
  0 siblings, 1 reply; 3+ messages in thread
From: Jarkko Sakkinen @ 2026-08-28  2:04 UTC (permalink / raw)
  To: microfish
  Cc: Peter Huewe, Jason Gunthorpe, linux-integrity, linux-kernel, stable

On Thu, Aug 27, 2026 at 11:55:11AM +0800, microfish wrote:
> On certain Lenovo/AMD systems, the BIOS declares an ACPI NVS region
> that covers a large memory range (e.g. 0xccc40000-0xccd3efff) which
> includes the TPM CRB MMIO area (0xccd35000-0xccd38fff). The E820
> subsystem registers this NVS region with IORESOURCE_BUSY in the
> iomem_resource tree.

Cannot and will not move forward given undefined and open set of gear.

There was also a corrupted email address in the CC list (microfish at
kernel dot org).

BR, Jarkko

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] tpm: crb: handle ACPI NVS memory region overlap
  2026-08-28  2:04 ` Jarkko Sakkinen
@ 2026-08-28 11:11   ` MicroFish
  0 siblings, 0 replies; 3+ messages in thread
From: MicroFish @ 2026-08-28 11:11 UTC (permalink / raw)
  To: jarkko
  Cc: f13208471983, jgg, linux-integrity, linux-kernel, peterhuewe, stable

On Fri, Aug 28, 2026 at 05:04:54AM +0300, Jarkko Sakkinen wrote:

> Cannot and will not move forward given undefined and open set of gear.
>
> There was also a corrupted email address in the CC list (microfish at
> kernel dot org).

Thanks for the review.

The affected hardware I have confirmed is the Lenovo ThinkPad E475
with an AMD APU.

This is the platform on which I reproduced the ACPI NVS and TPM CRB
MMIO region overlap described in the patch.

The incorrect CC address was my mistake. The correct address is
[f13208471983@163.com](mailto:f13208471983@163.com).

Best regards,
microfish


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-08-28 11:11 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-27  3:55 [PATCH] tpm: crb: handle ACPI NVS memory region overlap microfish
2026-08-28  2:04 ` Jarkko Sakkinen
2026-08-28 11:11   ` MicroFish

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®