Reasignación de DMA de IOMMU

En esta página se describe la característica de reasignación de DMA de IOMMU (IOMMUv2) que se introdujo en Windows 11 22H2 (WDDM 3.0). Consulte Aislamiento de GPU basado en IOMMU para obtener información sobre el aislamiento de GPU de IOMMU antes de WDDM 3.0.

Información general

Hasta WDDM 3.0, Dxgkrnl solo admitía el aislamiento de IOMMU a través de la reasignación física 1:1, lo que significa que las páginas lógicas a las que accede la GPU se traducen al mismo número de página físico. La reasignación de DMA de IOMMU permite que la GPU acceda a la memoria a través de direcciones lógicas que ya no están asignadas 1:1. En su lugar, Dxgkrnl puede proporcionar intervalos de direcciones contiguas lógicamente.

Dxgkrnl impone una restricción en las GPU: las GPU deben poder acceder a toda la memoria física para que el dispositivo se inicie. Si la dirección visible más alta de la GPU no supera la dirección física más alta instalada en el sistema, Dxgkrnl produce un error en la inicialización del adaptador. Los próximos servidores y estaciones de trabajo de gama alta pueden configurarse con más de 1 TB de memoria que supera la limitación común del espacio de direcciones de 40 bits de muchas GPU. La reasignación de DMA se usa como mecanismo para permitir que las GPU funcionen en este entorno.

En tiempo de inicio, Dxgkrnl determina si la reasignación lógica es necesaria comparando la dirección física más alta accesible del dispositivo con la memoria instalada en el sistema. Si es necesario, la reasignación de DMA se usa para asignar un intervalo de direcciones lógicas que se encuentra dentro de los límites visibles de la GPU a cualquier memoria física del sistema. Por ejemplo, si la GPU tiene un límite de 1 TB, Dxgkrnl asigna direcciones lógicas de [0, 1 TB) que luego se pueden asignar a cualquier memoria física del sistema a través de la IOMMU.

Adaptadores lógicos frente a físicos

Dxgkrnl distingue entre el concepto de un adaptador lógico y físico. Un adaptador físico representa un dispositivo de hardware individual que podría estar vinculado a otros dispositivos de una cadena LDA. Un adaptador lógico representa uno o varios adaptadores físicos vinculados.

Se crea un único dominio de DMA de IOMMU por adaptador lógico y se adjunta a todos los adaptadores físicos vinculados. Por lo tanto, todos los adaptadores físicos comparten el mismo dominio y la misma vista de memoria física.

Compatibilidad integrada frente a GPU discreta

Dado que la reasignación de DMA de IOMMU ofrece poco valor a las GPU integradas que deberían, por definición, estar diseñadas ya para acceder a toda la memoria física del sistema, la implementación de compatibilidad con las partes integradas es opcional, pero se recomienda.

Las GPU discretas deben admitir la reasignación de DMA de IOMMU, que es un requisito para la certificación WDDM 3.0.

Cambios de DDI

Se realizaron los siguientes cambios de DDI para admitir la reasignación de DMA de IOMMU.

Funcionalidades del controlador

Se requieren dos conjuntos de límites de controladores para admitir la reasignación lineal:

  • El controlador debe informar a Dxgkrnl sobre sus restricciones de memoria física; es decir, sobre su dirección física más alta visible a través de DXGKQAITYPE_PHYSICAL_MEMORY_CAPS y su estructura DXGK_PHYSICAL_MEMORY_CAPS asociada.
  • El controlador debe indicar su compatibilidad con la reasignación lineal de IOMMU a través de DXGKQAITYPE_IOMMU_CAPS y su estructura DXGK_IOMMU_CAPS asociada. Al indicar compatibilidad, el controlador indica que se admiten y usan todas las DDI descritas más adelante.

Ambos límites deben proporcionarse antes de que Dxgkrnl inicie el dispositivo a través de DXGKDDI_START_DEVICE para que el dispositivo se pueda crear y conectar a un dominio de IOMMU antes de que se pueda acceder a cualquier memoria. La reasignación lineal solo se puede realizar si el dispositivo no hace referencia a ninguna memoria física existente.

