次の方法で共有


ネスト仮想化

入れ子になった仮想化とは、ハードウェア仮想化拡張機能をエミュレートする Hyper-V ハイパーバイザーのことです。 これらのエミュレートされた拡張機能は、他の仮想化ソフトウェア (入れ子になったハイパーバイザーなど) で使用して、Hyper-V プラットフォーム上で実行できます。

この機能は、ゲスト パーティションでのみ使用できます。 仮想マシンごとに有効にする必要があります。 入れ子になった仮想化は、Windows ルート パーティションではサポートされていません。

入れ子になった仮想化のさまざまなレベルを定義するには、次の用語を使用します。

任期 Definition
L0 ハイパーバイザー 物理ハードウェアで実行されている Hyper-V ハイパーバイザー。
L1 ルート Windows ルート オペレーティング システム。
L1 ゲスト 入れ子になったハイパーバイザーのない Hyper-V 仮想マシン。
L1 ハイパーバイザー Hyper-V 仮想マシン内で実行されている入れ子になったハイパーバイザー。
L2 ルート Hyper-V 仮想マシンのコンテキスト内で実行されるルート Windows オペレーティング システム。
L2 ゲスト 入れ子になった仮想マシン。Hyper-V 仮想マシンのコンテキスト内で実行されます。

ベア メタルと比較すると、ハイパーバイザーは VM で実行するとパフォーマンスが大幅に低下する可能性があります。 L1 ハイパーバイザーは、L0 ハイパーバイザーによって提供される対応インターフェイスを使用して、Hyper-V VM で実行するように最適化できます。

現在、この機能は x64 でのみサポートされています。

対応 VMCS (Intel)

Intel プラットフォームでは、仮想化ソフトウェアは仮想マシン制御データ構造 (VMCS) を使用して、仮想化に関連するプロセッサの動作を構成します。 VMPTRLD 命令を使用して VMCS をアクティブにし、VMREAD および VMWRITE 命令を使用して変更する必要があります。 これらの命令は、多くの場合、エミュレートする必要があるため、入れ子になった仮想化の重要なボトルネックになります。

ハイパーバイザーは、ゲスト物理メモリ内のデータ構造を使用して仮想化関連のプロセッサ動作を制御するために使用できる"対応 VMCS" 機能を公開します。 このデータ構造は、通常のメモリ アクセス命令を使用して変更できるため、L1 ハイパーバイザーで VMREAD または VMWRITE または VMPTRLD 命令を実行する必要はありません。

L1 ハイパーバイザーは、 仮想プロセッサ 支援ページの対応するフィールドに 1 を書き込むことで、対応する VMCS を使用することを選択できます。 VP アシスト ページの別のフィールドは、現在アクティブな対応 VMCS を制御します。 対応する各 VMCS のサイズは 1 ページ (4 KB) であり、最初はゼロにする必要があります。 対応する VMCS をアクティブまたは最新にするために VMPTRLD 命令を実行する必要はありません。

L1 ハイパーバイザーが対応する VMCS を使用して VM エントリを実行すると、VMCS はプロセッサ上でアクティブと見なされます。 対応する VMCS は、同時に 1 つのプロセッサでのみアクティブにすることができます。 L1 ハイパーバイザーは、VMCLEAR 命令を実行して、対応する VMCS をアクティブ状態から非アクティブ状態に移行できます。 対応する VMCS がアクティブな間の VMREAD または VMWRITE 命令はサポートされていないため、予期しない動作が発生する可能性があります。

HV_VMX_ENLIGHTENED_VMCS構造体は、対応する VMCS のレイアウトを定義します。 すべての非合成フィールドは、Intel 物理 VMCS エンコードにマップされます。

フィールドのクリーンアップ

L0 ハイパーバイザーは、対応する VMCS の一部をキャッシュすることを選択できます。 対応 VMCS クリーン フィールドは、入れ子になった VM エントリのゲスト メモリから再読み込みされる、対応する VMCS のどの部分を制御します。 L1 ハイパーバイザーは、対応する VMCS が対応する VMCS クリーン フィールドを変更するたびにクリアする必要があります。そうしないと、L0 ハイパーバイザーで古いバージョンが使用される可能性があります。

クリーン フィールドの対応は、対応する VMCS の合成 "CleanFields" フィールドを介して制御されます。 既定では、L0 ハイパーバイザーが入れ子になった VM エントリごとに対応する VMCS フィールドを再読み込みする必要がある、すべてのビットが設定されます。

