PCI/PCIe Architecture Overview

PCI/PCIe architectureをfirmware視点で整理します。BDF、config space、BAR、bridge、enumeration、device missing debugを扱います。

更新 約 3 分
Đọc bằng 日本語 Tiếng Việt English
PCI cover

PCI/PCIe architectureは、firmwareがPCIe deviceを検出し、識別し、resourceを割り当て、driverへ見せるための基本モデルです。Firmware engineerにとって、PCIeは単なるスロットではありません。Root bridge、bus scan、configuration space、BAR sizing、bridge window、protocol install、driver bindingまで続く流れです。

OSからNVMe、NIC、拡張カードが見えない場合、OS driverだけが原因とは限りません。Firmware enumeration、BAR assignment、bridge window、slot依存のDevice Pathで失敗していることもあります。

短いmental model

PCIe systemは、だいたい次のように考えると読みやすいです。

CPU / SoC
└─ Root Complex
   ├─ PCI Root Bridge
   │  ├─ Root Port
   │  │  └─ Endpoint: NVMe, NIC, GPU
   │  └─ PCIe Switch
   │     ├─ Endpoint A
   │     └─ Endpoint B
   └─ Firmware PCI bus driver

Firmwareはこのtopologyをscanし、configuration spaceを読み、DXE driverが使うhandleとprotocolを作ります。

Enumerationがすること

PCI enumerationは、実務上は次の4つを決める処理です。

1. deviceはどのbus/device/functionにあるか
2. deviceは何の種類か
3. 必要なMMIOまたはI/O resourceはどれくらいか
4. どのdriverがbindできるか

典型的には、BDF scan、Vendor ID、Device ID、Class Codeの読み取り、BAR size probe、bridge bus number assignment、MMIO window allocation、EFI_PCI_IO_PROTOCOL installが行われます。

重要な用語

用語Debugで見る理由
BDFPCI functionの論理アドレス
Configuration SpaceID、BAR、capabilityを読む場所
Vendor ID / Device IDvendorと具体的なdeviceを識別する
Class Codegeneric driver matchingでdevice typeを見る
BARdeviceが要求するMMIOまたはI/O aperture
Bridge Windowbridge配下のdeviceへ割り当てるresource range
Root BridgePCI segmentへaccessするfirmware側の入口

Deviceが消える場合は、高位のdriverを疑う前に、BDFとconfiguration spaceから確認します。

UEFIではどこに出るか

EDK IIでは、PCIは主にPciHostBridgePciBusDxeEFI_PCI_ROOT_BRIDGE_IO_PROTOCOLEFI_PCI_IO_PROTOCOLに関係します。Device driverは通常、自分でbus全体をscanしません。PciIoがinstallされたcontroller handleを受け取り、Driver BindingのSupported()Start()でbindします。

そのため、PciIoがinstallされていなければ、device driverはbind対象を見つけられません。

実際の失敗例

NVMe cardを別のPCIe slotへ移動した後、bootしなくなることがあります。古いBoot####はNVRAMに残っていますが、Device Pathには古いPCI pathが入っています。Firmwareは新しいpathでcardをenumerateしますが、Boot####は古いpathを指したままです。BDSは名前だけ見ると正しいboot optionを選びますが、ConnectController()またはLoadImage()で失敗します。

このとき見るlogは次のようなものです。

- Boot####のfull Device Path
- 現在のPCI topology
- 新しいBDFでのVendor ID / Device ID
- BARとbridge windowの割り当て
- handleにEFI_PCI_IO_PROTOCOLがあるか

Source-reading checklist

[ ] root bridgeはenumerateされたか
[ ] bridge bus numberは正しいか
[ ] Vendor IDは読めるか、それとも0xFFFFか
[ ] BAR sizeは自然か
[ ] bridge windowはdownstream BARを収容できるか
[ ] EFI_PCI_IO_PROTOCOLはhandleにinstallされたか
[ ] Driver Binding Supported()は期待するClass CodeまたはIDにmatchするか
[ ] boot Device Pathは現在のtopologyと一致しているか

まとめ

PCI/PCIe architectureは、firmwareでdevice missingをdebugするための土台です。Driverを直す前に、deviceがenumerateされ、resourceを持ち、期待するhandle/protocolとして見えているかを確認します。

関連ノート

この記事が役に立ったら

ファームウェア、BIOS/UEFI、組み込みシステムを学んでいる人に共有したり、作者を応援したりできます。

ご意見

Nội dung liên quan

Một số bài viết, ghi chú hoặc project có liên quan đến nội dung bạn vừa đọc.

Biến note thành bài viết hoàn chỉnh

Notes là nơi ghi nhanh khái niệm.