arch/powerpc/mm/book3s64/iommu_api.c
Source file repositories/reference/linux-study-clean/arch/powerpc/mm/book3s64/iommu_api.c
File Facts
- System
- Linux kernel
- Corpus path
arch/powerpc/mm/book3s64/iommu_api.c- Extension
.c- Size
- 9405 bytes
- Lines
- 403
- Domain
- Architecture Layer
- Bucket
- arch/powerpc
- Inferred role
- Architecture Layer: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- 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/sched/signal.hlinux/slab.hlinux/rculist.hlinux/vmalloc.hlinux/mutex.hlinux/migrate.hlinux/hugetlb.hlinux/swap.hlinux/sizes.hlinux/mm.hasm/mmu_context.hasm/pte-walk.hlinux/mm_inline.h
Detected Declarations
struct mm_iommu_table_group_mem_tfunction mm_iommu_preregisteredfunction mm_iommu_do_allocfunction list_for_each_entry_rcufunction mm_iommu_newfunction mm_iommu_newdevfunction mm_iommu_unpinfunction mm_iommu_do_freefunction mm_iommu_freefunction mm_iommu_releasefunction mm_iommu_putfunction list_for_each_entry_rcufunction mm_iommu_ua_to_hpafunction mm_iommu_is_devmemfunction mm_iommu_mapped_incfunction mm_iommu_mapped_decfunction mm_iommu_initexport mm_iommu_preregisteredexport mm_iommu_newexport mm_iommu_newdevexport mm_iommu_putexport mm_iommu_lookupexport mm_iommu_getexport mm_iommu_ua_to_hpaexport mm_iommu_is_devmemexport mm_iommu_mapped_incexport mm_iommu_mapped_dec
Annotated Snippet
struct mm_iommu_table_group_mem_t {
struct list_head next;
struct rcu_head rcu;
unsigned long used;
atomic64_t mapped;
unsigned int pageshift;
u64 ua; /* userspace address */
u64 entries; /* number of entries in hpas/hpages[] */
/*
* in mm_iommu_get we temporarily use this to store
* struct page address.
*
* We need to convert ua to hpa in real mode. Make it
* simpler by storing physical address.
*/
union {
struct page **hpages; /* vmalloc'ed */
phys_addr_t *hpas;
};
#define MM_IOMMU_TABLE_INVALID_HPA ((uint64_t)-1)
u64 dev_hpa; /* Device memory base address */
};
bool mm_iommu_preregistered(struct mm_struct *mm)
{
return !list_empty(&mm->context.iommu_group_mem_list);
}
EXPORT_SYMBOL_GPL(mm_iommu_preregistered);
static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua,
unsigned long entries, unsigned long dev_hpa,
struct mm_iommu_table_group_mem_t **pmem)
{
struct mm_iommu_table_group_mem_t *mem, *mem2;
long i, ret, locked_entries = 0, pinned = 0;
unsigned int pageshift;
unsigned long entry, chunk;
if (dev_hpa == MM_IOMMU_TABLE_INVALID_HPA) {
ret = account_locked_vm(mm, entries, true);
if (ret)
return ret;
locked_entries = entries;
}
mem = kzalloc_obj(*mem);
if (!mem) {
ret = -ENOMEM;
goto unlock_exit;
}
if (dev_hpa != MM_IOMMU_TABLE_INVALID_HPA) {
mem->pageshift = __ffs(dev_hpa | (entries << PAGE_SHIFT));
mem->dev_hpa = dev_hpa;
goto good_exit;
}
mem->dev_hpa = MM_IOMMU_TABLE_INVALID_HPA;
/*
* For a starting point for a maximum page size calculation
* we use @ua and @entries natural alignment to allow IOMMU pages
* smaller than huge pages but still bigger than PAGE_SIZE.
*/
mem->pageshift = __ffs(ua | (entries << PAGE_SHIFT));
mem->hpas = vzalloc(array_size(entries, sizeof(mem->hpas[0])));
if (!mem->hpas) {
kfree(mem);
ret = -ENOMEM;
goto unlock_exit;
}
mmap_read_lock(mm);
chunk = (1UL << (PAGE_SHIFT + MAX_PAGE_ORDER)) /
sizeof(struct vm_area_struct *);
chunk = min(chunk, entries);
for (entry = 0; entry < entries; entry += chunk) {
unsigned long n = min(entries - entry, chunk);
ret = pin_user_pages(ua + (entry << PAGE_SHIFT), n,
FOLL_WRITE | FOLL_LONGTERM,
mem->hpages + entry);
if (ret == n) {
pinned += n;
continue;
}
if (ret > 0)
pinned += ret;
break;
}
Annotation
- Immediate include surface: `linux/sched/signal.h`, `linux/slab.h`, `linux/rculist.h`, `linux/vmalloc.h`, `linux/mutex.h`, `linux/migrate.h`, `linux/hugetlb.h`, `linux/swap.h`.
- Detected declarations: `struct mm_iommu_table_group_mem_t`, `function mm_iommu_preregistered`, `function mm_iommu_do_alloc`, `function list_for_each_entry_rcu`, `function mm_iommu_new`, `function mm_iommu_newdev`, `function mm_iommu_unpin`, `function mm_iommu_do_free`, `function mm_iommu_free`, `function mm_iommu_release`.
- Atlas domain: Architecture Layer / arch/powerpc.
- 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.