0

如果我只有通过 PCI-Express BAR(基地址寄存器)将设备缓冲区映射到的内存缓冲区的物理地址,我如何将此缓冲区映射到用户空间

例如,通常代码在 Linux 内核中应该是什么样子的?

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 - 将内核内存重新映射到用户空间

可能我可以这样用吗?

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我必须做些什么?wmaremap_pfn_range()

4

2 回答 2

2

映射 PCI 资源取决于架构。

BAR 已经通过 sysfs 文件提供给用户空间/sys/bus/pci/devices/*/resource*,支持mmap.

pci_mmap_resource这是由in函数实现的drivers/pci/pci-sysfs.c,最终调用pci_mmap_page_range.

于 2013-11-30T11:36:41.563 回答
1

Linux 内核,至少 2.6.x 版本使用该ioremap()功能。

void *vaddr = ioremap (phys_addr, size_addr);
if (vaddr) {
  /* do stuff with the memory using vaddr pointer */
  iounmap (vaddr);
}

您应该先调用 以request_mem_region()检查该内存空间是否已被另一个驱动程序回收,并礼貌地请求该内存由您的代码(驱动程序)拥有。完整的示例应如下所示:

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,这将反映您系统中每块内存的地址范围和所有者。

更新:我真的不知道这是否适用于 64 位内核。它适用于 32 位。如果 64 位内核没有这些内核函数,我猜它们会有类似的函数。

于 2013-11-29T20:52:32.623 回答