qcom camera smmu 学习(3)

  iommu_dma_alloc_iova 已经成功获取到了虚拟地址,iommu_map_sg 将把虚拟地址和物理散列表中的物理地址进行映射。 iommu_map_sg 在4.19 以后的内核这个接口已经删除了
    
 

size_t iommu_map_sg(struct iommu_domain *domain,
                  unsigned long iova, struct scatterlist *sg,
                  unsigned int nents, int prot)
{
    size_t mapped;
 
    mapped = domain->ops->map_sg(domain, iova, sg, nents, prot);
    trace_map_sg(domain, iova, mapped, prot);
    return mapped;
}

map_sg 调用的是arm_smmu_ops 中的arm_smmu_map_sg 其中又调用了 smmu_domain->pgtbl_ops。 smmu_domain 的初始化是在arm_smmu_master_alloc_smes 函数一步步调用完成的,参考文章https://blog.csdn.net/qq_28637193/article/details/103551684

arm_smmu_master_alloc_smes->iommu_group_get_for_dev->iommu_group_add_device->__iommu_attach_device->(domain->ops->attach_dev)->arm_smmu_attach_dev->arm_smmu_init_domain_context->
alloc_io_pgtable_ops->io_pgtable_init_table

io_pgtable_init_table 选择了不同的api 版本,以io_pgtable_arm_64_lpae_s2_init_fns 为例子分析

io_pgtable_arm_64_lpae_s2_init_fns->arm_64_lpae_alloc_pgtable_s2->arm_lpae_alloc_pgtable-> arm_lpae_map_sg


static struct arm_lpae_io_pgtable *
arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg)
{
    unsigned long va_bits, pgd_bits;
    struct arm_lpae_io_pgtable *data;
 
    arm_lpae_restrict_pgsizes(cfg);
 
    if (!(cfg->pgsize_bitmap & (SZ_4K | SZ_16K | SZ_64K)))
        return NULL;
 
    if (cfg->ias > ARM_LPAE_MAX_ADDR_BITS)
        return NULL;
 
    if (cfg->oas > ARM_LPAE_MAX_ADDR_BITS)
        return NULL;
 
    if (!selftest_running && cfg->iommu_dev->dma_pfn_offset) {
        dev_err(cfg->iommu_dev, "Cannot accommodate DMA offset for IOMMU page tables\n");
        return NULL;
    }
 
    data = kmalloc(sizeof(*data), GFP_KERNEL);
    if (!data)
        return NULL;
 
    data->pg_shift = __ffs(cfg->pgsize_bitmap);
    data->bits_per_level = data->pg_shift - ilog2(sizeof(arm_lpae_iopte));
 
    va_bits = cfg->ias - data->pg_shift;
    data->levels = DIV_ROUND_UP(va_bits, data->bits_per_level);
 
    /* Calculate the actual size of our pgd (without concatenation) */
    pgd_bits = va_bits - (data->bits_per_level * (data->levels - 1));
    data->pgd_bits = pgd_bits;
    data->pgd_size = 1UL << (pgd_bits + ilog2(sizeof(arm_lpae_iopte)));
 
    data->iop.ops = (struct io_pgtable_ops) {
        .map        = arm_lpae_map,
        .map_sg        = arm_lpae_map_sg,
        .unmap        = arm_lpae_unmap,
        .iova_to_phys    = arm_lpae_iova_to_phys,
        .is_iova_coherent = arm_lpae_is_iova_coherent,
        .iova_to_pte    = arm_lpae_iova_get_pte,
    };
 
    return data;
}

在往下是pte 是初始化相关,与arm smmu 体系结构相关。

你可能感兴趣的:(arm,android,linux)