在iova_domain中有一个变量granule
struct iova_domain {
spinlock_t iova_rbtree_lock; /* Lock to protect update of rbtree */
struct rb_root rbroot; /* iova domain rbtree root */
struct rb_node *cached32_node; /* Save last alloced node */
unsigned long granule; /* pfn granularity for this domain */
unsigned long start_pfn; /* Lower limit for this domain */
unsigned long dma_32bit_pfn;
struct iova_rcache rcaches[IOVA_RANGE_CACHE_MAX_SIZE]; /* IOVA range caches */
};
这个变量会在iommu_dma_init_domain 中通过init_iova_domain来赋值
首先在iommu_dma_init_domain 中得到order,__ffs 这个函数之前分析过,就
order = __ffs(domain->pgsize_bitmap);
是得到domain->pgsize_bitmap 的最低为1的为,我们以4096 为里的话,就是12.然后又1UL << order就等于4096,最后调用init_iova_domain来给granule 赋值.
init_iova_domain(iovad, 1UL << order, base_pfn, end_pfn);
init_iova_domain(struct iova_domain *iovad, unsigned long granule,
unsigned long start_pfn, unsigned long pfn_32bit)
{
/*
* IOVA granularity will normally be equal to the smallest
* supported IOMMU page size; both *must* be capable of
* representing individual CPU pages exactly.
*/
BUG_ON((granule > PAGE_SIZE) || !is_power_of_2(granule));
spin_lock_init(&iovad->iova_rbtree_lock);
iovad->rbroot = RB_ROOT;
iovad->cached32_node = NULL;
iovad->granule = granule;
iovad->start_pfn = start_pfn;
iovad->dma_32bit_pfn = pfn_32bit;
init_iova_rcaches(iovad);
}
所以这里的granule 就等于4096,也就说这个domain 最低是一个4096 对齐的.
这样我们在iommu_dma_map_page 中调用
size_t iova_off = iova_offset(iovad, phys);来计算iova_off的时候起始就是让phys以granule 对齐
static inline size_t iova_offset(struct iova_domain *iovad, dma_addr_t iova)
{
return iova & iova_mask(iovad);
}
static inline unsigned long iova_mask(struct iova_domain *iovad)
{
return iovad->granule - 1;
}
这样在调用(iommu_map(domain, dma_addr, phys - iova_off, len, prot))的时候,第三个参数paddr就表示需要映射的物理地址和这个domain 最小支持的page size的差值,一般情况下这个差值为0.因为我们通过iommu映射的时候一般都是pagesize对齐的。
如果不为0的话会在iommu_map->iommu_pgsize 中尝试合并.
最后在计算pte的时候会加上这个paddr
pte |= pfn_to_iopte(paddr >> data->pg_shift, data);
struct iova_domain {
spinlock_t iova_rbtree_lock; /* Lock to protect update of rbtree */
struct rb_root rbroot; /* iova domain rbtree root */
struct rb_node *cached32_node; /* Save last alloced node */
unsigned long granule; /* pfn granularity for this domain */
unsigned long start_pfn; /* Lower limit for this domain */
unsigned long dma_32bit_pfn;
struct iova_rcache rcaches[IOVA_RANGE_CACHE_MAX_SIZE]; /* IOVA range caches */
};
这个变量会在iommu_dma_init_domain 中通过init_iova_domain来赋值
首先在iommu_dma_init_domain 中得到order,__ffs 这个函数之前分析过,就
order = __ffs(domain->pgsize_bitmap);
是得到domain->pgsize_bitmap 的最低为1的为,我们以4096 为里的话,就是12.然后又1UL << order就等于4096,最后调用init_iova_domain来给granule 赋值.
init_iova_domain(iovad, 1UL << order, base_pfn, end_pfn);
init_iova_domain(struct iova_domain *iovad, unsigned long granule,
unsigned long start_pfn, unsigned long pfn_32bit)
{
/*
* IOVA granularity will normally be equal to the smallest
* supported IOMMU page size; both *must* be capable of
* representing individual CPU pages exactly.
*/
BUG_ON((granule > PAGE_SIZE) || !is_power_of_2(granule));
spin_lock_init(&iovad->iova_rbtree_lock);
iovad->rbroot = RB_ROOT;
iovad->cached32_node = NULL;
iovad->granule = granule;
iovad->start_pfn = start_pfn;
iovad->dma_32bit_pfn = pfn_32bit;
init_iova_rcaches(iovad);
}
所以这里的granule 就等于4096,也就说这个domain 最低是一个4096 对齐的.
这样我们在iommu_dma_map_page 中调用
size_t iova_off = iova_offset(iovad, phys);来计算iova_off的时候起始就是让phys以granule 对齐
static inline size_t iova_offset(struct iova_domain *iovad, dma_addr_t iova)
{
return iova & iova_mask(iovad);
}
static inline unsigned long iova_mask(struct iova_domain *iovad)
{
return iovad->granule - 1;
}
这样在调用(iommu_map(domain, dma_addr, phys - iova_off, len, prot))的时候,第三个参数paddr就表示需要映射的物理地址和这个domain 最小支持的page size的差值,一般情况下这个差值为0.因为我们通过iommu映射的时候一般都是pagesize对齐的。
如果不为0的话会在iommu_map->iommu_pgsize 中尝试合并.
最后在计算pte的时候会加上这个paddr
pte |= pfn_to_iopte(paddr >> data->pg_shift, data);