IOMMU DMA 다시 매핑

이 페이지에서는 Windows 11 22H2(WDDM 3.0)에 도입된 IOMMUv2(IOMMU DMA 다시 매핑 기능)에 대해 설명합니다. WDDM 3.0 이전의 IOMMU GPU 격리에 대한 자세한 내용은 IOMMU 기반 GPU 격리를 참조하세요.

개요

WDDM 3.0까지 Dxgkrnl 은 1:1 물리적 다시 매핑을 통해 IOMMU 격리만 지원했습니다. 즉, GPU에서 액세스하는 논리 페이지가 동일한 실제 페이지 번호로 변환되었습니다. IOMMU DMA 다시 매핑을 사용하면 GPU가 더 이상 매핑되지 않은 논리 주소를 통해 메모리에 액세스할 수 있습니다. 대신 Dxgkrnl 은 논리적으로 연속된 주소 범위를 제공할 수 있습니다.

Dxgkrnl 은 GPU에 제한을 적용합니다. GPU는 디바이스를 시작하려면 모든 실제 메모리에 액세스할 수 있어야 합니다. GPU의 가장 높은 표시 주소가 시스템에 설치된 가장 높은 실제 주소를 초과하지 않으면 Dxgkrnl 은 어댑터 초기화에 실패합니다. 예정된 서버 및 고급 워크스테이션은 많은 GPU의 일반적인 40비트 주소 공간 제한을 초과하는 1TB 이상의 메모리로 구성할 수 있습니다. DMA 다시 매핑은 GPU가 이 환경에서 작동할 수 있도록 하는 메커니즘으로 사용됩니다.

시작 시 Dxgkrnl 은 디바이스의 액세스 가능한 가장 높은 물리적 주소를 시스템에 설치된 메모리와 비교하여 논리 다시 매핑이 필요한지 여부를 결정합니다. 필요한 경우 DMA 다시 매핑을 사용하여 GPU의 표시되는 범위 내에 있는 논리적 주소 범위를 시스템의 물리적 메모리에 매핑합니다. 예를 들어 GPU에 1TB의 제한이 있는 경우 Dxgkrnl 은 [0, 1TB)의 논리 주소를 할당한 다음 IOMMU를 통해 시스템의 물리적 메모리에 매핑할 수 있습니다.

논리 어댑터와 물리적 어댑터 비교

Dxgkrnl 은 논리 어댑터와 물리적 어댑터의 개념을 구분합니다. 물리적 어댑터는 LDA 체인의 다른 디바이스와 연결되거나 연결되지 않을 수 있는 개별 하드웨어 디바이스를 나타냅니다. 논리 어댑터는 하나 이상의 연결된 실제 어댑터를 나타냅니다.

단일 IOMMU DMA 도메인은 논리 어댑터별로 만들어지고 연결된 모든 물리적 어댑터에 연결됩니다. 따라서 모든 물리적 어댑터는 동일한 도메인과 동일한 실제 메모리 보기를 공유합니다.

통합 및 불연속 GPU 지원

IOMMU DMA 다시 매핑은 통합 GPU에 거의 가치를 제공하지 않으므로 정의상 이미 시스템의 모든 실제 메모리에 액세스하도록 설계되어야 하므로 통합 부품에 대한 지원을 구현하는 것은 선택 사항이지만 권장됩니다.

불연속 GPU는 WDDM 3.0 인증에 대한 요구 사항인 IOMMU DMA 다시 매핑을 지원해야 합니다.

DDI 변경 내용

IOMMU DMA 다시 매핑을 지원하기 위해 다음과 같은 DDI가 변경되었습니다.

드라이버 기능

선형 다시 매핑을 지원하려면 두 가지 드라이버 대문자 집합이 필요합니다.

  • 드라이버는 Dxgkrnl 에 물리적 메모리 제한 사항을 알려야 합니다. 즉, DXGKQAITYPE_PHYSICAL_MEMORY_CAPS 및 연결된 DXGK_PHYSICAL_MEMORY_CAPS구조를 통해 가장 잘 보이는 실제 주소에 관한 것입니다.
  • 드라이버는 DXGKQAITYPE_IOMMU_CAPS 및 관련 DXGK_IOMMU_CAPS구조를 통해 IOMMU 선형 다시 매핑에 대한 지원을 나타내야 합니다. 지원을 표시하여 드라이버는 나중에 설명한 모든 DDI가 지원되고 사용됨을 나타냅니다.

메모리에 액세스하기 전에 디바이스를 만들고 IOMMU 도메인에 연결할 수 있도록 DxgkrnlDXGKDDI_START_DEVICE 통해 디바이스를 시작하기 전에 이러한 두 대문자를 모두 제공해야 합니다. 선형 다시 매핑은 디바이스가 기존 실제 메모리를 참조하지 않는 경우에만 수행할 수 있습니다.

