IOMMU DMA-Neuzuordnung

Diese Seite beschreibt das IOMMU DMA-Neuzuordnungsfeature (IOMMUv2), das in Windows 11 22H2 (WDDM 3.0) eingeführt wurde. Informationen zur IOMMU-GPU-Isolation finden Sie unter IOMMU-GPU-Isolation vor WDDM 3.0.

Übersicht

Bis zu WDDM 3.0 unterstützte Dxgkrnl die IOMMU-Isolierung nur durch 1:1-physisches Neumapping, d. h. die vom GPU aufgerufenen logischen Seiten wurden in dieselbe physische Seitennummer übersetzt. Die IOMMU DMA-Neuzuordnung ermöglicht der GPU den Zugriff auf den Speicher über logische Adressen, die nicht mehr 1:1 zugeordnet sind. Stattdessen kann Dxgkrnl logisch zusammenhängende Adressbereiche bereitstellen.

Dxgkrnl legt eine Einschränkung für GPUs fest: GPUs müssen auf den gesamten physischen Speicher zugreifen können, damit das Gerät gestartet werden kann. Wenn die höchste sichtbare Adresse der GPU die höchste im System installierte physische Adresse nicht überschreitet, schlägt die Initialisierung des Adapters durch Dxgkrnl fehl. Zukünftige Server und High-End-Workstations können mit über 1 TB Arbeitsspeicher konfiguriert werden, der die übliche 40-Bit-Adressraumbeschränkung vieler GPUs überschreitet. Die DMA-Neuzuordnung wird als Mechanismus verwendet, mit dem GPUs in dieser Umgebung funktionieren können.

Bei der Startzeit bestimmt Dxgkrnl, ob eine logische Neuzuordnung erforderlich ist, indem die höchste physische Adresse des Geräts mit dem auf dem System installierten Speicher verglichen wird. Wenn dies erforderlich ist, wird die DMA-Neuzuordnung verwendet, um einen logischen Adressbereich zuzuordnen, der sich innerhalb der sichtbaren Grenzen der GPU an jedem physischen Speicher im System befindet. Wenn die GPU beispielsweise einen Grenzwert von 1 TB hat, weist Dxgkrnl logische Adressen von [0, 1 TB) zu, die dann über die IOMMU einem physischen Speicher auf dem System zugeordnet werden können.

Logische und physische Adapter

Dxgkrnl unterscheidet zwischen dem Konzept eines logischen und physischen Adapters. Ein physischer Adapter stellt ein einzelnes Hardwaregerät dar, das möglicherweise mit anderen Geräten in einer LDA-Kette verknüpft ist. Ein logischer Adapter stellt einen oder mehrere verknüpfte physische Adapter dar.

Pro logischem Adapter wird eine einzelne IOMMU-DMA-Domäne erstellt und an alle physischen Adapter angefügt, die verknüpft sind. Daher teilen alle physischen Adapter dieselbe Domäne und dieselbe Ansicht des physischen Speichers.

Integrierte und diskrete GPU-Unterstützung

Da die IOMMU DMA-Neuzuordnung wenig Wert für integrierte GPUs bietet, die per Definition bereits für den Zugriff auf den gesamten physischen Speicher im System konzipiert sein sollten, ist die Implementierung der Unterstützung für integrierte Teile optional, wird jedoch empfohlen.

Diskrete GPUs müssen die IOMMU DMA-Neuzuordnung unterstützen, was eine Anforderung für die WDDM 3.0-Zertifizierung ist.

DDI-Änderungen

Die folgenden DDI-Änderungen wurden vorgenommen, um die Neuzuordnung von IOMMU DMA zu unterstützen.

Treiberfunktionen

Zwei Gruppen von Treiberkappen sind erforderlich, um die lineare Neuzuordnung zu unterstützen:

  • Der Treiber muss Dxgkrnl über seine physischen Speicherbeschränkungen informieren, d. h. über seine höchste sichtbare physische Adresse über DXGKQAITYPE_PHYSICAL_MEMORY_CAPS und die zugehörige DXGK_PHYSICAL_MEMORY_CAPS-Struktur.
  • Der Treiber muss seine Unterstützung für die lineare IOMMU-Neuzuordnung über DXGKQAITYPE_IOMMU_CAPS und seine zughörige DXGK_IOMMU_CAPS-Struktur angeben. Durch Angabe der Unterstützung gibt der Treiber an, dass alle später beschriebenen DDIs unterstützt und verwendet werden.

Beide dieser Kappen müssen bereitgestellt werden, bevor Dxgkrnl das Gerät über DXGKDDI_START_DEVICE startet, damit das Gerät erstellt und an eine IOMMU-Domäne angefügt werden kann, bevor auf einen Speicher zugegriffen werden kann. Eine lineare Neuzuordnung kann nur durchgeführt werden, wenn das Gerät auf keinen vorhandenen physischen Speicher verweist.

Exklusiver Zugriff

