我准备了一个在 ARM Intel Cyclone V SoC 上运行的应用程序。 我需要将 DMA 相干内存缓冲区映射到用户空间。 缓冲区在设备驱动程序中分配:
buf_addr = dmam_alloc_coherent(&pdev->dev, size, &dma_addr, GFP_KERNEL);
映射正确完成,并且我已经验证,硬件通过 dma_addr 硬件地址访问的缓冲区对于内核通过 buf_addr 指针是可见的。
然后在我做的设备驱动的mmap函数中:
unsigned long physical = virt_to_phys(buf_addr);
unsigned long vsize = vma->vm_end - vma->vm_start;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
remap_pfn_range(vma,vma->vm_start, physical >> PAGE_SHIFT , vsize, vma->vm_page_prot);
应用程序映射缓冲区:
buf = mmap(NULL,buf_size,PROT_READ | PROT_WRITE, dev_file, MAP_SHARED);
我没有从 remap_pfn_range 函数中得到任何错误。此外,应用程序能够访问映射内存,但它不是使用 dmam_alloc_coherent 分配的缓冲区。
最佳答案
我找到了宏 dma_mmap_coherent这似乎是专门为此目的而设的。 我已验证 mmap 函数中的以下修改可确保正常运行:
unsigned long vsize = vma->vm_end - vma->vm_start;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
remap=dma_mmap_coherent(&my_pdev->dev,vma,fdata, dma_addr, vsize);
因为 pdev 指针没有直接传递给 mmap 函数,它是通过全局变量 my_pdev 从探测函数传递过来的。如果驱动程序支持多个设备,则应将其存储在设备上下文中。
关于linux - 通过 remap_pfn_range 将 dmam_alloc_coherent 分配的内存映射到用户空间会给出指向错误内存区域的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53995151/