機能の検出

対応 VMCS インターフェイスのサポートは、 CPUID リーフ 0x40000004で報告されます。

対応する VMCS 構造は、将来の変更を考慮してバージョン管理されます。 対応する各 VMCS 構造体には、L0 ハイパーバイザーによって報告されるバージョン フィールドが含まれています。

現在サポートされている VMCS バージョンは 1 のみです。

ハイパーバイザーの実装に関する考慮事項

ほとんどの VMCS フィールドでは、アーキテクチャ機能検出メカニズムによって決定された VMCS フィールドが VM でサポートされている場合、対応する対応する VMCS フィールドが VM でサポートされます。 例外は CPUID リーフ 0x4000000Aで報告されます。

アーキテクチャ機能検出メカニズムが、対応する VMCS フィールドが定義されていない VMCS フィールドのサポートを示している場合、L1 ハイパーバイザーは、対応 VMCS の使用を選択した場合、この機能を有効にしないでください。

Hyper-V L0 ハイパーバイザーは、対応する VMCS フィールドまたは例外が定義されていない VMCS フィールドのサポートを示しません。 別の L0 ハイパーバイザーで新しい対応 VMCS フィールドまたは例外を定義する必要がある場合は、Microsoft にお問い合わせください。

Enlighened VMCB フィールド (AMD)

AMD には、ハイパーバイザー用に VMCB に予約された領域と、関連するクリーン ビットがあります。 予約済みバイトは、VMCB の制御セクション (オフセット 0x3E0-3FF) にあります。 クリーン ビットはビット 31 です (ハイパーバイザーが VMCB の "対応" 領域を変更するたびに、クリーン ビットを無効にする必要があります)。

Hyper-V では、予約された VMCB 領域を利用して、対応を構成します。 HV_SVM_ENLIGHTENED_VMCB_FIELDS構造体は、形式を文書化します。

対応する MSR ビットマップ

L0 ハイパーバイザーは、Intel プラットフォームと AMD プラットフォームの両方で "MSR-Bitmap" コントロールをエミュレートします。これにより、仮想化ソフトウェアは、どの MSR アクセスがインターセプトを生成するかを制御できます。

L1 ハイパーバイザーは、L0 ハイパーバイザーと連携して、MSR アクセスをより効率的にすることができます。 対応する VMCS/VMCB フィールド内の対応するフィールドを 1 に設定することで、対応する MSR ビットマップを有効にすることができます。 有効にすると、L0 ハイパーバイザーは MSR ビットマップの変更を監視しません。 代わりに、L1 ハイパーバイザーは、MSR ビットマップのいずれかに変更を加えた後、対応するクリーン フィールドを無効にする必要があります。

対応する MSR ビットマップのサポートは、 CPUID リーフ 0x4000000Aで報告されます。

ライブ マイグレーションとの互換性

Hyper-V には、あるホストから別のホストに子パーティションをライブ マイグレーションする機能があります。 ライブ マイグレーションは通常、子パーティションに対して透過的です。 ただし、入れ子になった仮想化の場合、L1 ハイパーバイザーは移行に注意する必要がある場合があります。

ライブ マイグレーション通知

L1 ハイパーバイザーは、パーティションの移行時に通知を要求できます。 この機能は、CPUID で "AccessReenlightenmentControls" 特権として列挙されます。 L0 ハイパーバイザーは、L1 ハイパーバイザーが割り込みベクトルとターゲット プロセッサを構成するために使用できる合成 MSR (HV_X64_MSR_REENLIGHTENMENT_CONTROL) を公開します。 L0 ハイパーバイザーは、各移行後に、指定されたベクターに割り込みを挿入します。

#define HV_X64_MSR_REENLIGHTENMENT_CONTROL (0x40000106)

typedef union
{
    UINT64 AsUINT64;
    struct
    {
        UINT64 Vector :8;
        UINT64 RsvdZ1 :8;
        UINT64 Enabled :1;
        UINT64 RsvdZ2 :15;
        UINT64 TargetVp :32;
    };
} HV_REENLIGHTENMENT_CONTROL;

指定されたベクトルは、固定 APIC 割り込みに対応している必要があります。 TargetVp は、仮想プロセッサ インデックスを指定します。

TSC エミュレーション

ゲスト パーティションは、TSC 周波数が異なる 2 台のマシン間でライブ マイグレーションされる場合があります。 このような場合は、 参照 TSC ページの TscScale 値を再計算する必要があります。

L0 ハイパーバイザーは、必要に応じて、L1 ハイパーバイザーが TscScale 値を再計算できるようになるまで、移行後にすべての TSC アクセスをエミュレートします。 L1 ハイパーバイザーは、HV_X64_MSR_TSC_EMULATION_CONTROL MSR に書き込むことで TSC エミュレーションを選択できます。 オプトインすると、L0 ハイパーバイザーは、移行が行われた後に TSC アクセスをエミュレートします。

L1 ハイパーバイザーは、HV_X64_MSR_TSC_EMULATION_STATUS MSR を使用して TSC アクセスが現在エミュレートされているかどうかを照会できます。 たとえば、L1 ハイパーバイザーは Live Migration 通知 をサブスクライブし、移行割り込みを受信した後に TSC の状態を照会できます。 また、この MSR を使用して (TscScale 値を更新した後に) TSC エミュレーションをオフにすることもできます。

#define HV_X64_MSR_TSC_EMULATION_CONTROL (0x40000107)
#define HV_X64_MSR_TSC_EMULATION_STATUS (0x40000108)

typedef union
{
    UINT64 AsUINT64;
    struct
    {
        UINT64 Enabled :1;
        UINT64 RsvdZ :63;
    };
 } HV_TSC_EMULATION_CONTROL;

typedef union
{
    UINT64 AsUINT64;
    struct
    {
        UINT64 InProgress : 1;
        UINT64 RsvdP1 : 63;
    };
} HV_TSC_EMULATION_STATUS;

仮想 TLB

ハイパーバイザーによって公開される仮想 TLB は、L2 GPU から GPU への変換をキャッシュするように拡張できます。 論理プロセッサ上の TLB と同様に、仮想 TLB は非コヒーレント キャッシュであり、この非コヒーレンスはゲストに表示されます。 ハイパーバイザーは、TLB を管理する操作を公開します。

直接仮想フラッシュ

ハイパーバイザーは、オペレーティング システムが仮想 TLB をより効率的に管理できるようにするハイパーコール (HvCallFlushVirtualAddressSpaceHvCallFlushVirtualAddressSpaceExHvCallFlushVirtualAddressList、HvCallFlushVirtualAddressListEx) を公開します。 L1 ハイパーバイザーは、ゲストがこれらのハイパーコールを使用することを許可し、それらを処理する責任を L0 ハイパーバイザーに委任することを選択できます。 これには、パーティション 支援ページ (および Intel プラットフォーム上の仮想 VMCS) を使用する必要があります。

使用されている場合、仮想 TLB は、キャッシュされたすべてのマッピングに、それらを作成した入れ子になったコンテキスト (VMCS または VMCB) の識別子を使用してタグ付けします。 L2 ゲストからの直接の仮想フラッシュ ハイパーコールに応答して、L0 ハイパーバイザーは、入れ子になったコンテキストによって作成されたすべてのキャッシュされたマッピングを無効にします。

  • VmId は呼び出し元の VmId と同じです
  • VpId が指定された ProcessorMask に含まれているか、HV_FLUSH_ALL_PROCESSORSが指定されています

直接仮想フラッシュのサポートは、 CPUID リーフ 0x4000000Aで報告されます。

コンフィギュレーション

仮想フラッシュ ハイパーコールの直接処理は、次の方法で有効になります。

  1. 仮想プロセッサ アシスト ページの NestedEnlightenmentsControl.Features.DirectHypercall フィールドを 1 に設定します。
  2. 対応 VMCS または VMCB の EnlightenmentsControl.NestedFlushVirtualHypercall フィールドを 1 に設定します。

L1 ハイパーバイザーを有効にする前に、対応する VMCS/VMCB の次の追加フィールドを構成する必要があります。

  • VpId: 対応する VMCS/VMCB が制御する仮想プロセッサの ID。
  • VmId: 対応する VMCS/VMCB が属している仮想マシンの ID。
  • PartitionAssistPage: パーティション 支援ページのゲスト物理アドレス。

L1 ハイパーバイザーでは、CPUID を介して次の機能もゲストに公開する必要があります。

  • UseHypercallForLocalFlush
  • UseHypercallForRemoteFlush

[Partition Assist]\(パーティションの支援\)

パーティション支援ページは、L1 ハイパーバイザーが割り当てる必要があるページ サイズのページ サイズ領域であり、直接フラッシュ ハイパーコールを使用する前にゼロを割り当てる必要があります。 その GPA は、対応する VMCS/VMCB 内のフィールドに書き込む必要があります。

struct
{
    UINT32 TlbLockCount;
} VM_PARTITION_ASSIST_PAGE;

合成 VM-Exit

呼び出し元のパーティション 支援ページの TlbLockCount が 0 以外の場合、L0 ハイパーバイザーは、直接仮想フラッシュ ハイパーコールを処理した後、合成終了理由を持つ VM-Exit を L1 ハイパーバイザーに配信します。

Intel プラットフォームでは、終了理由 HV_VMX_SYNTHETIC_EXIT_REASON_TRAP_AFTER_FLUSH を含む VM-Exit が配信されます。 AMD プラットフォームでは、終了コードが HV_SVM_EXITCODE_ENL された VM-Exit が配信され、ExitInfo1 が HV_SVM_ENL_EXITCODE_TRAP_AFTER_FLUSH に設定されます。

#define HV_VMX_SYNTHETIC_EXIT_REASON_TRAP_AFTER_FLUSH 0x10000031

#define HV_SVM_EXITCODE_ENL 0xF0000000
#define HV_SVM_ENL_EXITCODE_TRAP_AFTER_FLUSH   (1)

第 2 レベルのアドレス変換

ゲスト パーティションに対して入れ子になった仮想化が有効になっている場合、パーティションによって公開されるメモリ管理ユニット (MMU) には、第 2 レベルのアドレス変換のサポートが含まれます。 第 2 レベルのアドレス変換は、L1 ハイパーバイザーが物理メモリを仮想化するために使用できる機能です。 使用中は、ゲスト物理アドレス (GPO) として扱われる特定のアドレスは、L2 ゲスト物理アドレス (L2 GPO) として扱われ、一連のページング構造を走査することによって GPO に変換されます。

L1 ハイパーバイザーは、第 2 レベルのアドレス空間を使用する方法と場所を決定できます。 各第 2 レベルのアドレス空間は、ゲスト定義の 64 ビット ID 値によって識別されます。 Intel プラットフォームでは、この値は EPT ポインターと同じです。 AMD プラットフォームでは、値は nCR3 VMCB フィールドと等しくなります。

Compatibility

ハイパーバイザーによって公開される第 2 レベルのアドレス変換機能は、一般に、アドレス変換に対する VMX または SVM のサポートと互換性があります。 ただし、次のゲスト監視可能な違いがあります。

  • 内部的には、ハイパーバイザーは、L2 GPU を SPA に変換するシャドウ ページ テーブルを使用する場合があります。 このような実装では、これらのシャドウ ページ テーブルは、大きな TLB としてソフトウェアに表示されます。 ただし、いくつかの違いが観察可能な場合があります。 最初に、シャドウ ページ テーブルは 2 つの仮想プロセッサ間で共有できますが、従来の TLB はプロセッサごとの構造であり、独立しています。 この共有は、1 つの仮想プロセッサによるページ アクセスが、後で別の仮想プロセッサによって使用されるシャドウ ページ テーブル エントリに入力できるために表示される場合があります。
  • 一部のハイパーバイザー実装では、ゲスト ページ テーブルの内部書き込み保護を使用して、内部データ構造 (シャドウ ページ テーブルなど) から MMU マッピングを遅延フラッシュできます。 これらのテーブルへの書き込みはハイパーバイザーによって透過的に処理されるため、これはゲストにはアーキテクチャ上は見えません。 ただし、他のパーティションまたはデバイスによって基になる GPA ページに対して実行される書き込みでは、適切な TLB フラッシュがトリガーされない場合があります。
  • 一部のハイパーバイザー実装では、第 2 レベルのページ 障害によってキャッシュされたマッピングが無効にならない場合があります。

対応する第 2 レベルの TLB フラッシュ

ハイパーバイザーでは、ゲストが第 2 レベルの TLB をより効率的に管理できるようにする一連の拡張機能もサポートされています。 これらの拡張操作は、従来の TLB 管理操作と同じ意味で使用できます。

ハイパーバイザーでは、TLB を無効にするために次のハイパーコールがサポートされています。

Hypercall Description
HvCallFlushGuestPhysicalAddressSpace は、2 番目のレベルのアドレス空間内のキャッシュされた L2 GPA から GPA へのマッピングを無効にします。
HvCallFlushGuestPhysicalAddressList は、キャッシュされた GVA/L2 GPA を、第 2 レベルのアドレス空間の一部内の GPA マッピングに無効にします。

