PCI/PCIe Architecture Overview
PCI/PCIe architectureをfirmware視点で整理します。BDF、config space、BAR、bridge、enumeration、device missing debugを扱います。
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で見る理由 |
|---|---|
| BDF | PCI functionの論理アドレス |
| Configuration Space | ID、BAR、capabilityを読む場所 |
| Vendor ID / Device ID | vendorと具体的なdeviceを識別する |
| Class Code | generic driver matchingでdevice typeを見る |
| BAR | deviceが要求するMMIOまたはI/O aperture |
| Bridge Window | bridge配下のdeviceへ割り当てるresource range |
| Root Bridge | PCI segmentへaccessするfirmware側の入口 |
Deviceが消える場合は、高位のdriverを疑う前に、BDFとconfiguration spaceから確認します。
UEFIではどこに出るか
EDK IIでは、PCIは主にPciHostBridge、PciBusDxe、EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL、EFI_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.