共用方式為


IOMMU DMA 重新對應

此頁面描述 Windows 11 22H2 (WDDM 3.0) 中引進的 IOMMU DMA 重新對應功能 (IOMMUv2)。 如需 WDDM 3.0 之前 IOMMU GPU 隔離的相關信息,請參閱 IOMMU 型 GPU 隔離

概觀

在 WDDM 3.0 之前, Dxgkrnl 僅支援 IOMMU 隔離到 1:1 實體重新對應,這表示 GPU 存取的邏輯頁面會轉譯為相同的實體頁碼。 IOMMU DMA 重新對應可讓 GPU 透過不再對應 1:1 的邏輯位址來存取記憶體。 相反地, Dxgkrnl 能夠提供邏輯連續的位址範圍。

Dxgkrnl 會對 GPU 施加限制:GPU 必須能夠存取所有物理記憶體,才能讓裝置啟動。 如果 GPU 的最高可見位址未超過系統上所安裝的最高實體位址, Dxgkrnl 會讓適配卡的初始化失敗。 即將推出的伺服器和高端工作站可以設定超過 1 TB 的記憶體,以跨越許多 GPU 的一般 40 位位址空間限制。 DMA 重新對應是用來讓 GPU 在此環境中運作的機制。

在啟動時, Dxgkrnl 會比較裝置的最高可存取實體位址與系統上所安裝的記憶體,以判斷是否需要邏輯重新對應。 如有必要,會使用 DMA 重新對應,將 GPU 可見界限內的邏輯位址範圍對應至系統上的任何物理記憶體。 例如,如果 GPU 的限制為 1 TB, 則 Dxgkrnl 會從 [0, 1 TB] 配置邏輯位址,然後透過 IOMMU 對應至系統上的任何物理記憶體。

邏輯與實體配接器

Dxgkrnl 區分邏輯和實體配接器的概念。 實體適配卡代表可能與 LDA 鏈結中其他裝置連結的個別硬體裝置。 邏輯配接器代表一或多個鏈接器。

每個邏輯配接器都會建立單一 IOMMU DMA 網域,並連結至所有已連結的實體適配卡。 因此,所有實體配接器都會共用相同的網域和相同的物理內存檢視。

整合式與離散 GPU 支援

由於 IOMMU DMA 重新對應對整合式 GPU 提供很少的價值,因此根據定義,已設計為存取系統中的所有物理記憶體,因此對整合元件實作支援是選擇性的,但建議使用。

離散 GPU 必須支援 IOMMU DMA 重新對應,這是 WDDM 3.0 認證的需求。

DDI 變更

已進行下列 DDI 變更,以支援 IOMMU DMA 重新對應。

驅動程式功能

需要兩組驅動程式上限,才能支援線性重新對應:

  • 驅動程式必須通知 Dxgkrnl 其物理記憶體限制;也就是說,透過DXGKQAITYPE_PHYSICAL_MEMORY_CAPS及其相關聯的DXGK_PHYSICAL_MEMORY_CAPS結構,瞭解其最高可見實體位址。
  • 驅動程式必須指出其支援IOMMU線性重新對應,透過 DXGKQAITYPE_IOMMU_CAPS 及其相關聯的 DXGK_IOMMU_CAPS 結構。 藉由表示支持,驅動程式表示稍後所述的所有 DIS 都受到支援及使用。

在 Dxgkrnl 透過 DXGKDDI_START_DEVICE 啟動裝置之前,必須先提供這兩個上限,才能建立裝置並連結至 IOMMU 網域,才能存取任何記憶體。 只有在裝置未參考任何現有的物理記憶體時,才能進行線性重新對應。

獨佔存取

IOMMU 網域連結和卸離速度極快,但目前並非不可部分完成。 此條件表示在交換至具有不同對應之 IOMMU 網域時,不會保證透過 PCIe 發出的交易正確轉譯。

若要處理這種情況,從 Windows 10 1803 版(WDDM 2.4)開始,KMD 必須實作下列 DDI 配對, 才能呼叫 Dxgkrnl

