Condividi tramite


Mapping di DMA di IOMMU

Questa pagina descrive la funzionalità di modifica del mapping di IOMMU DMA (IOMMUv2) introdotta in Windows 11 22H2 (WDDM 3.0). Vedere Isolamento GPU basato su IOMMU per informazioni sull'isolamento GPU IOMMU prima di WDDM 3.0.

Panoramica

Fino a WDDM 3.0, Dxgkrnl supportava solo l'isolamento IOMMU fino al mapping fisico 1:1, ovvero le pagine logiche a cui si accede dalla GPU venivano convertite nello stesso numero di pagina fisico. Il mapping DMA di IOMMU consente alla GPU di accedere alla memoria tramite indirizzi logici non più mappati alla versione 1:1. Dxgkrnl è invece in grado di fornire intervalli di indirizzi logicamente contigui.

Dxgkrnl impone una restrizione sulle GPU: le GPU devono essere in grado di accedere a tutta la memoria fisica per consentire all'avvio del dispositivo. Se l'indirizzo visibile più alto della GPU non supera l'indirizzo fisico più alto installato nel sistema, Dxgkrnl non riesce l'inizializzazione dell'adattatore. I server futuri e le workstation di fascia alta possono essere configurati con più di 1 TB di memoria che superano la limitazione comune dello spazio degli indirizzi a 40 bit di molte GPU. Il mapping DMA viene usato come meccanismo per consentire il funzionamento delle GPU in questo ambiente.

Al momento dell'avvio , Dxgkrnl determina se è necessario eseguire il mapping logico confrontando l'indirizzo fisico più accessibile del dispositivo con la memoria installata nel sistema. Se necessario, il mapping di DMA viene usato per eseguire il mapping di un intervallo di indirizzi logico che si trova all'interno dei limiti visibili della GPU a qualsiasi memoria fisica nel sistema. Ad esempio, se la GPU ha un limite di 1 TB, Dxgkrnl alloca indirizzi logici da [0, 1 TB) che può quindi eseguire il mapping a qualsiasi memoria fisica nel sistema tramite IOMMU.

Adattatori logici e fisici

Dxgkrnl distingue tra il concetto di adattatore logico e fisico. Una scheda fisica rappresenta un singolo dispositivo hardware che può o meno essere collegato ad altri dispositivi in una catena LDA. Un adattatore logico rappresenta uno o più adattatori fisici collegati.

Viene creato un singolo dominio IOMMU DMA per scheda logica e collegato a tutte le schede fisiche collegate. Pertanto, tutti gli adattatori fisici condividono lo stesso dominio e la stessa visualizzazione della memoria fisica.

Supporto di GPU integrate e discrete

Poiché il mapping DMA di IOMMU offre poco valore alle GPU integrate che dovrebbero, per definizione, essere già progettate per accedere a tutta la memoria fisica nel sistema, l'implementazione del supporto sulle parti integrate è facoltativa ma consigliata.

Le GPU discrete devono supportare il mapping di DMA IOMMU, che è un requisito per la certificazione WDDM 3.0.

Modifiche DDI

Sono state apportate le modifiche DDI seguenti per supportare il mapping DMA di IOMMU.

Funzionalità del driver

Per supportare il mapping lineare sono necessari due set di limiti di driver:

Entrambi questi limiti devono essere forniti prima che Dxgkrnl avvii il dispositivo tramite DXGKDDI_START_DEVICE in modo che il dispositivo possa essere creato e collegato a un dominio IOMMU prima di poter accedere a qualsiasi memoria. Il nuovo mapping lineare può essere eseguito solo se il dispositivo non fa riferimento ad alcuna memoria fisica esistente.

Accesso esclusivo

Il collegamento e lo scollegamento del dominio IOMMU è estremamente veloce, ma non è tuttavia attualmente atomico. Ciò significa che non è garantito che una transazione emessa su PCIe venga convertita correttamente durante lo scambio in un dominio IOMMU con mapping diversi.

