pcivirt.h ヘッダー

仮想マシンへの VM の公開に使用されるインターフェイスを使用するためのリファレンス ガイド。

PCI Express Single-Root I/O Virtualization (SR-IOV) 仕様に準拠しているデバイスは、デバイスに複数のインターフェイスを提供できます。 仮想関数 (VFs) と呼ばれるこれらのインターフェイスは独立しており、物理機能 (PF) と呼ばれる初期デバイス インターフェイスを介して提供されます。 たとえば、SR-IOV をサポートするイーサネット NIC は、1 つの物理イーサネット ポート (物理ネットワークに接続) と多数の仮想イーサネット ポートを持つスイッチを持つよう設計できます。

PF の構成領域を使用すると、PF ドライバーは、メモリ マップされた I/O 領域やメッセージシグナル割り込みを含む VF の PCI リソースを管理できます。 VM は完全なデバイスのサブセットであるため、多機能パッケージの従来の関数よりもハードウェアで公開するコストが低くなる可能性があります。 これにより、デバイス メーカーはより多くのインターフェイスを構築し、共有リソースを一元的に管理できます。

Windows がコンピューター ハードウェアで直接実行されている場合、デバイス ドライバーは、プラグ アンド プレイ、電源管理、割り込み管理、およびその他のタスクに関連する操作に参加します。 信頼された Windows バス ドライバーとハードウェア抽象化レイヤー (HAL) 独自のバス構成とバス全体の構成。 ドライバーは同じ特権レベル内で実行され、カーネル モードでは信頼の境界はありません。

Windows が仮想マシン (VM) で実行されている場合、これらの前提条件は適用されません。 VM は、特権のない VM の制御下に置くことができます。 ただし、システムのセキュリティまたはパフォーマンスが影響を受けないように、ハードウェアをセキュリティチェックする必要があります。

VF で実行されているドライバーが構成領域の読み取りまたは書き込みを要求すると、要求は仮想化スタックによって受信され、SR-IOV デバイスの PF ドライバーに送信されます。 PF ドライバーは、これらの要求に応答し、VF の詳細を提供する必要があります。 PF ドライバーでは、ハードウェアに渡される構成の読み取りまたは書き込み要求が必要になる場合があります。

スタックは I/O MMU を使用して、デバイスが公開するさまざまなインターフェイスからのトラフィックを区別し、デバイスがアクセスできるメモリの領域と生成できる割り込みに関するポリシーを適用します。

PCI 仮想化。

ハードウェア要件

SR-IOV デバイス割り当てに使用するシステムは、SR-IOV ネットワークとダイレクト デバイス割り当ての要件を満たしている必要があります。 システムには IOMMU が必要です。その IOMMU は、デバイスをオペレーティング システムに制御できるように構成する必要があります。また、PCIe ACS (Access Control サービス) を有効にして、オペレーティング システムで使用するように構成する必要があります。 最後に、問題のデバイスは、行ベースの割り込みを使用しないでください。また、ATS (アドレス変換サービス) を必要としてはなりません。

詳細については、次を参照してください。

Hyper-V の SR-IOV について知りたかったこと。 第 1 部

個別のデバイスの割り当て - 説明と背景

システムでデバイスの割り当てがサポートされているかどうか、および特定の PCI デバイスがデバイス割り当てに使用できるかどうかを判断するには、次の手順を実行します。

個別のデバイス割り当てスクリプト

SR-IOV デバイスのクエリ

GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICEは、SR-IOV デバイスのドライバーによって提供されるデバイス クラス インターフェイスです。 この GUID は、デバイスの仮想化関連機能の管理に使用されるさまざまな関数テーブルを公開するすべてのデバイス スタックに対してクエリを実行する方法を提供します。 ドライバーが GUID を登録すると、IRP_MN_QUERY_INTERFACEを送信することで個々の機能が検出されます。 ドライバーは、GUID_SRIOV_DEVICE_INTERFACE_STANDARDでその要求に応答する必要があります。 ドライバーは、IOCTL_SRIOV_NOTIFICATIONとIOCTL_SRIOV_EVENT_COMPLETEも処理する必要があります。

