arch/sparc/mm/iommu.c
Source file repositories/reference/linux-study-clean/arch/sparc/mm/iommu.c
File Facts
- System
- Linux kernel
- Corpus path
arch/sparc/mm/iommu.c- Extension
.c- Size
- 12610 bytes
- Lines
- 458
- Domain
- Architecture Layer
- Bucket
- arch/sparc
- 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.
- 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/kernel.hlinux/init.hlinux/mm.hlinux/slab.hlinux/dma-map-ops.hlinux/of.hlinux/of_platform.hlinux/platform_device.hasm/io.hasm/mxcc.hasm/mbus.hasm/cacheflush.hasm/tlbflush.hasm/bitext.hasm/iommu.hasm/dma.hmm_32.h
Detected Declarations
function sbus_iommu_initfunction iommu_initfunction for_each_node_by_namefunction iommu_flush_iotlbfunction __sbus_iommu_map_physfunction sbus_iommu_map_phys_gflushfunction sbus_iommu_map_phys_pflushfunction __sbus_iommu_map_sgfunction for_each_sgfunction sbus_iommu_map_sg_gflushfunction sbus_iommu_map_sg_pflushfunction sbus_iommu_unmap_physfunction sbus_iommu_unmap_sgfunction for_each_sgfunction sbus_iommu_freefunction ld_mmu_iommumodule init iommu_init
Annotated Snippet
subsys_initcall(iommu_init);
/* Flush the iotlb entries to ram. */
/* This could be better if we didn't have to flush whole pages. */
static void iommu_flush_iotlb(iopte_t *iopte, unsigned int niopte)
{
unsigned long start;
unsigned long end;
start = (unsigned long)iopte;
end = PAGE_ALIGN(start + niopte*sizeof(iopte_t));
start &= PAGE_MASK;
if (viking_mxcc_present) {
while(start < end) {
viking_mxcc_flush_page(start);
start += PAGE_SIZE;
}
} else if (viking_flush) {
while(start < end) {
viking_flush_page(start);
start += PAGE_SIZE;
}
} else {
while(start < end) {
__flush_page_to_ram(start);
start += PAGE_SIZE;
}
}
}
static dma_addr_t __sbus_iommu_map_phys(struct device *dev, phys_addr_t paddr,
size_t len, bool per_page_flush, unsigned long attrs)
{
struct iommu_struct *iommu = dev->archdata.iommu;
unsigned long off = offset_in_page(paddr);
unsigned long npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
unsigned long pfn = __phys_to_pfn(paddr);
unsigned int busa, busa0;
iopte_t *iopte, *iopte0;
int ioptex, i;
if (unlikely(attrs & DMA_ATTR_MMIO))
return DMA_MAPPING_ERROR;
/* XXX So what is maxphys for us and how do drivers know it? */
if (!len || len > 256 * 1024)
return DMA_MAPPING_ERROR;
/*
* We expect unmapped highmem pages to be not in the cache.
* XXX Is this a good assumption?
* XXX What if someone else unmaps it here and races us?
*/
if (per_page_flush && !PhysHighMem(paddr)) {
unsigned long vaddr, p;
vaddr = (unsigned long)phys_to_virt(paddr);
for (p = vaddr & PAGE_MASK; p < vaddr + len; p += PAGE_SIZE)
flush_page_for_dma(p);
}
/* page color = pfn of page */
ioptex = bit_map_string_get(&iommu->usemap, npages, pfn);
if (ioptex < 0)
panic("iommu out");
busa0 = iommu->start + (ioptex << PAGE_SHIFT);
iopte0 = &iommu->page_table[ioptex];
busa = busa0;
iopte = iopte0;
for (i = 0; i < npages; i++) {
iopte_val(*iopte) = MKIOPTE(pfn, IOPERM);
iommu_invalidate_page(iommu->regs, busa);
busa += PAGE_SIZE;
iopte++;
pfn++;
}
iommu_flush_iotlb(iopte0, npages);
return busa0 + off;
}
static dma_addr_t sbus_iommu_map_phys_gflush(struct device *dev,
phys_addr_t phys, size_t len, enum dma_data_direction dir,
unsigned long attrs)
{
flush_page_for_dma(0);
return __sbus_iommu_map_phys(dev, phys, len, false, attrs);
}
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/init.h`, `linux/mm.h`, `linux/slab.h`, `linux/dma-map-ops.h`, `linux/of.h`, `linux/of_platform.h`, `linux/platform_device.h`.
- Detected declarations: `function sbus_iommu_init`, `function iommu_init`, `function for_each_node_by_name`, `function iommu_flush_iotlb`, `function __sbus_iommu_map_phys`, `function sbus_iommu_map_phys_gflush`, `function sbus_iommu_map_phys_pflush`, `function __sbus_iommu_map_sg`, `function for_each_sg`, `function sbus_iommu_map_sg_gflush`.
- Atlas domain: Architecture Layer / arch/sparc.
- Implementation status: integration 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.