dma_mmap_coherent 如何和iommu联系在一起呢?

本文解析了Linux内核中dma_mmap_coherent宏的作用原理,详细介绍了如何通过该宏调用dma_map_ops来实现内存映射的过程。特别关注了在ARM64架构下,通过do_iommu_attach设置dev->archdata.dma_ops为iommu_dma_ops的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当在code中调用dma_mmap_coherent时,这是个宏
#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, 0)
在dma_mmap_attrs 中又会掉用get_dma_ops 来得到dma的ops
static inline int
dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void *cpu_addr,
           dma_addr_t dma_addr, size_t size, unsigned long attrs)
{
    struct dma_map_ops *ops = get_dma_ops(dev);
    BUG_ON(!ops);
    if (ops->mmap)
        return ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
    return dma_common_mmap(dev, vma, cpu_addr, dma_addr, size);
}
get_dma_ops 的实现如下:
static inline struct dma_map_ops *get_dma_ops(struct device *dev)
{
    if (xen_initial_domain())
        return xen_dma_ops;
    else
        return __generic_dma_ops(dev);
}
在arm64中xen_initial_domain() 肯定是返回false的,因此继续看__generic_dma_ops
static inline struct dma_map_ops *__generic_dma_ops(struct device *dev)
{
    if (dev && dev->archdata.dma_ops)
        return dev->archdata.dma_ops;

    /*
     * We expect no ISA devices, and all other DMA masters are expected to
     * have someone call arch_setup_dma_ops at device creation time.
     */
    return &dummy_dma_ops;
}
在dma_map_ops 中首先判断dev->archdata.dma_ops 是否为NULL,而dev->archdata.dma_ops是在do_iommu_attach 中赋值的,显然不为null。

static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops,
               u64 dma_base, u64 size)
{
    struct iommu_domain *domain = iommu_get_domain_for_dev(dev);

    /*
     * If the IOMMU driver has the DMA domain support that we require,
     * then the IOMMU core will have already configured a group for this
     * device, and allocated the default domain for that group.
     */
    if (!domain || iommu_dma_init_domain(domain, dma_base, size, dev)) {
        pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",
            dev_name(dev));
        return false;
    }

    dev->archdata.dma_ops = &iommu_dma_ops;
    return true;
}
注意do_iommu_attach 中返回的是iommu_dma_ops。因此当用户调用dma_mmap_coherent 来申请coherent memory时,在CONFIG_IOMMU_DMA 定义了的情况下就等于在操作iommu的ops.
<think>好的,我现在需要回答用户在ARM64平台上使用dma_alloc_coherentdma_mmap_coherent映射的内存是否经过CPU缓存的问题。首先,我得回忆一下这两个函数的作用它们在内核中的实现机制。用户提到的dma_alloc_coherent函数,根据引用[1][4],它用于分配一致性DMA内存,这种内存的特点是CPU设备访问时不需要担心缓存一致性问题。也就是说,这种内存应该是非缓存的,或者内核会自动处理缓存同步。在ARM64架构中,通常DMA一致性内存会被映射到非缓存(Non-cacheable)或写合并(Write-combining)的内存区域,这样CPU访问时不会使用缓存,从而避免缓存一致性问题。接下来是dma_mmap_coherent函数,这个函数的作用是将DMA内存映射到用户空间。我需要确认当使用这个函数映射后,用户空间访问这段内存时是否经过CPU缓存。根据之前的理解,dma_alloc_coherent分配的内存已经是非缓存的,所以通过dma_mmap_coherent映射到用户空间后,用户空间的访问也应该直接操作物理内存,不经过缓存。但需要确认ARM64的具体实现是否有例外情况。 另外,引用[2]提到dma_alloc_coherent返回的虚拟地址是给CPU访问的,并且是非缓存的。这说明CPU在通过这个虚拟地址访问内存时,不会使用缓存,因此读写都是直接对内存进行操作,确保设备读取的数据是最新的,反之亦然。还有引用[3]提到的CMA(Contiguous MemoryAllocator)配置,可能影响dma_alloc_coherent的内存来源。但无论是否使用CMA,关键点在于内存的属性是否为非缓存。ARM64架构中,DMA一致性内存通常会被设置为Non-cacheable,这由页表属性决定,比如使用特定的内存类型如Device或NormalNon-cacheable。 此外,需要区分dma_alloc_coherent流式DMA映射的区别。流式映射(如dma_map_single)可能需要显式刷新缓存,而一致性映射则不需要,因为其内存本身是非缓存的。因此,在ARM64上,dma_alloc_coherent分配的内存无论是通过CPU还是设备访问,都不会经过缓存,保证一致性。 关于dma_mmap_coherent,这个函数在映射到用户空间时,应该保持同样的内存属性。用户空间的进程访问这段内存时,同样会绕过CPU缓存,直接访问物理内存,从而确保与设备之间的数据一致性。总结起来,ARM64平台上,这两个函数处理的内存都是非缓存的,CPU读写不会经过缓存,设备访问也是直接的。这样可以避免缓存一致性问题,确保数据传输的正确性。</think>在ARM64架构平台上,使用`dma_alloc_coherent``dma_mmap_coherent`分配及映射的内存**不会经过CPU缓存**,其读写行为直接作用于物理内存,确保设备与CPU之间的数据一致性[^1][^2][^4]。 ### 核心机制解析 1. **内存属性** `dma_alloc_coherent`分配的缓冲区会被映射为**非缓存(Non-cacheable)**或**写合并(Write-combining)**类型的内存区域。这种映射通过ARM64的页表属性(如`MT_DEVICE_nGnRnE`或`MT_NORMAL_NC`)实现,确保CPU访问时绕过缓存[^1][^4]。 2. **一致性保证** - **CPU访问**:通过返回的虚拟地址直接操作物理内存,无需缓存刷新[^2]。 - **设备访问**:DMA控制器直接读取物理内存,与CPU保持数据一致[^4]。 - **映射到用户空间**:`dma_mmap_coherent`会将相同的内存属性传递给用户空间进程,用户态代码访问时同样绕过缓存[^1][^4]。 3. **与流式DMA的对比** 流式DMA(如`dma_map_single`)需要显式调用`dma_sync_single_for_device/cpu`来同步缓存,而一致性DMA因非缓存特性无需此类操作[^1][^2]。 ### 示例代码片段 ```c // 内核驱动中分配一致性DMA内存 dma_addr_t dma_handle; void *cpu_addr = dma_alloc_coherent(dev, size, &dma_handle, GFP_KERNEL); // 映射到用户空间 int ret = dma_mmap_coherent(dev, vma, cpu_addr, dma_handle, size); ``` ### 性能影响 - **优势**:避免缓存一致性开销,适合高频次、低延迟的DMA操作。 - **劣势**:非缓存内存的访问速度可能低于缓存内存,需权衡场景需求[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值