IOMMU DMA の再マッピング

このページでは、Windows 11 22H2 (WDDM 3.0) で導入された IOMMU DMA 再マップ機能 (IOMMUv2) について説明します。 WDDM 3.0 よりも前の IOMMU GPU 分離については、IOMMU ベースの GPU 分離を参照してください。

概要

WDDM 3.0 までは、 Dxgkrnl は 1 対 1 の物理再マップによる IOMMU 分離のみをサポートしていました。つまり、GPU によってアクセスされる論理ページは同じ物理ページ番号に変換されていました。 IOMMU DMA の再マップにより、GPU は 1:1 でマップされなくなった論理アドレスを介してメモリにアクセスできます。 代わりに、 Dxgkrnl は論理的に連続したアドレス範囲を提供できます。

Dxgkrnl は GPU に制限を課します。デバイスを起動するには、GPU がすべての物理メモリにアクセスできる必要があります。 GPU の最も高い可視アドレスがシステムにインストールされている最も高い物理アドレスを超えていない場合、 Dxgkrnl はアダプタの初期化に失敗します。 今後のサーバーとハイエンド ワークステーションは、多くの GPU の一般的な 40 ビットのアドレス空間の制限を超える 1 TB を超えるメモリで構成できます。 DMA 再マッピングは、GPU がこの環境で動作できるようにするメカニズムとして使用されます。

起動時に、Dxgkrnl は、デバイスの最も高いアクセス可能な物理アドレスをシステムにインストールされているメモリと比較することによって、論理再マッピングが必要かどうかを判断します。 必要な場合は、DMA 再マッピングを使用して、GPU の可視境界内にある論理アドレス範囲をシステム上の任意の物理メモリにマップします。 たとえば、GPU に 1 TB の制限がある場合、Dxgkrnl は [0, 1 TB) から論理アドレスを割り当てます。これにより、IOMMU を介してシステム上の任意の物理メモリにマップできます。

論理アダプタと物理アダプタ

Dxgkrnl は、論理アダプタと物理アダプタの概念を区別します。 物理アダプタは、LDA チェーン内の他のデバイスとリンクされている場合とリンクされていない場合がある個々のハードウェア デバイスを表します。 論理アダプタは、1 つ以上のリンクされた物理アダプタを表します。

1 つの IOMMU DMA ドメインが論理アダプタごとに作成され、リンクされているすべての物理アダプタに接続されます。 したがって、すべての物理アダプターは、同じドメインと同じ物理メモリのビューを共有します。

統合 GPU とディスクリート GPU のサポート

IOMMU DMA の再マッピングでは、定義上、システム内のすべての物理メモリにアクセスするように設計されている必要のある統合 GPU にはほとんど価値を提供しないため、統合パーツに対するサポートの実装は省略可能ですが、推奨されます。

ディスクリート GPU は、WDDM 3.0 認定の要件である IOMMU DMA 再マッピングをサポートしている必要があります。

DDI の変更内容

IOMMU DMA の再マッピングをサポートするために、次の DDI 変更が行われました。

ドライバーの能力

線形再マップをサポートするには、次の 2 セットのドライバー キャップが必要です。

  • ドライバーは、その物理メモリの制限について Dxgkrnl に通知する必要があります。つまり、DXGKQAITYPE_PHYSICAL_MEMORY_CAPS とその関連する DXGK_PHYSICAL_MEMORY_CAPS 構造を介して最も可視性の高い物理アドレスについてです。
  • ドライバーは、DXGKQAITYPE_IOMMU_CAPSとそれに関連付けられている DXGK_IOMMU_CAPS 構造を介した IOMMU 線形再マップのサポートを示す必要があります。 サポートを示すことによって、ドライバーは、後で説明するすべての DDI がサポートされ、使用されていることを示します。

これら両方のキャップは、DxgkrnlDXGKDDI_START_DEVICE を介してデバイスを起動する前に指定する必要があります。これにより、メモリにアクセスする前にデバイスを作成して IOMMU ドメインに接続できます。 線形再マッピングは、デバイスが既存の物理メモリを参照していない場合にのみ実行できます。

排他アクセス

IOMMU ドメインのアタッチおよびデタッチは非常に高速ですが、現在はアトミックではありません。 これは、PCIe 経由で発行されたトランザクションが、異なるマッピングを持つ IOMMU ドメインにスワップされる間に正しく変換されることが保証されていないことを意味します。

この状況を処理するには、Windows 10 バージョン 1803 (WDDM 2.4) 以降、KMD は Dxgkrnl が呼び出す次の DDI ペアを実装する必要があります。

ドライバーは、デバイスが新しい IOMMU ドメインにスイッチされるたびに、そのハードウェアがサイレントであることを確認する必要があります。 つまり、ドライバーは、これら 2 つの呼び出しの間にデバイスからシステム メモリの読み取りまたは書き込みが行われないことを確認する必要があります。