Per gestire questa situazione, a partire da Windows 10 versione 1803 (WDDM 2.4), un KMD deve implementare la coppia DDI seguente per Dxgkrnl per chiamare:

Il driver deve assicurarsi che l'hardware sia invisibile all'utente ogni volta che il dispositivo passa a un nuovo dominio IOMMU. Ovvero, il driver deve assicurarsi che non legga o scriva nella memoria di sistema dal dispositivo tra queste due chiamate.

Tra queste due chiamate , Dxgkrnl garantisce quanto segue:

  • L'utilità di pianificazione è sospesa. Tutti i carichi di lavoro attivi vengono scaricati e non vengono inviati nuovi carichi di lavoro o pianificati nell'hardware.
  • Non vengono effettuate altre chiamate DDI.

Come parte di queste chiamate, il driver può scegliere di disabilitare e eliminare gli interrupt (inclusi gli interrupt Vsync) durante l'accesso esclusivo, anche senza notifiche esplicite dal sistema operativo.

Elenchi di descrittori di indirizzi

Per supportare le modalità di accesso fisico e logico e passare facilmente tra le due modalità in fase di esecuzione, Dxgkrnl fornisce una struttura DXGK_ADL che descrive un elenco di descrittori di indirizzi (ADL). Questa struttura di dati è simile a un file MDL, ma descrive una matrice di pagine che possono essere fisiche o logiche. Poiché queste pagine possono essere pagine logiche, gli indirizzi descritti da un ADL non possono essere mappati a un indirizzo virtuale per l'accesso diretto alla CPU.

operazione DXGK_OPERATION_MAP_APERTURE_SEGMENT2 per DxgkddiBuildpagingbuffer

VidMm fornisce la modalità buffer di paging DXGK_OPERATION_MAP_APERTURE_SEGMENT2 per il mapping della memoria al segmento di apertura perché la versione precedente usa un MDL incompatibile con gli indirizzi logici. Il callback DxgkddiBuildpagingbuffer dei driver WDDM 3.0 che supportano il mapping degli indirizzi logici riceve le chiamate alla modalità DXGK_OPERATION_MAP_APERTURE_SEGMENT2 e non riceve più chiamate alla modalità di DXGK_OPERATION_MAP_APERTURE_SEGMENT originale.

Questa operazione è necessaria per supportare il mapping di DMA logico. Si comporta in modo analogo all'operazione originale, ma fornisce un DXGK_ADL anziché un 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;

Per acconsentire esplicitamente all'operazione di DXGK_OPERATION_MAP_APERTURE_SEGMENT2 , il driver deve indicare il supporto per le chiamate MapApertureSegment2 nei limiti di gestione della memoria:

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

I limiti di gestione della memoria DXGK_VIDMMCAPS fanno parte della struttura dei dati DXGK_DRIVERCAPS . Il driver non è in grado di usare la funzionalità di modifica del mapping degli indirizzi logici (ovvero la ripetizione del mapping degli indirizzi logici) senza questo supporto abilitato.

Alcuni driver potrebbero richiedere l'accesso della CPU alla memoria durante una chiamata MapApertureSegment2 . Questa funzionalità viene facoltativamente fornita tramite un altro parametro MapApertureSegment2.CpuVisibleAddress . Questo indirizzo è un indirizzo virtuale in modalità kernel valido purché l'allocazione venga mappata nel segmento di apertura. Ovvero, questo indirizzo verrà liberato immediatamente dopo la chiamata di DXGK_OPERATION_UNMAP_APERTURE_SEGMENT corrispondente per la stessa allocazione.

Questo indirizzo potrebbe non essere necessario per tutte le allocazioni e pertanto è stato aggiunto un flag MapApertureCpuVisible ai flag di allocazione per indicare quando è necessario.

Se MapApertureCpuVisible non è specificato, MapApertureSegment2.CpuVisibleAddress è NULL per le operazioni di DXGK_OPERATION_MAP_APERTURE_SEGMENT2 .