Acceso exclusivo

La asociación y desasociación de dominios de IOMMU es extremadamente rápida, pero actualmente no es atómica. Esta condición significa que no se garantiza que una transacción emitida a través de PCIe se traduzca correctamente mientras se intercambia a un dominio de IOMMU con diferentes asignaciones.

Para controlar esta situación, a partir de Windows 10 versión 1803 (WDDM 2.4), un KMD debe implementar el siguiente par de DDI para que Dxgkrnl llame a:

El controlador debe asegurarse de que su hardware sea silencioso siempre que el dispositivo se cambie a un nuevo dominio de IOMMU. Es decir, el controlador debe asegurarse de que no lee ni escribe en la memoria del sistema desde el dispositivo entre estas dos llamadas.

Entre estas dos llamadas, Dxgkrnl realiza las siguientes garantías:

  • El programador está suspendido. Todas las cargas de trabajo activas se vacían y no se envían ni programan nuevas cargas de trabajo en el hardware.
  • No se realiza ninguna otra llamada DDI.

Como parte de estas llamadas, el controlador puede optar por deshabilitar y suprimir interrupciones (incluidas las interrupciones de Vsync) durante el acceso exclusivo, incluso sin notificación explícita del sistema operativo.

Listas de descriptores de direcciones

Para admitir los modos de acceso físico y lógico y cambiar entre los dos modos sin problemas en tiempo de ejecución, Dxgkrnl proporciona una estructura DXGK_ADL que describe una lista de descriptores de direcciones (ADL). Esta estructura de datos es similar a una MDL, salvo que describe una matriz de páginas que puede ser física o lógica. Dado que estas páginas pueden ser páginas lógicas, las direcciones descritas por una ADL no se pueden asignar a una dirección virtual para el acceso directo a la CPU.

Operación DXGK_OPERATION_MAP_APERTURE_SEGMENT2 para DxgkddiBuildpagingbuffer

VidMm proporciona el modo de búfer de paginación DXGK_OPERATION_MAP_APERTURE_SEGMENT2 para asignar memoria al segmento de apertura, ya que la versión anterior usa una MDL que no es compatible con las direcciones lógicas. La devolución de llamada DxgkddiBuildpagingbuffer de los controladores WDDM 3.0 que admiten la reasignación de direcciones lógicas recibe llamadas al modo DXGK_OPERATION_MAP_APERTURE_SEGMENT2 y ya no recibe llamadas al modo DXGK_OPERATION_MAP_APERTURE_SEGMENT original.

Esta operación es necesaria para admitir la reasignación lógica de DMA. Se comporta de forma similar a la operación original, pero proporciona una DXGK_ADL en lugar de una 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;

Para optar por la operación DXGK_OPERATION_MAP_APERTURE_SEGMENT2, el controlador debe indicar la compatibilidad con las llamadas MapApertureSegment2 en los límites de administración de memoria:

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

Los límites de administración de memoria DXGK_VIDMMCAPS forman parte de la estructura de datos DXGK_DRIVERCAPS. El controlador no puede usar la funcionalidad de reasignación de DMA (es decir, reasignación de direcciones lógicas) sin esta compatibilidad habilitada.

Algunos controladores pueden requerir acceso de CPU a la memoria durante una llamada a MapApertureSegment2. Esta funcionalidad se proporciona opcionalmente a través de otro parámetro MapApertureSegment2.CpuVisibleAddress. Esta dirección es una dirección virtual en modo kernel que es válida siempre que la asignación se asigne al segmento de apertura. Es decir, esta dirección se liberará inmediatamente después de la llamada DXGK_OPERATION_UNMAP_APERTURE_SEGMENT correspondiente para la misma asignación.

Es posible que esta dirección no sea necesaria para todas las asignaciones. La marca MapApertureCpuVisible se agregó a las marcas de asignación para indicar cuándo se requiere esta dirección.

Si no se especifica MapApertureCpuVisible, MapApertureSegment2.CpuVisibleAddress es NULL para las operaciones de DXGK_OPERATION_MAP_APERTURE_SEGMENT2.

