CPU 仮想化の既知の制限

CPU 機能を完全にエミュレートするのが不可能または難しすぎる場合、KVM は その機能をまったく実装しないか、仮想マシンとベアメタルの挙動に差を 持ち込むかを選ばなければならない。

このファイルでは、KVM が CPU 機能を仮想化する上で持つ既知の制限の一部を 記述する。

x86

KVM_GET_SUPPORTED_CPUID の問題

x87 機能

他のほとんどの CPUID 機能ビットと異なり、CPUID[EAX=7,ECX=0]:EBX[6] (FDP_EXCPTN_ONLY)と CPUID[EAX=7,ECX=0]:EBX]13] (ZERO_FCS_FDS) は、 その機能が存在する場合にクリアされ、存在しない場合にセットされる。

CPUID でこれらのビットをクリアしても、ゲストの動作には影響しない。 ハードウェアでこれらのビットがセットされていれば、そのハードウェア上で 動作するどの仮想マシンでも、その機能は存在しない。

回避策: ゲストの CPUID では常にこれらのビットをセットすることを推奨する。 ただし、これらの機能が存在することを前提とするソフトウェア(たとえば WIN87EM.DLL)は、これらの CPUID 機能ビットより前のものと考えられ、 いずれにせよそれらをチェックすることを知らない点に注意されたい。

KVM_SET_VCPU_EVENTS の問題

エラーコードに関して不正な KVM_SET_VCPU_EVENTS の入力は、Intel CPU で VM エントリの失敗を引き起こす*ことがある*。CET 以前の Intel CPU は、 VMCS を通じた例外注入が "error code valid" フラグを正しく設定することを 要求する。たとえば #GP の注入時はフラグをセットし、#UD の注入時はクリアし、 ソフト例外の注入時はクリアする、などである。IA32_VMX_BASIC[56] を '1' と 列挙する Intel CPU は VMX の整合性チェックを緩め、AMD CPU には制限が まったくない。KVM_SET_VCPU_EVENTS はベクタと "has_error_code" の妥当性を 検査しない。つまり、KVM の ABI は AMD の挙動に従う。

ネスト仮想化機能

AMD CPU では、GIF がクリアされているとき、ブレークポイントレジスタの 一致による #DB 例外やトラップは無視され、CPU によって破棄される。CPU は この挙動を完全に仮想化することを VMM に任せる。ゲストで vGIF が有効な 場合でも同じである(つまり、vGIF=0 でもゲスト実行中に CPU は #DB を 落とさない)。KVM はこの挙動を仮想化しない。ユースケースがまれであるのに 対し、複雑さに見合う価値がないためである。対処法の 1 つは、KVM が #DB を 横取りし、ブレークポイントを一時的に無効にし、その命令をシングルステップ 実行してからブレークポイントを再度有効にするというものである。

x2APIC

KVM_X2APIC_API_USE_32BIT_IDS が有効なとき、KVM はハック/クワークを有効に する。対象の vCPU が従来の xAPIC を有効にしていても、その x2APIC ID を 使って単一の vCPU にイベントを送れるようにするものである。たとえば、 255 個を超える vCPU を持つ VM で、INIT-SIPI 経由でホットプラグされた vCPU を 立ち上げる場合などである。このクワークの副作用として、複数の vCPU が同じ 物理 APIC ID を持つ場合、KVM はその APIC ID を対象とするイベントを、最も 小さい vCPU ID を持つ vCPU にのみ配送する。KVM_X2APIC_API_USE_32BIT_IDS が 有効でない場合、KVM は割り込みを処理するときに x86 アーキテクチャに従う (対象の APIC ID に一致するすべての vCPU が割り込みを受け取る)。

MTRR

KVM はゲストの MTRR メモリタイプを仮想化しない。KVM は MTRR MSR への アクセス、すなわちゲストでの {RD,WR}MSR をエミュレートするので、これは 期待どおりに動作する。しかし KVM は、実効メモリタイプを決めるときにゲストの MTRR を尊重せず、ゲストメモリのすべてがライトバック(WB)の MTRR を持つ ものとして扱う。

CR0.CD

KVM は Intel CPU で CR0.CD を仮想化しない。MTRR MSR と同様、KVM は CR0.CD へのアクセスをエミュレートするので、CR0 へのロードと CR0 からのストアは 期待どおりに動作する。しかし CR0.CD=1 を設定しても、ゲストメモリの キャッシュ可否には影響しない。

なお、このエラッタは AMD CPU には影響しない。AMD は CR0.CD をハードウェアで 完全に仮想化する。すなわち、ゲスト実行中でも CR0.CD=1 のときは CPU キャッシュを "no fill" モードにする。