Upload
naoya-kaneko
View
4.450
Download
9
Embed Size (px)
DESCRIPTION
virtio勉強会 #1でしゃべった内容。 未完成版。pdfで上げたのが見えないので上げ直し。
Citation preview
1
2013/06/09
virtio の基本的なところ(DRAFT)@n_kane
2
参考資料
✤ というかこのスライドよりむしろ以下の資料を読みましょう ...
✤ Virtio PCI Card Specification
✤ http://github.com/rustyrussell/virtio-spec
✤ とある virtio ドライバの接続部分〜インタフェース〜 by @hasegaw
✤ http://www.slideshare.net/TakeshiHasegawa1/osc2011-tokyofall-virtio
3
ここでするお話について
✤ virtio の基本的なところのお話
✤ どううごいているか
✤ どうシステムソフトウェアから使えるか
✤ ( つまり )virtio pci card specification のサブセット的な内容
✤ 主に plan9 の virtio 実装をメインにお話を進めます
4
ここでしないお話について
✤ 仮想化周りの歴史的背景、実現方法、実装、構造 e.t.c.
✤ virtio での通信が VMM 内でどうハンドリングされているか
✤ indirect モード , MSI-X の活用など
5
お題目
✤ virtio で何ができるの?
✤ virtio デバイスとその見え方
✤ virtio を使った通信
6
virtio で何ができるの?
7
virtio でホスト・ゲスト間通信!
✤ 何か不思議な力により
✤ ホスト&ゲスト OS 間で共有できるリングバッファができます
✤ しかもメモリ空間が許すかぎり何本でも
✤ ここに適切に情報を詰めてやることで
✤ ゲストからホストへ、あるいはホストからゲストへデータの転送ができます
8
データの転送ができるなら ....
✤ 準仮想化ドライバ作るときに使えるよね!
✤ たとえば
✤ コントロール用 , TX 用 , RX 用のリングバッファがあれば
✤ NIC っぽい動作をさせられるのでは! ( ホスト側ががんばれば )
9
“virtio デバイス”というもの
10
virtio device
✤ virtio デバイス
✤ なんらかのまとまった機能を持った仮想的な対象物 = デバイス
✤ たとえば NIC, ブロックデバイス , ファイルシステム e.t.c
✤ いくつかのリングバッファを用いて操作してやることで一定の役割を果たしてくれる人のこと
11
virtio device as a PCI device
✤ virtio デバイスはゲストから、 PCI デバイスとして認識されます
✤ ベンダ ID : 0x1AF4
✤ プロダクト ID : 0x1000 - 0x1040
✤ これだとどの virtio デバイスだか区別がつかない ....
✤ Subsystem Device ID でデバイスのタイプを判断
12
http://marsee101.blog19.fc2.com/blog-entry-84.html より拝借
0x1000 〜 0x1040 0x1AF4
IDID TYPETYPE
1 NIC
2 BLOCK
3 CONSOLE
5MEMORYBALLOON
9 9P
Subsytem Device ID の例
13
認識できたら初期化 ... の前に
✤ PCI I/O Space に何が入っているかを抑えておきましょう
デバイス ( ホスト ) からゲストに対して提示される利用可能な機能(feature) 一覧 ( 各ビット )
ゲストが利用する機能 (feature)を書き込みデバイス ( ホスト ) に伝えるフィールド
Virtio Header
14
認識できたら初期化 ... の前に
✤ PCI I/O Space に何が入っているかを抑えておきましょう
Qselect に示される番号のリングバッファのアドレス ÷ 4096(guest physical)
操作中のリングバッファの番号
Qselect に示される番号のリングバッファ長 ( デスクリプタの数 )
Virtio Header
15
認識できたら初期化 ... の前に
✤ PCI I/O Space に何が入っているかを抑えておきましょう
デバイスの初期化状態や利用状況についてゲストが告知するために利用
割り込み状態の通知
リングバッファを操作した際にゲストがその番号を書き込む
Virtio Header
16
virtio デバイスの初期化 ( 共通 )
1 各 OS ごとの PCI デバイス認識フェーズ
2 ベースアドレスレジスタから map( 左の構造がみえるようになる )
3 Status の ACKNOWLEDGE(0x1) ビットを立ててデバイスを発見できたこと、 virtio デバイスだと分かっていることを通知
Virtio Header
16
17
virtio デバイスの初期化 ( 共通 )
4 Status の DRIVER(0x2) ビットを立てて、ゲストがこのデバイスをサポート == ドライバを実装していることを通知
5 デバイス固有の初期化
6 リングバッファの用意 ( 後述 )
7 Devfeat の内、利用する物を Drvfeatに書き込み ( 後述 )
Virtio Header
17
18
virtio デバイスの初期化 ( 共通 )
8 すべて正常に成功したら , Status のDRIVER_OK(0x4) ビットを立てる
8 失敗したら , Status のFAILED(0x80)ビットを立てる
以上で attach の部分は終了!18
19
リングバッファの構造
20
リングバッファとは
✤ 実態はメモリ上のこんなかんじのデータ
21
リングバッファとは
✤ 実態はメモリ上のこんなかんじのデータ
デスクリプタテーブル
available リング
used リング
22
デスクリプタ
✤ 一つの転送を扱うエンティティ
23
デスクリプタ
✤ 一つの転送を扱うエンティティ
転送対象のデータのアドレス(guest physical)
データ長
このデスクリプタの扱いについてのフラグ
後続して転送するデスクリプタの番号
24
デスクリプタ
✤ 一つの転送を扱うエンティティ
フラグフラグ (( 値値 )) 意味意味
VRING_DESC_F_NEXT(0x01)
next フィールドに示される後続要素がある ( デスクリプ
タチェーンによる転送 )
VRING_DESC_F_WRITE(0x02)
このデスクリプタは ( ホストから見て )Write Only である . ホスト→ゲスト方向の転
送
VRING_DESC_F_INDIRECT
(0x04)Indirect モードによる転送
25
デスクリプタテーブル
✤ ( そのまま ) デスクリプタの配列
✤ 長さは Virtio Header の Qsize( 個 )
✤ 転送の度に動的に alloc するのではなく、このテーブルからフリーなデスクリプタを見つけてきて使うという方式
✤ 基本的には”インデックス値”でアクセスされる
26
available リング
このリング用のフラグ( 割り込み抑制など※ ) デスクリプタテーブル
used リング
avail リング中の先頭インデックス値 (availidx)
デスクリプタ番号を書き込むリング本体
ここに指定された番号のデスクリプタが処理されるまでは割り込み
抑制
27
used リング
このリング用のフラグ( 割り込み抑制など※ ) デスクリプタテーブル
available リング
used リング中の先頭インデックス値 (usedidx)
デスクリプタ番号が書き込まれるリング本体
ここに指定された番号のデスクリプタが処理されるまでは割り込み
抑制
28
available リングと used リング
✤ 基本的には前述のデスクリプタの番号を入れておく配列 ( 長さ Qsize)
✤ available リング
✤ ゲストがデスクリプタの番号を書き込んでリング上のインデックス値 (availidx) を進めると、それが ( ホストにより ) 処理される
✤ used リング
✤ ホストにより処理されたデスクリプタの番号が書き込まれ、リング上のインデックス値(usedidx) が更新される
✤ 正確には”デスクリプタの番号”と”デスクリプタチェーンの長さ”が入る
✤ このオペレーション周りは後述
29
リングバッファの扱い方 - 初期化 -
30
先ほど飛ばしたお話
✤ リングバッファを用意するのはゲストの責任。以下の流れで行う。
1. 触りたいリングの番号 (i) を Qselect にセット
2. Qsize をみる
3. 0 ならこのデバイスで Qselect 番目のリングは使えないので終わり
4. > 0 ならその長さのリングが使える
5. 前述のリングバッファを Qsize を元に作る
6. Qaddr にリングバッファの物理アドレスをセット
7. i++; goto 1;
Virtio Header
31
初期化周りの細い話
✤ virtio の本筋とはあまり関係ないけれど、利便性のために OS でやっていること
✤ デスクリプタテーブルのチェーン化 (右図 )
✤ フリーなデスクリプタ番号の保持 (右図の free)
✤ avail リング , used リングの先頭アドレス保持
✤ 過去の usedidx の保持 (lastused)
32
リングバッファの扱い方 - 転送 -
33
転送の手順
✤ 箇条書きにすると ....
1. 転送パスのキューを引っ張ってくる
2. その中でフリーなデスクリプタを探してきて、適切に情報を詰める
3. avail リングの先頭にその番号を書き込み , availidx を +1 して更新
4. Virtio Header の Qnotify に転送パスのキューの番号を書き込む
✤ この時点でホストに制御が移って処理が行われる
34
分かりづらいので図に ...
初期状態
4 番がフリーなので情報をつめて ...
availidx のところに番号を書き込む
availidx を進めて、変更を加えたリング番号を Qnotify に書き込み
35
転送が終わったら ....
✤ 割り込みが入って何かデバイス ( ホスト ) から応答があるはず ....→used リリリリリリリ
1. 現在の usedidx と lastused の差から変更があったことを検知
2. lastused == usedidx になるまで used リングのデスクリプタを処理
3. 処理が終わったデスクリプタはデスクリプタテーブルに戻す
36
イメージ図
割り込みが入った時点
usedidx と lastused の差から変更を検知
一つ進めて該当するデスクリプタを処理
終わった物は返す
37
slide is never done
38
virtio-net の場合の事情
✤ virtqueue は3つ : tx/rx/control
✤ Drvfeat