本文介绍了如果我只有设备缓冲区 (PCIe) 的物理地址,如何将此缓冲区映射到用户空间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我只有通过 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) 的物理地址,如何将此缓冲区映射到用户空间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 07:26
查看更多