Mapping di DMA IOMMU
Questa pagina descrive la funzionalità di 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 a 1:1, il che significa che le pagine logiche a cui si accede dalla GPU venivano convertite nello stesso numero di pagina fisico. Il mapping di DMA IOMMU consente alla GPU di accedere alla memoria tramite indirizzi logici non più mappati alle 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 della scheda. I server futuri e le workstation di fascia alta possono essere configurati con oltre 1 TB di memoria che superano la limitazione comune dello spazio degli indirizzi a 40 bit di molte GPU. Il remapping 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 gli indirizzi logici da [0, 1 TB) che possono 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 potrebbe essere collegato ad altri dispositivi in una catena LDA. Una scheda logica rappresenta una o più schede fisiche collegate.
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 integrato e discreto della GPU
Poiché il mapping di 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 nelle parti integrate è facoltativa ma consigliata.
Le GPU discrete devono supportare il mapping di DMA IOMMU, un requisito per la certificazione WDDM 3.0.
Modifiche DDI
Sono state apportate le modifiche DDI seguenti per supportare il mapping di DMA IOMMU.
Funzionalità del driver
Per supportare il mapping lineare sono necessari due set di limiti di driver:
- Il driver deve informare Dxgkrnl sulle restrizioni di memoria fisica, ovvero sul suo indirizzo fisico più alto visibile tramite DXGKQAITYPE_PHYSICAL_MEMORY_CAPS e la struttura DXGK_PHYSICAL_MEMORY_CAPS associata.
- Il driver deve indicare il supporto per il mapping lineare IOMMU tramite DXGKQAITYPE_IOMMU_CAPS e la struttura di DXGK_IOMMU_CAPS associata. Indicando il supporto, il driver indica che tutte le DDI descritte più avanti sono supportate e usate.
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 mapping lineare può essere eseguito solo se il dispositivo non fa riferimento a memoria fisica esistente.
Accesso esclusivo
Il collegamento e lo scollegamento del dominio IOMMU è estremamente veloce, ma non è tuttavia attualmente atomico. Questa condizione significa che non è garantito che una transazione eseguita 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:
- DxgkDdiBeginExclusiveAccess viene chiamato per notificare al KMD che un commutatore di dominio IOMMU sta per verificarsi.
- DxgkDdiEndExclusiveAccess viene chiamato dopo il completamento dell'opzione di dominio IOMMU.
Il driver deve assicurarsi che l'hardware sia invisibile all'utente ogni volta che il dispositivo viene passato 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 dei 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.
DXGK_OPERATION_MAP_APERTURE_SEGMENT2'operazione per DxgkddiBuildpagingbuffer
VidMm fornisce la modalità buffer di paging DXGK_OPERATION_MAP_APERTURE_SEGMENT2 per il mapping della memoria al segmento di apertura, poiché la versione precedente usa un MDL non compatibile con gli indirizzi logici. Il callback dxgkddiBuildpagingbuffer dei driver WDDM 3.0 che supportano il mapping degli indirizzi logici ricevono chiamate alla modalità DXGK_OPERATION_MAP_APERTURE_SEGMENT2 e non ricevono più chiamate alla modalità 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 il 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 DXGK_OPERATION_UNMAP_APERTURE_SEGMENT corrispondente per la stessa allocazione.
Questo indirizzo potrebbe non essere necessario per tutte le allocazioni. Il flag MapApertureCpuVisible è stato aggiunto ai flag di allocazione per indicare quando questo indirizzo è obbligatorio.
Se MapApertureCpuVisible non è specificato, MapApertureSegment2.CpuVisibleAddress è NULL per le operazioni di DXGK_OPERATION_MAP_APERTURE_SEGMENT2.
MapApertureCpuVisible fa parte della funzionalità MapAperatureSegingBuffer di DxgkDdiBuildPagingBuffer2, 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 supportati 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 DELLA 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 , 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:
Possibilità di gestire la memoria fisica. Questa funzionalità può includere l'allocazione della memoria tramite funzioni di memoria non di pagina, ad esempio MmAllocatePagesforMdl o MmAllocateContiguousMemory e funzioni di memoria di paging, ad esempio ZwCreateSection o ZwAllocateVirtualMemory. È necessaria anche la possibilità di esprimere gli intervalli di spazio di I/O.
Possibilità di eseguire il mapping di un indirizzo logico visibile dalla GPU dalla memoria fisica. Questa funzionalità fornirà al chiamante un elenco di pagine logiche (analogamente alla matrice PFN di un MDL) che la GPU può essere programmata per l'accesso. La chiamata a queste funzioni garantisce che le pagine fisiche sottostanti siano bloccate e non paging.
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 di queste funzioni vengono convalidati in base a questo requisito e controllano i bug se IRQL è DISPATCH_LEVEL o versione successiva.
Modifiche 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 informa PnP che il dispositivo supporta il mapping DMA. Dxgkrnl e HAL quindi coordinate 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. Questo valore univoco consente ai driver di impostare questa chiave in INF e di non preoccuparsi dei problemi di compatibilità di livello inferiore.