特権 VM で実行されるSR_IOV デバイスのドライバーは、ホスト OS です。 マシン全体のプラグ アンド プレイと電源管理を所有し、特権のない VM で PCI Express SR-IOV 仮想関数を公開します。GUID_SRIOV_DEVICE_INTERFACE_STANDARDを提供する必要があります (ヘッダー Pcivirt.h で定義されています)。 そのドライバーは、FDO を作成する PCI Express SR-IOV 物理関数 (PF) ドライバーであるか、FDO がポート ドライバーによって管理されている場合は、そのデバイス ノードの下位フィルターである可能性があります。

ドライバーが VM の構成空間にアクセスできるように、デバイス インターフェイスが必要です。

PF ドライバーのEVT_WDF_DRIVER_DEVICE_ADD実装で、次のタスクを実行します。

  • WdfDeviceCreate を呼び出して関数デバイス オブジェクト (FDO) を作成した後、WdfDeviceCreateDeviceInterface を呼び出してGUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE登録します。 これにより、仮想化スタックは、SR-IOV デバイスへのデバイス ハンドルを取得できます。
  • GUID_SRIOV_DEVICE_INTERFACE_STANDARDを公開します。
    • SRIOV_DEVICE_INTERFACE_STANDARD構造体を初期化し、PF ドライバーによって実装されるコールバック関数の関数ポインターにメンバーを設定します。
    • WDF_QUERY_INTERFACE_CONFIG_INITを呼び出して構造体を構成します。
    • WdfDeviceAddQueryInterface を呼び出して、FDO にインターフェイスを登録します。
    // Make the device visible as an assignable device.
    //
    status = WdfDeviceCreateDeviceInterface(
        fdo,
        &GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE,
        NULL);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
                    "Failed to create interface: %!STATUS!",
                    status);
        goto Cleanup;
    }

    //
    // Expose SRIOV_DEVICE_INTERFACE_STANDARD
    //
    RtlZeroMemory(&sriovInterface, sizeof(sriovInterface));
    sriovInterface.Size = sizeof(sriovInterface);
    sriovInterface.Version = 1;
    sriovInterface.Context = deviceContext;
    sriovInterface.InterfaceReference = Virtualization_ReferenceInterface;
    sriovInterface.InterfaceDereference = Virtualization_DereferenceInterface;
    sriovInterface.ReadVfConfig = Virtualization_ReadConfig;
    sriovInterface.WriteVfConfig = Virtualization_WriteConfig;
    sriovInterface.ReadVfConfigBlock = Virtualization_ReadBlock;
    sriovInterface.WriteVfConfigBlock = Virtualization_WriteBlock;
    sriovInterface.ResetVf = Virtualization_ResetFunction;
    sriovInterface.SetVfPowerState = Virtualization_SetPowerState;
    sriovInterface.GetDeviceLocation = Virtualization_GetDeviceLocation;
    sriovInterface.GetVendorAndDevice = Virtualization_GetVendorAndDevice;
    sriovInterface.QueryProbedBars = Virtualization_QueryProbedBars;
    sriovInterface.QueryLuid = Virtualization_QueryLuid;


    WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig,
                                    (PINTERFACE)&sriovInterface,
                                    &GUID_SRIOV_DEVICE_INTERFACE_STANDARD,
                                    NULL);

    status = WdfDeviceAddQueryInterface(fdo, &qiConfig);

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
                    "WdfDeviceAddQueryInterface failed: %!STATUS!\n",
                    status);
        goto Cleanup;
    }

プラグ アンド プレイ イベントの処理

