webdevqa.jp.net

PCIeのベースアドレスレジスタ(BAR)とは何ですか?

私が理解した基本的なドキュメントをいくつか読んだ後、ベースアドレスレジスタはPCIe IPからアクセスできるアドレス空間です。 PCIe IPは、ベースアドレスレジスタでデータを送信するか、受信したデータを書き込むことができます。

私は正しいですか?または何か不足していますか?

15
tollin jose

これは非常に基本的な質問だと思うので、読むことをお勧めします。

ベースアドレスレジスタ(BAR)は次の目的で使用されます。
-デバイスがメインメモリにマップするメモリの量を指定します。
-デバイス列挙後、マップされたメモリブロックが始まる(ベース)アドレスを保持します。

デバイスは、最大6個の32ビットBARを持つか、2つのBARを組み合わせて64ビットBARにすることができます。

10
Paebbels

Linuxカーネルの観点

何かを学ぶ良い方法は、それと対話することです。そのためにLinuxカーネルを使用しましょう。

QEMUエミュレートデバイスでの最小限のPCIの例を次に示します: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/366b1c1af269f56d6a7e6464f2862ba2bc368062/kernel_module/pci.c

PCI構成の最初の64バイトは、次のように標準化されています。

enter image description here

LDD3からの画像。

したがって、6つのBARがあることがわかります。 wikiページ は各BARのコンテンツを表示します:

enter image description here

ただし、領域の幅にはマジックライトが必要です: PCI/PCIe BARサイズはどのように決定されますか?

このメモリはPCIデバイスによって設定され、カーネルに情報を提供します。

各BARは、PCIデバイスへの個別の通信チャネルとして機能するアドレス範囲に対応しています。

各領域の長さはハードウェアによって定義され、構成レジスタを介してソフトウェアに伝達されます。

各領域には、長さ、特にメモリタイプに加えて、ハードウェアで定義されたプロパティもあります。

  • IORESOURCE_IOinXおよびoutXでアクセスする必要があります
  • IORESOURCE_MEMioreadXおよびiowriteXでアクセスする必要があります

いくつかのLinuxカーネルPCI関数は、BARをパラメーターとして使用して、使用する通信チャネルを識別します。例:

mmio = pci_iomap(pdev, BAR, pci_resource_len(pdev, BAR));
pci_resource_flags(dev, BAR);
pci_resource_start(pdev, BAR);
pci_resource_end(pdev, BAR);

QEMUデバイスのソースコードを調べると、QEMUデバイスがこれらの領域を次のように登録していることがわかります。

memory_region_init_io(&edu->mmio, OBJECT(edu), &edu_mmio_ops, edu,
                "edu-mmio", 1 << 20);
pci_register_bar(pdev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &edu->mmio);

そして、BARのプロパティがハードウェアで定義されていることは明らかです。 BAR番号0、タイプメモリPCI_BASE_ADDRESS_SPACE_MEMORY、およびメモリ領域は1MiBの長さ1 << 20

参照: http://wiki.osdev.org/PCI#Base_Address_Registers もちろん。