拱= x86_64的
按照此问题中列出的流程,我正在使用DMA解决方案, Direct Memory Access in Linux
我对ioremap
的呼叫成功返回地址,pt。
在致remap_pfn_range
的电话中,我使用virt_to_phys(pt) >> PAGE_SHIFT
来指定ioremap
电话生成的区域的pfn。
当执行使用mmap
的用户空间应用程序并调用remap_pfn_range
时,计算机崩溃。我假设映射已关闭,我正在强制系统使用已分配的内存(退出前屏幕毛刺),但我不清楚错配发生的位置。系统有4 Gigs of Ram,我使用内核启动选项mem=2048M
保留了2Gigs。
我使用BUFFER_SIZE=1024u*1024u*1024u
和BUFFER_OFFSET=2u*1024u*1024u*1024u
。
将这些放入pt=ioremap(BUFFER_SIZE,BUFFER_OFFSET)
我相信pt应该等于位于2GB边界直到3GB边界的物理内存的虚拟地址。这个假设准确吗?
当我执行我的内核模块时,但是我将remap_pfn_range
更改为使用vma->vm_pgoff>>PAGE_SHIFT
作为目标pfn,代码执行时没有错误,我可以读取和写入内存。但是,这并没有使用我想要的保留物理内存。
由于使用vma->vm_pgoff>>PAGE_SHIFT
时一切正常,我相信我的罪魁祸首是在ioremap
和remap_pfn_range
之间
感谢您的任何建议!
使用此内核模块背后的动机是需要为PCI设备提供大量连续的DMA缓冲区。在这个应用程序中,重新编译内核不是一个选项,所以我试图用模块+硬件完成它。
答案 0 :(得分:1)
我对ioremap的调用成功返回地址,pt。
在我使用remap_pfn_range的调用中,virt_to_phys(pt)>> PAGE_SHIFT, 指定ioremap调用生成的区域的pfn。
这是非法的,因为ioremap会在vmalloc区域中保留虚拟区域。 virt_to_phys()仅适用于线性映射的内存部分。
将这些放入pt = ioremap(BUFFER_SIZE,BUFFER_OFFSET)我相信pt 应该等于虚拟地址到位于的物理内存 2GB边界直到3GB边界。这个假设准确吗?
这不完全正确,例如在我的机器上 cat / proc / iomem
...
00001000-0009ebff : System RAM
...
00100000-1fffffff : System RAM
...
可能有几个存储体,非强制存储器将从物理地址空间的地址0x0开始。
有用