* [RFC PATCH 0/4] iommu: Add IOMMU_DEBUG_PAGEALLOC sanitizer
@ 2025-10-03 17:32 Mostafa Saleh
2025-10-03 17:32 ` [RFC PATCH 1/4] drivers/iommu: Add page_ext for IOMMU_DEBUG_PAGEALLOC Mostafa Saleh
` (4 more replies)
0 siblings, 5 replies; 12+ messages in thread
From: Mostafa Saleh @ 2025-10-03 17:32 UTC (permalink / raw)
To: linux-mm, iommu, linux-kernel, linux-doc
Cc: corbet, joro, will, robin.murphy, akpm, vbabka, surenb, mhocko,
jackmanb, hannes, ziy, david, lorenzo.stoakes, Liam.Howlett,
rppt, Mostafa Saleh
Overview
--------
This patch series introduces a new debugging feature,
IOMMU_DEBUG_PAGEALLOC, designed to catch DMA use-after-free bugs
and IOMMU mapping leaks from buggy drivers.
The kernel has powerful sanitizers like KASAN and DEBUG_PAGEALLOC
for catching CPU-side memory corruption. However, there is limited
runtime sanitization for DMA mappings managed by the IOMMU. A buggy
driver can free a page while it is still mapped for DMA, leading to
memory corruption or use-after-free vulnerabilities when that page is
reallocated and used for a different purpose.
Inspired by DEBUG_PAGEALLOC, this sanitizer tracks IOMMU mappings on a
per-page basis, as it’s not possible to unmap the pages, because it
requires to lock and walk all domains on every kernel free, instead we
rely on page_ext to add an IOMMU-specific mapping reference count for
each page.
And on each page allocated/freed from the kernel we simply check the
count and WARN if it is not zero.
Concurrency
-----------
By design this check is racy where one caller can map pages just after
the check, which can lead to false negatives.
In my opinion this is acceptable for sanitizers (for ex KCSAN have
that property).
Otherwise we have to implement locks in iommu_map/unmap for all domains
which is not favourable even for a debug feature.
The sanitizer only guarantees that the refcount itself doesn’t get
corrupted using atomics. And there are no false positives.
CPU vs IOMMU Page Size
----------------------
IOMMUs can use different page sizes and which can be non-homogeneous;
not even all of them have the same page size.
To solve this, the refcount is always incremented and decremented in
units of the smallest page size supported by the IOMMU domain. This
ensures the accounting remains consistent regardless of the size of
the map or unmap operation, otherwise double counting can happen.
Testing & Performance
---------------------
This was tested on Morello with Arm64 + SMMUv3
Also I booted RockPi-4b with Rockchip IOMMU.
Did some tests on Qemu including different SMMUv3/CPU page size (arm64).
I also ran dma_map_benchmark on Morello:
echo dma_map_benchmark > /sys/bus/pci/devices/0000\:06\:00.0/driver_override
echo 0000:06:00.0 > /sys/bus/pci/devices/0000\:06\:00.0/driver/unbind
echo 0000:06:00.0 > /sys/bus/pci/drivers/dma_map_benchmark/bind
./dma_map_bechmark -t $threads -g $nr_pages
CONFIG refers to "CONFIG_IOMMU_DEBUG_PAGEALLOC"
cmdline refer to "iommu.debug_pagealloc"
Numbers are (map latency)/(unmap latency), lower is better.
CONFIG=n CONFIG=y CONFIG=y
cmdline=0 cmdline=1
4K - 1 thread 0.1/0.6 0.1/0.6 0.1/0.7
4K - 4 threads 0.1/1.0 0.1/1.1 0.1/1.1
1M - 1 thread 0.8/21.2 0.8/21.2 5.6/42.5
1M - 4 threads 1.1/46.3 1.1/46.1 5.9/45.5
Thanks,
Mostafa
Mostafa Saleh (4):
drivers/iommu: Add page_ext for IOMMU_DEBUG_PAGEALLOC
drivers/iommu: Add calls for iommu debug
drivers/iommu-debug: Track IOMMU pages
drivers/iommu-debug: Check state of mapped/unmapped kernel memory
.../admin-guide/kernel-parameters.txt | 6 +
drivers/iommu/Kconfig | 14 ++
drivers/iommu/Makefile | 1 +
drivers/iommu/iommu-debug.c | 160 ++++++++++++++++++
drivers/iommu/iommu.c | 21 ++-
include/linux/iommu-debug.h | 24 +++
include/linux/mm.h | 7 +
mm/page_ext.c | 4 +
8 files changed, 235 insertions(+), 2 deletions(-)
create mode 100644 drivers/iommu/iommu-debug.c
create mode 100644 include/linux/iommu-debug.h
--
2.51.0.618.g983fd99d29-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC PATCH 1/4] drivers/iommu: Add page_ext for IOMMU_DEBUG_PAGEALLOC
2025-10-03 17:32 [RFC PATCH 0/4] iommu: Add IOMMU_DEBUG_PAGEALLOC sanitizer Mostafa Saleh
@ 2025-10-03 17:32 ` Mostafa Saleh
2025-10-27 11:42 ` Jörg Rödel
2025-10-03 17:32 ` [RFC PATCH 2/4] drivers/iommu: Add calls for iommu debug Mostafa Saleh
` (3 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: Mostafa Saleh @ 2025-10-03 17:32 UTC (permalink / raw)
To: linux-mm, iommu, linux-kernel, linux-doc
Cc: corbet, joro, will, robin.murphy, akpm, vbabka, surenb, mhocko,
jackmanb, hannes, ziy, david, lorenzo.stoakes, Liam.Howlett,
rppt, Mostafa Saleh
Add a new config IOMMU_DEBUG_PAGEALLOC, which registers new data to
page_ext.
This config will be used by the IOMMU API to track pages mapped in
the IOMMU to catch drivers trying to free kernel memory that they
still map in their domains, causing all types of memory corruption.
This behaviour is disabled by default and can be enabled using
kernel cmdline iommu.debug_pagealloc.
Signed-off-by: Mostafa Saleh <smostafa@google.com>
---
.../admin-guide/kernel-parameters.txt | 6 ++++
drivers/iommu/Kconfig | 14 ++++++++
drivers/iommu/Makefile | 1 +
drivers/iommu/iommu-debug.c | 32 +++++++++++++++++++
include/linux/iommu-debug.h | 17 ++++++++++
mm/page_ext.c | 4 +++
6 files changed, 74 insertions(+)
create mode 100644 drivers/iommu/iommu-debug.c
create mode 100644 include/linux/iommu-debug.h
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 74ca438d2d6d..b2691a5527dd 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2539,6 +2539,12 @@
1 - Bypass the IOMMU for DMA.
unset - Use value of CONFIG_IOMMU_DEFAULT_PASSTHROUGH.
+ iommu.debug_pagealloc=
+ [KNL,EARLY] When CONFIG_IOMMU_DEBUG_PAGEALLOC is set, this
+ parameter enables the feature at boot time. By default, it
+ is disabled and the system will work mostly the same as a
+ kernel built without CONFIG_IOMMU_DEBUG_PAGEALLOC.
+
io7= [HW] IO7 for Marvel-based Alpha systems
See comment before marvel_specify_io7 in
arch/alpha/kernel/core_marvel.c.
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 70d29b14d851..5b40ec9b6e04 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -383,4 +383,18 @@ config SPRD_IOMMU
Say Y here if you want to use the multimedia devices listed above.
+config IOMMU_DEBUG_PAGEALLOC
+ bool "Debug page memory allocations against IOMMU"
+ depends on DEBUG_PAGEALLOC && IOMMU_API && PAGE_EXTENSION
+ help
+ This config checks when a page is freed by the kernel
+ it's not mapped in any IOMMU domain. It can help with
+ debugging use-after-free from driver doing DMA.
+ This santaizer can have false-negative cases where some
+ problems won't be detected.
+ Expect overhead when enabling this + enabling the kernel
+ command line iommu.debug_pagealloc.
+
+ If unsure, say N here.
+
endif # IOMMU_SUPPORT
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 355294fa9033..c834d3f70dfc 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -34,3 +34,4 @@ obj-$(CONFIG_IOMMU_SVA) += iommu-sva.o
obj-$(CONFIG_IOMMU_IOPF) += io-pgfault.o
obj-$(CONFIG_SPRD_IOMMU) += sprd-iommu.o
obj-$(CONFIG_APPLE_DART) += apple-dart.o
+obj-$(CONFIG_IOMMU_DEBUG_PAGEALLOC) += iommu-debug.o
\ No newline at end of file
diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
new file mode 100644
index 000000000000..297a35137b38
--- /dev/null
+++ b/drivers/iommu/iommu-debug.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 - Google Inc
+ * Author: Mostafa Saleh <smostafa@google.com>
+ * IOMMU API santaizers and debug
+ */
+#include <linux/atomic.h>
+#include <linux/iommu-debug.h>
+#include <linux/kernel.h>
+#include <linux/page_ext.h>
+
+static bool needed;
+
+struct iommu_debug_metadate {
+ atomic_t ref;
+};
+
+static __init bool need_iommu_debug(void)
+{
+ return needed;
+}
+
+struct page_ext_operations page_iommu_debug_ops = {
+ .size = sizeof(struct iommu_debug_metadate),
+ .need = need_iommu_debug,
+};
+
+static int __init iommu_debug_pagealloc(char *str)
+{
+ return kstrtobool(str, &needed);
+}
+early_param("iommu.debug_pagealloc", iommu_debug_pagealloc);
diff --git a/include/linux/iommu-debug.h b/include/linux/iommu-debug.h
new file mode 100644
index 000000000000..a9c11855c4ed
--- /dev/null
+++ b/include/linux/iommu-debug.h
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 - Google Inc
+ * Author: Mostafa Saleh <smostafa@google.com>
+ * IOMMU API santaizers and debug
+ */
+
+#ifndef __LINUX_IOMMU_DEBUG_H
+#define __LINUX_IOMMU_DEBUG_H
+
+#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC
+
+extern struct page_ext_operations page_iommu_debug_ops;
+
+#endif /* CONFIG_IOMMU_DEBUG_PAGEALLOC */
+
+#endif /* __LINUX_IOMMU_DEBUG_H */
diff --git a/mm/page_ext.c b/mm/page_ext.c
index d7396a8970e5..37c764a55a0f 100644
--- a/mm/page_ext.c
+++ b/mm/page_ext.c
@@ -11,6 +11,7 @@
#include <linux/page_table_check.h>
#include <linux/rcupdate.h>
#include <linux/pgalloc_tag.h>
+#include <linux/iommu-debug.h>
/*
* struct page extension
@@ -89,6 +90,9 @@ static struct page_ext_operations *page_ext_ops[] __initdata = {
#ifdef CONFIG_PAGE_TABLE_CHECK
&page_table_check_ops,
#endif
+#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC
+ &page_iommu_debug_ops,
+#endif
};
unsigned long page_ext_size;
--
2.51.0.618.g983fd99d29-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC PATCH 2/4] drivers/iommu: Add calls for iommu debug
2025-10-03 17:32 [RFC PATCH 0/4] iommu: Add IOMMU_DEBUG_PAGEALLOC sanitizer Mostafa Saleh
2025-10-03 17:32 ` [RFC PATCH 1/4] drivers/iommu: Add page_ext for IOMMU_DEBUG_PAGEALLOC Mostafa Saleh
@ 2025-10-03 17:32 ` Mostafa Saleh
2025-10-27 11:43 ` Jörg Rödel
2025-10-03 17:32 ` [RFC PATCH 3/4] drivers/iommu-debug: Track IOMMU pages Mostafa Saleh
` (2 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: Mostafa Saleh @ 2025-10-03 17:32 UTC (permalink / raw)
To: linux-mm, iommu, linux-kernel, linux-doc
Cc: corbet, joro, will, robin.murphy, akpm, vbabka, surenb, mhocko,
jackmanb, hannes, ziy, david, lorenzo.stoakes, Liam.Howlett,
rppt, Mostafa Saleh
Add calls for the new iommu debug config IOMMU_DEBUG_PAGEALLOC:
- iommu_debug_init: Enable the debug mode if configured by the user.
- iommu_debug_map: Track iommu pages mapped, using physical address.
- iommu_debug_unmap: Track iommu pages unmapped, using IO virtual
address.
- iommu_debug_remap: Track iommu pages, already mapped using IOVA.
We have to do the unmap/remap as once pages are unmapped we lose the
information of the physical address.
This is racy, but the API is racy by construction as it uses refcounts
and doesn't attempt to lock/synchronize with the IOMMU API as that will
be costly, meaning that possibility of false negative exists.
Signed-off-by: Mostafa Saleh <smostafa@google.com>
---
drivers/iommu/iommu-debug.c | 23 +++++++++++++++++++++++
drivers/iommu/iommu.c | 21 +++++++++++++++++++--
include/linux/iommu-debug.h | 6 ++++++
3 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
index 297a35137b38..607f1fcf2235 100644
--- a/drivers/iommu/iommu-debug.c
+++ b/drivers/iommu/iommu-debug.c
@@ -5,11 +5,13 @@
* IOMMU API santaizers and debug
*/
#include <linux/atomic.h>
+#include <linux/iommu.h>
#include <linux/iommu-debug.h>
#include <linux/kernel.h>
#include <linux/page_ext.h>
static bool needed;
+static DEFINE_STATIC_KEY_FALSE(iommu_debug_initialized);
struct iommu_debug_metadate {
atomic_t ref;
@@ -25,6 +27,27 @@ struct page_ext_operations page_iommu_debug_ops = {
.need = need_iommu_debug,
};
+void iommu_debug_map(struct iommu_domain *domain, phys_addr_t phys, size_t size)
+{
+}
+
+void iommu_debug_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
+{
+}
+
+void iommu_debug_remap(struct iommu_domain *domain, unsigned long iova, size_t size)
+{
+}
+
+void iommu_debug_init(void)
+{
+ if (!needed)
+ return;
+
+ pr_info("iommu: Debugging page allocations, expect overhead or disable iommu.debug_pagealloc");
+ static_branch_enable(&iommu_debug_initialized);
+}
+
static int __init iommu_debug_pagealloc(char *str)
{
return kstrtobool(str, &needed);
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 060ebe330ee1..56c89636a33c 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -18,6 +18,7 @@
#include <linux/errno.h>
#include <linux/host1x_context_bus.h>
#include <linux/iommu.h>
+#include <linux/iommu-debug.h>
#include <linux/iommufd.h>
#include <linux/idr.h>
#include <linux/err.h>
@@ -231,6 +232,9 @@ static int __init iommu_subsys_init(void)
if (!nb)
return -ENOMEM;
+#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC
+ iommu_debug_init();
+#endif
for (int i = 0; i < ARRAY_SIZE(iommu_buses); i++) {
nb[i].notifier_call = iommu_bus_notifier;
bus_register_notifier(iommu_buses[i], &nb[i]);
@@ -2518,10 +2522,14 @@ int iommu_map_nosync(struct iommu_domain *domain, unsigned long iova,
}
/* unroll mapping in case something went wrong */
- if (ret)
+ if (ret) {
iommu_unmap(domain, orig_iova, orig_size - size);
- else
+ } else {
trace_map(orig_iova, orig_paddr, orig_size);
+#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC
+ iommu_debug_map(domain, orig_paddr, orig_size);
+#endif
+ }
return ret;
}
@@ -2583,6 +2591,10 @@ static size_t __iommu_unmap(struct iommu_domain *domain,
pr_debug("unmap this: iova 0x%lx size 0x%zx\n", iova, size);
+#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC
+ iommu_debug_unmap(domain, iova, size);
+#endif
+
/*
* Keep iterating until we either unmap 'size' bytes (or more)
* or we hit an area that isn't mapped.
@@ -2602,6 +2614,11 @@ static size_t __iommu_unmap(struct iommu_domain *domain,
unmapped += unmapped_page;
}
+#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC
+ if (unmapped < size)
+ iommu_debug_remap(domain, iova, size - unmapped);
+#endif
+
trace_unmap(orig_iova, size, unmapped);
return unmapped;
}
diff --git a/include/linux/iommu-debug.h b/include/linux/iommu-debug.h
index a9c11855c4ed..8d3ea661660f 100644
--- a/include/linux/iommu-debug.h
+++ b/include/linux/iommu-debug.h
@@ -11,6 +11,12 @@
#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC
extern struct page_ext_operations page_iommu_debug_ops;
+struct iommu_domain;
+
+void iommu_debug_map(struct iommu_domain *domain, phys_addr_t phys, size_t size);
+void iommu_debug_unmap(struct iommu_domain *domain, unsigned long iova, size_t size);
+void iommu_debug_remap(struct iommu_domain *domain, unsigned long iova, size_t size);
+void iommu_debug_init(void);
#endif /* CONFIG_IOMMU_DEBUG_PAGEALLOC */
--
2.51.0.618.g983fd99d29-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC PATCH 3/4] drivers/iommu-debug: Track IOMMU pages
2025-10-03 17:32 [RFC PATCH 0/4] iommu: Add IOMMU_DEBUG_PAGEALLOC sanitizer Mostafa Saleh
2025-10-03 17:32 ` [RFC PATCH 1/4] drivers/iommu: Add page_ext for IOMMU_DEBUG_PAGEALLOC Mostafa Saleh
2025-10-03 17:32 ` [RFC PATCH 2/4] drivers/iommu: Add calls for iommu debug Mostafa Saleh
@ 2025-10-03 17:32 ` Mostafa Saleh
2025-10-27 11:46 ` Jörg Rödel
2025-10-03 17:32 ` [RFC PATCH 4/4] drivers/iommu-debug: Check state of mapped/unmapped kernel memory Mostafa Saleh
2025-10-18 8:46 ` [RFC PATCH 0/4] iommu: Add IOMMU_DEBUG_PAGEALLOC sanitizer Qinxin Xia
4 siblings, 1 reply; 12+ messages in thread
From: Mostafa Saleh @ 2025-10-03 17:32 UTC (permalink / raw)
To: linux-mm, iommu, linux-kernel, linux-doc
Cc: corbet, joro, will, robin.murphy, akpm, vbabka, surenb, mhocko,
jackmanb, hannes, ziy, david, lorenzo.stoakes, Liam.Howlett,
rppt, Mostafa Saleh
Using the new calls use an atomic refcount to track how many times
a page is mapped in any of the IOMMUs.
For unmap we need to use iova_to_phys() to get the physical address
of the pages.
We use the smallest supported page size as the granularity of tracking
per domain.
This is important as it possible to map pages and unmap them with
larger sizes (as in map_sg()) cases.
Signed-off-by: Mostafa Saleh <smostafa@google.com>
---
drivers/iommu/iommu-debug.c | 83 +++++++++++++++++++++++++++++++++++++
1 file changed, 83 insertions(+)
diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
index 607f1fcf2235..cec8f594c7fa 100644
--- a/drivers/iommu/iommu-debug.c
+++ b/drivers/iommu/iommu-debug.c
@@ -27,16 +27,99 @@ struct page_ext_operations page_iommu_debug_ops = {
.need = need_iommu_debug,
};
+static struct page_ext *get_iommu_page_ext(phys_addr_t phys)
+{
+ struct page *page = phys_to_page(phys);
+ struct page_ext *page_ext = page_ext_get(page);
+
+ return page_ext;
+}
+
+static struct iommu_debug_metadate *get_iommu_data(struct page_ext *page_ext)
+{
+ return page_ext_data(page_ext, &page_iommu_debug_ops);
+}
+
+static void iommu_debug_inc_page(phys_addr_t phys)
+{
+ struct page_ext *page_ext = get_iommu_page_ext(phys);
+ struct iommu_debug_metadate *d = get_iommu_data(page_ext);
+
+ WARN_ON(atomic_inc_return(&d->ref) <= 0);
+ page_ext_put(page_ext);
+}
+
+static void iommu_debug_dec_page(phys_addr_t phys)
+{
+ struct page_ext *page_ext = get_iommu_page_ext(phys);
+ struct iommu_debug_metadate *d = get_iommu_data(page_ext);
+
+ WARN_ON(atomic_dec_return(&d->ref) < 0);
+ page_ext_put(page_ext);
+}
+
+/*
+ * IOMMU pages size might not match the CPU page size, in that case, we use
+ * the smallest IOMMU page size to refcount the pages in the vmemap.
+ * That's is important as both map and unmap has to use the same page size
+ * to update the refcount to avoid double counting the same page.
+ * And as we can't know from iommu_unmap() what was the original page size
+ * used for map, we just use the minimum supported one for both.
+ */
+static size_t iommu_debug_page_size(struct iommu_domain *domain)
+{
+ return 1UL << __ffs(domain->pgsize_bitmap);
+}
+
void iommu_debug_map(struct iommu_domain *domain, phys_addr_t phys, size_t size)
{
+ size_t off;
+ size_t page_size = iommu_debug_page_size(domain);
+
+ if (!static_branch_likely(&iommu_debug_initialized))
+ return;
+
+ for (off = 0 ; off < size ; off += page_size) {
+ if (!pfn_valid(__phys_to_pfn(phys + off)))
+ continue;
+ iommu_debug_inc_page(phys + off);
+ }
}
void iommu_debug_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
{
+ size_t off;
+ size_t page_size = iommu_debug_page_size(domain);
+
+ if (!static_branch_likely(&iommu_debug_initialized))
+ return;
+
+ for (off = 0 ; off < size ; off += page_size) {
+ phys_addr_t phys = iommu_iova_to_phys(domain, iova + off);
+
+ if (!phys || !pfn_valid(__phys_to_pfn(phys + off)))
+ continue;
+
+ iommu_debug_dec_page(phys);
+ }
}
void iommu_debug_remap(struct iommu_domain *domain, unsigned long iova, size_t size)
{
+ size_t off;
+ size_t page_size = iommu_debug_page_size(domain);
+
+ if (!static_branch_likely(&iommu_debug_initialized))
+ return;
+
+ for (off = 0 ; off < size ; off += page_size) {
+ phys_addr_t phys = iommu_iova_to_phys(domain, iova + off);
+
+ if (!phys || !pfn_valid(__phys_to_pfn(phys + off)))
+ continue;
+
+ iommu_debug_inc_page(phys);
+ }
}
void iommu_debug_init(void)
--
2.51.0.618.g983fd99d29-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC PATCH 4/4] drivers/iommu-debug: Check state of mapped/unmapped kernel memory
2025-10-03 17:32 [RFC PATCH 0/4] iommu: Add IOMMU_DEBUG_PAGEALLOC sanitizer Mostafa Saleh
` (2 preceding siblings ...)
2025-10-03 17:32 ` [RFC PATCH 3/4] drivers/iommu-debug: Track IOMMU pages Mostafa Saleh
@ 2025-10-03 17:32 ` Mostafa Saleh
2025-10-18 8:46 ` [RFC PATCH 0/4] iommu: Add IOMMU_DEBUG_PAGEALLOC sanitizer Qinxin Xia
4 siblings, 0 replies; 12+ messages in thread
From: Mostafa Saleh @ 2025-10-03 17:32 UTC (permalink / raw)
To: linux-mm, iommu, linux-kernel, linux-doc
Cc: corbet, joro, will, robin.murphy, akpm, vbabka, surenb, mhocko,
jackmanb, hannes, ziy, david, lorenzo.stoakes, Liam.Howlett,
rppt, Mostafa Saleh
Now, as the page_ext holds count of IOMMU mappings, we can use it to
assert that any page allocated/freed is indeed not in the IOMMU.
The sanitizer doesn’t protect against mapping/unmapping during this
period. However, that’s less harmful as the page is not used by the
kernel.
Signed-off-by: Mostafa Saleh <smostafa@google.com>
---
drivers/iommu/iommu-debug.c | 22 ++++++++++++++++++++++
include/linux/iommu-debug.h | 1 +
include/linux/mm.h | 7 +++++++
3 files changed, 30 insertions(+)
diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
index cec8f594c7fa..09157fef697e 100644
--- a/drivers/iommu/iommu-debug.c
+++ b/drivers/iommu/iommu-debug.c
@@ -71,6 +71,28 @@ static size_t iommu_debug_page_size(struct iommu_domain *domain)
return 1UL << __ffs(domain->pgsize_bitmap);
}
+static unsigned int iommu_debug_page_count(unsigned long phys)
+{
+ unsigned int ref;
+ struct page_ext *page_ext = get_iommu_page_ext(phys);
+ struct iommu_debug_metadate *d = get_iommu_data(page_ext);
+
+ ref = atomic_read(&d->ref);
+ page_ext_put(page_ext);
+ return ref;
+}
+
+void iommu_debug_check_unmapped(const struct page *page, int numpages)
+{
+ if (!static_branch_likely(&iommu_debug_initialized))
+ return;
+
+ while (numpages--) {
+ WARN_ON(iommu_debug_page_count(page_to_phys(page)));
+ page++;
+ }
+}
+
void iommu_debug_map(struct iommu_domain *domain, phys_addr_t phys, size_t size)
{
size_t off;
diff --git a/include/linux/iommu-debug.h b/include/linux/iommu-debug.h
index 8d3ea661660f..aaf893cfafd0 100644
--- a/include/linux/iommu-debug.h
+++ b/include/linux/iommu-debug.h
@@ -17,6 +17,7 @@ void iommu_debug_map(struct iommu_domain *domain, phys_addr_t phys, size_t size)
void iommu_debug_unmap(struct iommu_domain *domain, unsigned long iova, size_t size);
void iommu_debug_remap(struct iommu_domain *domain, unsigned long iova, size_t size);
void iommu_debug_init(void);
+void iommu_debug_check_unmapped(const struct page *page, int numpages);
#endif /* CONFIG_IOMMU_DEBUG_PAGEALLOC */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 06978b4dbeb8..00f5de44faa0 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -36,6 +36,7 @@
#include <linux/rcuwait.h>
#include <linux/bitmap.h>
#include <linux/bitops.h>
+#include <linux/iommu-debug.h>
struct mempolicy;
struct anon_vma;
@@ -3806,12 +3807,18 @@ extern void __kernel_map_pages(struct page *page, int numpages, int enable);
#ifdef CONFIG_DEBUG_PAGEALLOC
static inline void debug_pagealloc_map_pages(struct page *page, int numpages)
{
+#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC
+ iommu_debug_check_unmapped(page, numpages);
+#endif
if (debug_pagealloc_enabled_static())
__kernel_map_pages(page, numpages, 1);
}
static inline void debug_pagealloc_unmap_pages(struct page *page, int numpages)
{
+#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC
+ iommu_debug_check_unmapped(page, numpages);
+#endif
if (debug_pagealloc_enabled_static())
__kernel_map_pages(page, numpages, 0);
}
--
2.51.0.618.g983fd99d29-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 0/4] iommu: Add IOMMU_DEBUG_PAGEALLOC sanitizer
2025-10-03 17:32 [RFC PATCH 0/4] iommu: Add IOMMU_DEBUG_PAGEALLOC sanitizer Mostafa Saleh
` (3 preceding siblings ...)
2025-10-03 17:32 ` [RFC PATCH 4/4] drivers/iommu-debug: Check state of mapped/unmapped kernel memory Mostafa Saleh
@ 2025-10-18 8:46 ` Qinxin Xia
4 siblings, 0 replies; 12+ messages in thread
From: Qinxin Xia @ 2025-10-18 8:46 UTC (permalink / raw)
To: Mostafa Saleh, linux-mm, iommu, linux-kernel, linux-doc
Cc: corbet, joro, will, robin.murphy, akpm, vbabka, surenb, mhocko,
jackmanb, hannes, ziy, david, lorenzo.stoakes, Liam.Howlett,
rppt
在 2025/10/4 1:32, Mostafa Saleh 写道:
> Overview
> --------
> This patch series introduces a new debugging feature,
> IOMMU_DEBUG_PAGEALLOC, designed to catch DMA use-after-free bugs
> and IOMMU mapping leaks from buggy drivers.
>
> The kernel has powerful sanitizers like KASAN and DEBUG_PAGEALLOC
> for catching CPU-side memory corruption. However, there is limited
> runtime sanitization for DMA mappings managed by the IOMMU. A buggy
> driver can free a page while it is still mapped for DMA, leading to
> memory corruption or use-after-free vulnerabilities when that page is
> reallocated and used for a different purpose.
>
> Inspired by DEBUG_PAGEALLOC, this sanitizer tracks IOMMU mappings on a
> per-page basis, as it’s not possible to unmap the pages, because it
> requires to lock and walk all domains on every kernel free, instead we
> rely on page_ext to add an IOMMU-specific mapping reference count for
> each page.
> And on each page allocated/freed from the kernel we simply check the
> count and WARN if it is not zero.
>
> Concurrency
> -----------
> By design this check is racy where one caller can map pages just after
> the check, which can lead to false negatives.
> In my opinion this is acceptable for sanitizers (for ex KCSAN have
> that property).
> Otherwise we have to implement locks in iommu_map/unmap for all domains
> which is not favourable even for a debug feature.
> The sanitizer only guarantees that the refcount itself doesn’t get
> corrupted using atomics. And there are no false positives.
>
> CPU vs IOMMU Page Size
> ----------------------
> IOMMUs can use different page sizes and which can be non-homogeneous;
> not even all of them have the same page size.
>
> To solve this, the refcount is always incremented and decremented in
> units of the smallest page size supported by the IOMMU domain. This
> ensures the accounting remains consistent regardless of the size of
> the map or unmap operation, otherwise double counting can happen.
>
> Testing & Performance
> ---------------------
> This was tested on Morello with Arm64 + SMMUv3
> Also I booted RockPi-4b with Rockchip IOMMU.
> Did some tests on Qemu including different SMMUv3/CPU page size (arm64).
>
> I also ran dma_map_benchmark on Morello:
>
> echo dma_map_benchmark > /sys/bus/pci/devices/0000\:06\:00.0/driver_override
> echo 0000:06:00.0 > /sys/bus/pci/devices/0000\:06\:00.0/driver/unbind
> echo 0000:06:00.0 > /sys/bus/pci/drivers/dma_map_benchmark/bind
> ./dma_map_bechmark -t $threads -g $nr_pages
>
> CONFIG refers to "CONFIG_IOMMU_DEBUG_PAGEALLOC"
> cmdline refer to "iommu.debug_pagealloc"
> Numbers are (map latency)/(unmap latency), lower is better.
>
> CONFIG=n CONFIG=y CONFIG=y
> cmdline=0 cmdline=1
> 4K - 1 thread 0.1/0.6 0.1/0.6 0.1/0.7
> 4K - 4 threads 0.1/1.0 0.1/1.1 0.1/1.1
> 1M - 1 thread 0.8/21.2 0.8/21.2 5.6/42.5
> 1M - 4 threads 1.1/46.3 1.1/46.1 5.9/45.5
>
> Thanks,
> Mostafa
>
> Mostafa Saleh (4):
> drivers/iommu: Add page_ext for IOMMU_DEBUG_PAGEALLOC
> drivers/iommu: Add calls for iommu debug
> drivers/iommu-debug: Track IOMMU pages
> drivers/iommu-debug: Check state of mapped/unmapped kernel memory
>
> .../admin-guide/kernel-parameters.txt | 6 +
> drivers/iommu/Kconfig | 14 ++
> drivers/iommu/Makefile | 1 +
> drivers/iommu/iommu-debug.c | 160 ++++++++++++++++++
> drivers/iommu/iommu.c | 21 ++-
> include/linux/iommu-debug.h | 24 +++
> include/linux/mm.h | 7 +
> mm/page_ext.c | 4 +
> 8 files changed, 235 insertions(+), 2 deletions(-)
> create mode 100644 drivers/iommu/iommu-debug.c
> create mode 100644 include/linux/iommu-debug.h
>
Hi,
I have tested the patch on kunpeng 920 and it works as expected.
Tested-by: Qinxin Xia <xiaqinxin@huawei.com>
Thanks,
Qinxin Xia
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 1/4] drivers/iommu: Add page_ext for IOMMU_DEBUG_PAGEALLOC
2025-10-03 17:32 ` [RFC PATCH 1/4] drivers/iommu: Add page_ext for IOMMU_DEBUG_PAGEALLOC Mostafa Saleh
@ 2025-10-27 11:42 ` Jörg Rödel
2025-10-29 14:21 ` Mostafa Saleh
0 siblings, 1 reply; 12+ messages in thread
From: Jörg Rödel @ 2025-10-27 11:42 UTC (permalink / raw)
To: Mostafa Saleh
Cc: linux-mm, iommu, linux-kernel, linux-doc, corbet, will,
robin.murphy, akpm, vbabka, surenb, mhocko, jackmanb, hannes,
ziy, david, lorenzo.stoakes, Liam.Howlett, rppt
On Fri, Oct 03, 2025 at 05:32:26PM +0000, Mostafa Saleh wrote:
> +config IOMMU_DEBUG_PAGEALLOC
> + bool "Debug page memory allocations against IOMMU"
> + depends on DEBUG_PAGEALLOC && IOMMU_API && PAGE_EXTENSION
> + help
> + This config checks when a page is freed by the kernel
> + it's not mapped in any IOMMU domain. It can help with
> + debugging use-after-free from driver doing DMA.
> + This santaizer can have false-negative cases where some
> + problems won't be detected.
> + Expect overhead when enabling this + enabling the kernel
> + command line iommu.debug_pagealloc.
> +
> + If unsure, say N here.
Expected indentation here is <tab><space><space> and not <tab><tab>.
> --- /dev/null
> +++ b/drivers/iommu/iommu-debug.c
Is there a plan for this file to contain more than page-alloc debugging? If
not, it should get a more specific name, like iommu-debug-pagealloc.c or
similar.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 2/4] drivers/iommu: Add calls for iommu debug
2025-10-03 17:32 ` [RFC PATCH 2/4] drivers/iommu: Add calls for iommu debug Mostafa Saleh
@ 2025-10-27 11:43 ` Jörg Rödel
2025-10-29 14:22 ` Mostafa Saleh
0 siblings, 1 reply; 12+ messages in thread
From: Jörg Rödel @ 2025-10-27 11:43 UTC (permalink / raw)
To: Mostafa Saleh
Cc: linux-mm, iommu, linux-kernel, linux-doc, corbet, will,
robin.murphy, akpm, vbabka, surenb, mhocko, jackmanb, hannes,
ziy, david, lorenzo.stoakes, Liam.Howlett, rppt
On Fri, Oct 03, 2025 at 05:32:27PM +0000, Mostafa Saleh wrote:
> Add calls for the new iommu debug config IOMMU_DEBUG_PAGEALLOC:
> - iommu_debug_init: Enable the debug mode if configured by the user.
> - iommu_debug_map: Track iommu pages mapped, using physical address.
> - iommu_debug_unmap: Track iommu pages unmapped, using IO virtual
> address.
> - iommu_debug_remap: Track iommu pages, already mapped using IOVA.
>
> We have to do the unmap/remap as once pages are unmapped we lose the
> information of the physical address.
> This is racy, but the API is racy by construction as it uses refcounts
> and doesn't attempt to lock/synchronize with the IOMMU API as that will
> be costly, meaning that possibility of false negative exists.
>
> Signed-off-by: Mostafa Saleh <smostafa@google.com>
> ---
> drivers/iommu/iommu-debug.c | 23 +++++++++++++++++++++++
> drivers/iommu/iommu.c | 21 +++++++++++++++++++--
> include/linux/iommu-debug.h | 6 ++++++
> 3 files changed, 48 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
> index 297a35137b38..607f1fcf2235 100644
> --- a/drivers/iommu/iommu-debug.c
> +++ b/drivers/iommu/iommu-debug.c
> @@ -5,11 +5,13 @@
> * IOMMU API santaizers and debug
> */
> #include <linux/atomic.h>
> +#include <linux/iommu.h>
> #include <linux/iommu-debug.h>
> #include <linux/kernel.h>
> #include <linux/page_ext.h>
>
> static bool needed;
> +static DEFINE_STATIC_KEY_FALSE(iommu_debug_initialized);
>
> struct iommu_debug_metadate {
> atomic_t ref;
> @@ -25,6 +27,27 @@ struct page_ext_operations page_iommu_debug_ops = {
> .need = need_iommu_debug,
> };
>
> +void iommu_debug_map(struct iommu_domain *domain, phys_addr_t phys, size_t size)
> +{
> +}
> +
> +void iommu_debug_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
> +{
> +}
> +
> +void iommu_debug_remap(struct iommu_domain *domain, unsigned long iova, size_t size)
> +{
> +}
> +
> +void iommu_debug_init(void)
> +{
> + if (!needed)
> + return;
> +
> + pr_info("iommu: Debugging page allocations, expect overhead or disable iommu.debug_pagealloc");
> + static_branch_enable(&iommu_debug_initialized);
> +}
> +
> static int __init iommu_debug_pagealloc(char *str)
> {
> return kstrtobool(str, &needed);
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> index 060ebe330ee1..56c89636a33c 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -18,6 +18,7 @@
> #include <linux/errno.h>
> #include <linux/host1x_context_bus.h>
> #include <linux/iommu.h>
> +#include <linux/iommu-debug.h>
> #include <linux/iommufd.h>
> #include <linux/idr.h>
> #include <linux/err.h>
> @@ -231,6 +232,9 @@ static int __init iommu_subsys_init(void)
> if (!nb)
> return -ENOMEM;
>
> +#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC
> + iommu_debug_init();
> +#endif
> for (int i = 0; i < ARRAY_SIZE(iommu_buses); i++) {
> nb[i].notifier_call = iommu_bus_notifier;
> bus_register_notifier(iommu_buses[i], &nb[i]);
> @@ -2518,10 +2522,14 @@ int iommu_map_nosync(struct iommu_domain *domain, unsigned long iova,
> }
>
> /* unroll mapping in case something went wrong */
> - if (ret)
> + if (ret) {
> iommu_unmap(domain, orig_iova, orig_size - size);
> - else
> + } else {
> trace_map(orig_iova, orig_paddr, orig_size);
> +#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC
> + iommu_debug_map(domain, orig_paddr, orig_size);
> +#endif
These #ifdefs need to be in a header file, not the actual source code.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 3/4] drivers/iommu-debug: Track IOMMU pages
2025-10-03 17:32 ` [RFC PATCH 3/4] drivers/iommu-debug: Track IOMMU pages Mostafa Saleh
@ 2025-10-27 11:46 ` Jörg Rödel
2025-10-29 14:24 ` Mostafa Saleh
0 siblings, 1 reply; 12+ messages in thread
From: Jörg Rödel @ 2025-10-27 11:46 UTC (permalink / raw)
To: Mostafa Saleh
Cc: linux-mm, iommu, linux-kernel, linux-doc, corbet, will,
robin.murphy, akpm, vbabka, surenb, mhocko, jackmanb, hannes,
ziy, david, lorenzo.stoakes, Liam.Howlett, rppt
On Fri, Oct 03, 2025 at 05:32:28PM +0000, Mostafa Saleh wrote:
> void iommu_debug_map(struct iommu_domain *domain, phys_addr_t phys, size_t size)
> {
> + size_t off;
> + size_t page_size = iommu_debug_page_size(domain);
> +
> + if (!static_branch_likely(&iommu_debug_initialized))
> + return;
This still adds function call overhead even in cases where iommu-debugging is
disabled. Move the static_branches to the header files as well.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 1/4] drivers/iommu: Add page_ext for IOMMU_DEBUG_PAGEALLOC
2025-10-27 11:42 ` Jörg Rödel
@ 2025-10-29 14:21 ` Mostafa Saleh
0 siblings, 0 replies; 12+ messages in thread
From: Mostafa Saleh @ 2025-10-29 14:21 UTC (permalink / raw)
To: Jörg Rödel
Cc: linux-mm, iommu, linux-kernel, linux-doc, corbet, will,
robin.murphy, akpm, vbabka, surenb, mhocko, jackmanb, hannes,
ziy, david, lorenzo.stoakes, Liam.Howlett, rppt
On Mon, Oct 27, 2025 at 12:42:09PM +0100, Jörg Rödel wrote:
> On Fri, Oct 03, 2025 at 05:32:26PM +0000, Mostafa Saleh wrote:
> > +config IOMMU_DEBUG_PAGEALLOC
> > + bool "Debug page memory allocations against IOMMU"
> > + depends on DEBUG_PAGEALLOC && IOMMU_API && PAGE_EXTENSION
> > + help
> > + This config checks when a page is freed by the kernel
> > + it's not mapped in any IOMMU domain. It can help with
> > + debugging use-after-free from driver doing DMA.
> > + This santaizer can have false-negative cases where some
> > + problems won't be detected.
> > + Expect overhead when enabling this + enabling the kernel
> > + command line iommu.debug_pagealloc.
> > +
> > + If unsure, say N here.
>
> Expected indentation here is <tab><space><space> and not <tab><tab>.
My bad, I will fix it in v2.
>
> > --- /dev/null
> > +++ b/drivers/iommu/iommu-debug.c
>
> Is there a plan for this file to contain more than page-alloc debugging? If
> not, it should get a more specific name, like iommu-debug-pagealloc.c or
> similar.
I have no solid plans for other features, but I was hoping to build on top
of that in the future, but for now we can make it “iommu-debug-pagealloc.c”
Thanks,
Mostafa
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 2/4] drivers/iommu: Add calls for iommu debug
2025-10-27 11:43 ` Jörg Rödel
@ 2025-10-29 14:22 ` Mostafa Saleh
0 siblings, 0 replies; 12+ messages in thread
From: Mostafa Saleh @ 2025-10-29 14:22 UTC (permalink / raw)
To: Jörg Rödel
Cc: linux-mm, iommu, linux-kernel, linux-doc, corbet, will,
robin.murphy, akpm, vbabka, surenb, mhocko, jackmanb, hannes,
ziy, david, lorenzo.stoakes, Liam.Howlett, rppt
On Mon, Oct 27, 2025 at 12:43:06PM +0100, Jörg Rödel wrote:
> On Fri, Oct 03, 2025 at 05:32:27PM +0000, Mostafa Saleh wrote:
> > Add calls for the new iommu debug config IOMMU_DEBUG_PAGEALLOC:
> > - iommu_debug_init: Enable the debug mode if configured by the user.
> > - iommu_debug_map: Track iommu pages mapped, using physical address.
> > - iommu_debug_unmap: Track iommu pages unmapped, using IO virtual
> > address.
> > - iommu_debug_remap: Track iommu pages, already mapped using IOVA.
> >
> > We have to do the unmap/remap as once pages are unmapped we lose the
> > information of the physical address.
> > This is racy, but the API is racy by construction as it uses refcounts
> > and doesn't attempt to lock/synchronize with the IOMMU API as that will
> > be costly, meaning that possibility of false negative exists.
> >
> > Signed-off-by: Mostafa Saleh <smostafa@google.com>
> > ---
> > drivers/iommu/iommu-debug.c | 23 +++++++++++++++++++++++
> > drivers/iommu/iommu.c | 21 +++++++++++++++++++--
> > include/linux/iommu-debug.h | 6 ++++++
> > 3 files changed, 48 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
> > index 297a35137b38..607f1fcf2235 100644
> > --- a/drivers/iommu/iommu-debug.c
> > +++ b/drivers/iommu/iommu-debug.c
> > @@ -5,11 +5,13 @@
> > * IOMMU API santaizers and debug
> > */
> > #include <linux/atomic.h>
> > +#include <linux/iommu.h>
> > #include <linux/iommu-debug.h>
> > #include <linux/kernel.h>
> > #include <linux/page_ext.h>
> >
> > static bool needed;
> > +static DEFINE_STATIC_KEY_FALSE(iommu_debug_initialized);
> >
> > struct iommu_debug_metadate {
> > atomic_t ref;
> > @@ -25,6 +27,27 @@ struct page_ext_operations page_iommu_debug_ops = {
> > .need = need_iommu_debug,
> > };
> >
> > +void iommu_debug_map(struct iommu_domain *domain, phys_addr_t phys, size_t size)
> > +{
> > +}
> > +
> > +void iommu_debug_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
> > +{
> > +}
> > +
> > +void iommu_debug_remap(struct iommu_domain *domain, unsigned long iova, size_t size)
> > +{
> > +}
> > +
> > +void iommu_debug_init(void)
> > +{
> > + if (!needed)
> > + return;
> > +
> > + pr_info("iommu: Debugging page allocations, expect overhead or disable iommu.debug_pagealloc");
> > + static_branch_enable(&iommu_debug_initialized);
> > +}
> > +
> > static int __init iommu_debug_pagealloc(char *str)
> > {
> > return kstrtobool(str, &needed);
> > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> > index 060ebe330ee1..56c89636a33c 100644
> > --- a/drivers/iommu/iommu.c
> > +++ b/drivers/iommu/iommu.c
> > @@ -18,6 +18,7 @@
> > #include <linux/errno.h>
> > #include <linux/host1x_context_bus.h>
> > #include <linux/iommu.h>
> > +#include <linux/iommu-debug.h>
> > #include <linux/iommufd.h>
> > #include <linux/idr.h>
> > #include <linux/err.h>
> > @@ -231,6 +232,9 @@ static int __init iommu_subsys_init(void)
> > if (!nb)
> > return -ENOMEM;
> >
> > +#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC
> > + iommu_debug_init();
> > +#endif
> > for (int i = 0; i < ARRAY_SIZE(iommu_buses); i++) {
> > nb[i].notifier_call = iommu_bus_notifier;
> > bus_register_notifier(iommu_buses[i], &nb[i]);
> > @@ -2518,10 +2522,14 @@ int iommu_map_nosync(struct iommu_domain *domain, unsigned long iova,
> > }
> >
> > /* unroll mapping in case something went wrong */
> > - if (ret)
> > + if (ret) {
> > iommu_unmap(domain, orig_iova, orig_size - size);
> > - else
> > + } else {
> > trace_map(orig_iova, orig_paddr, orig_size);
> > +#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC
> > + iommu_debug_map(domain, orig_paddr, orig_size);
> > +#endif
>
> These #ifdefs need to be in a header file, not the actual source code.
I will fix it in v2.
Thanks,
Mostafa
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 3/4] drivers/iommu-debug: Track IOMMU pages
2025-10-27 11:46 ` Jörg Rödel
@ 2025-10-29 14:24 ` Mostafa Saleh
0 siblings, 0 replies; 12+ messages in thread
From: Mostafa Saleh @ 2025-10-29 14:24 UTC (permalink / raw)
To: Jörg Rödel
Cc: linux-mm, iommu, linux-kernel, linux-doc, corbet, will,
robin.murphy, akpm, vbabka, surenb, mhocko, jackmanb, hannes,
ziy, david, lorenzo.stoakes, Liam.Howlett, rppt
On Mon, Oct 27, 2025 at 12:46:02PM +0100, Jörg Rödel wrote:
> On Fri, Oct 03, 2025 at 05:32:28PM +0000, Mostafa Saleh wrote:
> > void iommu_debug_map(struct iommu_domain *domain, phys_addr_t phys, size_t size)
> > {
> > + size_t off;
> > + size_t page_size = iommu_debug_page_size(domain);
> > +
> > + if (!static_branch_likely(&iommu_debug_initialized))
> > + return;
>
> This still adds function call overhead even in cases where iommu-debugging is
> disabled. Move the static_branches to the header files as well.
I see, I will fix it in v2.
Thanks,
Mostafa
>
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2025-10-29 14:24 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-10-03 17:32 [RFC PATCH 0/4] iommu: Add IOMMU_DEBUG_PAGEALLOC sanitizer Mostafa Saleh
2025-10-03 17:32 ` [RFC PATCH 1/4] drivers/iommu: Add page_ext for IOMMU_DEBUG_PAGEALLOC Mostafa Saleh
2025-10-27 11:42 ` Jörg Rödel
2025-10-29 14:21 ` Mostafa Saleh
2025-10-03 17:32 ` [RFC PATCH 2/4] drivers/iommu: Add calls for iommu debug Mostafa Saleh
2025-10-27 11:43 ` Jörg Rödel
2025-10-29 14:22 ` Mostafa Saleh
2025-10-03 17:32 ` [RFC PATCH 3/4] drivers/iommu-debug: Track IOMMU pages Mostafa Saleh
2025-10-27 11:46 ` Jörg Rödel
2025-10-29 14:24 ` Mostafa Saleh
2025-10-03 17:32 ` [RFC PATCH 4/4] drivers/iommu-debug: Check state of mapped/unmapped kernel memory Mostafa Saleh
2025-10-18 8:46 ` [RFC PATCH 0/4] iommu: Add IOMMU_DEBUG_PAGEALLOC sanitizer Qinxin Xia
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox