次の方法で共有


入れ子になった仮想化

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

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

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

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

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

対応 VMCS (Intel)

Intel プラットフォームでは、仮想化ソフトウェアは仮想マシン制御データ構造 (VMCS) を使用して、仮想化に関連するプロセッサの動作を構成します。 VMCS は、VMPTRLD 命令を使用してアクティブにし、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 が対応する VMCS を変更するたびにクリアする必要があります。そうしないと、L0 ハイパーバイザーで古いバージョンが使用される可能性があります。

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

機能の検出

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

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

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

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

ほとんどの VMCS フィールドでは、VMCS フィールドが VM でサポートされている場合、アーキテクチャ機能検出メカニズムによって決定される VM に対応する VMCS フィールドがサポートされます。 例外は 、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 GPO から GPO への変換をキャッシュするように拡張できます。 論理プロセッサ上の TLB と同様に、仮想 TLB は非コヒーレント キャッシュであり、この非コヒーレンスはゲストに表示されます。 ハイパーバイザーは、TLB を管理する操作を公開します。

直接仮想フラッシュ

ハイパーバイザーはハイパーコール (HvCallFlushVirtualAddressSpaceHvCallFlushVirtualAddressSpaceExHvCallFlushVirtualAddressListHvCallFlushVirtualAddressListEx) を公開し、オペレーティング システムが仮想 TLB をより効率的に管理できるようにします。 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

[パーティション アシスト] ページ

パーティション支援ページは、直接フラッシュ ハイパーコールを使用する前に 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)

Second Level Address Translation

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

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

互換性

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

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

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

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

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

Hypercall 説明
HvCallFlushGuestPhysicalAddressSpace は、キャッシュされた L2 GPA から GPA へのマッピングを、2 番目のレベルのアドレス空間内で無効にします。
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 リーフで、このエンライトのサポートをアドバタイズします。

この対応を有効にするには、Virtual Processor Assist ページの HV_NESTED_ENLIGHTENMENTS_CONTROL データ構造で VirtualizationException を "1" に設定します。

入れ子になった仮想化 MSR

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

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

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

入れ子になった SynIC MSR

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

基になるプロセッサのインデックスを見つけるには、呼び出し元が最初に 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