From nobody Sat Feb 7 18:20:56 2026 Received: from mail-wm1-f74.google.com (mail-wm1-f74.google.com [209.85.128.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 673BD3A4F26 for ; Wed, 14 Jan 2026 16:43:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768409014; cv=none; b=MpensgJU0Zqo0H/vJYsKOZd4sKHQx9XNYChz6/8V2fp2HKGxrIf/Crl/0Vhz7C5ZIulsxILr0y7Ph++9qbSBtr3av2VEgua664A6rOKPS3T86G/SR14vwTZRfBDDbrlk8NS5lmVaI34p86Zhi+j35hFAvGhfTbvYPvLVq7BgyC8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768409014; c=relaxed/simple; bh=7BYRgRnhfN3fHr35Z4lIewD7nb4bdgg7dJRSYUFPl2k=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=khlw8cNcwams5sMGu05qnT9YHSYF/5iP2IJ96E3OZrKOVLGSJvBpH2z9znC6QzY8q2fRPR7WLhaLWgusTNLoUxWIA/73xxmigxcIccZd6ZMfi724hbnjbICzCstJm2AMGw+pLsLMR0fIL9BfPKHsRn5SAg72p8KNMJEzmciDwGs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--smostafa.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=iCmITmYz; arc=none smtp.client-ip=209.85.128.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--smostafa.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="iCmITmYz" Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-47d1622509eso163395e9.3 for ; Wed, 14 Jan 2026 08:43:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1768409011; x=1769013811; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=NagltRQpX2SlKWY3/YB/PdnajjFmvEiNKHSf6/veCZ0=; b=iCmITmYzBFUH9gYHFUZPjgDr1WAUBC4PkanBW9XOw9HBQEr0Fd7MGoISiB+V+LCw7h Z8HyT6dFWF3lNxxflP1tJaoaW08cO61FsOmtT/adxI4vRkv+Xj+YSSdQ8aSlbF78HQYt orEyr4M17eirungbI6dkPTXCWFRY9/QOR2dcsNUCHSvdvdcTZaphpSRjxoHaqmfwCiQR UFLUmsRgIBcAzXMa+XTAwdAVH31X/mNzkiC3BKhtZZgu11I0oNXkX2ZgwmTu0rXN8XZ4 ZsPEOCMVShMuzC76+3tcWs6gVqDsr9liXXa/pq+B4CUkZueVJg8oLoN7wLUh7efAFrEC sL3g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768409011; x=1769013811; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=NagltRQpX2SlKWY3/YB/PdnajjFmvEiNKHSf6/veCZ0=; b=ABZBDIB+W7mHJMRcSwXA4xkUj/vEa0zFGVrJYQViprz3Xa201QlatqYVdt9C5v1ZWU ZPUQPuKnWiGSpnt5u3OvU8s0g58l3T0ZpR+kWYem2PumN1rWfPTYXcsRdomGuUkD02GS OJNJinqzbKFkfq9dnmHS3uuk26uyUQnMzsRoPHaCPFSvqszEd5joBBarFoysReM60y5t H1J22Q38yM8230HQteUeUecOpvMvwJyyfRLMoAwnkPZC6NZXxtwd0Xkg/dWTSSLeUA3X zRgrmz6LBWBdgr+rZUwrFPEu/jSB648UGJOh7plvbBIE75lDiA1vk95cPWfoI2vYwh9Q DMjA== X-Forwarded-Encrypted: i=1; AJvYcCXwwFIjSDylLtN94sxNo/D8bir1+DDcg0V0rRGjv7PfjsgKZ3VlI5ThlfudfKoU9NJQTGiPPRXFy9Nsn10=@vger.kernel.org X-Gm-Message-State: AOJu0YyTdEemm3cG3Aatezd24pD/WkYCdhLXsgDqfwNwcjmDIqkpbBdQ QLhpFtoIMOYjSxeotTvpE6DKPrgNLkzhVkKzOqKleozitVoaIcgV8eUYVw44ZpJiQ4hDk6G7vBR Qc6wUFYq7uWagDw== X-Received: from wmbd23.prod.google.com ([2002:a05:600c:58d7:b0:477:9654:b44c]) (user=smostafa job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:8707:b0:477:7f4a:44b4 with SMTP id 5b1f17b1804b1-47ee33192c2mr42786345e9.1.1768409011069; Wed, 14 Jan 2026 08:43:31 -0800 (PST) Date: Wed, 14 Jan 2026 16:43:18 +0000 In-Reply-To: <20260114164322.787125-1-smostafa@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260114164322.787125-1-smostafa@google.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog Message-ID: <20260114164322.787125-2-smostafa@google.com> Subject: [PATCH v7 1/5] mm/page_ext: Add page_ext_get_phys() From: Mostafa Saleh To: linux-mm@kvack.org, iommu@lists.linux.dev, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org Cc: corbet@lwn.net, joro@8bytes.org, will@kernel.org, robin.murphy@arm.com, akpm@linux-foundation.org, vbabka@suse.cz, surenb@google.com, mhocko@suse.com, jackmanb@google.com, hannes@cmpxchg.org, ziy@nvidia.com, david@redhat.com, lorenzo.stoakes@oracle.com, Liam.Howlett@oracle.com, rppt@kernel.org, xiaqinxin@huawei.com, baolu.lu@linux.intel.com, rdunlap@infradead.org, Mostafa Saleh Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In the next patches, IOMMU code will add data to page_ext. The IOMMU code would operate on physical addresses which can be outside of system RAM. Add a new function page_ext_get_phys() to abstract the logic of checking the address and returning the page_ext. Signed-off-by: Mostafa Saleh --- include/linux/page_ext.h | 6 ++++++ mm/page_ext.c | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/include/linux/page_ext.h b/include/linux/page_ext.h index 76c817162d2f..bd373496e166 100644 --- a/include/linux/page_ext.h +++ b/include/linux/page_ext.h @@ -93,6 +93,7 @@ static inline bool page_ext_iter_next_fast_possible(unsig= ned long next_pfn) #endif =20 extern struct page_ext *page_ext_get(const struct page *page); +extern struct page_ext *page_ext_get_phys(phys_addr_t phys); extern void page_ext_put(struct page_ext *page_ext); extern struct page_ext *page_ext_lookup(unsigned long pfn); =20 @@ -215,6 +216,11 @@ static inline struct page_ext *page_ext_get(const stru= ct page *page) return NULL; } =20 +static inline struct page_ext *page_ext_get_phys(phys_addr_t phys) +{ + return NULL; +} + static inline void page_ext_put(struct page_ext *page_ext) { } diff --git a/mm/page_ext.c b/mm/page_ext.c index d7396a8970e5..95e8c40131b7 100644 --- a/mm/page_ext.c +++ b/mm/page_ext.c @@ -534,6 +534,29 @@ struct page_ext *page_ext_get(const struct page *page) return page_ext; } =20 +/** + * page_ext_get_phys() - Get the page_ext structure for a physical address. + * @phys: The physical address to query. + * + * This function safely gets the `struct page_ext` associated with a given + * physical address. It performs validation to ensure the address correspo= nds + * to a valid, online struct page before attempting to access it. + * It should return NULL for (MMIO, ZONE_DEVICE, holes, offline memory) + * + * Return: NULL if no page_ext exists for this physical address. + * Context: Any context. Caller may not sleep until they have called + * page_ext_put(). + */ +struct page_ext *page_ext_get_phys(phys_addr_t phys) +{ + struct page *page =3D pfn_to_online_page(__phys_to_pfn(phys)); + + if (!page) + return NULL; + + return page_ext_get(page); +} + /** * page_ext_put() - Working with page extended information is done. * @page_ext: Page extended information received from page_ext_get(). --=20 2.52.0.457.g6b5491de43-goog From nobody Sat Feb 7 18:20:56 2026 Received: from mail-ej1-f74.google.com (mail-ej1-f74.google.com [209.85.218.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ABD903A4F31 for ; Wed, 14 Jan 2026 16:43:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768409015; cv=none; b=Qq6erJafK7mH7bc/3NTVMH95y0aBwxiXmRjf5Vdd7rST6yKRXXbW93Q8fmm4suObQN3d53ay7dDY3i/ILMXNPy5p6c/GW8CgEphGk2lKHAffSeZEk3fqBuwbpC95v4zWDSRK6Hiv4KE1C74qCR2NTxsUyg0qKMAWmY3+l5mMFKQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768409015; c=relaxed/simple; bh=SZY94J/dNfahSXQwuNsteL87RmDThOrVNSQsYPBPH3g=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=uzY0fbAKP/0fttaVIHMPr0Rmdh2vBGJGXH1z5cSMqQMEhM0XdTQMSR35lRvgxGkXhgsosrmWYlv2DpamI6oftJnv6V/FqY4J+iVd3D5hhuzlctoJo9NtfQ1woOwLdg3lMOYbKekvBl12DTZm4RY+LQVrYvOaBBH9huquFUmYcNM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--smostafa.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=UQICtyHB; arc=none smtp.client-ip=209.85.218.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--smostafa.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="UQICtyHB" Received: by mail-ej1-f74.google.com with SMTP id a640c23a62f3a-b844098869cso5114866b.2 for ; Wed, 14 Jan 2026 08:43:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1768409012; x=1769013812; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=7B7vkHmo1gB7yzDxYR9VV+0wyuHcnCvbFYocb2WwDHM=; b=UQICtyHB6y0jRooNnSECb1iYWkXhuN95x0OVahDAenXrCLO3II5kCWQs2FxGFHbfhl 4QvOi7h5NmcPocMv3T7PT17HW7Ki2H6kYozRu9yFoee6nSVtBjJEpdGMVPh1+ye6aCI9 SFQODusAZNZOYgqG8hBdpxBSL64Xh8VNXEV1apvlpeex9ZXOcfxtCW/PUqd3eh1yiJyS 1TxNVpx4vuIghlLYt9iIaJ/ElPZWkKKOrXdd6BWbrSYtPhnvc76ySC5pb6O/McIxkc6Z 6MccHBGEuAly8V+QaRhai/6q0rPLh/IS378ldrghoGrs3NMTx6UTaBvORBXcW39ND/+E 4Z6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768409012; x=1769013812; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=7B7vkHmo1gB7yzDxYR9VV+0wyuHcnCvbFYocb2WwDHM=; b=Sw+YO76AeQ1Ekp+uLeNesxMTqszjP+fCB31Od6RE8QXCpQhNxIjc0idsqmxJJLvBS8 sZb9NgNgF+KMkbVmOw8wsd48PEubgt2E2s1MXxKDMf93kbX1LzH54cRcTBVLquB7shl0 o/ApSUamdtbPn1BD+EZwhblKlSoqWXwVcgeJPTE8XttOTlxLgDYfOq00M9/hC7qkVscd HFuwJ+Pz8gfrBLXhbm5jWB0TGkBzd2XLExDPfbKgo3OZrRIExEVhEhi0shdeasCwDwsq sUOLRqYBUujfXHCGkX8SCy0JKg2TJ2F1w5ScxwuidMDKmy0yW/dOGfuJZ55hXUldZmJE dn/g== X-Forwarded-Encrypted: i=1; AJvYcCXMmdapVxxlITO0PH3okPQAhlqNqihFwZ/PWzS/6OtvDnH3wiEL8kB5/6Wo8AXBI2vpERA3yPvVMfj9RoU=@vger.kernel.org X-Gm-Message-State: AOJu0Yy16ohjgIaAElkXnFdzJkAK8JLKTeByKDDIfecN4PLndjjynZSs RhxKLchvUwzvAd30zhxNSx18D88ZXlCPZDlW1IGhfJBfgkPUMXf4YZhpuwmljRLhK7hH4qvlWI4 kQhTuMcbpNjbpzQ== X-Received: from ejcfj22.prod.google.com ([2002:a17:906:9c96:b0:b83:23f7:8971]) (user=smostafa job=prod-delivery.src-stubby-dispatcher) by 2002:a17:906:6a1c:b0:b80:149b:badd with SMTP id a640c23a62f3a-b87612a48a9mr267326266b.37.1768409011939; Wed, 14 Jan 2026 08:43:31 -0800 (PST) Date: Wed, 14 Jan 2026 16:43:19 +0000 In-Reply-To: <20260114164322.787125-1-smostafa@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260114164322.787125-1-smostafa@google.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog Message-ID: <20260114164322.787125-3-smostafa@google.com> Subject: [PATCH v7 2/5] iommu: Add page_ext for IOMMU_DEBUG_PAGEALLOC From: Mostafa Saleh To: linux-mm@kvack.org, iommu@lists.linux.dev, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org Cc: corbet@lwn.net, joro@8bytes.org, will@kernel.org, robin.murphy@arm.com, akpm@linux-foundation.org, vbabka@suse.cz, surenb@google.com, mhocko@suse.com, jackmanb@google.com, hannes@cmpxchg.org, ziy@nvidia.com, david@redhat.com, lorenzo.stoakes@oracle.com, Liam.Howlett@oracle.com, rppt@kernel.org, xiaqinxin@huawei.com, baolu.lu@linux.intel.com, rdunlap@infradead.org, Mostafa Saleh , "David Hildenbrand (Red Hat)" , Pranjal Shrivastava Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Acked-by: David Hildenbrand (Red Hat) Reviewed-by: Pranjal Shrivastava Reviewed-by: Lu Baolu Signed-off-by: Mostafa Saleh --- .../admin-guide/kernel-parameters.txt | 9 ++++++ drivers/iommu/Kconfig | 19 +++++++++++ drivers/iommu/Makefile | 1 + drivers/iommu/iommu-debug-pagealloc.c | 32 +++++++++++++++++++ include/linux/iommu-debug-pagealloc.h | 17 ++++++++++ mm/page_ext.c | 4 +++ 6 files changed, 82 insertions(+) create mode 100644 drivers/iommu/iommu-debug-pagealloc.c create mode 100644 include/linux/iommu-debug-pagealloc.h diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentatio= n/admin-guide/kernel-parameters.txt index a8d0afde7f85..d484d9d8d0a4 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2675,6 +2675,15 @@ Kernel parameters 1 - Bypass the IOMMU for DMA. unset - Use value of CONFIG_IOMMU_DEFAULT_PASSTHROUGH. =20 + iommu.debug_pagealloc=3D + [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 behaves the same way as a kernel + built without CONFIG_IOMMU_DEBUG_PAGEALLOC. + Format: { "0" | "1" } + 0 - Sanitizer disabled. + 1 - Sanitizer enabled, expect runtime overhead. + io7=3D [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 99095645134f..f86262b11416 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -384,6 +384,25 @@ config SPRD_IOMMU =20 Say Y here if you want to use the multimedia devices listed above. =20 +config IOMMU_DEBUG_PAGEALLOC + bool "Debug IOMMU mappings against page allocations" + depends on DEBUG_PAGEALLOC && IOMMU_API && PAGE_EXTENSION + help + This enables a consistency check between the kernel page allocator and + the IOMMU subsystem. It verifies that pages being allocated or freed + are not currently mapped in any IOMMU domain. + + This helps detect DMA use-after-free bugs where a driver frees a page + but forgets to unmap it from the IOMMU, potentially allowing a device + to overwrite memory that the kernel has repurposed. + + These checks are best-effort and may not detect all problems. + + Due to performance overhead, this feature is disabled by default. + You must enable "iommu.debug_pagealloc" from the kernel command + line to activate the runtime checks. + + If unsure, say N. endif # IOMMU_SUPPORT =20 source "drivers/iommu/generic_pt/Kconfig" diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 8e8843316c4b..0275821f4ef9 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -36,3 +36,4 @@ obj-$(CONFIG_IOMMU_SVA) +=3D iommu-sva.o obj-$(CONFIG_IOMMU_IOPF) +=3D io-pgfault.o obj-$(CONFIG_SPRD_IOMMU) +=3D sprd-iommu.o obj-$(CONFIG_APPLE_DART) +=3D apple-dart.o +obj-$(CONFIG_IOMMU_DEBUG_PAGEALLOC) +=3D iommu-debug-pagealloc.o diff --git a/drivers/iommu/iommu-debug-pagealloc.c b/drivers/iommu/iommu-de= bug-pagealloc.c new file mode 100644 index 000000000000..4022e9af7f27 --- /dev/null +++ b/drivers/iommu/iommu-debug-pagealloc.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2025 - Google Inc + * Author: Mostafa Saleh + * IOMMU API debug page alloc sanitizer + */ +#include +#include +#include +#include + +static bool needed; + +struct iommu_debug_metadata { + atomic_t ref; +}; + +static __init bool need_iommu_debug(void) +{ + return needed; +} + +struct page_ext_operations page_iommu_debug_ops =3D { + .size =3D sizeof(struct iommu_debug_metadata), + .need =3D 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-pagealloc.h b/include/linux/iommu-de= bug-pagealloc.h new file mode 100644 index 000000000000..83e64d70bf6c --- /dev/null +++ b/include/linux/iommu-debug-pagealloc.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2025 - Google Inc + * Author: Mostafa Saleh + * IOMMU API debug page alloc sanitizer + */ + +#ifndef __LINUX_IOMMU_DEBUG_PAGEALLOC_H +#define __LINUX_IOMMU_DEBUG_PAGEALLOC_H + +#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC + +extern struct page_ext_operations page_iommu_debug_ops; + +#endif /* CONFIG_IOMMU_DEBUG_PAGEALLOC */ + +#endif /* __LINUX_IOMMU_DEBUG_PAGEALLOC_H */ diff --git a/mm/page_ext.c b/mm/page_ext.c index 95e8c40131b7..5fe65a0ac4f3 100644 --- a/mm/page_ext.c +++ b/mm/page_ext.c @@ -11,6 +11,7 @@ #include #include #include +#include =20 /* * struct page extension @@ -89,6 +90,9 @@ static struct page_ext_operations *page_ext_ops[] __initd= ata =3D { #ifdef CONFIG_PAGE_TABLE_CHECK &page_table_check_ops, #endif +#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC + &page_iommu_debug_ops, +#endif }; =20 unsigned long page_ext_size; --=20 2.52.0.457.g6b5491de43-goog From nobody Sat Feb 7 18:20:56 2026 Received: from mail-ed1-f73.google.com (mail-ed1-f73.google.com [209.85.208.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C86F33A4F43 for ; Wed, 14 Jan 2026 16:43:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768409016; cv=none; b=egJazor/+NSVUk1/YXzjuHOw1LZVL82ss1Zfkjmkc7L02PTWE476NEPpdyWYaIX7mab+9MRXmtmHwsxy2vLEJbhQCRuwyA/yCFzlzGOUYz6vZPrjesXfeW+XMuXHchnvLfyrFbB4335WFQo/T3DMeh/MEO1YI0qejYKHGwKvFMI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768409016; c=relaxed/simple; bh=aVLtfsmeLEMhp2ORt1tnvgbLgSD0YJ90dSkoXHBqBTc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ADVtRY5sB2gGN2qmxR61qFwloGGVzsBOdoNW53Uni1AqzjL4lAVZTD+qCZ+homSe6ukLTIu0FoJmdQ3WGYjroMaAvk2ysLWPszJ6HXPRK2TO1EMTwF40BtHVVBBfFjFnc3vjiyxlI2vC+y6aoWb5iUY6oPsh2MiQUWrnkZ67IVY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--smostafa.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=hl0ZZVMK; arc=none smtp.client-ip=209.85.208.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--smostafa.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="hl0ZZVMK" Received: by mail-ed1-f73.google.com with SMTP id 4fb4d7f45d1cf-653f94a664eso755866a12.2 for ; Wed, 14 Jan 2026 08:43:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1768409013; x=1769013813; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=guvkPBegEDYZPDzaTTld5oNSHvfpDoo/mBDTxGLtjdA=; b=hl0ZZVMKG/CPtmHrCQUpleGRQE7ROUj6POE5U3OVmXMr4pXAPsk+CBOZS+y/gry6hG 20/MQ8kh50dFb9yn130dEwVxh+5YeodxgKDjI2PC7vGx5+bqtei8XAfZ+iKQ/KFL3USS MlbAAIDTYxUd8e9F0KNU43c8sCTb/9In6kLDtiy2LKJiLH1kycglUZhoecdxg4HyCuG5 CRTCOMbVXKyrIJD98eL8wHr5q37cagzc2M0yFl7qBql3ORnTP4x5Z63uMqgAJJT6obid QVY5TzEzIsJKjyTMSMBBYtZzMou2byiyD0o1c0FvSydan09W9PUgP2rmZe2bfa9mRbpx sXRw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768409013; x=1769013813; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=guvkPBegEDYZPDzaTTld5oNSHvfpDoo/mBDTxGLtjdA=; b=TjJa9Wqg5cEQ4zSvAlYYvHsCwslHcS+HjtrFpVOf28siFKt335FFNq6cRWGJhIlfaf n2GZtW1YOEi9yEOVBo7LNJea6k4cQntBvjT+HTbl9I8lOoWYiwjAGaTNPXUVhnaItFNo +6Bo4ic7kWh79RqlYlh1LnhAlBWa2U6vqCCWUgdxpfN/sVFa3jLt6+airxquzoA0EGF8 pDGG3KaesWbh/EV+yaZabC7Tuy3YMq2KcBRsNMmxdLFs7znDkhqAmlvVPnkF2xDZ/6FJ sNutWy8ABPqYZGG7P4NgG9xKggdtqeiiS330bPeOGyo0/93JFlwd7yhxfcyZa8/wGInS 5FgA== X-Forwarded-Encrypted: i=1; AJvYcCULc68CayrNxB1h028p6B1TPlGLYS4Dlf49dV8k2pLKgTszlLb/D6FQR43/7OEgb/mmUl/D06jpdsSbGaw=@vger.kernel.org X-Gm-Message-State: AOJu0YwWGrcutRkHw3HQL2xJGHLTTIxa0V39pRkpp5k8tbcc5jazAm6D T1pLgHJrG9hSXxGmAjLHvcP8r8az6r8m0sMi+RaTRAJ2t1wvI7hnCsPqWZlXXtCK/2YEHjBimRW old0zXgZ2qQoPLg== X-Received: from edrl19.prod.google.com ([2002:aa7:c3d3:0:b0:64d:3026:fea6]) (user=smostafa job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6402:26c8:b0:649:64d3:1554 with SMTP id 4fb4d7f45d1cf-653ec125e44mr2681693a12.15.1768409013075; Wed, 14 Jan 2026 08:43:33 -0800 (PST) Date: Wed, 14 Jan 2026 16:43:20 +0000 In-Reply-To: <20260114164322.787125-1-smostafa@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260114164322.787125-1-smostafa@google.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog Message-ID: <20260114164322.787125-4-smostafa@google.com> Subject: [PATCH v7 3/5] iommu: Add calls for IOMMU_DEBUG_PAGEALLOC From: Mostafa Saleh To: linux-mm@kvack.org, iommu@lists.linux.dev, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org Cc: corbet@lwn.net, joro@8bytes.org, will@kernel.org, robin.murphy@arm.com, akpm@linux-foundation.org, vbabka@suse.cz, surenb@google.com, mhocko@suse.com, jackmanb@google.com, hannes@cmpxchg.org, ziy@nvidia.com, david@redhat.com, lorenzo.stoakes@oracle.com, Liam.Howlett@oracle.com, rppt@kernel.org, xiaqinxin@huawei.com, baolu.lu@linux.intel.com, rdunlap@infradead.org, Mostafa Saleh , Samiullah Khawaja , Pranjal Shrivastava Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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_begin: Track start of iommu unmap operation, with IOVA and size. - iommu_debug_unmap_end: Track the end of unmap operation, passing the actual unmapped size versus the tracked one at unmap_begin. We have to do the unmap_begin/end 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. Reviewed-by: Samiullah Khawaja Reviewed-by: Lu Baolu Reviewed-by: Pranjal Shrivastava Signed-off-by: Mostafa Saleh --- drivers/iommu/iommu-debug-pagealloc.c | 28 +++++++++++++ drivers/iommu/iommu-priv.h | 58 +++++++++++++++++++++++++++ drivers/iommu/iommu.c | 11 ++++- include/linux/iommu-debug-pagealloc.h | 1 + 4 files changed, 96 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/iommu-debug-pagealloc.c b/drivers/iommu/iommu-de= bug-pagealloc.c index 4022e9af7f27..1d343421da98 100644 --- a/drivers/iommu/iommu-debug-pagealloc.c +++ b/drivers/iommu/iommu-debug-pagealloc.c @@ -5,11 +5,15 @@ * IOMMU API debug page alloc sanitizer */ #include +#include #include #include #include =20 +#include "iommu-priv.h" + static bool needed; +DEFINE_STATIC_KEY_FALSE(iommu_debug_initialized); =20 struct iommu_debug_metadata { atomic_t ref; @@ -25,6 +29,30 @@ struct page_ext_operations page_iommu_debug_ops =3D { .need =3D need_iommu_debug, }; =20 +void __iommu_debug_map(struct iommu_domain *domain, phys_addr_t phys, size= _t size) +{ +} + +void __iommu_debug_unmap_begin(struct iommu_domain *domain, + unsigned long iova, size_t size) +{ +} + +void __iommu_debug_unmap_end(struct iommu_domain *domain, + unsigned long iova, size_t size, + size_t unmapped) +{ +} + +void iommu_debug_init(void) +{ + if (!needed) + return; + + pr_info("iommu: Debugging page allocations, expect overhead or disable io= mmu.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-priv.h b/drivers/iommu/iommu-priv.h index c95394cd03a7..aaffad5854fc 100644 --- a/drivers/iommu/iommu-priv.h +++ b/drivers/iommu/iommu-priv.h @@ -5,6 +5,7 @@ #define __LINUX_IOMMU_PRIV_H =20 #include +#include #include =20 static inline const struct iommu_ops *dev_iommu_ops(struct device *dev) @@ -65,4 +66,61 @@ static inline int iommufd_sw_msi(struct iommu_domain *do= main, int iommu_replace_device_pasid(struct iommu_domain *domain, struct device *dev, ioasid_t pasid, struct iommu_attach_handle *handle); + +#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC + +void __iommu_debug_map(struct iommu_domain *domain, phys_addr_t phys, + size_t size); +void __iommu_debug_unmap_begin(struct iommu_domain *domain, + unsigned long iova, size_t size); +void __iommu_debug_unmap_end(struct iommu_domain *domain, + unsigned long iova, size_t size, size_t unmapped); + +static inline void iommu_debug_map(struct iommu_domain *domain, + phys_addr_t phys, size_t size) +{ + if (static_branch_unlikely(&iommu_debug_initialized)) + __iommu_debug_map(domain, phys, size); +} + +static inline void iommu_debug_unmap_begin(struct iommu_domain *domain, + unsigned long iova, size_t size) +{ + if (static_branch_unlikely(&iommu_debug_initialized)) + __iommu_debug_unmap_begin(domain, iova, size); +} + +static inline void iommu_debug_unmap_end(struct iommu_domain *domain, + unsigned long iova, size_t size, + size_t unmapped) +{ + if (static_branch_unlikely(&iommu_debug_initialized)) + __iommu_debug_unmap_end(domain, iova, size, unmapped); +} + +void iommu_debug_init(void); + +#else +static inline void iommu_debug_map(struct iommu_domain *domain, + phys_addr_t phys, size_t size) +{ +} + +static inline void iommu_debug_unmap_begin(struct iommu_domain *domain, + unsigned long iova, size_t size) +{ +} + +static inline void iommu_debug_unmap_end(struct iommu_domain *domain, + unsigned long iova, size_t size, + size_t unmapped) +{ +} + +static inline void iommu_debug_init(void) +{ +} + +#endif /* CONFIG_IOMMU_DEBUG_PAGEALLOC */ + #endif /* __LINUX_IOMMU_PRIV_H */ diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 2ca990dfbb88..01b062575519 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -232,6 +232,8 @@ static int __init iommu_subsys_init(void) if (!nb) return -ENOMEM; =20 + iommu_debug_init(); + for (int i =3D 0; i < ARRAY_SIZE(iommu_buses); i++) { nb[i].notifier_call =3D iommu_bus_notifier; bus_register_notifier(iommu_buses[i], &nb[i]); @@ -2562,10 +2564,12 @@ int iommu_map_nosync(struct iommu_domain *domain, u= nsigned long iova, } =20 /* 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); + iommu_debug_map(domain, orig_paddr, orig_size); + } =20 return ret; } @@ -2627,6 +2631,8 @@ static size_t __iommu_unmap(struct iommu_domain *doma= in, =20 pr_debug("unmap this: iova 0x%lx size 0x%zx\n", iova, size); =20 + iommu_debug_unmap_begin(domain, iova, size); + /* * Keep iterating until we either unmap 'size' bytes (or more) * or we hit an area that isn't mapped. @@ -2647,6 +2653,7 @@ static size_t __iommu_unmap(struct iommu_domain *doma= in, } =20 trace_unmap(orig_iova, size, unmapped); + iommu_debug_unmap_end(domain, orig_iova, size, unmapped); return unmapped; } =20 diff --git a/include/linux/iommu-debug-pagealloc.h b/include/linux/iommu-de= bug-pagealloc.h index 83e64d70bf6c..a439d6815ca1 100644 --- a/include/linux/iommu-debug-pagealloc.h +++ b/include/linux/iommu-debug-pagealloc.h @@ -9,6 +9,7 @@ #define __LINUX_IOMMU_DEBUG_PAGEALLOC_H =20 #ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC +DECLARE_STATIC_KEY_FALSE(iommu_debug_initialized); =20 extern struct page_ext_operations page_iommu_debug_ops; =20 --=20 2.52.0.457.g6b5491de43-goog From nobody Sat Feb 7 18:20:56 2026 Received: from mail-wr1-f73.google.com (mail-wr1-f73.google.com [209.85.221.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 899C73A4F40 for ; Wed, 14 Jan 2026 16:43:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768409017; cv=none; b=sZUYVphooo1LXBVJVvfzSnDwhUGTplOUeWUMHBl37Sjc7b0rW0e20lt1mXL7j4j+HUkhQjV1dY/t2E3VRS7tOqj62q2K1lbdOIAxUprVLSGSdYoikZ7RYg5Hp8DVA/dhiwk+r+mkmH/VkAL9zebudTegfNe1AvkPA5eHn1B/FFY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768409017; c=relaxed/simple; bh=oTypUmL8Y7fARfHGzXR113k/PBV6oYH6cemBWWQriHU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=jaOUfXLMXOtrJQgSeHZPetkW5DSe5iCR/zXdMeIwIihIsP6oSsNqX8dgRFDpAptWr9zeg54JphzXt6O+lgz/oyT17qM+nu0mFULkvLnKC67mucAIwBsuxQXG+/FSWk5VGc9oJPAsxUxrAd8xIQbESKUJVxuzZixZ8l2Tlmbfp7g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--smostafa.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=rlrsLE5H; arc=none smtp.client-ip=209.85.221.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--smostafa.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="rlrsLE5H" Received: by mail-wr1-f73.google.com with SMTP id ffacd0b85a97d-432488a0ce8so29254f8f.2 for ; Wed, 14 Jan 2026 08:43:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1768409014; x=1769013814; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=tdaemC/8rVdnYF36w5DJ/vmlH80Wji91vs6XJXHQNS8=; b=rlrsLE5HIY9pKqchWXLezyqrE1LD/UtAlNuqFBJk/JbDX37aG+RGphP1bDBgybIcFu vYoxhwPNVmho8nHZ2AXy859VT8GTybPH/Qr5p6350QSSEjyY2SCYmBhaZWmoWGNqNaX4 rwm1La5ktnpyazN8MDDQEnzfcd7ItK7b16KqOpPKtAs8bSELFvnWyK2Z/81WM+4MapRu sgLaEeDz2809rIrxoCZmwzvJpSZVUFU4yR9soQNq3A4JQI6wT3x7gBWflokj5pBF57iK QD8EqvbJ5m92Teslpeb2gMz0aewJpB7PECK5KL48C7NuA1mw6LtvITmg0FRspZhzmwMW tTLg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768409014; x=1769013814; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=tdaemC/8rVdnYF36w5DJ/vmlH80Wji91vs6XJXHQNS8=; b=mN8mYavwKKFi1KPNG+Soa6vbD4Uy6nUrg7VxID+zwsrZBdO9i9HflpneHE8kxZ34vg U9HOjQKt1isEx8+K07idlctWvywHqE2EvAFg80HHVS4yBILL6wR44TJ4Lx9w0awt6y0a oZm67O0qB0DgVSr6c3eCnATCWyGsp//xuOS3SsFCfb5V5UKvF2iEp6Cevyh/tCt2moBV 7h19fP0vy1On+uaHI8TbHHCuIvk2qfOr+YKnKriiLLxm8D9rbQNsfdk9XusBNVxA+bAS BKzzEx4J0NHpAyBUve9Xe7vF6OT/7hHHrhs7OvWliRyvXhtD/IyesQfLMFLwOTMrhB7D NJMQ== X-Forwarded-Encrypted: i=1; AJvYcCVAC/nl4PD4BJ3QBOGzI3ErPQYt2SrVT4CnrD+l/H9APqPDplMgDC20QLtZhL/4fgX5H/cT3nnaNJ44k9E=@vger.kernel.org X-Gm-Message-State: AOJu0YyD90dH/ibQliW6fd+Np4bzpQb4PKJ6u3X1FE6nLxoTlKE8ElYF cHvKcJH+EzBCToRWiy1HDhYdkF+KjA45KQnzQQJfVjBW+IzswZVNqokioZvfS4JfCwHn7xbb+rH OvZ7lbsMLkBZoUw== X-Received: from wrwe15.prod.google.com ([2002:a5d:65cf:0:b0:430:f6cb:a9d2]) (user=smostafa job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6000:4304:b0:430:fdfc:7dd3 with SMTP id ffacd0b85a97d-4342c5537ffmr3522133f8f.50.1768409014021; Wed, 14 Jan 2026 08:43:34 -0800 (PST) Date: Wed, 14 Jan 2026 16:43:21 +0000 In-Reply-To: <20260114164322.787125-1-smostafa@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260114164322.787125-1-smostafa@google.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog Message-ID: <20260114164322.787125-5-smostafa@google.com> Subject: [PATCH v7 4/5] iommu: debug-pagealloc: Track IOMMU pages From: Mostafa Saleh To: linux-mm@kvack.org, iommu@lists.linux.dev, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org Cc: corbet@lwn.net, joro@8bytes.org, will@kernel.org, robin.murphy@arm.com, akpm@linux-foundation.org, vbabka@suse.cz, surenb@google.com, mhocko@suse.com, jackmanb@google.com, hannes@cmpxchg.org, ziy@nvidia.com, david@redhat.com, lorenzo.stoakes@oracle.com, Liam.Howlett@oracle.com, rppt@kernel.org, xiaqinxin@huawei.com, baolu.lu@linux.intel.com, rdunlap@infradead.org, Mostafa Saleh Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 is possible to map pages and unmap them with larger sizes (as in map_sg()) cases. Signed-off-by: Mostafa Saleh --- drivers/iommu/iommu-debug-pagealloc.c | 86 +++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/drivers/iommu/iommu-debug-pagealloc.c b/drivers/iommu/iommu-de= bug-pagealloc.c index 1d343421da98..3ce3385588b2 100644 --- a/drivers/iommu/iommu-debug-pagealloc.c +++ b/drivers/iommu/iommu-debug-pagealloc.c @@ -29,19 +29,105 @@ struct page_ext_operations page_iommu_debug_ops =3D { .need =3D need_iommu_debug, }; =20 +static struct iommu_debug_metadata *get_iommu_data(struct page_ext *page_e= xt) +{ + 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 =3D page_ext_get_phys(phys); + struct iommu_debug_metadata *d; + + if (!page_ext) + return; + + d =3D get_iommu_data(page_ext); + + WARN_ON(atomic_inc_return_relaxed(&d->ref) <=3D 0); + page_ext_put(page_ext); +} + +static void iommu_debug_dec_page(phys_addr_t phys) +{ + struct page_ext *page_ext =3D page_ext_get_phys(phys); + struct iommu_debug_metadata *d; + + if (!page_ext) + return; + + d =3D get_iommu_data(page_ext); + + WARN_ON(atomic_dec_return_relaxed(&d->ref) < 0); + page_ext_put(page_ext); +} + +/* + * IOMMU page size doesn't have to match the CPU page size. So, we use + * the smallest IOMMU page size to refcount the pages in the vmemmap. + * That 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, end; + size_t page_size =3D iommu_debug_page_size(domain); + + if (WARN_ON(!phys || check_add_overflow(phys, size, &end))) + return; + + for (off =3D 0 ; off < size ; off +=3D page_size) { + if (!pfn_valid(__phys_to_pfn(phys + off))) + continue; + iommu_debug_inc_page(phys + off); + } +} + +static void __iommu_debug_update_iova(struct iommu_domain *domain, + unsigned long iova, size_t size, bool inc) +{ + size_t off, end; + size_t page_size =3D iommu_debug_page_size(domain); + + if (WARN_ON(check_add_overflow(iova, size, &end))) + return; + + for (off =3D 0 ; off < size ; off +=3D page_size) { + phys_addr_t phys =3D iommu_iova_to_phys(domain, iova + off); + + if (!phys || !pfn_valid(__phys_to_pfn(phys))) + continue; + + if (inc) + iommu_debug_inc_page(phys); + else + iommu_debug_dec_page(phys); + } } =20 void __iommu_debug_unmap_begin(struct iommu_domain *domain, unsigned long iova, size_t size) { + __iommu_debug_update_iova(domain, iova, size, false); } =20 void __iommu_debug_unmap_end(struct iommu_domain *domain, unsigned long iova, size_t size, size_t unmapped) { + if ((unmapped =3D=3D size) || WARN_ON_ONCE(unmapped > size)) + return; + + /* If unmap failed, re-increment the refcount. */ + __iommu_debug_update_iova(domain, iova + unmapped, + size - unmapped, true); } =20 void iommu_debug_init(void) --=20 2.52.0.457.g6b5491de43-goog From nobody Sat Feb 7 18:20:56 2026 Received: from mail-wr1-f74.google.com (mail-wr1-f74.google.com [209.85.221.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 68B0C3A63E7 for ; Wed, 14 Jan 2026 16:43:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768409018; cv=none; b=EvzBlvzZtUp2l/pAVDziwue3bGavW3LSHMkkObOEHtT3Hbq4f7K40QMAtlJ4Gpjkccfpr8hdbrb/Xk23l0vjCyK4TcDnQpUae1SslPtq4q6u7fAu9iCbDTrzGjoJF5ttY/x7KkIusIE9wyh8/uWt2cTGHmBQBYwjQeq0xta54JI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768409018; c=relaxed/simple; bh=dzaYjfbIZZavp/S2MnKk+6oK1c7oQVF6rcvC3rrGw2Q=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=YZ5Asamq1yebjSCAUNw8t5YDlbWkMJUN0zI+pOUjPozSA50gp73EwOYE4yGAU6K6B+2nZLETjuylWF0jDeKhmXYCuISBP+ov+n4/XSclcFD+s8+5NNmJBj541IPlKMogMnl+XLRu4QdPO1TllUOXlYy20aK+j2QZEqtUp8KGClg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--smostafa.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=P/Hf0UZx; arc=none smtp.client-ip=209.85.221.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--smostafa.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="P/Hf0UZx" Received: by mail-wr1-f74.google.com with SMTP id ffacd0b85a97d-430fe16b481so17152f8f.3 for ; Wed, 14 Jan 2026 08:43:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1768409015; x=1769013815; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:from:to:cc:subject:date:message-id :reply-to; bh=lp9W32Kped56Je6lvPD7Xlxv6Ozf5Aka/rllxnPof5w=; b=P/Hf0UZxSUrFsPl2uLiWbu78LsSUl9fAKysbjchf4cfdZXi5sYyG/CmFj3wO3swjps 6FP/x3iqLcWAQr3vPZa5rKZXL4siCXZ+LSPpB5z49PSUES77zKJGfnDf74iylfHJaPgU NawlIIaN8qpnFdAwaFZ4aBzIr7BnHp8CO7+oBVBGf3uls5LHU03guXHOPzkg1j1FfiYw J7goX9e1SVOBPricoMDenmAW5JXpC4f55WFzBL81mfjSyjp+LsbkKZQbRYaoZKBzkz74 5+1omG5WkndYeDNvY3urlGdvjE2IZ7zrbkFB12Oa3iVhLI6JwK5XajJy+v7POOTeWOoZ xFkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768409015; x=1769013815; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to; bh=lp9W32Kped56Je6lvPD7Xlxv6Ozf5Aka/rllxnPof5w=; b=FziocEj5bW8dVQt9L61+0af91493oiRzt/ej017Vzhbakai8QT16OyqcULRhDXTCU9 PDs4YH7F6A45K1gX6JdBU82IHDFgA1SF8a0Z9p3WrLTu/VJikfijwATUWUg+WqnRo1ir 85NxRVEcbsNwo9JhnRwd4D3uc2lmYRX+vW2CYX5X7/SGsrzWz90BmSoSRDaRM2CrlX2R ky9ciZFKlOHmcrWueIxPicKjPWr8gE59KagpnVHu3JK5ZkSYRIFiMfQmXbAQECcYelno i1bFTAI+u1mb8kxkf0OVJpxQ2+2EpLzleKf3pCRYYuToIE8B7Cpp9HRN1kZxW5/ukPqx p16g== X-Forwarded-Encrypted: i=1; AJvYcCW4FsY7hf4VWHneyj8FBZatFH+6X16YE2r4gydJtDu1w6EtU060ZVRJI3PBqzD23zDSy6JwY7/AiuVhgc4=@vger.kernel.org X-Gm-Message-State: AOJu0Yz07A+ZgJDdQBi4rrUwyT8JjRXZYDwsOwmbImDIcOZSLA7Dei6F kr5PYm5IA6bdw97MbZgNrNfVZk/X7DwhhrLCN1mqCFCS0M5q7mAZ+W7TLjmvnui5Vr89fyExx2O WqqRSiTs6ZLBW1g== X-Received: from wmbd23.prod.google.com ([2002:a05:600c:58d7:b0:477:9654:b44c]) (user=smostafa job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:5285:b0:477:7ab8:aba with SMTP id 5b1f17b1804b1-47ee32e0be0mr36180785e9.1.1768409014935; Wed, 14 Jan 2026 08:43:34 -0800 (PST) Date: Wed, 14 Jan 2026 16:43:22 +0000 In-Reply-To: <20260114164322.787125-1-smostafa@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260114164322.787125-1-smostafa@google.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog Message-ID: <20260114164322.787125-6-smostafa@google.com> Subject: [PATCH v7 5/5] iommu: debug-pagealloc: Check mapped/unmapped kernel memory From: Mostafa Saleh To: linux-mm@kvack.org, iommu@lists.linux.dev, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org Cc: corbet@lwn.net, joro@8bytes.org, will@kernel.org, robin.murphy@arm.com, akpm@linux-foundation.org, vbabka@suse.cz, surenb@google.com, mhocko@suse.com, jackmanb@google.com, hannes@cmpxchg.org, ziy@nvidia.com, david@redhat.com, lorenzo.stoakes@oracle.com, Liam.Howlett@oracle.com, rppt@kernel.org, xiaqinxin@huawei.com, baolu.lu@linux.intel.com, rdunlap@infradead.org, Mostafa Saleh , Samiullah Khawaja , Pranjal Shrivastava Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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=E2=80=99t protect against mapping/unmapping during this period. However, that=E2=80=99s less harmful as the page is not used by the kernel. Reviewed-by: Samiullah Khawaja Reviewed-by: Lu Baolu Reviewed-by: Pranjal Shrivastava Signed-off-by: Mostafa Saleh --- drivers/iommu/iommu-debug-pagealloc.c | 23 +++++++++++++++++++++++ include/linux/iommu-debug-pagealloc.h | 14 ++++++++++++++ include/linux/mm.h | 5 +++++ 3 files changed, 42 insertions(+) diff --git a/drivers/iommu/iommu-debug-pagealloc.c b/drivers/iommu/iommu-de= bug-pagealloc.c index 3ce3385588b2..a283b5dbe26f 100644 --- a/drivers/iommu/iommu-debug-pagealloc.c +++ b/drivers/iommu/iommu-debug-pagealloc.c @@ -9,6 +9,7 @@ #include #include #include +#include =20 #include "iommu-priv.h" =20 @@ -75,6 +76,28 @@ static size_t iommu_debug_page_size(struct iommu_domain = *domain) return 1UL << __ffs(domain->pgsize_bitmap); } =20 +static bool iommu_debug_page_count(const struct page *page) +{ + unsigned int ref; + struct page_ext *page_ext =3D page_ext_get(page); + struct iommu_debug_metadata *d =3D get_iommu_data(page_ext); + + ref =3D atomic_read(&d->ref); + page_ext_put(page_ext); + return ref !=3D 0; +} + +void __iommu_debug_check_unmapped(const struct page *page, int numpages) +{ + while (numpages--) { + if (WARN_ON(iommu_debug_page_count(page))) { + pr_warn("iommu: Detected page leak!\n"); + dump_page_owner(page); + } + page++; + } +} + void __iommu_debug_map(struct iommu_domain *domain, phys_addr_t phys, size= _t size) { size_t off, end; diff --git a/include/linux/iommu-debug-pagealloc.h b/include/linux/iommu-de= bug-pagealloc.h index a439d6815ca1..46c3c1f70150 100644 --- a/include/linux/iommu-debug-pagealloc.h +++ b/include/linux/iommu-debug-pagealloc.h @@ -13,6 +13,20 @@ DECLARE_STATIC_KEY_FALSE(iommu_debug_initialized); =20 extern struct page_ext_operations page_iommu_debug_ops; =20 +void __iommu_debug_check_unmapped(const struct page *page, int numpages); + +static inline void iommu_debug_check_unmapped(const struct page *page, int= numpages) +{ + if (static_branch_unlikely(&iommu_debug_initialized)) + __iommu_debug_check_unmapped(page, numpages); +} + +#else +static inline void iommu_debug_check_unmapped(const struct page *page, + int numpages) +{ +} + #endif /* CONFIG_IOMMU_DEBUG_PAGEALLOC */ =20 #endif /* __LINUX_IOMMU_DEBUG_PAGEALLOC_H */ diff --git a/include/linux/mm.h b/include/linux/mm.h index 6f959d8ca4b4..32205d2a24b2 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -36,6 +36,7 @@ #include #include #include +#include =20 struct mempolicy; struct anon_vma; @@ -4133,12 +4134,16 @@ extern void __kernel_map_pages(struct page *page, i= nt numpages, int enable); #ifdef CONFIG_DEBUG_PAGEALLOC static inline void debug_pagealloc_map_pages(struct page *page, int numpag= es) { + iommu_debug_check_unmapped(page, numpages); + if (debug_pagealloc_enabled_static()) __kernel_map_pages(page, numpages, 1); } =20 static inline void debug_pagealloc_unmap_pages(struct page *page, int nump= ages) { + iommu_debug_check_unmapped(page, numpages); + if (debug_pagealloc_enabled_static()) __kernel_map_pages(page, numpages, 0); } --=20 2.52.0.457.g6b5491de43-goog