Remappage DMA IOMMU
Cette page décrit la fonctionnalité de remappage DMA IOMMU (IOMMUv2) qui a été introduite dans Windows 11 22H2 (WDDM 3.0). Veuillez consulter la section Isolation GPU basée sur IOMMU pour obtenir des informations sur l’isolation GPU IOMMU avant WDDM 3.0.
Vue d’ensemble
Jusqu’à WDDM 3.0, Dxgkrnl ne prenait en charge l’isolation IOMMU qu’à travers un remappage physique 1:1, ce qui signifie que les pages logiques accessibles par le GPU étaient traduites vers le même numéro de page physique. Le remappage DMA IOMMU permet au GPU d’accéder à la mémoire via des adresses logiques qui ne sont plus mappées en 1:1. Au lieu de cela, Dxgkrnl est capable de fournir des plages d’adresses logiques contiguës.
Dxgkrnl impose une restriction aux GPU : les GPU doivent être capables d’accéder à toute la mémoire physique pour que le périphérique puisse démarrer. Si l’adresse visible la plus élevée du GPU ne dépasse pas l’adresse physique la plus élevée installée sur le système, Dxgkrnl échoue l’initialisation de l’adaptateur. Les futurs serveurs et stations de travail haut de gamme peuvent être configurés avec plus de 1 To de mémoire, dépassant la limitation courante de l’espace d’adressage de 40 bits de nombreux GPU. Le remappage DMA est utilisé comme mécanisme pour permettre aux GPU de fonctionner dans cet environnement.
Au démarrage, Dxgkrnl détermine si un remappage logique est nécessaire en comparant l’adresse physique la plus élevée accessible par le périphérique à la mémoire installée sur le système. Si c’est nécessaire, le remappage DMA est utilisé pour mapper une plage d’adresses logiques qui se trouve dans les limites visibles du GPU à n’importe quelle mémoire physique du système. Par exemple, si le GPU a une limite de 1 To, alors Dxgkrnl alloue des adresses logiques de [0, 1 To) qui peuvent ensuite être mappées à n’importe quelle mémoire physique du système via l’IOMMU.
Adaptateurs logiques versus physiques
Dxgkrnl distingue entre le concept d’un adaptateur logique et d’un adaptateur physique. Un adaptateur physique représente un périphérique matériel individuel qui pourrait être lié à d’autres dispositifs dans une chaîne LDA. Un adaptateur logique représente un ou plusieurs adaptateurs physiques liés.
Un seul domaine DMA IOMMU est créé par adaptateur logique et attaché à tous les adaptateurs physiques qui sont liés. Ainsi, tous les adaptateurs physiques partagent le même domaine et la même vue de la mémoire physique.
Support GPU intégré versus discret
Étant donné que le remappage DMA IOMMU offre peu d’avantages aux GPU intégrés qui, par définition, devraient déjà être conçus pour accéder à toute la mémoire physique du système, la mise en œuvre du support sur les composants intégrés est optionnelle mais recommandée.
Les GPU discrets doivent prendre en charge le remappage DMA IOMMU, ce qui est une exigence pour la certification WDDM 3.0.
Modifications de l’DDI
Les changements suivants dans le DDI ont été effectués pour prendre en charge le remappage DMA IOMMU.
Capacités du pilote
Deux ensembles de capacités du pilote sont nécessaires pour prendre en charge le remappage linéaire :
- Le pilote doit informer Dxgkrnl de ses restrictions de mémoire physique ; c’est-à-dire de son adresse physique visible la plus élevée via DXGKQAITYPE_PHYSICAL_MEMORY_CAPS et sa structure associée DXGK_PHYSICAL_MEMORY_CAPS.
- Le pilote doit indiquer sa prise en charge du remappage linéaire IOMMU via DXGKQAITYPE_IOMMU_CAPS et sa structure associée DXGK_IOMMU_CAPS. En indiquant son support, le pilote indique que tous les DDI décrits plus loin sont pris en charge et utilisés.
Ces deux capacités doivent être fournies avant que Dxgkrnl ne démarre le périphérique via DXGKDDI_START_DEVICE, afin que le périphérique puisse être créé et attaché à un domaine IOMMU avant que toute mémoire ne puisse être accédée. Le remappage linéaire ne peut être effectué que si le périphérique ne référence aucune mémoire physique existante.
Accès exclusif
L’attachement et le détachement du domaine IOMMU sont extrêmement rapides, mais ne sont néanmoins pas actuellement atomiques. Cette condition signifie qu’une transaction émise via PCIe n’est pas garantie d’être traduite correctement lors du basculement vers un domaine IOMMU avec des mappages différents.
Pour gérer cette situation, à partir de Windows 10 version 1803 (WDDM 2.4), un KMD doit implémenter la paire de DDI suivante pour que Dxgkrnl puisse appeler :
- DxgkDdiBeginExclusiveAccess est appelé pour notifier le KMD qu’un changement de domaine IOMMU est sur le point de se produire.
- DxgkDdiEndExclusiveAccess est appelé après que le changement de domaine IOMMU est terminé.
Le pilote doit s’assurer que son matériel est inactif chaque fois que le périphérique est basculé vers un nouveau domaine IOMMU. C’est-à-dire que le pilote doit s’assurer qu’il ne lit ni n’écrit dans la mémoire système depuis le périphérique entre ces deux appels.
Entre ces deux appels, Dxgkrnl garantit les éléments suivants :
- Le planificateur est suspendu. Toutes les charges de travail actives sont vidées, et aucune nouvelle charge de travail n’est envoyée ou planifiée sur le matériel.
- Aucun autre appel DDI n’est effectué.
Dans le cadre de ces appels, le pilote peut choisir de désactiver et de supprimer les interruptions (y compris les interruptions Vsync) pendant l’accès exclusif, même sans notification explicite du système d’exploitation.
Listes descripteurs d’adresses
Pour prendre en charge à la fois les modes d’accès physique et logique et passer d’un mode à l’autre de manière transparente à l’exécution, Dxgkrnl fournit une structure DXGK_ADL qui décrit une liste descripteur d’adresses (ADL). Cette structure de données est similaire à un MDL, mais décrit un tableau de pages qui peuvent être physiques ou logiques. Étant donné que ces pages peuvent être des pages logiques, les adresses décrites par une ADL ne peuvent pas être mappées à une adresse virtuelle pour un accès direct par le CPU.
Opération DXGK_OPERATION_MAP_APERTURE_SEGMENT2 pour DxgkDdiBuildPagingBuffer
VidMm fournit le mode tampon de pagination DXGK_OPERATION_MAP_APERTURE_SEGMENT2 pour mapper la mémoire au segment d’ouverture puisque la version précédente utilise un MDL qui est incompatible avec les adresses logiques. Le callback DxgkDdiBuildPagingBuffer des pilotes WDDM 3.0 qui prennent en charge le remappage d’adresses logiques reçoit des appels au mode DXGK_OPERATION_MAP_APERTURE_SEGMENT2, et ne reçoit plus d’appels au mode original DXGK_OPERATION_MAP_APERTURE_SEGMENT.
Cette opération est nécessaire pour prendre en charge le remappage DMA logique. Elle se comporte de manière similaire à l’opération originale, mais fournit une DXGK_ADL au lieu d’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;
Pour adhérer à l’opération DXGK_OPERATION_MAP_APERTURE_SEGMENT2, le pilote doit indiquer la prise en charge des appels MapApertureSegment2 dans les capacités de gestion de la mémoire :
typedef struct _DXGK_VIDMMCAPS {
union {
struct {
...
UINT MapAperture2Supported : 1;
...
}
...
} DXGK_VIDMMCAPS;
Les DXGK_VIDMMCAPS capacités de gestion de la mémoire font partie de la structure de données DXGK_DRIVERCAPS. Le pilote ne peut pas utiliser la fonctionnalité de remappage DMA (c’est-à-dire le remappage d’adresses logiques) sans cette prise en charge activée.
Certains pilotes pourraient nécessiter un accès CPU à la mémoire pendant un appel MapApertureSegment2. Cette fonctionnalité est fournie de manière optionnelle via un autre paramètre MapApertureSegment2.CpuVisibleAddress. Cette adresse est une adresse virtuelle en mode noyau qui est valide tant que l’allocation est mappée dans le segment d’ouverture. C’est-à-dire que cette adresse sera libérée immédiatement après l’appel correspondant DXGK_OPERATION_UNMAP_APERTURE_SEGMENT pour la même allocation.
Cette adresse peut ne pas être nécessaire pour toutes les allocations. Le flag MapApertureCpuVisible a été ajouté aux indicateurs d’allocation pour indiquer quand cette adresse est nécessaire.
Si MapApertureCpuVisible n’est pas spécifié, MapApertureSegment2.CpuVisibleAddress est NULL pour les opérations DXGK_OPERATION_MAP_APERTURE_SEGMENT2.
MapApertureCpuVisible fait partie de la fonctionnalité MapApertureSegment2 de DxgkDdiBuildPagingBuffer, donc le pilote doit définir DXGK_VIDMMCAPS MapAperature2Supported pour utiliser ce champ. Si MapAperature2Supported n’est pas défini mais que le pilote spécifie MapApertureCpuVisible, l’appel à DxgkDdiCreateAllocation échoue.
De plus, pour recevoir l’opération DXGK_OPERATION_MAP_APERTURE_SEGMENT2, le pilote doit définir le flag DXGK_ALLOCATIONINFOFLAGS_WDDM2_0 AccessedPhysically. Si AccessedPhysically n’est pas défini, toute allocation qui spécifie un segment d’ouverture dans leur ensemble de segments pris en charge est mise à niveau vers le segment de mémoire système implicite, qui ne reçoit pas d’appels MAP_APERTURE (puisqu’il n’y a pas de plages d’ouverture à mapper).
En résumé, pour recevoir correctement l’adresse CPU d’une allocation de mémoire système, le pilote doit définir les flags/caps suivants :
- DXGK_DRIVERCAPS::MemoryManagementCaps.MapAperture2Supported = 1
- DXGK_ALLOCATIONINFOFLAGS_WDDM2_0::MapApertureCpuVisible = 1
- DXGK_ALLOCATIONINFOFLAGS_WDDM2_0::AccessedPhysically = 1
Pour les appels MapApertureSegment2, l’ADL est toujours initialisé et transmis comme contigu lorsque le mappage logique est activé. Le pilote doit vérifier les flags de l’ADL pour déterminer si l’allocation est contiguë, et se comporter en conséquence.
Services de gestion de la mémoire
Il existe trois exigences fondamentales pour les fonctions de gestion de la mémoire :
La capacité de gérer la mémoire physique. Cette capacité peut inclure l’allocation de mémoire via des fonctions de mémoire non paginée telles que MmAllocatePagesforMdl ou MmAllocateContiguousMemory, et des fonctions de mémoire paginée telles que ZwCreateSection ou ZwAllocateVirtualMemory. La capacité d’exprimer des plages d’espace d’E/S est également requise.
La capacité de mapper une adresse logique visible par le GPU depuis la mémoire physique. Cette capacité fournirait à l’appelant une liste de pages logiques (semblable à un tableau PFN d’un MDL) que le GPU peut être programmé pour accéder. L’appel à ces fonctions garantirait que les pages physiques sous-jacentes sont verrouillées et non paginables.
La capacité de mapper des adresses virtuelles CPU depuis la mémoire physique à la fois en mode utilisateur et en mode noyau, avec un type de cache spécifié (Cache vs WriteCombined).
Le tableau suivant répertorie les DDI et les structures d’entrée associées introduites pour décrire l’allocation de mémoire physique et le mappage de vues logiques/virtuelles. Ces DDI sont un ensemble mis à jour pour remplacer les callbacks précédents fournis aux pilotes pour gérer les mappages IOMMU (DxgkCbAllocatePagesforMdl, DxgkCbAllocateContiguousMemory, DxgkCbMapMdlToIoMmu). Pour les pilotes WDDM 3.0 qui prennent en charge le remappage logique, ces anciennes fonctions de callback sont obsolètes et ne peuvent pas être utilisées. Le pilote doit utiliser à la place les fonctions de callback de gestion de la mémoire suivantes.
Les fonctions de callback doivent être appelées à un IRQL <= APC_LEVEL. À partir de WDDM 3.2, les pilotes qui appellent l’une de ces fonctions sont validés par rapport à cette exigence et génèrent un bugcheck si l’IRQL est au niveau DISPATCH_LEVEL ou supérieur.
Modifications INF
Chaque type de périphérique pris en charge doit ajouter la clé et la valeur de registre suivantes à la section appropriée du fichier INF :
[DMAr.reg]
; Add REG_DWORD 'DmaRemappingCompatible' with value of 3
HKR,Parameters,DmaRemappingCompatible,0x00010001,```3
Cette valeur informe le PnP que le périphérique prend en charge le remappage DMA. Dxgkrnl et le HAL se coordonnent ensuite pour déterminer quel type de mode de mappage doit être utilisé (Remappage, Passthrough, etc.).
Bien que cette clé de registre était présente sur les versions antérieures de Windows, la valeur « 3 » est unique à partir de Windows 10 version 1803 (WDDM 2.4) et est ignorée sur les versions plus anciennes qui ne la prennent pas en charge. Cette valeur unique permet aux pilotes de définir cette clé dans le fichier INF sans se soucier des problèmes de compatibilité avec les versions antérieures.