drivers/iommu/iova.c
Source file repositories/reference/linux-study-clean/drivers/iommu/iova.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/iommu/iova.c- Extension
.c- Size
- 26476 bytes
- Lines
- 1011
- Domain
- Driver Families
- Bucket
- drivers/iommu
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration 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.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/iova.hlinux/kmemleak.hlinux/module.hlinux/slab.hlinux/smp.hlinux/bitops.hlinux/cpu.hlinux/workqueue.h
Detected Declarations
struct iova_magazinestruct iova_cpu_rcachestruct iova_rcachefunction init_iova_domainfunction __get_cached_rbnodefunction __cached_rbnode_insert_updatefunction __cached_rbnode_delete_updatefunction iova_insert_rbtreefunction __alloc_and_insert_iova_rangefunction free_iova_memfunction roundup_power_of_twofunction private_find_iovafunction remove_iovafunction __free_iovafunction free_iovafunction alloc_iova_fastfunction free_iovafunction iova_domain_free_rcachesfunction put_iova_domainfunction __is_range_overlapfunction alloc_and_init_iovafunction __insert_new_rangefunction __adjust_overlap_rangefunction reserve_iovafunction iova_rcache_rangefunction iova_magazine_freefunction iova_magazine_free_pfnsfunction iova_magazine_fullfunction iova_magazine_emptyfunction iova_magazine_popfunction iova_magazine_pushfunction iova_depot_pushfunction iova_depot_work_funcfunction iova_domain_init_rcachesfunction for_each_possible_cpufunction __iova_rcache_insertfunction iova_rcache_insertfunction __iova_rcache_getfunction iova_rcache_getfunction free_iova_rcachesfunction for_each_possible_cpufunction cpufunction free_global_cached_iovasfunction iova_cpuhp_deadfunction iova_cache_getfunction iova_cache_putexport init_iova_domainexport alloc_iova
Annotated Snippet
struct iova_magazine {
union {
unsigned long size;
struct iova_magazine *next;
};
unsigned long pfns[IOVA_MAG_SIZE];
};
static_assert(!(sizeof(struct iova_magazine) & (sizeof(struct iova_magazine) - 1)));
struct iova_cpu_rcache {
spinlock_t lock;
struct iova_magazine *loaded;
struct iova_magazine *prev;
};
struct iova_rcache {
spinlock_t lock;
unsigned int depot_size;
struct iova_magazine *depot;
struct iova_cpu_rcache __percpu *cpu_rcaches;
struct iova_domain *iovad;
struct delayed_work work;
};
static struct kmem_cache *iova_magazine_cache;
unsigned long iova_rcache_range(void)
{
return PAGE_SIZE << (IOVA_RANGE_CACHE_MAX_SIZE - 1);
}
static struct iova_magazine *iova_magazine_alloc(gfp_t flags)
{
struct iova_magazine *mag;
mag = kmem_cache_alloc(iova_magazine_cache, flags);
if (mag)
mag->size = 0;
return mag;
}
static void iova_magazine_free(struct iova_magazine *mag)
{
if (mag)
kmem_cache_free(iova_magazine_cache, mag);
}
static void
iova_magazine_free_pfns(struct iova_magazine *mag, struct iova_domain *iovad)
{
unsigned long flags;
int i;
spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
for (i = 0 ; i < mag->size; ++i) {
struct iova *iova = private_find_iova(iovad, mag->pfns[i]);
if (WARN_ON(!iova))
continue;
remove_iova(iovad, iova);
free_iova_mem(iova);
}
spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
mag->size = 0;
}
static bool iova_magazine_full(struct iova_magazine *mag)
{
return mag->size == IOVA_MAG_SIZE;
}
static bool iova_magazine_empty(struct iova_magazine *mag)
{
return mag->size == 0;
}
static unsigned long iova_magazine_pop(struct iova_magazine *mag,
unsigned long limit_pfn)
{
int i;
unsigned long pfn;
/* Only fall back to the rbtree if we have no suitable pfns at all */
for (i = mag->size - 1; mag->pfns[i] > limit_pfn; i--)
if (i == 0)
Annotation
- Immediate include surface: `linux/iova.h`, `linux/kmemleak.h`, `linux/module.h`, `linux/slab.h`, `linux/smp.h`, `linux/bitops.h`, `linux/cpu.h`, `linux/workqueue.h`.
- Detected declarations: `struct iova_magazine`, `struct iova_cpu_rcache`, `struct iova_rcache`, `function init_iova_domain`, `function __get_cached_rbnode`, `function __cached_rbnode_insert_update`, `function __cached_rbnode_delete_update`, `function iova_insert_rbtree`, `function __alloc_and_insert_iova_range`, `function free_iova_mem`.
- Atlas domain: Driver Families / drivers/iommu.
- Implementation status: integration 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.