VirtIOデバイスの初期化
VirtIOデバイスとして動作するためには以下の2段階の初期化が必要です.
- VirtIOデバイスとしての初期化
- デバイスの種類に応じた初期化
デバイスの種類に応じた初期化はデバイスに応じたものとなるので今回は省略し,今回はVirtIOデバイスとしての初期化について,レジスタの読み書きについて流れを見ました.
初期化シーケンス
VirtIOデバイスはメモリマップされたレジスタファイルの値をOSが読み書きして初期化します.
以下は,ブロックデバイスとしてVirtIOデバイスの初期化を完了させるために必要な流れです.R/WはOS側から見た記述です.デバイス側では,OSが正しく初期化を完了できるようにレジスタファイルの値をあらかじめ設定しておく,あるいは書き込まれた値に応じた処理を行ないレジスタファイルの値を変更する必要があります.
| ステップ | アドレス | レジスタ | RW | 値(例) | 内容 |
| 0 | 0x000 | MagicValue | R | 0x74726976 | マジックナンバー |
| 1 | 0x004 | Version | R | 0x2 | VirtIOのバージョン |
| 2 | 0x008 | DeviceID | R | 0x2 | デバイスの種類(0x2=ブロックデバイス) |
| 3 | 0x00c | VendorID | R | 0xffeeddcc | ベンダーID |
| 4 | 0x070 | Status | W | 0x0 | デバイスのリセット |
| 5 | 0x070 | Status | R | 0x1 | ACKNOWLEDGEビットを確認 デバイスのリセット完了 |
| 6 | 0x070 | Status | W | 0x1 | ACKNOWLEDGEビットの書き込み |
| 7 | 0x070 | Status | R | 0x1 | エラーが発生していないか確認する |
| 8 | 0x070 | Status | W | 0x3 | DRIVERビットを設定しネゴシエーションを開始する |
| 9 | 0x014 | DeviceFeatureSel | W | 0x1 | 読み取るDeviceFeatureの領域を選択 1なので[63:32]を対象とする |
| 10 | 0x010 | DeviceFeature | R | 0x1 | DeviceFeature[63:32]を読み取る |
| 11 | 0x014 | DeviceFeatureSel | W | 0x0 | 読み取るDeviceFeatureの領域を選択 0なので[31:0]を対象とする |
| 12 | 0x010 | DeviceFeature | R | 0x0 | DeviceFeature[31:0]を読み取る |
| 13 | 0x024 | DriverFeatureSel | W | 0x1 | DriverFeatureの領域を選択 1なので[63:32]を対象とする |
| 14 | 0x020 | DriverFeature | W | 0x1 | DriverFeature[63:32]を設定する |
| 15 | 0x024 | DriverFeatureSel | W | 0x0 | DriverFeatureの領域を選択 0なので[31:0]を対象とする |
| 16 | 0x020 | DriverFeature | W | 0x0 | DriverFeature[31:0]を設定する |
| 17 | 0x070 | Status | R | 0x3 | エラーが発生していないかを確認する |
| 18 | 0x070 | Status | W | 0xb | FEATURES_OKビットを設定しネゴシエーションを完了 |
| 19 | 0x070 | Status | R | 0xb | エラーが発生していないかを確認する |
| 20 | 0x030 | QueueSel | W | 0x0 | Virtqueueの選択 |
| 21 | 0x044 | QueueReady | R | 0x0 | キューの準備が未完了か確認 |
| 22 | 0x034 | QueueNumMax | R | 0x10 | Virtqueue内の最大キュー数を確認 |
| 23 | 0x038 | QueueNum | W | 0x10 | Virtqueue内で使用するキュー数を設定 |
| 24 | 0x080 | QueueDescLow | W | 0x1e42e000 | VirtqueueのDescriptor Tableの下位アドレスを設定 |
| 25 | 0x084 | QueueDescHigh | W | 0x0 | Descriptor Tableの上位アドレスを設定 |
| 26 | 0x090 | QueueDriverLow | W | 0x1e42e100 | VirtqueueのDriver(Available Ring)の下位アドレスを設定 |
| 27 | 0x094 | QueueDriverHigh | W | 0x0 | Driver(Available Ring)の上位アドレスを設定 |
| 28 | 0x0a0 | QueueDeviceLow | W | 0x1e42f000 | VirtqueueのDevice(Used Ring)の下位アドレスを設定 |
| 29 | 0x0a4 | QueueDeviceHigh | W | 0x0 | Device(Used Ring)の上位アドレスを設定 |
| 30 | 0x044 | QueueReady | W | 0x1 | キューの準備が完了したことを設定 |
| 31 | 0x0fc | ConfigGeneration | R | 0x0 | デバイスの構成のバージョンを読み取る |
| 32~ | 0x100~ | Config | デバイスの種類に応じて読み書きする |
実際に動作しているAXIトランザクションをILAでキャプチャした画像です.

デバイスの種類に応じたレジスタも送受信すると以下のようなログでOSにデバイスとして認識してもらえます.

まとめ
仕様書のレジスタマップだけでは実際にどのような順序で読み書きされているのかが分かりづらかったので実際の動きをテキストに書き起こしてみました. どのようにデバイスの存在や機能の有無を確認し有効化するのか流れで理解する事ができました.


コメント