drivers/iommu/iommu-debug-pagealloc.c
Source file repositories/reference/linux-study-clean/drivers/iommu/iommu-debug-pagealloc.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/iommu/iommu-debug-pagealloc.c- Extension
.c- Size
- 4062 bytes
- Lines
- 165
- Domain
- Driver Families
- Bucket
- drivers/iommu
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/atomic.hlinux/iommu.hlinux/iommu-debug-pagealloc.hlinux/kernel.hlinux/page_ext.hlinux/page_owner.hiommu-priv.h
Detected Declarations
struct iommu_debug_metadatafunction need_iommu_debugfunction iommu_debug_inc_pagefunction iommu_debug_dec_pagefunction iommu_debug_page_sizefunction iommu_debug_page_countfunction __iommu_debug_check_unmappedfunction __iommu_debug_mapfunction __iommu_debug_update_iovafunction __iommu_debug_unmap_beginfunction __iommu_debug_unmap_endfunction iommu_debug_initfunction iommu_debug_pagealloc
Annotated Snippet
struct iommu_debug_metadata {
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_metadata),
.need = need_iommu_debug,
};
static struct iommu_debug_metadata *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 = page_ext_from_phys(phys);
struct iommu_debug_metadata *d;
if (!page_ext)
return;
d = get_iommu_data(page_ext);
WARN_ON(atomic_inc_return_relaxed(&d->ref) <= 0);
page_ext_put(page_ext);
}
static void iommu_debug_dec_page(phys_addr_t phys)
{
struct page_ext *page_ext = page_ext_from_phys(phys);
struct iommu_debug_metadata *d;
if (!page_ext)
return;
d = 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);
}
static bool iommu_debug_page_count(const struct page *page)
{
unsigned int ref;
struct page_ext *page_ext = page_ext_get(page);
struct iommu_debug_metadata *d = get_iommu_data(page_ext);
ref = atomic_read(&d->ref);
page_ext_put(page_ext);
return ref != 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;
size_t page_size = iommu_debug_page_size(domain);
if (WARN_ON(!phys || check_add_overflow(phys, size, &end)))
return;
for (off = 0 ; off < size ; off += page_size)
iommu_debug_inc_page(phys + off);
Annotation
- Immediate include surface: `linux/atomic.h`, `linux/iommu.h`, `linux/iommu-debug-pagealloc.h`, `linux/kernel.h`, `linux/page_ext.h`, `linux/page_owner.h`, `iommu-priv.h`.
- Detected declarations: `struct iommu_debug_metadata`, `function need_iommu_debug`, `function iommu_debug_inc_page`, `function iommu_debug_dec_page`, `function iommu_debug_page_size`, `function iommu_debug_page_count`, `function __iommu_debug_check_unmapped`, `function __iommu_debug_map`, `function __iommu_debug_update_iova`, `function __iommu_debug_unmap_begin`.
- Atlas domain: Driver Families / drivers/iommu.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.