From nobody Sun Feb 8 20:00:13 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