Upgrade to Pro — share decks privately, control downloads, hide ads and more …

BareMetalで遊ぶ Raspberry Pi 5 PCIe編/KernelVM Tokyo17

BareMetalで遊ぶ Raspberry Pi 5 PCIe編/KernelVM Tokyo17

KernelVM Tokyo 17で発表した資料です。
https://kernelvm.connpass.com/event/321962/

BareMetal Raspberry Pi 5でPCIeを制御してみました。

Changelog:
- 2024/08/10 16:48 pp.49の図のアドレスを修正

Toshifumi NISHINAGA

August 10, 2024
Tweet

More Decks by Toshifumi NISHINAGA

Other Decks in Programming

Transcript

  1. BareMetalで遊ぶ Raspberry Pi 5 PCIe編 Toshifumi NISHINAGA (CV: ついなちゃん) @tnishinaga

    2024-08-10 KernelVM Tokyo 17 https://speakerdeck.com/tnishinaga/kernelvm-tokyo17 1
  2. PCI/PCIeとは? • PCとデバイスをつなぐ規格のひとつ • 近いもの: USBとか • Raspberry Pi 5ではSoCとRP1チップ

    の接続に使われている • PCIと発展型のPCIeがある • PCIe仕様はPCIの仕様がベース • 基本PCIe側で説明(しているつもり) 7 Pi 5のSoC BCM2712 RP1 SoCとRP1をつなぐ PCIe配線(x4)
  3. SoC PCIeの論理接続構成 • PCIeはツリー型のネットワーク構成 • 根っこはRoot Complex(RC) • デバイス(EndPoint/EP)は各バスの下に 接続

    • Bridge(※)を介すと別のバスを作れる • 各デバイスの識別は以下で行う • 接続しているバス番号(Bus) • バス内のデバイス番号(Device) • Linux等ではdevice • FreeBSDではslot 8 Bridge Bus1 EndPoint /Device Bus:1, Slot:1 Bus0 Bus:0, Slot:0 Processor PCI/PCIe controller Host/PCI Bridge Root Complex ※PCIeでは正確ではありませんが、説明のためbridgeと呼びます
  4. Pi5とRP1の例 • Root Complex • BroadcomのPCIeコントローラー • bcrmstb-pcie • BCM2712には3つ搭載

    • PCIe0: 未使用? • PCIe1: Pi5の外部コネクタ • PCIe2: RP1 • PCIe bridge • RC内にあるbridge • Bus0とBus1をつなぐ • RP1 • BUS1のSlot1, Func0に存在 • 他のデバイスは繋がれていないのでBusとSlot は固定 9 BCM2712 Bridge Bus1 RP1 Bus:1, Slot:1 Bus0 Bus:0, Slot:0 Cortex-A72 bcrmstb-pcie Host/PCI Bridge Root Complex
  5. PCI/PCIeのメモリ空間 • メモリ空間 • 一般的なメモリ空間 • 設定済みならCPUからアクセス可能 • IOメモリ空間 •

    (多分)今は使われていない • Configuration空間 • デバイスやブリッジを設定するためのメモリ空間 • アクセス方法はデバイス固有 11
  6. メモリ空間 • デバイスの持つメモリ空間 • ペリフェラルのMMIOやSRAM が存在 • CPUメモリにマップしてアク セスする •

    map設定はPCI configuration spaceのBARで行う(後述) 12 processor memory space device memory space map
  7. PCI/PCIeコンフィギュレーション空間 • PCI/PCIeデバイスごとに存在す る設定領域 • 書き換え方法はコントローラー 依存 • Pi 5はSoCのPCIeコントローラー経

    由でやる • 各領域のサイズは以下 • PCI: 0x00 – 0x40 • PCIe: 0x040 - 0xFFF(MAX) 13 PCI Configuration Space Extended Configuration Space 0x0000 0x0040 0x1000 参考: Figure 3-2: PCI Compatible Configuration Register Space, PCI Express Technology 3.0, Mindshare
  8. PCIeデバイスを制御するまでの概要 1. PCIeコントローラーの初期化 1. クロック設定やRC/EP選択等 2. RCのPCIe bridgeを設定 1. BARやBUS番号等を設定

    3. デバイス(EP)を設定 1. BAR等を設定 4. 完了 1. 以降はプロセッサのメモリ経由でデバイスを制御 14 デバイス固有 PCIe共通
  9. PCIeコントローラーの初 期化 • 主にPCIeのHost/PCI Bridge 部を設定する • 右図赤枠部 • PCIeコントローラーごとに

    手順が異なる(はず) 16 SoC Bridge Bus1 EndPoint /Device Bus:1, Slot:1 Bus0 Bus:0, Slot:0 Processor PCI/PCIe controller Host/PCI Bridge Root Complex
  10. brcmstb-pcieコントローラー • BroadcomのPCIeコントローラー • settop boxで使われているらしい • > Bcrmstb is

    a new Broadcom STB PCI Express controller driver used by some settop boxes. • > https://www.phoronix.com/news/Intel-Gateway-SoC-PCIe-5.6 • Raspberry Pi 4から採用 • Pi 4とPi 5はレジスタ配置が微妙に違う • 仕様は非公開 • 多分NDAが必要 • 今回は各種既存ソースコードを読んで仕様や使い方を把握 • ハード固有の処理の詳細はわからないのでなぞるだけ • ↑多分こういう処理じゃないかとかわかる方教えて下さい 17
  11. 参考にしたコード • FreeBSDのドライバ • https://github.com/freebsd/freebsd- src/blob/ad9cc86bf60cee2b35e804b348840a096f66561d/sys/arm/broadcom/bcm2835/bcm2838_pci.c • 基本はこのドライバで動作を学習 • レジスタ名が役割に応じてリネームされていてわかりやすい

    • OSの知識なしの場合でも処理が比較的追いやすかった • Pi4向け実装のみ。Pi5向け実装はまだない • raspberrypi/linuxのドライバ • https://github.com/raspberrypi/linux/blob/rpi-6.6.y/drivers/pci/controller/pcie-brcmstb.c • Pi 5向けの実装のオリジナルはここ • pciの一般的な設定方法もわかりやすい • EDK2のドライバ • https://github.com/worproject/edk2- platforms/blob/8e1779b538bcc1e6dc68d7df625394f933651d7a/Silicon/Broadcom/Bcm27xx/Library/Bcm271 2PciHostBridgeLib/Bcm2712PciHostBridge.c • Pi5向け実装あり。linuxより読みやすい(多分linuxのドライバベース) • linuxよりコードがフラット • dts使わないので変数の中身がわかりやすい 18
  12. メモリレイアウト • 0x0000-0x1000 • Bus0とBus1をつなぐP2P BridgeのPCI/PCIe config space • Bus0,

    Slot0, Func0のアクセスはここを読み書 きする • https://github.com/freebsd/freebsd- src/blob/ad9cc86bf60cee2b35e804b348840a096f66561d/ sys/arm/broadcom/bcm2835/bcm2838_pci.c#L276-L281 • 0x1000-0x5000 • RC設定用のレジスタたち • 0x8000-0x9004 • PCI/PCIe config space読み書き用レジスタ • ECAMと似ているが微妙に違う • 使い方 • addressでconfig spaceのbus, slot, funcを指定 • config dataに指定したspaceが割り当てられる • dataでconfig spaceにアクセス 19 +0x0000 +0x1000 +0x2000 +0x4000 +0x5000 +0x8000 +0x9000 +0xFFFF RC PCI/PCIe configuration space mdio等のconfig config data 主にbar関係 config address 謎
  13. PCIeコントローラー初期化の手順 • リセット • PERSTのアサート • phyのリセット • 各種クロックの再設定 •

    AXIエラーの抑制 • Pi5から追加 • DMAの設定 • 各種タイムアウトの設定 • 各種BARの無効化 • メモリwindowの設定 • Root Port classの設定 • P2P bridgeにする • 割り込みの無効化 • リンクスピードの設定 • BARのエンディアン設定 • ASPMの設定 • リセットの解除 • 今回は未実施 • DMAの設定 • MSI割り込みの設定 20
  14. Outbound設定 • 一部CPUメモリ空間へのアクセスを PCIメモリ空間へのアクセスに変換す る設定 • 以下を指定して設定 • CPUメモリのbase address

    • PCI側のbase address • マップするサイズ • 各baseよりlimitアドレスを計算 22 processor memory space device memory space outbound 0x1f_0..0 0x1ff...c Base Limit 0x0..0 Base
  15. Outbound設定例(Pi5 PCIe2) • 割当情報 • CPU base: 0x1f_0000_0000 • PCI

    base: 0x0000_0000 • size: 0xffff_fffc • 32bit空間全部 • CPUメモリ0x1f_0..0へのアクセ スはPCIデバイスの32bitメモリ空 間全体へのアクセスになる 23 processor memory space device memory space 0x1f_0..0 0x1ff...c Base Limit 0x0..0 Base 0xF..F
  16. Outbound設定方法 • outbound_cpu_window_limit設定 • base 16bit, limit 16bitの合計32bitで1セット x 4

    • Base/Limit CPUメモリアドレス >> 20(=/1MiB) をセットする • outbound_cpu_window(0x4080~0x40a0)設 定 • base用32bit, limit用32bitの合計64bitで1セット x 4 • Base/Limit CPUメモリアドレスの上位32bitを書 き込む • outbound_bus_window(0x400c~0x402c)設 定 • PCI側のbaseアドレス(64bit)を書き込む • PCI側はLimitアドレス設定が(多分)不要 24 outbound cpu window register(32bit) 0x1F_0...0 0x1_F000 >> 20 Base window_limit register(32bit) 0x0000_001F >> 32
  17. Inbound設定 • PCIeデバイスからCPUメモリを読み書 きするバスマスターアクセスを行うた めの設定 • DMAでデバイスからCPUメモリを読み書 きするために必要 • ↑NVMeなど高速非同期通信を行うデバイスで

    はこれをうまく使うのが重要(homelithさん より) • Pi5では64GiBフルアクセスできるよう 設定する • アクセス制限はIOMMUでやる 25 processor memory space device memory space inbound
  18. ブリッジの設定 • ブリッジを設定してRP1の 参加するBus1を作る • 右図赤枠部 • 以降はPCI/PCIeデバイスの 一般的な設定の話 27

    SoC Bridge Bus1 EndPoint /Device Bus:1, Slot:1 Bus0 Bus:0, Slot:0 Processor PCI/PCIe controller Host/PCI Bridge Root Complex
  19. ブリッジ設定でやること • PCI config space • command部を設定 • バス番号を設定 •

    メモリリミットの設定 • PCIe config space • ペイロードサイズの設定 28
  20. PCI config headerの詳細 • PCIコンフィギュレーション空間 にあるヘッダ • 前半24-byteは共通ヘッダ部 • 後半の構成はHeader

    Type事に違う • PCIeの文脈では以下の2種がある • Type0: PCIデバイス(EP) • Type1: PCI-to-PCI Bridge • Typeの判別は共通部のTypeフィ ールドで行う 29 共通部 Type固有部 0x0000 0x0018 0x0040 参考: Figure 3-2: PCI Compatible Configuration Register Space, PCI Express Technology 3.0, Mindshare Type 0x000C 0x0E 0x0C 0x0D 0x0F
  21. PCI Header Type1 • PCI to PCI Bridge用のヘッダ • BUS番号の設定やメモリリミ

    ットの設定ができる • 以降Type1 headerを設定して いく 30 https://wiki.osdev.org/PCI より引用
  22. command部の設定 • 以下をHighにする • BusMaster • PCIアクセスを生成するのに必要 • Memory Space

    • メモリ空間へのアクセスに必要 31 https://wiki.osdev.org/PCI より引用
  23. バス番号の設定 • Primary Bus Number(0x18) • Bridgeより上にいるBus番号 • 0を設定 •

    Secondary Bus Number(0x19) • Bridgeの下に生やすBus番号 • 1に設定 • Subordinate Bus Number(0x1a) • 下流にあるBus番号の最大値 • 1に設定 32 https://wiki.osdev.org/PCI より引用 Bridge Bus1 EndPoint /Device Bus0 Bus:0, Slot:0
  24. メモリリミットの設定 • bridgeの下流で利用できるメモリアドレス範囲に制限をかける • 以下のフィールドを設定する • Memory Base(0x20, 16bit) •

    Memory Limit(0x22, 16bit) • Prefechable Memory Base(0x24, 16bit) • Prefechable Memory Limit(0x26, 16bit) • Prefechable Base Upper 32bit(0x28, 32bit) • Prefechable Limit Upper 32bit(0x2c, 32bit) 33 参考: https://wiki.osdev.org/PCI
  25. Prefetchable/Non-Prefetchable Memory • Prefetchable Memory • 読んでも副作用のないメモリ • 事前読み込み(prefetch)可能 •

    Non-Prefetchable Memory • 読み込みに副作用のあるメモリ • 例: MMIOでフラグレジスタのを読み込むとフラグがリセットされる • 事前読み込み不可 34
  26. 例: Pi5のメモリプリフェッチ可否領域 • RP1の接続されているメモリ(0x1f_0...0) はNon-Prefetchable • 最初はlimitが0x1f_f...bだけど、後で0x1f_005f_ffffになる • RP1のメモリ空間に合わせて縮小している? (※)

    • →0x1f_0...0をbase、0x1f_005f_ffffをlimitとしてリミット設定すれば良い • 64bit memory map(0x1c_0...0)はPrefetchable • 使ってない領域なのでskip 35 ↑linuxの起動ログ ※メモリサイズおよびprefetch可否はデバイスのBAR[3]からわかる 参考: https://osdev.jp/wiki/PCI-Memo
  27. Non-Prefetchableメモリ設定 • base/limit(オフセット)アドレスの上位12bitを Memory Base/Limitレジスタ(各16bit)の上位 12bitに書き込む(左詰め) • アドレス(32bit)の下位20bitは固定 • Baseは0x0_0000

    • Limitは0xF_FFFF • 参考元 • https://www.macnica.co.jp/business/semiconductor/ articles/microchip/140354/ • https://www.macnica.co.jp/business/semiconductor/ articles/microchip/140362/ • Prefetchableな方法はPCI_Express_Technology_3.0, Figure 4.8: Example Prefetchable Memory Base/Limit Register Values,pp.138, MindShareを参照 36 limit 0x005F_FFFF base 0x0000_0000 CPU memory(offset) limit 0x0050 base 0x0000 PCI Type 1 Memory Limit/Base ↑0x1F_0..0 ~ 0x1F_005F_FFFF を通す場合の設定例 >> 20 << 4 >> 20 << 4
  28. Extended Configuration Spaceの詳細 • PCIeで追加されたConfiguration Space • PCI configuration Spaceの後ろに

    ある • 具体的なオフセットはPCIヘッダの 「Capabilities Pointer」に記載 • 対応する速度等の確認や設定を行 う 37 PCI Configuration Space Extended Configuration Space 0x0000 0x0040 0x1000 参考: Figure 3-2: PCI Compatible Configuration Register Space, PCI Express Technology 3.0, Mindshare
  29. Extended Configuration Spaceの探索 • Extended Configuration Spaceには複 数のstructureが存在する • どのstructureかはCapability

    IDで特定 • 今回制御するのはPCI Express Capability Structure(0x01) • Next Cap Pointerを辿って探索 • 0が入っていたら探索終了 • その他の場合、目的のCapIDが見つかる まで探索 38 参考: http://nahitafu.cocolog-nifty.com/nahitafu/2007/02/pci_express_2b63.html PCI Configuration Space Extended Configuration Space CapPtr structure CapPtr structure 0
  30. PCI Express Capability Structure • PCIeに関するstatusや設定 が入っている構造体 • PCIeのGenや速度設定がで きる

    39 https://www.intel.com/content/www/us/en /docs/programmable/683488/16-0/pci- express-capability-structure.html Figure 31.より引用
  31. PCI Express Capability Structure の設定 • Genとリンクスピードの設定 • brcmstb-pciドライバ内で設定 •

    ペイロードサイズの設定 40 https://www.intel.com/content/www/us/en /docs/programmable/683488/16-0/pci- express-capability-structure.html Figure 31.より引用。 赤枠内は今回設定する部分
  32. Genとリンクスピード設定 • Gen設定 • Link Control 2[0:3] で設定 • RP1はGen2設定

    • リンクスピード設定 • Link Capabilities[0:3] で設定 • RP1は5.0GT/s 設定 • RO だけどなぜか設定できる(※) 41 https://www.intel.com/content/www/us/en /docs/programmable/683488/16-0/pci- express-capability-structure.html Table 55,60より引用 ※ linuxではdtsでgenを設定すると強制的にそのGenでの設定を試みる ↑これはnvme接続時(PCIe1)にPCIe1をGen3に設定する話とは多分無関係
  33. Bridgeのペイロードサイズ設定 • ペイロードサイズ • PCIeでやり取りするデータのパケットサイズ • 参考: https://faq-avaldata.dga.jp/faq_detail.html?id=150 • 最大サイズはDevice

    Capabilities Registerから取得 • Linuxでは MPS(Max Payload Size) • BridgeのMPSは、自身と下流のデバイスのMPSの最小値を設定 42
  34. bridgeのMPS設定例 • 例: Pi 5 linux起動時のdmesg • bridgeのMPSは512だけど、RP1のMPS が256なので256(/512)を設定 •

    ログを出しているコード • https://github.com/raspberrypi/linux/blob/7 69634f344626ed73bcda14c91b567067974d7 b2/drivers/pci/probe.c#L2070 43 Bridge Bus1 RP1 MPS 512 設定値 256 MPS 256 設定値 256
  35. デバイス(EP)設定 • RP1のデバイスを設定 • 主にBARを使ってCPUとデバイス のメモリマップを設定する 46 SoC Bridge Bus1

    EndPoint /Device Bus:1, Slot:1 Bus0 Bus:0, Slot:0 Processor PCI/PCIe controller Host/PCI Bridge Root Complex
  36. BaseAddressRegister(BAR) • PCIデバイスのメモリをCPUにマップ するためのレジスタ • BARにはCPU側のメモリアドレスの オフセットを設定 • ベースはRCが決める •

    PCIデバイスのどのメモリ(とアドレ ス)にどのBARが対応してるかはデ バイス次第(?) • マニュアル参照 • 32bitアドレスは1つ、64bitは2つで設 定 • 詳細はosdev-jpのwiki参照 • https://osdev.jp/wiki/PCI-Memo 49 processor memory space device memory space BAR2 0x4000_0000 0x1f_40..0 RC BAR 0x1f_0...0
  37. 例: RP1のBAR設定 • RP1はBAR1にペリフェラル、BAR2にShared SRAMが割当 • > The AP accesses

    Peripherals and Shared SRAM over PCIe as offsets from the assigned base addresses in BAR1 and BAR2 respectively. • 2.3.1. PCIe and 40-bit to peripheral address mapping, Raspberry Pi RP1 Peripherals, https://datasheets.raspberrypi.com/rp1/rp1-peripherals.pdf より 引用 • LinuxではBAR1をoffset 0, BAR2をoffset 0x0040_0000に設定 • RCでbaseを0x1f_0000_0000 に設定しているため 50
  38. PCIe関係の初期化と設定 52 SoC Bridge Bus1 EndPoint /Device Bus:1, Slot:1 Bus0

    Bus:0, Slot:0 Processor PCI/PCIe controller Host/PCI Bridge Root Complex
  39. UARTとGPIOの設定 53 SoC Bridge Bus1 EndPoint /Device Bus:1, Slot:1 Bus0

    Bus:0, Slot:0 Processor PCI/PCIe controller Host/PCI Bridge Root Complex
  40. Hello World 54 SoC Bridge Bus1 EndPoint /Device Bus:1, Slot:1

    Bus0 Bus:0, Slot:0 Processor PCI/PCIe controller Host/PCI Bridge Root Complex
  41. オチ • 実はfirmwareの設定をすればPCIeドライ バ自作は不要だった • 初期化済みのPCIe&RP1のセットをKernelに わたすオプションがある • https://tnishinaga.hatenablog.com/entry/2024/ 06/04/012033

    • SoC内のUARTペリフェラルもearly printに 使える • Debug端子からシリアル出力できる • https://forums.raspberrypi.com/viewtopic.php? p=2159255&hilit=pciex4_reset%3D0#p2159255 57 Pi 5のDebug端子
  42. 参考資料 • PCI Express Technology 3.0, Mindshare • 一番参考になった本 •

    PCIeに関する情報が網羅的に書かれている • PCI/PCIeデバイス設定方法に関する記述は少なめ • https://www.mindshare.com/Books/Titles/PCI_Express_Technology_3.0 • Stratix V Avalon-ST Interface with SR-IOV PCIe Solutions: User Guide • PCIe capabilities structureの詳細が書かれている • https://www.intel.com/content/www/us/en/docs/programmable/683488/16-0/pci-express-capability-structure.html • osdev • configuration spaceの詳細を理解するのに有用 • https://wiki.osdev.org/PCI • https://wiki.osdev.org/PCI_Express • マクニカの特集やFAQ • 特定レジスタの詳細を知るのに有用 • https://www.macnica.co.jp/business/semiconductor/support/faqs/intel/92193/ • osdev-jp • BARの詳細がわかる • https://osdev.jp/wiki/PCI-Memo 58