단독 액세스

IOMMU 도메인 연결 및 분리는 매우 빠르지만 현재 원자성이 아닙니다. 즉, 다른 매핑을 사용하여 IOMMU 도메인으로 교환하는 동안 PCIe를 통해 발급된 트랜잭션이 올바르게 변환되지 않습니다.

이 상황을 처리하려면 Windows 10 버전 1803(WDDM 2.4)부터 KMD는 Dxgkrnl이 호출할 다음 DDI 쌍을 구현해야 합니다.

드라이버는 디바이스가 새 IOMMU 도메인으로 전환될 때마다 하드웨어가 자동으로 유지되도록 해야 합니다. 즉, 드라이버는 이러한 두 호출 사이에 디바이스에서 시스템 메모리를 읽거나 쓰지 않도록 해야 합니다.

이러한 두 호출 사이에 Dxgkrnl 은 다음을 보장합니다.

  • 스케줄러가 일시 중단됩니다. 모든 활성 워크로드가 플러시되고 하드웨어에 새 워크로드가 전송되거나 예약되지 않습니다.
  • 다른 DDI 호출은 이루어지지 않습니다.

이러한 호출의 일부로 드라이버는 OS에서 명시적 알림 없이도 단독 액세스 중에 인터럽트(Vsync 인터럽트 포함)를 사용하지 않도록 설정하고 표시하지 않도록 선택할 수 있습니다.

주소 설명자 목록

Dxgkrnl은 물리적 및 논리적 액세스 모드를 모두 지원하고 런타임에 두 모드 간에 원활하게 전환하기 위해 ADL(주소 설명자 목록)을 설명하는 DXGK_ADL 구조를 제공합니다. 이 데이터 구조는 MDL과 비슷하지만 물리적 또는 논리적일 수 있는 페이지 배열을 설명합니다. 이러한 페이지는 논리적 페이지일 수 있으므로 ADL에서 설명하는 주소는 직접 CPU 액세스를 위해 가상 주소에 매핑할 수 없습니다.

DxgkddiBuildpagingbuffer에 대한 DXGK_OPERATION_MAP_APERTURE_SEGMENT2 작업

VidMm 은 이전 버전이 논리 주소와 호환되지 않는 MDL을 사용하기 때문에 메모리를 조리개 세그먼트에 매핑하기 위한 DXGK_OPERATION_MAP_APERTURE_SEGMENT2 페이징 버퍼 모드를 제공합니다. 논리 주소 다시 매핑을 지원하는 WDDM 3.0 드라이버의 DxgkddiBuildpagingbuffer 콜백은 DXGK_OPERATION_MAP_APERTURE_SEGMENT2 모드에 대한 호출을 수신하고 더 이상 원래 DXGK_OPERATION_MAP_APERTURE_SEGMENT 모드에 대한 호출을 받지 않습니다.

논리 DMA 다시 매핑을 지원하려면 이 작업이 필요합니다. 원래 작업과 비슷하게 동작하지만 MDL 대신 DXGK_ADL 제공합니다.

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;

DXGK_OPERATION_MAP_APERTURE_SEGMENT2 작업을 옵트인하려면 드라이버는 메모리 관리 한도에서 MapApertureSegment2 호출에 대한 지원을 표시해야 합니다.

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

DXGK_VIDMMCAPS 메모리 관리 한도는 DXGK_DRIVERCAPS 데이터 구조의 일부입니다. 드라이버는 이 지원을 사용하지 않고 DMA 다시 매핑(즉, 논리적 주소 다시 매핑) 기능을 사용할 수 없습니다.

일부 드라이버는 MapApertureSegment2 호출 중에 메모리에 대한 CPU 액세스 권한이 필요할 수 있습니다. 이 기능은 필요에 따라 다른 MapApertureSegment2.CpuVisibleAddress 매개 변수를 통해 제공됩니다. 이 주소는 할당이 조리개 세그먼트에 매핑되는 한 유효한 커널 모드 가상 주소입니다. 즉, 이 주소는 동일한 할당에 대한 해당 DXGK_OPERATION_UNMAP_APERTURE_SEGMENT 호출 직후에 해제됩니다.

이 주소는 모든 할당에 필요하지 않을 수 있으므로 필요한 시기를 나타내기 위해 MapApertureCpuVisible 플래그가 할당 플래그에 추가되었습니다.

MapApertureCpuVisible가 지정되지 않은 경우 MapApertureSegment2.CpuVisibleAddressDXGK_OPERATION_MAP_APERTURE_SEGMENT2 작업에 대해 NULL입니다.

