You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

dma_alloc_coherent分配内存经mmap映射到用户空间在5.14内核出现异常的问题

dma_alloc_coherent分配内存经mmap映射到用户空间在5.14内核出现异常的问题

碰到过类似的内核版本差异导致的映射问题,给你梳理几个大概率的排查方向和解决思路:

可能的核心原因与排查步骤

1. 内存页权限与映射标志的变化

5.14内核对用户空间内存映射的权限校验比4.18更严格,你可以先检查mmap处理逻辑里的页保护属性和VM标志:

  • 确认在调用remap_pfn_range前,有没有给vma->vm_page_prot设置正确的权限,比如用pgprot_readwrite结合pgprot_noncached(DMA内存通常需要非缓存属性);
  • 必须加上VM_SHARED标志,否则用户空间和内核空间的内存不会同步,你看到的0xFFFFFF大概率是未同步的缓存脏数据或者默认的填充值;
  • 建议同时加上VM_IO | VM_DONTEXPAND | VM_DONTDUMP这类针对设备内存的标志,避免内核对这块内存做不必要的优化或回收。

2. DMA内存地址的处理方式差异

4.18里直接用virt_to_phys转虚拟地址为物理地址再算PFN的方式,在5.14可能不再可靠:

  • 优先用virt_to_pfn直接从dma_alloc_coherent返回的虚拟地址获取页帧号,而不是自己算phys >> PAGE_SHIFT;
  • 如果是用dma_alloc_coherent返回的dma_addr_t(DMA总线地址),要改用dma_to_pfn来转换,5.14内核对DMA地址的管理逻辑有调整,直接转物理地址可能拿到错误的PFN。

3. 缓存一致性问题

DMA内存的缓存策略在5.14内核有调整,默认的缓存属性可能导致用户空间读不到内核写入的数据:

  • 在内核写入DMA内存后,显式调用dma_wmb()(写内存屏障)确保数据刷到内存;
  • 在用户空间读取前,内核侧可以调用flush_dcache_page()刷新对应页的缓存,或者在mmap时直接设置非缓存属性从根源避免一致性问题。

4. 内核日志的隐藏线索

别漏了看dmesg输出,5.14内核会输出很多之前4.18不会打印的调试信息,比如页权限不足、映射时的页表项错误,这些信息能直接定位问题。

修正后的示例代码片段

给你一个调整后的mmap处理函数参考,适配5.14内核的要求:

static int my_drv_mmap(struct file *filp, struct vm_area_struct *vma)
{
    struct my_drv_data *drv_data = filp->private_data;
    unsigned long pfn;
    unsigned long map_size = vma->vm_end - vma->vm_start;

    // 校验映射大小不超过分配的DMA内存
    if (map_size > drv_data->dma_buf_size) {
        pr_err("mmap size exceed allocated DMA buffer\n");
        return -EINVAL;
    }

    // 从DMA虚拟地址获取正确的PFN
    pfn = virt_to_pfn(drv_data->dma_virt_addr);

    // 设置非缓存的可读可写页保护
    vma->vm_page_prot = pgprot_noncached(pgprot_readwrite(vma->vm_page_prot));
    // 加上必要的VM标志
    vma->vm_flags |= VM_SHARED | VM_IO | VM_DONTEXPAND | VM_DONTDUMP;

    // 执行映射
    if (remap_pfn_range(vma, vma->vm_start, pfn, map_size, vma->vm_page_prot)) {
        pr_err("remap_pfn_range failed for DMA buffer\n");
        return -EAGAIN;
    }

    return 0;
}

快速验证方法

先在内核里往DMA内存写入一段测试数据(比如0x12345678),然后直接读取内核虚拟地址确认数据正确,排除是dma_alloc_coherent本身的问题;再通过mmap到用户空间读取,如果还是读不到,就肯定是映射逻辑的权限或地址转换问题。

备注:内容来源于stack exchange,提问作者Michele

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 16:18:05