仮想化スタックは、VM に適切なメッセージを送信し、応答 (タイムアウトあり) を待機し、応答しない VM の場合は、PnP イベントの拒否、特権のない VM からのデバイスの突然の削除などの適切なアクションを適用する役割を担います。 GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICEを実装する PF ドライバーは、仮想化スタックが PnP イベントに対応できるようにするこれらの I/O 制御要求も処理する必要があります。

  • 仮想化スタックは、最初にデバイスにIOCTL_SRIOV_ATTACHを送信します。 これにより、仮想化スタックに特定の PnP イベントについて通知する必要があることをデバイスに通知します。

  • これは、仮想化スタックがIOCTL_SRIOV_DETACHを送信するまで有効です。

  • 仮想化スタックは、IOCTL_SRIOV_NOTIFICATION要求を送信して、PnP イベントに関するデバイスに対してクエリを実行します。 PF ドライバーは、IOCTL_SRIOV_NOTIFICATION要求を完了することで、PnP イベントの仮想化スタックに通知できます。

  • 仮想化スタックは、IOCTL_SRIOV_EVENT_COMPLETEを送信することで、これらのイベントのブロックを解除します。

pcivirt.h には、次のプログラミング インターフェイスが含まれています。

IOCTL

 
IOCTL_SRIOV_ATTACH

要求は、仮想化スタックが SR-IOV デバイスによって受信プラグ アンド プレイイベントに登録することを示します。
IOCTL_SRIOV_DETACH

要求は、仮想化スタックがプラグ アンド プレイ イベントの登録を解除することを示します (以前はIOCTL_SRIOV_ATTACH要求を通じて登録されています)。
IOCTL_SRIOV_EVENT_COMPLETE

要求は、仮想化スタックまたは SR-IOV デバイスが、SRIOV_PF_EVENTに記載されているイベントのいずれかを受信したことを示します。
IOCTL_SRIOV_INVALIDATE_BLOCK

IOCTL_SRIOV_INVALIDATE_BLOCK要求は、仮想化スタックが指定した構成ブロックの内容をリセットすることを示します。
IOCTL_SRIOV_MITIGATED_RANGE_UPDATE

IOCTL_SRIOV_MITIGATED_RANGE_UPDATE要求は、仮想化スタックが軽減策の範囲に更新することを示します。
IOCTL_SRIOV_NOTIFICATION

要求は、SRIOV_PF_EVENTに一覧表示されているイベントのいずれかが発生したときに仮想化スタックに通知されることを示します。
IOCTL_SRIOV_PROXY_QUERY_LUID

この要求は、インターフェイスを実装するSR_IOV デバイスのローカル一意識別子を提供します。
IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT

要求によって、軽減する必要があるメモリ マップ I/O 領域の範囲が決まります。
IOCTL_SRIOV_QUERY_MITIGATED_RANGES

要求によって、インターセプトを配置する必要がある特定の範囲が決定されます。

コールバック関数

 
READ_WRITE_MITIGATED_REGISTER

軽減されたアドレス空間への読み取りまたは書き込み。
SRIOV_GET_DEVICE_LOCATION

PCI セグメント、バス、デバイス、関数番号など、バス上の PCI デバイスの現在の場所に関する情報を取得します。
SRIOV_GET_MMIO_REQUIREMENTS

このコールバック関数はサポートされていません。
SRIOV_GET_RESOURCE_FOR_BAR

特定のベース アドレスレジスタ (BAR) の変換されたリソースを取得します。
SRIOV_GET_VENDOR_AND_DEVICE_IDS

VF のより汎用的なプラグ アンド プレイ ID を生成するために使用する PCI Express SR-IOV 仮想関数 (VF) のベンダー ID とデバイス ID を指定します。 これらの ID は、VF の構成空間から直接読み取ることはできません。
SRIOV_QUERY_LUID

SR-IOV デバイスのローカル一意識別子を取得します。
SRIOV_QUERY_LUID_VF

一意の識別子を指定して、PCI Express SR-IOV 仮想関数 (VF) を取得します。
SRIOV_QUERY_PROBED_BARS

値 -1 が最初に書き込まれた場合は、物理関数の (PF) ベース アドレス レジスタ (BAR) から読み取られたデータに対してクエリを実行します。
SRIOV_QUERY_PROBED_BARS_2

指定された PCI Express SR-IOV 仮想関数 (VF) ベース アドレス レジスタ (BAR) から読み取られたデータに対して、値 -1 が最初に書き込まれた場合にクエリを実行します。
SRIOV_QUERY_VF_LUID

