みなさんご存知の通り,今年BitVisorにIntel CPU向けの(unsafe) nested virtualizationのサポートが追加されました1.
ここで,VMCS Shadowingと呼ばれるNested Virtualizationを高速化するためのCPUの機能が有効であれば使うようになっています.
用語
- L0: 大元のハイパーバイザのこと.ここではBitVisor
- L1: L0上で動かすハイパーバイザのこと
- L2: L1上で動くゲストOSのこと
VMCS Shadowingの概要
VMCS Shadowingは, VMX non-rootのguestが発行するVMREAD/VMWRITE命令をVMEXITせずにCPUが実行する機能です(2013年ごろから登場).
Intel SDM Vol3の24.10 VMCS TYPES: ORDINARY AND SHADOW あたりに書いてあります.
VMCS Shadowingの設定項目としては,以下のようなものがあります.
- VMCS Region
- VMCS Revision shadow-VMCS Identifier (先頭4byte)の31bit = 1
- このVMCSではVMENTRYできなくなる
- もしCPUが対応していない場合,VMPTRLDは失敗する
- VMCS Revision shadow-VMCS Identifier (先頭4byte)の31bit = 1
- Secondary Processor-Based VM-Execution Controls
- bit14: VMCS Shadowing = 1
- VMCS guest state
- Guest non-register state
- VMCS Link Pointer (64bit)
- Guest non-register state
- VMCS Shadowing Bitmap
- このbitが1ならshadow VMCSに関わらずVMEXITが発生
VMCS guest stateにあるVMCS Link Pointerで指すVMCSをL1がVMREAD/VMWRITEで読み書きすることになります.
また,VMCS Shadowing用のVMCSは,shadow-VMCS identifierのビットを1にする必要がありますが,VMPTRLDをした後にVMCSのshadow-VMCS identifierを書き換えるには一旦VMCLEARしなければならない点に注意が必要です.
実装の方法
単純に考えると,VMCS Shadowingの実装方法は二種類あります.
一つはVMCS Shadowingで利用するVMCSと,L2へVMENTRYする際のVMCSを共有する方法です.
このためには,L2にVMENTRYする際と,L1用にVMCS Link Pointerを設定する際で逐一shadow-VMCS identifierを書き換える + (VMCLEARすることになるので) L2へのVMENTRYにはVMRESUMEではなくVMLAUNCHを常に使うことになります.Host stateの書き換えも必要です.
もう一つの方法はVMCS Shadowing用とVMENTRY用で別々にVMCSを持つことです.
この場合は,L2にVMENTRYする際,Shadowing用のVMCSから適切にデータをVMENTRY用のVMCSへコピーする必要があります.
どちらの実装をするべきなのか,というのはSDMには書いていないように思います.
前者ではVMCLEAR+VMLAUNCHのコストが,後者ではデータコピーのコストが気になる点です.
あまり深く確認していませんが,Xenでは前者,KVMでは後者のように実装されていた気がします.
BitVisorでは後者が採用されています.
この理由の一つはゲストに対してVMCS Shadowing対応する際この方が都合が良かったから...という認識です.(が,コードの詳細確認できてません..)
ちなみに,BitVisor Summitで話を伺ったところ性能的にはVMCS Shadowing用とVMENTRY用でVMCSを共有した方が良かったらしいです.
VMCS Shadowingの効果
前に測定したら,ESXi on BitVisor上のゲストから直結している別のマシンへのpingのレイテンシが210usから182usに改善しました(-28).(ベアメタル上では168us).
ちなみにESXi on KVMでは394us→332us(-53)でした.
ただこれ自分がVMCS Shadowing実装した時のものの評価で,今のBitVisorに入っている実装のものとは異なります.すみません..
ちなみに
VMCS ShadowingがあってもやはりNested Virtualizationのオーバヘッドは一般に大きく,どう軽量化するかというのは依然課題の一つです.
12/23にリリースされたLinux 4.20のChangeLogをみていたら,KVMにEnlightened VMCSというものが実装されていました.
これはHyper-Vの準仮想化の機能で,L1が作成するL1/L2のVMCSを通常のメモリ上に配置し,VMEXITなしにVMCS操作をおこなうというものらしいです.
以下に説明があります.
- Vitaly Kuznetsov, A SLIGHTLY DIFFERENT NESTING - KVM on Hyper-V, FOSDEM 2018.
参考文献
以下にBitVisorのVMCS Shadowingに関する説明があります(p.33-4).
- 榮樂 英樹, BitVisor 2018年の主な変更点, BitVisor Summit 7, 2018.
-
AMD向けには前からあります. ↩