MapApertureCpuVisible fa parte della funzionalità MapAperatureSegingBuffer diDxgkDdiBuildPagingBuffer2, quindi il driver deve impostare DXGK_VIDMMCAPS MapAperature2Supported per usare questo campo. Se MapAperature2Supported non è impostato ma il driver specifica MapApertureCpuVisible, la chiamata a DxgkDdiCreateAllocation ha esito negativo.

Inoltre, per ricevere l'operazione di DXGK_OPERATION_MAP_APERTURE_SEGMENT2 , il driver deve impostare il flag DXGK_ALLOCATIONINFOFLAGS_WDDM2_0 AccessedPhysically . Se AccessedPhysically non è impostato, qualsiasi allocazione che specifica un segmento di apertura nel set di segmenti supportato viene aggiornata al segmento di memoria di sistema implicito, che non riceve chiamate MAP_APERTURE (poiché non sono presenti intervalli di aperture da mappare).

In sintesi, per ricevere correttamente l'indirizzo CPU di un'allocazione di memoria di sistema, il driver deve impostare i flag/cap seguenti:

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

Per le chiamate MapApertureSegment2 , l'ADL viene sempre inizializzato e passato come contiguo quando il mapping logico è abilitato. Il driver deve controllare i flag ADL per determinare se l'allocazione è contigua e comportarsi di conseguenza.

Servizi di gestione della memoria

Esistono tre requisiti fondamentali per le funzioni di gestione della memoria:

  1. Possibilità di gestire la memoria fisica. Ciò può includere l'allocazione della memoria tramite funzioni di memoria non in pagine, ad esempio MmAllocatePagesforMdl o MmAllocateContiguousMemory e funzioni di memoria di paging come ZwCreateSection o ZwAllocateVirtualMemory. È necessaria anche la possibilità di esprimere gli intervalli di spazi di I/O.

  2. Possibilità di eseguire il mapping di un indirizzo logico visibile alla GPU dalla memoria fisica. In questo modo il chiamante con un elenco di pagine logiche (in modo analogo alla matrice PFN di un MDL) che la GPU può essere programmata per accedere. La chiamata a queste funzioni garantisce che le pagine fisiche sottostanti siano bloccate e non paging.

  3. Possibilità di eseguire il mapping degli indirizzi virtuali della CPU dalla memoria fisica sia in modalità utente che in modalità kernel, con un tipo di cache specificato (Cached vs WriteCombined).

La tabella seguente elenca le DDI e le strutture di input associate introdotte per descrivere l'allocazione della memoria fisica e il mapping di viste logiche/virtuali. Queste DDI sono un set aggiornato per sostituire i callback precedenti forniti ai driver per la gestione dei mapping IOMMU (DxgkCbAllocatePagesforMdl, DxgkCbAllocateContiguousMemory, DxgkCbMapMdlToIoMmu). Per i driver WDDM 3.0 che supportano il mapping logico, queste funzioni di callback precedenti sono deprecate e non possono essere usate. Il driver deve invece usare le funzioni di callback di gestione della memoria seguenti.

Le funzioni di callback devono essere chiamate in IRQL <= APC_LEVEL. A partire da WDDM 3.2, i driver che chiamano una qualsiasi di queste funzioni vengono convalidati in base a questo requisito e controllano se IRQL è DISPATCH_LEVEL o versione successiva.

Callback Struttura di callback associata
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

Modifiche di INF

Ogni tipo di dispositivo supportato deve aggiungere la chiave e il valore del Registro di sistema seguenti alla sezione appropriata di INF:

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

Questo valore indica a PnP che il dispositivo supporta il mapping DMA. Dxgkrnl e HAL si coordinateranno quindi per determinare il tipo di modalità di mapping da usare (mapping, pass-through e così via).

Anche se questa chiave del Registro di sistema era presente nelle versioni precedenti di Windows, il valore '3' è univoco a partire da Windows 10 versione 1803 (WDDM 2.4) e viene ignorato nelle build precedenti che non lo supportano. In questo modo i driver possono impostare questa chiave in INF e non preoccuparsi dei problemi di compatibilità di livello inferiore.