PCI Express SR-IOV 仮想関数 (VF) のローカル一意識別子を取得します。
SRIOV_READ_BLOCK

PCI Express SR-IOV 仮想関数 (VF) の指定された構成ブロックからデータを読み取ります。
SRIOV_READ_CONFIG

指定した PCI Express SR-IOV 仮想関数 (VF) の構成領域からデータを読み取ります。
SRIOV_RESET_FUNCTION

指定した PCI Express SR-IOV 仮想関数 (VF) をリセットします。
SRIOV_SET_POWER_STATE

指定した PCI Express SR-IOV 仮想関数 (VF) の電源状態を設定します。
SRIOV_WRITE_BLOCK

PCI Express SR-IOV 仮想関数 (VF) の指定された構成ブロックにデータを書き込みます。
SRIOV_WRITE_CONFIG

PCI Express SR-IOV 仮想関数 (VF) に構成データを書き込みます。

構造

 
MITIGABLE_DEVICE_INTERFACE

mitigable デバイス インターフェイスの物理関数 (PF) ドライバーによって実装されるコールバック関数への関数ポインターを格納します。
SRIOV_DEVICE_INTERFACE_STANDARD

SR-IOV デバイスの デバイス スタックに物理関数 (PF) ドライバーによって実装されるコールバック関数への関数ポインターを格納します。
SRIOV_DEVICE_INTERFACE_STANDARD_2

SR-IOV デバイスの デバイス スタックに物理関数 (PF) ドライバーによって実装されるコールバック関数への関数ポインターを格納します。 これは、SRIOV_DEVICE_INTERFACE_STANDARDの拡張バージョンです。
SRIOV_INVALIDATE_BLOCK

構成ブロック情報が含まれます。 この構造体は、IOCTL_SRIOV_INVALIDATE_BLOCK要求で使用されます。
SRIOV_MITIGATED_RANGE_COUNT_INPUT

この構造体は、IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT要求への入力バッファーとして使用され、軽減する必要があるメモリ マップ I/O 領域の範囲を決定します。
SRIOV_MITIGATED_RANGE_COUNT_OUTPUT

この構造体は、軽減する必要があるメモリ マップ I/O 領域の範囲の配列を含むIOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT要求によって受信される出力バッファーです。
SRIOV_MITIGATED_RANGE_UPDATE_INPUT

この構造体は、メモリ マップされた I/O 領域を軽減する必要がある仮想関数 (VF) を示すために、IOCTL_SRIOV_MITIGATED_RANGE_UPDATE要求への入力バッファーとして使用されます。
SRIOV_MITIGATED_RANGE_UPDATE_OUTPUT

この構造体は、メモリ マップされた I/O 領域が軽減された仮想関数 (VF) を示す、IOCTL_SRIOV_MITIGATED_RANGE_UPDATE要求によって受信された出力バッファーです。
SRIOV_MITIGATED_RANGES_INPUT

この構造体は、インターセプトを配置する必要がある特定の範囲を取得するためのIOCTL_SRIOV_QUERY_MITIGATED_RANGES要求の入力バッファーです。
SRIOV_MITIGATED_RANGES_OUTPUT

この構造体は、インターセプトを配置する必要がある特定の範囲を取得するために、IOCTL_SRIOV_QUERY_MITIGATED_RANGES要求によって受信される出力バッファーです。
SRIOV_PNP_EVENT_COMPLETE

SR-IOV 物理関数 (PF) ドライバーが偶数の完了に対して設定する必要があるイベントの状態プラグ アンド プレイ格納します。 この構造体は、IOCTL_SRIOV_EVENT_COMPLETE要求の入力バッファーで使用されます。
SRIOV_PROXY_QUERY_LUID_OUTPUT

インターフェイスを実装するSR_IOV デバイスのローカル一意識別子を格納します。 この構造体は、IOCTL_SRIOV_PROXY_QUERY_LUID要求の出力バッファーです。

列挙

 
SRIOV_PF_EVENT

SR-IOV デバイスのイベント値を定義します。