AMD プラットフォームでは、すべての TLB エントリに ASID (アドレス空間識別子) でアーキテクチャ上のタグが付けられます。 ASID を無効にすると、ASID に関連付けられているすべての TLB 全体が無効になります。 入れ子になったハイパーバイザーは、必要に応じて、 HV_SVM_ENLIGHTENED_VMCB_FIELDSで EnlightenedNptTlb を "1" に設定することで、"対応 TLB" を選択できます。 入れ子になったハイパーバイザーが対応をオプトインすると、ASID の無効化は、第 1 レベルのアドレス変換 (つまり仮想アドレス空間) から派生した TLB 全体をフラッシュするだけです。 入れ子になったページ テーブル (NPT) から派生した TLB エントリをフラッシュし、L0 ハイパーバイザーにシャドウ ページ テーブルの再構築を強制するには、HvCallFlushGuestPhysicalAddressSpace または HvCallFlushGuestPhysicalAddressList ハイパーコールを使用する必要があります。

入れ子になった仮想化の例外

Intel プラットフォーム上。 L1 ハイパーバイザーは、ページ フォールト例外クラスで仮想化例外を組み合わせることを選択できます。 L0 ハイパーバイザーは、ハイパーバイザーの入れ子になった仮想化機能の CPUID リーフで、このエンライトメントのサポートをアドバタイズします。

この対応を有効にするには、[仮想プロセッサ アシスト] ページの データ構造HV_NESTED_ENLIGHTENMENTS_CONTROL VirtualizationException を "1" に設定します。

入れ子になった仮想化 MSR

入れ子になった VP インデックス レジスタ

L1 ハイパーバイザーは、現在のプロセッサの基になる VP インデックスを報告する MSR を公開します。

MSR アドレス レジスタ名 Description
0x40001002 HV_X64_MSR_NESTED_VP_INDEX 入れ子になったルート パーティションで、現在のプロセッサの基になる VP インデックスを報告します。

入れ子になった SynIC MSR

入れ子になったルート パーティションでは、次の MSR を使用して、ベース ハイパーバイザーの対応する SynIC レジスタ にアクセスできます。

基になるプロセッサのインデックスを検索するには、呼び出し元が最初に HV_X64_MSR_NESTED_VP_INDEX を使用する必要があります。

MSR アドレス レジスタ名 基になる MSR
0x40001080 HV_X64_MSR_NESTED_SCONTROL HV_X64_MSR_SCONTROL
0x40001081 HV_X64_MSR_NESTED_SVERSION HV_X64_MSR_SVERSION
0x40001082 HV_X64_MSR_NESTED_SIEFP HV_X64_MSR_SIEFP
0x40001083 HV_X64_MSR_NESTED_SIMP HV_X64_MSR_SIMP
0x40001084 HV_X64_MSR_NESTED_EOM HV_X64_MSR_EOM
0x40001090 HV_X64_MSR_NESTED_SINT0 HV_X64_MSR_SINT0
0x40001091 HV_X64_MSR_NESTED_SINT1 HV_X64_MSR_SINT1
0x40001092 HV_X64_MSR_NESTED_SINT2 HV_X64_MSR_SINT2
0x40001093 HV_X64_MSR_NESTED_SINT3 HV_X64_MSR_SINT3
0x40001094 HV_X64_MSR_NESTED_SINT4 HV_X64_MSR_SINT4
0x40001095 HV_X64_MSR_NESTED_SINT5 HV_X64_MSR_SINT5
0x40001096 HV_X64_MSR_NESTED_SINT6 HV_X64_MSR_SINT6
0x40001097 HV_X64_MSR_NESTED_SINT7 HV_X64_MSR_SINT7
0x40001098 HV_X64_MSR_NESTED_SINT8 HV_X64_MSR_SINT8
0x40001099 HV_X64_MSR_NESTED_SINT9 HV_X64_MSR_SINT9
0x4000109A HV_X64_MSR_NESTED_SINT10 HV_X64_MSR_SINT10
0x4000109B HV_X64_MSR_NESTED_SINT11 HV_X64_MSR_SINT11
0x4000109C HV_X64_MSR_NESTED_SINT12 HV_X64_MSR_SINT12
0x4000109D HV_X64_MSR_NESTED_SINT13 HV_X64_MSR_SINT13
0x4000109E HV_X64_MSR_NESTED_SINT14 HV_X64_MSR_SINT14
0x4000109F HV_X64_MSR_NESTED_SINT15 HV_X64_MSR_SINT15