问题描述
如果我只有通过 PCI-Express BAR(基地址寄存器)映射到设备缓冲区的内存缓冲区的物理地址,我如何将该缓冲区映射到用户空间?
If I have only the physical address of the memory buffer to which is mapped the device buffer via the PCI-Express BAR (Base Address Register), how can I map this buffer to user-space?
例如,代码在 Linux 内核中通常应该是什么样子?
For example, how does usually the code should look like in Linux-kernel?
unsigned long long phys_addr = ...; // get device phys addr
unsigned long long size_buff = ...l // get device size buff
// ... mmap(), remap_pfn_range(), Or what should I do now?
在:Linux x86_64
来自:https://stackoverflow.com/a/17278263/1558037
ioremap()
将物理地址映射到内核虚拟地址.remap_pfn_range()
将物理地址直接映射到用户空间.
来自:https://stackoverflow.com/a/9075865/1558037
int remap_pfn_range(struct vm_area_struct *vma, unsigned long virt_addr,
unsigned long pfn, unsigned long size, pgprot_t prot);
remap_pfn_range - 将内核内存重新映射到用户空间
remap_pfn_range - remap kernel memory to userspace
我可以这样使用吗?
unsigned long long phys_addr = ...; // get device phys addr
unsigned long long size_buff = ...l // get device size buff
remap_pfn_range(vma, vma->vm_start, (phys_addr >> PAGE_SHIFT),
size_buff, vma->vm_page_prot);
问题:但是,我可以从哪里获得 wma
,以及在调用 remap_pfn_range 之前我必须对
?wma
做什么()
Question: But, where can I get wma
, and what I must pre-do with wma
before call to remap_pfn_range()
?
推荐答案
Linux 内核,至少 2.6.x 版本使用 ioremap()
函数.
The Linux kernel, at least, versions 2.6.x use the ioremap()
function.
void *vaddr = ioremap (phys_addr, size_addr);
if (vaddr) {
/* do stuff with the memory using vaddr pointer */
iounmap (vaddr);
}
您应该先调用 request_mem_region()
以检查该内存空间是否已被另一个驱动程序回收,并礼貌地请求该内存归您的代码(驱动程序)所有.完整的示例应如下所示:
You should make a previous call to request_mem_region()
to check if that memory space is already reclaimed by another driver, and politely request that memory to be owned by your code (driver). The complete example should look like this:
void *vaddr;
if (request_mem_region (phys_addr, size_addr, "my_driver")) {
vaddr = ioremap (phys_addr, size_addr);
if (vaddr) {
/* do stuff with the memory */
iounmap (vaddr);
}
release_mem_region (phys_addr, size_addr);
}
您可以通过检查/proc/iomem
来检查您的所有权,这将反映您系统中每块内存的地址范围和所有者.
You can check your ownership by checking /proc/iomem
, which will reflect the address range and the owner of every piece of memory in your system.
更新:我真的不知道这是否适用于 64 位内核.它适用于 32 位.如果 64 位内核没有这些内核函数,我猜他们会有类似的.
UPDATE: I don't really know if this works for 64-bit kernels. It does for 32-bit. If 64-bit kernel don't have these kernel functions, they will have similar ones, I guess.
这篇关于如果我只有设备缓冲区 (PCIe) 的物理地址,如何将此缓冲区映射到用户空间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!