地址描述符列表
为了同时支持物理和逻辑访问模式,并在运行时无缝切换这两种模式,Dxgkrnl 提供了一个描述地址描述符列表 (ADL) 的 DXGK_ADL 结构。 此数据结构类似于 MDL,但描述了一个可以是物理或逻辑的页面数组。 由于这些页可以是逻辑页,因此不能将 ADL 描述的地址映射到虚拟地址以直接访问 CPU。
DxgkddiBuildpagingbuffer 的 DXGK_OPERATION_MAP_APERTURE_SEGMENT2 操作
VidMm 提供 DXGK_OPERATION_MAP_APERTURE_SEGMENT2 分页缓冲区模式,用于将内存映射到光圈段,因为以前的版本使用与逻辑地址不兼容的 MDL。 支持逻辑地址重新映射到 DXGK_OPERATION_MAP_APERTURE_SEGMENT2 模式的 WDDM 3.0 驱动程序的 DxgkddiBuildpagingbuffer 回调,并且不再接收对原始 DXGK_OPERATION_MAP_APERTURE_SEGMENT 模式的调用。
此操作是支持逻辑 DMA 重新映射所必需的。 它的行为与原始操作类似,但提供 DXGK_ADL 而不是 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;
若要选择加入 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.CpuVisibleAddress 对于 DXGK_OPERATION_MAP_APERTURE_SEGMENT2 操作为 NULL。
MapApertureCpuVisible 是 DxgkDdiBuildPagingBuffer 的 MapAperatureSegment2 功能的一部分,因此驱动程序必须设置 DXGK_VIDMMCAPS MapAperature2Supported 才能使用此字段。 如果未设置 MapAperature2Supported,但驱动程序指定 MapApertureCpuVisible,则对 DxgkDdiCreateAllocation 的调用将失败。
此外,为了接收 DXGK_OPERATION_MAP_APERTURE_SEGMENT2 操作,驱动程序必须设置 DXGK_ALLOCATIONINFOFLAGS_WDDM2_0 AccessedPhysically 标志。 如果未设置 AccessedPhysically,则任何在其支持的段集中指定光圈段的分配都将升级为隐式系统内存段,该内存段不会接收 MAP_APERTURE 调用(因为没有要映射的光圈范围)。
总之,若要正确接收系统内存分配的 CPU 地址,驱动程序必须设置以下标志/上限:
- DXGK_DRIVERCAPS::MemoryManagementCaps.MapAperture2Supported = 1
- DXGK_ALLOCATIONINFOFLAGS_WDDM2_0::MapApertureCpuVisible = 1
- DXGK_ALLOCATIONINFOFLAGS_WDDM2_0::AccessedPhysically = 1
对于 MapApertureSegment2 调用,启用逻辑映射时,ADL 始终被初始化并作为连续传递。 驱动程序必须检查 ADL 标志,以确定分配是否连续,并相应地采取行动。