Linux 5.4.233 内核中 iommu_map 函数实现深度分析
iommu_map 是 Linux 内核中用于建立 IOVA(I/O 虚拟地址)到物理地址映射 的核心函数,其实现涉及 IOMMU 硬件操作、页表管理和内存保护机制。以下基于 5.4.233 内核源码进行详细解析:
1. 函数定义与参数
函数位于 drivers/iommu/iommu.c:
int iommu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot)
- domain:IOMMU 域,包含硬件特定的页表信息。
- iova:设备使用的虚拟地址起始位置。
- paddr:物理地址起始位置。
- size:映射的内存区域大小。
- prot:保护标志(如
IOMMU_READ、IOMMU_WRITE)。
2. 实现流程分析
(1) 参数合法性校验
if (!domain || !domain->ops->map)
return -EINVAL;
if (size & ~PAGE_MASK)
return -EINVAL; // 检查 size 是否页对齐
- 确保
domain有效且支持映射操作。 - 映射大小必须是页对齐的(4KB/2MB/1GB)。
(2) 计算页表粒度和映射次数
size_t mapped = 0;
while (mapped < size) {
// 尝试以最大支持的页大小(如 1GB)进行映射
size_t pgsize = iommu_pgsize(domain, paddr, iova, size - mapped);
// 调用具体 IOMMU 驱动的 map 方法
ret = domain->ops->map(domain, iova + mapped, paddr + mapped,
pgsize, prot);
if (ret)
break;
mapped += pgsize;
}
- 页粒度选择:通过
iommu_pgsize()选择当前硬件支持的最大页大小(优化页表项数量)。 - 循环映射:若映射失败(如部分区域已被占用),则尝试更小的页粒度。
(3) 底层驱动映射操作
以 Intel IOMMU (VT-d) 为例(drivers/iommu/intel-iommu.c):
static int intel_iommu_map(...) {
// 获取页表地址
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
// 操作页表项
return __domain_mapping(dmar_domain, iova, paddr, size, prot);
}
- 页表遍历:通过多级页表(如 4 级页表)查找或创建对应的页表项。
- 更新页表项:将
iova映射到paddr,并设置权限位(读/写/缓存等)。

最低0.47元/天 解锁文章
211

被折叠的 条评论
为什么被折叠?



