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*をサポートする sysfs ファイルを使用して、ユーザー空間で既に利用可能です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 に答える