IOMMU配置过程

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_READIOMMU_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,并设置权限位(读/写/缓存等)。
(4) 错误处理与回滚

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值