IOMMU Domain Attach und Detach ist extrem schnell, ist aber dennoch nicht atomar. Diese Bedingung bedeutet, dass eine über PCIe ausgegebene Transaktion nicht garantiert korrekt übersetzt wird, während sie mit unterschiedlichen Zuordnungen in eine IOMMU-Domäne ausgetauscht wird.

Um diese Situation zu behandeln, muss ein KMD ab Windows 10, Version 1803 (WDDM 2.4), das folgende DDI-Paar für Dxgkrnl implementieren, um aufzurufen:

Der Treiber muss sicherstellen, dass die Hardware automatisch ausgeführt wird, wenn das Gerät zu einer neuen IOMMU-Domäne wechselt. Das heißt, der Treiber muss sicherstellen, dass der Systemspeicher zwischen diesen beiden Aufrufen nicht vom Gerät aus gelesen oder in den Systemspeicher geschrieben wird.

Zwischen diesen beiden Aufrufen stellt Dxgkrnl die folgenden Garantien dar:

  • Der Scheduler wird angehalten. Alle aktiven Workloads werden geleert, und es werden keine neuen Workloads an die Hardware gesendet oder geplant.
  • Es werden keine anderen DDI-Anrufe getätigt.

Im Rahmen dieser Aufrufe kann sich der Treiber entscheiden, Unterbrechungen (einschließlich Vsync-Interrupts) während des exklusiven Zugriffs zu deaktivieren und zu unterdrücken, auch ohne explizite Benachrichtigung vom Betriebssystem.

Adressdeskriptorlisten

Um sowohl physische als auch logische Zugriffsmodi zu unterstützen und zur Laufzeit nahtlos zwischen den beiden Modi zu wechseln, bietet Dxgkrnl eine DXGK_ADL Struktur, die eine Adressdeskriptorliste (ADL) beschreibt. Diese Datenstruktur ähnelt einer MDL, beschreibt jedoch ein Array von Seiten, die entweder physisch oder logisch sein können. Da diese Seiten logische Seiten sein können, können die von einer ADL beschriebenen Adressen nicht einer virtuellen Adresse für den direkten CPU-Zugriff zugeordnet werden.

DXGK_OPERATION_MAP_APERTURE_SEGMENT2-Vorgang für DxgkddiBuildpagingbuffer

VidMm stellt den DXGK_OPERATION_MAP_APERTURE_SEGMENT2-Pagingpuffermodus zum Zuordnen des Speichers zum Blendensegment bereit, da die vorherige Version eine MDL verwendet, die nicht mit logischen Adressen kompatibel ist. Der DxgkddiBuildpagingbuffer-Rückruf von WDDM 3.0-Treibern, die die logische Adressneuzuordnung unterstützen, empfangen Anrufe im DXGK_OPERATION_MAP_APERTURE_SEGMENT2-Modus und empfangen keine Anrufe mehr an den ursprünglichen DXGK_OPERATION_MAP_APERTURE_SEGMENT-Modus.

Dieser Vorgang ist erforderlich, um die logische DMA-Neuzuordnung zu unterstützen. Sie verhält sich ähnlich wie der ursprüngliche Vorgang, stellt jedoch eine DXGK_ADL anstelle einer MDL bereit.

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;

Um den Vorgang DXGK_OPERATION_MAP_APERTURE_SEGMENT2 zu aktivieren, muss der Treiber die Unterstützung für MapApertureSegment2 Aufrufe in den Speicherverwaltungskappen angeben:

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

Die DXGK_VIDMMCAPS-Speicherverwaltungskappen sind Teil der DXGK_DRIVERCAPS-Datenstruktur. Der Treiber kann die DMA-Neuzuordnungsfunktion (d. h. logische Adressneuzuordnung) nicht verwenden, ohne dass diese Unterstützung aktiviert ist.

Einige Treiber erfordern möglicherweise während eines MapApertureSegment2-Aufrufs CPU-Zugriff auf den Arbeitsspeicher. Diese Funktionalität wird optional über einen anderen MapApertureSegment2.CpuVisibleAddress-Parameter bereitgestellt. Diese Adresse ist eine virtuelle Kernelmodusadresse, die gültig ist, solange die Zuordnung dem Blendensegment zugeordnet ist. Das heißt, diese Adresse wird unmittelbar nach dem entsprechenden DXGK_OPERATION_UNMAP_APERTURE_SEGMENT Aufruf für dieselbe Zuordnung freigegeben.

Diese Adresse ist möglicherweise nicht für alle Zuordnungen erforderlich. Das MapApertureCpuVisible-Flag wurde den Zuordnungskennzeichnungen hinzugefügt, um anzugeben, wann diese Adresse erforderlich ist.

Wenn MapApertureCpuVisible nicht angegeben ist, ist MapApertureSegment2.CpuVisibleAddress NULL für DXGK_OPERATION_MAP_APERTURE_SEGMENT2 Vorgänge.

