IOMMU DMA-Neuzuordnung

Auf dieser Seite wird die IOMMU DMA-Neuzuordnungsfunktion (IOMMUv2) beschrieben, die in Windows 11 22H2 (WDDM 3.0) eingeführt wurde. Informationen zur IOMMU-GPU-Isolation vor WDDM 3.0 finden Sie unter IOMMU-basierte GPU-Isolation .

Übersicht

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

Dxgkrnl erzwingt eine Einschränkung für GPUs: 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 physische Adresse, die auf dem System installiert ist, nicht überschreitet, schlägt Dxgkrnl die Initialisierung des Adapters fehl. Zukünftige Server und High-End-Arbeitsstationen können mit über 1 TB Arbeitsspeicher konfiguriert werden, der die allgemeine 40-Bit-Adressraumbeschränkung vieler GPUs überschreitet. Die DMA-Neuzuordnung wird als Mechanismus verwendet, damit GPUs in dieser Umgebung funktionieren können.

Beim Start ermittelt Dxgkrnl , ob eine logische Neuzuordnung erforderlich ist, indem die am höchsten zugängliche physische Adresse des Geräts mit dem auf dem System installierten Arbeitsspeicher verglichen wird. Wenn dies erforderlich ist, wird die DMA-Neuzuordnung verwendet, um einen logischen Adressbereich zuzuordnen, der innerhalb der sichtbaren Grenzen der GPU zu jedem physischen Speicher im System liegt. Wenn die GPU beispielsweise einen Grenzwert von 1 TB aufweist, ordnet Dxgkrnl logische Adressen von [0, 1 TB) zu, die dann über die IOMMU jedem physischen Arbeitsspeicher 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 mit anderen Geräten in einer LDA-Kette verknüpft sein kann oder nicht. 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 sich alle physischen Adapter dieselbe Domäne und dieselbe Ansicht des physischen Speichers.

Integrierte und diskrete GPU-Unterstützung

Da die IOMMU DMA-Neuzuordnung nur wenig Wert für integrierte GPUs bietet, die per Definition bereits für den Zugriff auf den gesamten physischen Arbeitsspeicher 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. Dies ist eine Voraussetzung für die WDDM 3.0-Zertifizierung.

DDI-Änderungen

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

Treiberfunktionen

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

Beide Obergrenzen 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 den Arbeitsspeicher zugegriffen werden kann. Eine lineare Neuzuordnung kann nur durchgeführt werden, wenn das Gerät auf keinen vorhandenen physischen Speicher verweist.

Exklusiver Zugriff

Das Anfügen und Trennen von IOMMU-Domänen ist extrem schnell, aber derzeit nicht atomar. Dies bedeutet, dass eine über PCIe ausgestellte Transaktion nicht garantiert richtig übersetzt wird, während sie in eine IOMMU-Domäne mit unterschiedlichen Zuordnungen ausgetauscht wird.

Um diese Situation zu bewältigen, muss ein KMD ab Windows 10 Version 1803 (WDDM 2.4) das folgende DDI-Paar implementieren, damit Dxgkrnl aufrufen kann:

Der Treiber muss sicherstellen, dass seine Hardware im Hintergrund ist, wenn das Gerät in eine neue IOMMU-Domäne gewechselt wird. Das heißt, der Treiber muss sicherstellen, dass er zwischen diesen beiden Aufrufen nicht vom Gerät liest oder in den Systemspeicher schreibt.

Zwischen diesen beiden Aufrufen gibt Dxgkrnl die folgenden Garantien ein:

  • 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-Aufrufe durchgeführt.

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

Adressdeskriptorlisten

Dxgkrnl bietet eine DXGK_ADL Struktur, die eine Adressdeskriptorliste (ADL) beschreibt, um sowohl physische als auch logische Zugriffsmodi zu unterstützen und nahtlos zur Laufzeit zwischen den beiden Modi zu wechseln. Diese Datenstruktur ähnelt einer MDL, beschreibt jedoch ein Array von Seiten, die entweder physisch oder logisch sein können. Da es sich bei diesen Seiten um logische Seiten handeln kann, können die von einer ADL beschriebenen Adressen nicht einer virtuellen Adresse für 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 mit logischen Adressen nicht kompatibel ist. Der DxgkddiBuildpagingbuffer-Rückruf von WDDM 3.0-Treibern, die die logische Adressremapping unterstützen, erhalten Anrufe in den DXGK_OPERATION_MAP_APERTURE_SEGMENT2-Modus und erhalten keine Anrufe mehr im ursprünglichen DXGK_OPERATION_MAP_APERTURE_SEGMENT Modus.

