AMD SVM(AMD-V)についてちょっと勉強してみた 再まとめ
SVMの概要
SVMはIntel VTと同じく仮想化をハードウェアレベルで実装したもので、CPUにGuest環境を動作させる専用モードとモード切り替えの拡張命令を持つ。
Guest環境で実行されるインストラクションのうち、直接CPUで実行するとHost環境に影響を及ぼす幾つかのセンシティブ命令とレジスタアクセス、IOアクセスやソフトウェア割り込みなどは全てインターセプトされる。
VMCBと呼ばれるメモリ上の構造体に、GuestのCPUステート(State save area)やインターセプトの設定(Control area)を記録する。モード切り替えの時にはここからCPUステートを復帰/退避させる。
VMCBは4KBアライメントされた4KBの領域で、物理アドレスで指定されなければならない。
動作遷移
1. VMCBのメモリ領域を確保
↓
2. インターセプトする命令/イベント、コントロールビット、プロセッサステートを設定
↓
3. RAX(EAX)レジスタへVMCBの物理アドレスを代入
↓
4. VMRUN命令でゲストを起動
↓
5. ゲストが実行される rIPから実行を開始し、インターセプトされるまで命令を実行し続ける
↓
6. インターセプトがかかって制御がホストへ戻る(これを#VMEXITと呼ぶ)
↓
7. 要因を調べ、適切な処理を行う
↓
8. 4へ戻る
VMCB
[Control area|State save area|reserved]
<- 4096byte > |
○Control areaにあるもの
・インターセプトのオンオフ
・CR read/write
・DR read/write
・exceptions
・その他
・iopm、msrpmのアドレス
・tscオフセット
・GuestのASID
・Guestの割り込みの設定
・VMEXITの要因情報
・ネステッドページングの設定
・イベントインジェクションの設定
・LBR仮想化の設定
○State save areaにあるもの
・レジスタ全てGuestモードの特殊レジスタの一部・RAXレジスタの退避場所
・KernelGSBase
・SYSENTER_(CS|ESP|EIP)
SVM拡張命令セット
VMRUN | Guestモードへ切り替え |
VMLOAD | VMCBからレジスタ復帰 |
VMSAVE | VMCBへレジスタ退避 |
VMMCALL | GuestモードからHostモードを呼び出し |
VMMCALL以外は全てcpl = 0である必要がある。
メモリ管理とページング
Guestのメモリ空間はCR3をインターセプトしてShadow Pagingするか、同等の事をハードウェアで処理するNested Pagingを使うかしてHost OSの都合の良い領域を割り当てさせるのが前提になっている。
でもそれだと、起動直後にページング無効になってる時のメモリアクセスに困る。
そこで、SVMではGuestに限りリアルモードだろうとページングが動くようになっている。
これをPaged Real Modeと呼ぶ(AMDのドキュメントの15.18)。
これでGuestがページング無効な状態でも無理矢理ページングして好きな領域に割り当て出来る。
常にページングしろ、って前提に見える。
であるからか、VMCBに仮想マシンのメモリ空間のオフセットアドレス設定フィールドとかは存在しない。
じゃ、ページングを完全に切っちゃったらGuestでは一体何が見えるの?という好奇心に駆られ、実験してみた所qemu-system-x86_64ではホストのメモリがそのまま見えた(リアルモードで0x0から数バイトしか試してないけど)。
実機では試してないので分からない、もしかしたら動きが違うかもしれない。
本当はメモリ保護エラー的なものでインターセプトされるべきな気もするが、ドキュメントを読む限りそういう仕様にはなっていないように見える。
逆に、ページングを切ったとき何が起きるべきかについての言及もみつけられてない。
VMとHost OSのマルチタスキング/スケジューリング
本当に4-8を繰り返すとマルチタスキング出来ないので、恐らくタイマ割り込み契機でGuestからCPUを取り上げて他タスクにコンテキストスイッチするんじゃないのかな。