每當裝置切換到新的 IOMMU 網域時,驅動程式必須確保其硬體為無訊息。 也就是說,驅動程式必須確保它不會在這兩個呼叫之間從裝置讀取或寫入系統記憶體。

在這兩個呼叫之間, Dxgkrnl 會提供下列保證:

  • 排程器已暫停。 所有作用中工作負載都會排清,而且硬體上不會傳送任何新的工作負載或排程。
  • 不會進行其他 DDI 呼叫。

在這些呼叫過程中,驅動程式可以選擇在獨佔存取期間停用和隱藏中斷(包括 Vsync 中斷),即使沒有來自 OS 的明確通知也一樣。

位址描述項清單

為了支援實體和邏輯存取模式,並在運行時間順暢地切換這兩種模式,Dxgkrnl 提供描述位址描述項清單 (ADL) 的DXGK_ADL結構。 此數據結構類似於 MDL,但描述可以是實體或邏輯的頁面陣列。 因為這些頁面可以是邏輯頁面,因此ADL所描述的位址無法對應至虛擬位址以進行直接CPU存取。

DxgkddiBuildpagingbuffer 的DXGK_OPERATION_MAP_APERTURE_SEGMENT2作業

VidMm 提供 DXGK_OPERATION_MAP_APERTURE_SEGMENT2 分頁緩衝區模式,以便將記憶體對應至光圈區段,因為舊版使用與邏輯位址不相容的 MDL。 支援邏輯位址重新對應至DXGK_OPERATION_MAP_APERTURE_SEGMENT2模式之 WDDM 3.0 驅動程式的 DxgkddiBuildpagingbuffer 回呼,不再接收對原始DXGK_OPERATION_MAP_APERTURE_SEGMENT模式的呼叫。

需要這項作業才能支持邏輯 DMA 重新對應。 其行為與原始作業類似,但提供DXGK_ADL而非 MDL。

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.CpuVisibleAddress 為 NULL,適用於DXGK_OPERATION_MAP_APERTURE_SEGMENT2作業。

MapApertureCpuVisible 是 DxgkDdiBuildPagingBuffer 的 MapAperatureSegment2 功能的一部分,因此驅動程式必須設定 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 旗標,以判斷配置是否連續,並據以運作。

記憶體管理服務

記憶體管理功能有三個基本需求:

  1. 管理物理記憶體的能力。 這項功能可能包括透過非分頁記憶體函式配置記憶體,例如 MmAllocatePagesforMdl MmAllocateContiguousMemory,以及 ZwCreateSection ZwAllocateVirtualMemory分頁記憶體函式。 也需要表達IO空間範圍的能力。

  2. 從物理記憶體對應 GPU 可見邏輯位址的能力。 這項功能會提供呼叫端的邏輯頁面清單(就像 MDL 的 PFN 陣列),GPU 可進行程式設計來存取。 呼叫這些函式可確保基礎實體頁面已鎖定且無法分頁。

  3. 能夠在使用者模式和核心模式中對應來自物理記憶體的 CPU 虛擬位址,並具有指定的快取類型(Cached vs WriteCombined)。

下表列出描述邏輯/虛擬檢視的實體記憶體配置和對應所引進的 DIS 和相關輸入結構。 這些 DIS 是更新的集合,可取代提供給驅動程式的先前回呼來管理 IOMMU 對應(DxgkCbAllocatePagesforMdl、DxgkCbAllocateContiguousMemoryDxgkCbMapMdlToIoMmu)。 對於支持邏輯重新對應的 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

此值會通知 PnP 裝置支援 DMA 重新對應。 Dxgkrnl 和 HAL 接著會協調以判斷應該使用哪種類型的對應模式(重新對應、傳遞等等)。

雖然此登錄機碼存在於舊版 Windows 上,但值 '3' 從 Windows 10 1803 版 (WDDM 2.4) 開始是唯一的,但在不支援它的舊版組建上會被忽略。 這個唯一值可讓驅動程式在 INF 中設定此索引鍵,而不必擔心相容性問題降低層級。