drivers/iommu/io-pgtable-arm.c
Source file repositories/reference/linux-study-clean/drivers/iommu/io-pgtable-arm.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/iommu/io-pgtable-arm.c- Extension
.c- Size
- 35755 bytes
- Lines
- 1302
- 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.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- 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/atomic.hlinux/bitops.hlinux/io-pgtable.hlinux/sizes.hlinux/slab.hlinux/types.hlinux/dma-mapping.hasm/barrier.hio-pgtable-arm.hiommu-pages.h
Detected Declarations
struct arm_lpae_io_pgtablestruct io_pgtable_walk_datastruct iova_to_phys_datafunction iopte_leaffunction iopte_tablefunction paddr_to_ioptefunction iopte_to_paddrfunction ARM_LPAE_PGD_IDXfunction DDI0487function __arm_lpae_dma_addrfunction __arm_lpae_cfg_freefunction __arm_lpae_free_pagesfunction __arm_lpae_sync_ptefunction __arm_lpae_clear_ptefunction __arm_lpae_init_ptefunction arm_lpae_init_ptefunction arm_lpae_install_tablefunction __arm_lpae_mapfunction arm_lpae_prot_to_ptefunction arm_lpae_map_pagesfunction __arm_lpae_free_pgtablefunction arm_lpae_free_pgtablefunction __arm_lpae_unmapfunction arm_lpae_unmap_pagesfunction visit_iova_to_physfunction arm_lpae_iova_to_physfunction visit_pgtable_walkfunction arm_lpae_pgtable_walkfunction io_pgtable_visitfunction __arm_lpae_iopte_walkfunction visit_dirtyfunction arm_lpae_read_and_clear_dirtyfunction arm_lpae_restrict_pgsizesfunction arm_lpae_alloc_pgtablefunction arm_64_lpae_alloc_pgtable_s1function arm_64_lpae_alloc_pgtable_s2function arm_32_lpae_alloc_pgtable_s1function arm_32_lpae_alloc_pgtable_s2function arm_mali_lpae_alloc_pgtable
Annotated Snippet
struct arm_lpae_io_pgtable {
struct io_pgtable iop;
int pgd_bits;
int start_level;
int bits_per_level;
void *pgd;
};
typedef u64 arm_lpae_iopte;
static inline bool iopte_leaf(arm_lpae_iopte pte, int lvl,
enum io_pgtable_fmt fmt)
{
if (lvl == (ARM_LPAE_MAX_LEVELS - 1) && fmt != ARM_MALI_LPAE)
return iopte_type(pte) == ARM_LPAE_PTE_TYPE_PAGE;
return iopte_type(pte) == ARM_LPAE_PTE_TYPE_BLOCK;
}
static inline bool iopte_table(arm_lpae_iopte pte, int lvl)
{
if (lvl == (ARM_LPAE_MAX_LEVELS - 1))
return false;
return iopte_type(pte) == ARM_LPAE_PTE_TYPE_TABLE;
}
static arm_lpae_iopte paddr_to_iopte(phys_addr_t paddr,
struct arm_lpae_io_pgtable *data)
{
arm_lpae_iopte pte = paddr;
/* Of the bits which overlap, either 51:48 or 15:12 are always RES0 */
return (pte | (pte >> (48 - 12))) & ARM_LPAE_PTE_ADDR_MASK;
}
static phys_addr_t iopte_to_paddr(arm_lpae_iopte pte,
struct arm_lpae_io_pgtable *data)
{
u64 paddr = pte & ARM_LPAE_PTE_ADDR_MASK;
if (ARM_LPAE_GRANULE(data) < SZ_64K)
return paddr;
/* Rotate the packed high-order bits back to the top */
return (paddr | (paddr << (48 - 12))) & (ARM_LPAE_PTE_ADDR_MASK << 4);
}
/*
* Convert an index returned by ARM_LPAE_PGD_IDX(), which can point into
* a concatenated PGD, into the maximum number of entries that can be
* mapped in the same table page.
*/
static inline int arm_lpae_max_entries(int i, struct arm_lpae_io_pgtable *data)
{
int ptes_per_table = ARM_LPAE_PTES_PER_TABLE(data);
return ptes_per_table - (i & (ptes_per_table - 1));
}
/*
* Check if concatenated PGDs are mandatory according to Arm DDI0487 (K.a)
* 1) R_DXBSH: For 16KB, and 48-bit input size, use level 1 instead of 0.
* 2) R_SRKBC: After de-ciphering the table for PA size and valid initial lookup
* a) 40 bits PA size with 4K: use level 1 instead of level 0 (2 tables for ias = oas)
* b) 40 bits PA size with 16K: use level 2 instead of level 1 (16 tables for ias = oas)
* c) 42 bits PA size with 4K: use level 1 instead of level 0 (8 tables for ias = oas)
* d) 48 bits PA size with 16K: use level 1 instead of level 0 (2 tables for ias = oas)
*/
static inline bool arm_lpae_concat_mandatory(struct io_pgtable_cfg *cfg,
struct arm_lpae_io_pgtable *data)
{
unsigned int ias = cfg->ias;
unsigned int oas = cfg->oas;
/* Covers 1 and 2.d */
if ((ARM_LPAE_GRANULE(data) == SZ_16K) && (data->start_level == 0))
return (oas == 48) || (ias == 48);
/* Covers 2.a and 2.c */
if ((ARM_LPAE_GRANULE(data) == SZ_4K) && (data->start_level == 0))
return (oas == 40) || (oas == 42);
/* Case 2.b */
return (ARM_LPAE_GRANULE(data) == SZ_16K) &&
(data->start_level == 1) && (oas == 40);
}
static dma_addr_t __arm_lpae_dma_addr(void *pages)
Annotation
- Immediate include surface: `linux/atomic.h`, `linux/bitops.h`, `linux/io-pgtable.h`, `linux/sizes.h`, `linux/slab.h`, `linux/types.h`, `linux/dma-mapping.h`, `asm/barrier.h`.
- Detected declarations: `struct arm_lpae_io_pgtable`, `struct io_pgtable_walk_data`, `struct iova_to_phys_data`, `function iopte_leaf`, `function iopte_table`, `function paddr_to_iopte`, `function iopte_to_paddr`, `function ARM_LPAE_PGD_IDX`, `function DDI0487`, `function __arm_lpae_dma_addr`.
- Atlas domain: Driver Families / drivers/iommu.
- Implementation status: source implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
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.