Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

USB3.0ドライバ開発の道

1,198 views

Published on

MikanOS(x86-64パソコン用OS)のUSBホストコントローラドライバを開発するにあたり,遭遇した罠を集めました。

Published in: Software
  • Be the first to comment

USB3.0ドライバ開発の道

  1. 1. USB3.0ドライバ開発の道 USBホストコントローラドライバの難所紹介 2020/11/13 ラボ勉強会 @uchan_nos
  2. 2. MikanOSのUSBドライバ開発の罠たち この資料はMikanOSのUSBホストコントローラドライバを開発す るにあたり,遭遇した罠ポイントを集めたもの MikanOS: @uchan_nosが開発している教育用OS ソースコード https://github.com/uchan-nos/mikanos/ 罠ポイントは思い付いた主なものを載せた これがすべてではない みんなもレッツUSBドライバ開発!
  3. 3. 罠リスト QEMUのCRCRのバグ No Opコマンドがエラー 送信イベントが来ない USBデバイスの初期化エラー xHCを始動するとフリーズ 一部機種でデバイス不可視
  4. 4. 罠リスト QEMUのCRCRのバグ No Opコマンドがエラー 送信イベントが来ない USBデバイスの初期化エラー xHCを始動するとフリーズ 一部機種でデバイス不可視
  5. 5. Command Ring xHCにコマンドを送るためのキュー OSがpush,xHCがpop 要素はTRBという16バイトの構造体 TRB最終ワードのビット0がcycle bit OSは末尾にLink TRBを配置し,コマン ドリングを1周させる 周回するたびにcycle bitを反転 CRCRがcommand ringの先頭を指す TRB TRB TRB … xHCが消費者 OSが生産者 Command Ring Link TRB 1 1 1 0 CRCR
  6. 6. CRCR: Command Ring Control Register Command Ring PointerにCRの先頭アドレスを設定 CRR (Command Ring Running) はCR動作中に1になるはず 他のフィールドは0が読み出されることになっている RCS: Reading this flag always returns ‘0’. CS: Reading this bit shall always return ‘0’. CA: Reading this bit always returns ‘0’. Command Ring Pointer: Reading this field always returns ‘0’. xHCI for USB Requirement Specificationより
  7. 7. CRCR.CRRで動作チェック Command ringにTRBをpushし,ドアベルレジスタに書き込む →xHCがcommand ringから取得開始する(CRR=1になる) 当時の僕「上手くコマンドが認識されないなあ… そうだ,CRCR.CRRをチェックしてみよう」 QEMUで実験 まったくCRR=1にならない
  8. 8. QEMUのバグ static uint64_t xhci_oper_read(void *ptr, hwaddr reg, unsigned size) { XHCIState *xhci = ptr; uint32_t ret; switch (reg) { … case 0x18: /* CRCR low */ ret = xhci->crcr_low & ~0xe; break; case 0x1c: /* CRCR high */ ret = xhci->crcr_high; break; … https://github.com/qemu/qemu/blob/3c8c36c9087da957f580a9bb5ebf7814a753d1c6/hw/usb/hcd-xhci.c#L2867-L2872 1 1 0 0 0 11~0xe = QEMUではCRCR.CRRをマスクしてしまっている! 加えて,0になるべきフィールドをマスクしてない
  9. 9. 罠リスト QEMUのCRCRのバグ No Opコマンドがエラー 送信イベントが来ない USBデバイスの初期化エラー xHCを始動するとフリーズ 一部機種でデバイス不可視
  10. 10. No Opコマンドがエラーになる No Opコマンド:Command ringの動作確認用コマンド このコマンドがうまく動く → Command ringが正しくセットアップされている No Opコマンドを送るとTRB Errorが返ってくる 仕様を読んでも辻褄が合わないぞ?
  11. 11. QEMUにNo Opコマンドが無い QEMUにNo Opコマンドが実装されていないだけだった hikaliumさんがその後パッチ投稿  https://github.com/qemu/qemu/commit/dc2c037fd23ea3dcf2e13afda22c1c64ab56f96b
  12. 12. 罠リスト QEMUのCRCRのバグ No Opコマンドがエラー 送信イベントが来ない USBデバイスの初期化エラー xHCを始動するとフリーズ 一部機種でデバイス不可視
  13. 13. xHC スロット USBデバイスとエンドポイント エンドポイント=通信チャネル USBデバイスは最大16個のEPを持つ 必ずEP0=Default Control Pipeを持つ EP0を使ってその他のEPの構成情報を得る xHC側にTransfer Ringを用意し,EPと接続 EPは4種類 USBデバイス EP EP EP スロット TR TR TR 転送種別 転送方向 転送の特徴 Control Bidirectional 各種ディスクリプタを読むなど Isochronous Out/In 時間当たりの転送量を保証 Bulk Out/In 記憶装置などの大容量転送 Interrupt Out/In 小容量の定期的な転送
  14. 14. Transfer Ring USBデバイスに対する送受信のキュー 構造はcommand ringと同じ エンドポイント毎に1つのTR No Op TRBを送信しても送信完了イベ ントが返ってこない TRBのIOC (Interrupt on Completion) を1にしなければならないのだった TRB TRB TRB … xHCが消費者 OSが生産者 Transfer Ring Link TRB 1 1 1 0 Endpoint Context
  15. 15. 罠リスト QEMUのCRCRのバグ No Opコマンドがエラー 送信イベントが来ない USBデバイスの初期化エラー xHCを始動するとフリーズ 一部機種でデバイス不可視
  16. 16. USBデバイスの初期化フロー 1. デバイス接続を検知(PORTSC.CCS=1) 2. ポートをリセット 3. スロットを割り当て(Enable Slotコマンド) スロット:xHCが利用するメモリ上の構造体 4. アドレスを割り当て(Address Deviceコマンド) アドレス幅は7ビット 0~127 Address Deviceコマンド:デバイスにアドレスを割り当てる どんな設定をしてもUSB Transaction Errorになる…
  17. 17. Address Deviceコマンドのエラー原因 ポートリセット後,デバイスはデフォルトアドレス0を持つ 同一アドレスを持つ複数のデバイスが存在するとダメ 1. 複数のデバイスを接続して並行に初期化しようとする 初期化が終わらないとデバイス種別を判定できないため, USBキーボードに限定するとしても全デバイスの初期化が必要 2. アドレス0を持つデバイスが複数発生する 3. Address Deviceコマンドがエラー ポートリセット~Address Deviceコマンドまでは 直列に実行する必要がある!
  18. 18. 罠リスト QEMUのCRCRのバグ No Opコマンドがエラー 送信イベントが来ない USBデバイスの初期化エラー xHCを始動するとフリーズ 一部機種でデバイス不可視
  19. 19. xHCを始動させるとシステムフリーズ 1. xHCをリセット 2. メモリ構造を生成し初期化 3. xHCのレジスタを設定 メモリ構造のアドレスを設定したり 4. xHCの動作を開始 USBCMDのRun/Stopビットに1を書く Run/Stopに1を書いた少し後に,システム全体がフリーズ 例外ハンドラで文字を書いている途中で止まる(上図) シャットダウンではなく,止まる forループの途中なのでプログラムのミスは疑いにくい (同じロジックを繰り返し実行している)
  20. 20. HC BIOS Owned Semaphore システムがフリーズする=バスロック系? プログラム外に原因がありそう。BIOS? 仕様書をふと眺めているとUSB Legacy Support Capabilityに HC BIOS Owned Semaphoreなるビットを発見 “The BIOS sets this bit to establish ownership of the xHC.” 調べてみると,このビットが1になっていた 隣にHC OS Owned Semaphoreというビットもある “System software sets this bit to request ownership of the xHC.” これらを適切に設定したらフリーズしなくなった!
  21. 21. 罠リスト QEMUのCRCRのバグ No Opコマンドがエラー 送信イベントが来ない USBデバイスの初期化エラー xHCを始動するとフリーズ 一部機種でデバイス不可視
  22. 22. 一部の機種でUSBデバイスが検出されない osdev-jpメンバーからUSBマウス,キーボードが使えない報告 報告があった機種の1つはAcer Aspire E1-572-A54D 発売日は2013年6月 CPU: i5-4200U (Haswell) 搭載されているxHCのデバイスコードは0x9c31 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31 https://github.com/torvalds/linux/blob/3650b228f83adda7e5ee532e2b90429c03f7b9ec/drivers/usb/host/xhci-pci.c#L37 Lynx Point-LPはUSB3.0が普及し始めた頃のチップセット Linuxにusb_enable_intel_xhci_ports()という関数がある Intel製チップセットの場合だけ呼ばれる USB3_PSSENやXUSB2PRという謎のレジスタへ書き込み
  23. 23. USB3_PSSENとXUSB2PR Intel 9あたりの時代のチップセットに載ってるレジスタ USB3_PSSEN: USB 3.0 Port SuperSpeed Enable Register XUSB2PR: xHC USB 2.0 Port Routing Register USB3_PSSENのビットに1を書くと,SuperSpeedが有効に XUSB2PRのビットに1を書くと,EHC→xHCに制御権が移動 EHCIにしか対応しないOSに配慮した過渡期の仕様 EHC xHC USBポート群 XUSB2PR
  24. 24. xHCI仕様書には載っていない xHCI仕様書に”5.2 PCI Configuration Registers (USB)”という節が 一応は存在する でもUSB3_PSSEN/XUSB2PRに関する記述は無い チップセット固有の,しかも過渡期の仕様だから? 2つのレジスタをLinuxと同様に設定したらうまく動いた! PCIコンフィグレー ション空間 USB3_PSSEN XUSB2PR BAR xHCレジスタ 空間 メモリ上の データ構造群 xHCI仕様の範疇

×