Dieser Vorgang ist erforderlich, um die logische DMA-Neuzuordnung zu unterstützen. Es verhält sich ähnlich wie der ursprüngliche Vorgang, stellt jedoch anstelle einer MDL eine DXGK_ADL 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 sich für den DXGK_OPERATION_MAP_APERTURE_SEGMENT2-Vorgang zu entscheiden, muss der Treiber die Unterstützung für MapApertureSegment2-Aufrufe in den Obergrenzen für die Speicherverwaltung angeben:

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

Die DXGK_VIDMMCAPS Arbeitsspeicherverwaltungsobergrenzen sind Teil der DXGK_DRIVERCAPS Datenstruktur. Der Treiber kann die DMA-Neuzuordnungsfunktion (d. h. die logische Adresszuordnung) 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 Adresse im Kernelmodus, die gültig ist, solange die Zuordnung dem Blendensegment zugeordnet ist. Das heißt, diese Adresse wird sofort 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. Daher wurde den Zuordnungsflags ein MapApertureCpuVisible-Flag hinzugefügt, um anzugeben, wann es benötigt wird.

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

MapApertureCpuVisible ist Teil der MapAperatureSegment2-Funktionalität von DxgkDdiBuildPagingBuffer. Daher muss der Treiber DXGK_VIDMMCAPS MapAperature2Supported festlegen, um dieses Feld verwenden zu können. Wenn MapAperature2Supported nicht festgelegt ist, aber der Treiber MapApertureCpuVisible angibt, schlägt der Aufruf von DxgkDdiCreateAllocation fehl.

Darüber hinaus muss der Treiber zum Empfangen des DXGK_OPERATION_MAP_APERTURE_SEGMENT2-Vorgangs das flag DXGK_ALLOCATIONINFOFLAGS_WDDM2_0 AccessedPhysically festlegen. Wenn "AccessedPhysically " nicht festgelegt ist, wird jede Zuordnung, die ein Blendensegment in der unterstützten Segmentmenge angibt, auf das implizite Systemspeichersegment aktualisiert, das keine MAP_APERTURE Aufrufe empfängt (da keine Blendenbereiche zugeordnet werden müssen).

Zusammenfassend kann gesagt werden, dass der Treiber die folgenden Flags/Caps festlegen muss, um die CPU-Adresse einer Systemspeicherbelegung ordnungsgemäß zu erhalten:

  • 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 zu bestimmen, ob die Zuordnung zusammenhängend ist, und sich entsprechend verhalten.

Speicherverwaltungsdienste

Es gibt drei grundlegende Anforderungen an die Speicherverwaltungsfunktionen:

  1. Die Möglichkeit, physischen Arbeitsspeicher zu verwalten. Dies kann die Zuweisung von Arbeitsspeicher über nicht ausgelagerte Speicherfunktionen wie MmAllocatePagesforMdl oder MmAllocateContiguousMemory sowie ausgelagerte Speicherfunktionen wie ZwCreateSection oder ZwAllocateVirtualMemory umfassen. Die Möglichkeit, E/A-Speicherplatzbereiche auszudrücken, ist ebenfalls erforderlich.

  2. Die Möglichkeit, eine gpu-sichtbare logische Adresse aus dem physischen Speicher zuzuordnen. Dadurch wird dem Aufrufer eine Liste mit logischen Seiten bereitgestellt (ähnlich wie das PFN-Array einer MDL), auf die die GPU programmiert werden kann. Das Aufrufen dieser Funktionen würde sicherstellen, dass die zugrunde liegenden physischen Seiten gesperrt und nicht ausgelagert werden können.

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

In der folgenden Tabelle sind die DDIs und die zugehörigen Eingabestrukturen aufgeführt, die eingeführt wurden, um die Zuordnung des physischen Arbeitsspeichers und die Zuordnung logischer/virtueller Ansichten zu beschreiben. Diese DDIs sind ein aktualisierter Satz, um die vorherigen Rückrufe zu ersetzen, die Treibern für die Verwaltung 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 Rückruffunktionen für die Speicherverwaltung verwenden.

Rückruffunktionen müssen unter IRQL <= APC_LEVEL aufgerufen werden. Ab WDDM 3.2 werden Treiber, die eine dieser Funktionen aufrufen, anhand dieser Anforderung überprüft und fehlercheckt, ob der 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 darüber, dass das Gerät die DMA-Neuzuordnung unterstützt. Dxgkrnl und die HAL koordinieren dann, um zu bestimmen, welcher Typ des Zuordnungsmodus verwendet werden soll (Neuerstellung, 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. Dadurch können Treiber diesen Schlüssel im INF festlegen und sich nicht um Kompatibilitätsprobleme kümmern.