MapApertureCpuVisible forma parte de la funcionalidad MapAperatureSegment2 de DxgkDdiBuildPagingBuffer, por lo que el controlador debe establecer DXGK_VIDMMCAPS MapAperature2Supported para usar este campo. Si MapAperature2Supported no está establecido, pero el controlador especifica MapApertureCpuVisible, se produce un error en la llamada a DxgkDdiCreateAllocation.

Además, para recibir la operación de DXGK_OPERATION_MAP_APERTURE_SEGMENT2, el controlador debe establecer la marca DXGK_ALLOCATIONINFOFLAGS_WDDM2_0 AccessedPhysically. Si AccessedPhysically no se establece, cualquier asignación que especifique un segmento de apertura en su conjunto de segmentos admitido se actualiza al segmento de memoria del sistema implícito, que no recibe llamadas MAP_APERTURE (ya que no hay ningún intervalo de apertura que asignar).

En resumen, para recibir correctamente la dirección de CPU de una asignación de memoria del sistema, el controlador debe establecer las marcas o límites siguientes:

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

En el caso de las llamadas MapApertureSegment2, la ADL siempre se inicializa y se pasa como contigua cuando se habilita la asignación lógica. El controlador debe comprobar las marcas de ADL para determinar si la asignación es contigua y comportarse en consecuencia.

Servicio de administración de memoria

Hay tres requisitos fundamentales para las funciones de administración de memoria:

  1. La capacidad de administrar la memoria física. Esta funcionalidad puede incluir la asignación de memoria a través de funciones de memoria no paginadas, como MmAllocatePagesforMdl o MmAllocateContiguousMemory y funciones de memoria paginadas como ZwCreateSection o ZwAllocateVirtualMemory. También se requiere la capacidad de expresar intervalos de espacio de E/S.

  2. La capacidad de asignar una dirección lógica visible para GPU a partir de la memoria física. Esta funcionalidad proporcionaría al llamador una lista de páginas lógicas (similar a la matriz PFN de una MDL) que la GPU puede programar para acceder. La llamada a estas funciones garantizaría que las páginas físicas subyacentes están bloqueadas y no son paginables.

  3. La capacidad de asignar direcciones virtuales de CPU desde la memoria física tanto en modo de usuario como en modo kernel, con un tipo de caché especificado (Cached vs WriteCombined).

En la tabla siguiente se enumeran las DDI y las estructuras de entrada asociadas introducidas para describir la asignación de memoria física de vistas lógicas o virtuales. Estas DDI son un conjunto actualizado para reemplazar las devoluciones de llamada anteriores proporcionadas a los controladores para administrar las asignaciones de IOMMU (DxgkCbAllocatePagesforMdl, DxgkCbAllocateContiguousMemory, DxgkCbMapMdlToIoMmu). En el caso de los controladores WDDM 3.0 que admiten la reasignación lógica, estas funciones de devolución de llamada anteriores están en desuso y no se pueden usar. En su lugar, el controlador debe usar las siguientes funciones de devolución de llamada de administración de memoria.

Se debe llamar a las funciones de devolución de llamada en IRQL <= APC_LEVEL. A partir de WDDM 3.2, los controladores que llaman a cualquiera de estas funciones se validan con este requisito y se comprueban errores si IRQL es DISPATCH_LEVEL o superior.

Devolución de llamada Estructura de devolución de llamada asociada
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

Cambios de INF

Cada tipo de dispositivo admitido debe agregar la siguiente clave del Registro y el valor a la sección adecuada de INF:

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

Este valor informa a PnP de que el dispositivo admite la reasignación de DMA. Dxgkrnl y HAL se coordinan para determinar qué tipo de modo de asignación se debe usar (reasignación, tránsito, etc.).

Aunque esta clave del Registro estaba presente en versiones anteriores de Windows, el valor "3" es único a partir de Windows 10 versión 1803 (WDDM 2.4) y se omite en compilaciones anteriores que no lo admiten. Este valor único permite a los controladores establecer esta clave en el INF y no preocuparse por los problemas de compatibilidad de nivel inferior.