MapApertureCpuVisibleDxgkDdiBuildPagingBufferMapAperatureSegment2 기능의 일부이므로 이 필드를 사용하려면 드라이버가 mapAperature2Supported를 DXGK_VIDMMCAPS 설정해야 합니다. MapAperature2Supported가 설정되지 않았지만 드라이버가 MapApertureCpuVisible을 지정하면 DxgkDdiCreateAllocation에 대한 호출이 실패합니다.

또한 DXGK_OPERATION_MAP_APERTURE_SEGMENT2 작업을 수신하려면 드라이버가 accessedPhysically 플래그를 DXGK_ALLOCATIONINFOFLAGS_WDDM2_0 설정해야 합니다. AccessedPhysically가 설정되지 않은 경우 지원되는 세그먼트 집합에서 조리개 세그먼트를 지정하는 할당은 암시적 시스템 메모리 세그먼트로 업그레이드되며, 이 세그먼트는 매핑할 조리개 범위가 없으므로 MAP_APERTURE 호출을 받지 않습니다.

요약하자면, 시스템 메모리 할당의 CPU 주소를 올바르게 받으려면 드라이버는 다음 플래그/대문자를 설정해야 합니다.

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

MapApertureSegment2 호출의 경우 논리 매핑을 사용하도록 설정하면 ADL이 항상 초기화되고 연속으로 전달됩니다. 드라이버는 ADL 플래그를 검사 할당이 연속인지 여부를 확인하고 그에 따라 동작해야 합니다.

메모리 관리 서비스

메모리 관리 기능에는 다음과 같은 세 가지 기본 요구 사항이 있습니다.

  1. 실제 메모리를 관리하는 기능입니다. 여기에는 MmAllocatePagesforMdl 또는 MmAllocateContiguousMemory와 같은 비페이지 메모리 함수를 통한 메모리 할당과 ZwCreateSection 또는 ZwAllocateVirtualMemory와 같은 페이징된 메모리 함수가 포함될 수 있습니다. IO 공간 범위를 표현하는 기능도 필요합니다.

  2. 실제 메모리에서 GPU 표시 논리 주소를 매핑하는 기능입니다. 이렇게 하면 호출자에게 GPU가 액세스하도록 프로그래밍할 수 있는 논리적 페이지 목록(MDL의 PFN 배열과 유사)을 제공합니다. 이러한 함수를 호출하면 기본 물리적 페이지가 잠겨 있고 페이지가 지정되지 않습니다.

  3. 사용자 모드와 커널 모드 모두에서 물리적 메모리의 CPU 가상 주소를 지정된 캐시 유형(Cached 및 WriteCombined)으로 매핑하는 기능입니다.

다음 표에는 물리적 메모리 할당 및 논리/가상 뷰 매핑을 설명하기 위해 도입된 DDI 및 관련 입력 구조가 나열되어 있습니다. 이러한 DDI는 IOMMU 매핑을 관리하기 위해 드라이버에 제공된 이전 콜백을 대체하도록 업데이트된 집합입니다(DxgkCbAllocatePagesforMdl, DxgkCbAllocateContiguousMemory, DxgkCbMapMdlToIoMmu). 논리 다시 매핑을 지원하는 WDDM 3.0 드라이버의 경우 이러한 이전 콜백 함수는 더 이상 사용되지 않으며 사용할 수 없습니다. 대신 드라이버는 다음 메모리 관리 콜백 함수를 사용해야 합니다.

콜백 함수는 IRQL <= APC_LEVEL 호출해야 합니다. WDDM 3.2부터 이러한 함수를 호출하는 드라이버는 IRQL이 DISPATCH_LEVEL 이상인 경우 이 요구 사항 및 버그 검사에 대해 유효성을 검사합니다.

콜백 연결된 콜백 구조
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 변경 내용

지원되는 각 디바이스 유형은 INF의 적절한 섹션에 다음 레지스트리 키와 값을 추가해야 합니다.

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

이 값은 디바이스가 DMA 다시 매핑을 지원한다는 것을 PnP에 알릴 수 있습니다. 그런 다음 Dxgkrnl 및 HAL이 조정하여 사용해야 하는 매핑 모드 유형(다시 매핑, 통과 등)을 결정합니다.

이 레지스트리 키는 이전 버전의 Windows에 있었지만 값 '3'은 Windows 10 버전 1803(WDDM 2.4)부터 고유하며 이를 지원하지 않는 이전 빌드에서는 무시됩니다. 이렇게 하면 드라이버가 INF에서 이 키를 설정할 수 있으며 호환성 문제에 대해 걱정하지 않아도 됩니다.