これら 2 つの呼び出しの間に、 Dxgkrnl は次のことを保証します。

  • スケジューラが中断されていること。 すべてのアクティブなワークロードがフラッシュされ、新しいワークロードはハードウェアに送信されたり、ハードウェアでスケジュールされたりしないこと。
  • 他の DDI 呼び出しが行われないこと。

これらの呼び出しの一環として、ドライバーは、OS からの明示的な通知がなくても、排他アクセス中に割り込みを無効にして抑制 (Vsync 割り込みを含む) を選択できます。

アドレス記述子リスト

物理アクセス モードと論理アクセス モードの両方をサポートし、実行時に 2 つのモードをシームレスに切り替えるために、Dxgkrnl はアドレス記述子リスト (ADL) を記述するDXGK_ADL 構造を提供します。 このデータ構造は MDL に似ていますが、物理的または論理的なページの配列を記述しています。 これらのページは論理ページである場合があるため、ADL によって記述されたアドレスを仮想アドレスにマップして CPU に直接アクセスすることはできません。

DxgkddiBuildpagingbuffer の DXGK_OPERATION_MAP_APERTURE_SEGMENT2 操作

VidMm は、以前のバージョンでは論理アドレスと互換性のない MDL を使用していたため、メモリをアパーチャセグメントにマッピングするための DXGK_OPERATION_MAP_APERTURE_SEGMENT2 ページング バッファー モードを提供します。 論理アドレスの再マップをサポートする WDDM 3.0 ドライバーの DxgkddiBuildpagingbuffer コールバックは、DXGK_OPERATION_MAP_APERTURE_SEGMENT2 モードへの呼び出しを受信し、元の DXGK_OPERATION_MAP_APERTURE_SEGMENT モードへの呼び出しは受信しなくなります。

この操作は、論理 DMA の再マッピングをサポートするために必要です。 これは元の操作と同様に動作しますが、MDL ではなくDXGK_ADL を提供します。

typedef enum _DXGK_BUILDPAGINGBUFFER_OPERATION
{
#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_9)
    DXGK_OPERATION_MAP_APERTURE_SEGMENT2 = 17,
#endif //  DXGKDDI_INTERFACE_VERSION
};

// struct _DXGKARG_BUILDPAGINGBUFFER:
struct
{
    HANDLE  hDevice;
    HANDLE  hAllocation;
    UINT    SegmentId;
    SIZE_T  OffsetInPages;
    SIZE_T  NumberOfPages;
    DXGK_ADL Adl;
    DXGK_MAPAPERTUREFLAGS Flags;
    ULONG   AdlOffset;
    PVOID   CpuVisibleAddress;
} MapApertureSegment2;

DXGK_OPERATION_MAP_APERTURE_SEGMENT2 操作にオプトインするには、ドライバーがメモリ管理キャップMapApertureSegment2 呼び出しのサポートを示す必要があります。