MapApertureCpuVisible ist Teil der DxgkDdiBuildPagingBuffer-Funktionalität von MapAperatureSegment2, daher muss der Treiber DXGK_VIDMMCAPS MapAperature2Supported setzen, um dieses Feld zu verwenden. Wenn MapAperature2Supported nicht festgelegt ist, der Treiber jedoch MapApertureCpuVisible angibt, schlägt der Aufruf von DxgkDdiCreateAllocation fehl.

Um den Vorgang DXGK_OPERATION_MAP_APERTURE_SEGMENT2 zu empfangen, muss der Treiber außerdem das Flag DXGK_ALLOCATIONINFOFLAGS_WDDM2_0 AccessedPhysically setzen. Wenn "AccessedPhysically " nicht festgelegt ist, wird jede Zuordnung, die ein Blendensegment in ihrem unterstützten Segmentsatz angibt, auf das implizite Systemspeichersegment aktualisiert, das keine MAP_APERTURE Aufrufe empfängt (da keine Blendenbereiche zugeordnet werden).

Um die CPU-Adresse einer Systemspeicherzuweisung ordnungsgemäß zu empfangen, muss der Treiber die folgenden Flags/Caps festlegen:

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

Bei MapApertureSegment2-Aufrufen wird die ADL immer initialisiert und als zusammenhängend übergeben, wenn die logische Zuordnung aktiviert ist. Der Treiber muss die ADL-Flags überprüfen, um festzustellen, ob die Zuordnung zusammenhängend ist und sich entsprechend verhält.

Speicherverwaltungsdienste

Es gibt drei grundlegende Anforderungen für die Speicherverwaltungsfunktionen:

  1. Die Möglichkeit zum Verwalten des physischen Speichers. Diese Funktion kann die Speicherzuweisung über nicht ausgelagerte Speicherfunktionen wie MmAllocatePagesforMdl oder MmAllocateContiguousMemory und über ausgelagerte Speicherfunktionen wie ZwCreateSection oder ZwAllocateVirtualMemory umfassen. Die Möglichkeit zum Ausdrücken von E/A-Raumbereichen ist ebenfalls erforderlich.

  2. Die Möglichkeit, eine GPU-sichtbare logische Adresse aus dem physischen Speicher zuzuordnen. Diese Funktion würde dem Aufrufer eine Liste der logischen Seiten (ähnlich wie das PFN-Array einer MDL) bereitstellen, auf die die GPU für den Zugriff programmiert werden kann. Das Aufrufen dieser Funktionen würde garantieren, dass die zugrunde liegenden physischen Seiten gesperrt und nicht seitenfähig sind.

  3. Die Möglichkeit, virtuelle CPU-Adressen aus dem physischen Speicher sowohl im Benutzermodus als auch im Kernelmodus mit einem angegebenen Cachetyp (zwischengespeichert und WriteCombined) zuzuordnen.

In der folgenden Tabelle sind die DDIs und die zugehörigen Eingabestrukturen aufgeführt, die eingeführt wurden, um die Zuordnung physischer Speicher und die Zuordnung logischer/virtueller Ansichten zu beschreiben. Diese DDIs sind ein aktualisierter Satz, der die vorherigen Rückrufe ersetzt, die Treibern zum Verwalten von IOMMU-Zuordnungen bereitgestellt wurden (DxgkCbAllocatePagesforMdl, DxgkCbAllocateContiguousMemory, DxgkCbMapMdlToIoMmu). Für WDDM 3.0-Treiber, die die logische Neuzuordnung unterstützen, sind diese älteren Rückruffunktionen veraltet und können nicht verwendet werden. Der Treiber sollte stattdessen die folgenden Speicherverwaltungsrückruffunktionen verwenden.

Rückruffunktionen müssen bei IRQL <= APC_LEVEL aufgerufen werden. Ab WDDM 3.2 werden Treiber, die eine dieser Funktionen aufrufen, anhand dieser Anforderung überprüft und Fehlerüberprüfung, ob die IRQL DISPATCH_LEVEL oder höher ist.

Rückruf Zugeordnete Rückrufstruktur
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-Änderungen

Jeder unterstützte Gerätetyp muss dem entsprechenden Abschnitt des INF den folgenden Registrierungsschlüssel und -wert hinzufügen:

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

Dieser Wert informiert PnP, dass das Gerät die DMA-Neuzuordnung unterstützt. Dxgkrnl und die HAL koordinieren dann, um zu bestimmen, welche Art von Zuordnungsmodus verwendet werden soll (Neuzuordnung, Passthrough usw.).

Obwohl dieser Registrierungsschlüssel in älteren Versionen von Windows vorhanden war, ist der Wert "3" ab Windows 10 Version 1803 (WDDM 2.4) eindeutig und wird bei älteren Builds ignoriert, die ihn nicht unterstützen. Dieser eindeutige Wert ermöglicht es Treibern, diesen Schlüssel in der INF festzulegen und sich keine Sorgen um Kompatibilitätsprobleme nach unten zu machen.