typedef struct _DXGK_VIDMMCAPS {
  union {
    struct {
        ...
        UINT MapAperture2Supported : 1;
        ...
    }
    ...
} DXGK_VIDMMCAPS;

DXGK_VIDMMCAPS メモリ管理キャップは、DXGK_DRIVERCAPS データ構造の一部です。 このサポートが有効になっていないと、ドライバーは DMA の再マッピング (つまり、論理アドレスの再マッピング) 機能を使用できません。

一部のドライバーでは、MapApertureSegment2 呼び出し中にメモリへの CPU アクセスが必要になる場合があります。 この機能は、必要に応じて別の MapApertureSegment2.CpuVisibleAddress パラメーターを使用して提供されます。 このアドレスは、割り当てがアパーチャ セグメントにマップされている限り有効なカーネル モードの仮想アドレスです。 つまり、このアドレスは、同じ割り当ての対応する DXGK_OPERATION_UNMAP_APERTURE_SEGMENT 呼び出し後すぐに解放されます。

このアドレスはすべての割り当てに必要なわけではない可能性があるため、 必要なタイミングを示すためにMapApertureCpuVisible フラグが割り当てフラグ に追加されました。

MapApertureCpuVisible が指定されていない場合、MapApertureSegment2.CpuVisibleAddressDXGK_OPERATION_MAP_APERTURE_SEGMENT2 操作で NULL になります。

MapApertureCpuVisibleDxgkDdiBuildPagingBufferMapAperatureSegment2 機能の一部であるため、このフィールドを使用するには、ドライバー が DXGK_VIDMMCAPS MapAperature2Supported を設定する必要があります。 MapAperature2Supported が設定されていないが、ドライバーが MapApertureCpuVisible を指定している場合、DxgkDdiCreateAllocation の呼び出しは失敗します。

さらに、DXGK_OPERATION_MAP_APERTURE_SEGMENT2 操作を受信するには、ドライバーが DXGK_ALLOCATIONINFOFLAGS_WDDM2_0 AccessedPhysically フラグを設定する必要があります。 AccessedPhysically が設定されていない場合、サポートされているセグメント セット内のアパーチャセグメントを指定する割り当ては暗黙的なシステム メモリ セグメントにアップグレードされ、MAP_APERTURE呼び出しを受信しません (マップする絞り範囲がないため)。

要約すると、システム メモリ割り当ての CPU アドレスを適切に受信するには、ドライバーで次のフラグ/キャップを設定する必要があります。

  • DXGK_DRIVERCAPS::MemoryManagementCaps.MapAperture2Supported = 1
  • DXGK_ALLOCATIONINFOFLAGS_WDDM2_0::MapApertureCpuVisible = 1
  • DXGK_ALLOCATIONINFOFLAGS_WDDM2_0::AccessedPhysically = 1

MapApertureSegment2 呼び出しでは、論理マッピングが有効になっている場合、ADL は常に初期化され、連続として渡されます。 ドライバーは、ADL フラグをチェックして割り当てが連続しているかどうかを判断し、それに応じて動作する必要があります。

メモリ管理サービス

メモリ管理機能には、次の 3 つの基本的な要件があります。

  1. 物理メモリを管理する能力。 これには、MmAllocatePagesforMdlMmAllocateContiguousMemory などの非ページ化メモリ機能を介したメモリの割り当て、および ZwCreateSectionZwAllocateVirtualMemory などのページ化メモリ機能が含まれる場合があります。 IO 空間範囲を表現する能力も必要となります。

  2. 物理メモリから GPU可視化論理アドレスをマップする能力。 これにより、呼び出し元には、GPU がアクセスするようにプログラミングできる論理ページの一覧 (MDL の PFN 配列に類似するもの) が提供されます。 これらの機能を呼び出すと、基になる物理ページがロックされ、ページ化できないことが保証されます。

  3. 指定したキャッシュの種類 (Cached と WriteCombined) を使用して、ユーザー モードとカーネル モードの両方で物理メモリから CPU 仮想アドレスをマップする能力。

次の表に、論理/仮想ビューでの物理メモリの割り当てとマッピングについて説明するために導入された DDI と関連する入力構造を示します。 これらの DDI は、IOMMU マッピングを管理するためにドライバーに提供された以前のコールバック (DxgkCbAllocatePagesforMdlDxgkCbAllocateContiguousMemoryDxgkCbMapMdlToIoMmu) を置き換えるために更新されたセットです。 論理再マップをサポートする WDDM 3.0 ドライバーの場合、これらの古いコールバック機能は非推奨となり、使用できません。 ドライバーは、代わりに、次のメモリ管理コールバック機能を使用する必要があります。

コールバック機能は IRQL <= APC_LEVEL で呼び出す必要があります。 WDDM 3.2 以降では、これらの機能のいずれかを呼び出すドライバーは、IRQL がDISPATCH_LEVEL以上の場合、この要件とバグに対して検証されます。

コールバック 関連付けられたコールバック構造
DXGKCB_CREATEPHYSICALMEMORYOBJECT DXGKARGCB_CREATE_PHYSICAL_MEMORY_OBJECT
DXGKCB_DESTROYPHYSICALMEMORYOBJECT DXGKARGCB_DESTROY_PHYSICAL_MEMORY_OBJECT
DXGKCB_MAPPHYSICALMEMORY DXGKARGCB_MAP_PHYSICAL_MEMORY
DXGKCB_UNMAPPHYSICALMEMORY DXGKARGCB_UNMAP_PHYSICAL_MEMORY
DXGKCB_ALLOCATEADL DXGKARGCB_ALLOCATE_ADL
DXGKCB_FREEADL
DXGKCB_OPENPHYSICALMEMORYOBJECT DXGKARGCB_OPEN_PHYSICAL_MEMORY_OBJECT
DXGKCB_CLOSEPHYSICALMEMORYOBJECT DXGKARGCB_CLOSE_PHYSICAL_MEMORY_OBJECT

INF の変更

サポートされているデバイスの種類ごとに、次のレジストリ キーと値を INF の適切なセクションに追加する必要があります。

[DMAr.reg]
; Add REG_DWORD 'DmaRemappingCompatible' with value of 3 
HKR,Parameters,DmaRemappingCompatible,0x00010001,```3

この値は、デバイスが DMA 再マッピングをサポートしていることを PnP に通知します。 Dxgkrnl と HAL はその後、使用する必要があるマッピング モードの種類 (再マッピング、パススルーなど) を決定するために調整されます。

このレジストリ キーは以前のバージョンの Windows に存在していましたが、値 '3' は Windows 10 バージョン 1803 (WDDM 2.4) 以降のユニークなものとなり、サポートされていない古いビルドでは無視されます。 これにより、ドライバーは INF でこのキーを設定でき、互換性の問題を心配する必要はありません。