三级线程处理和同步可确保:
内核模式驱动程序中只有一个线程(调用线程)。*
图形硬件处于空闲状态。
驱动程序当前没有处理任何直接内存访问 (DMA) 缓冲区,也没有传递 GPU 计划程序。
视频内存完全被逐出主机 CPU 内存。
WDDM 保证在线程处理和同步的三级下对显示微型端口驱动程序进行如下调用。
- DxgkDdiAddDevice
- DxgkDdiQueryChildRelations*
- DxgkDdiRemoveDevice
- DxgkDdiResetFromTimeout
- DxgkDdiRestartFromTimeout
- DxgkDdiSetPowerState*
- DxgkDdiStartDevice
- DxgkDdiStopDevice
- DxgkDdiUnload
*例外情况是,DxgkDdiQueryAdapterInfo 可以与 DxgkDdiSetPowerState 或 DxgkDdiQueryChildRelations 同时调用。 这样,当调用 DxgkDdiQueryAdapterInfo 时,系统可以避免将设备从低功耗状态唤醒。 驱动程序需要使用必要的同步从 DxgkDdiQueryAdapterInfo 返回正确的信息。
一、Level 3调用执行条件验证
硬件状态检测代码:
BOOLEAN IsGpuIdle(PDEVICE_CONTEXT pDevExt) {
// 检查6个主要引擎状态位
ULONG status = READ_REGISTER_ULONG(pDevExt->pEngineRegs + 0x1A4);
return (status & 0x3F) == 0x3F; // 所有引擎空闲标志
}
二、关键调用实现模板
2.1 设备启动流程(DxgkDdiStartDevice)
NTSTATUS DxgkDdiStartDevice(
_In_ CONST PVOID MiniportDeviceContext,
_Inout_ DXGK_START_INFO* pStartInfo)
{
// Level 3自动同步保证
PAGED_CODE();
// 1. PCIe配置空间初始化
if (!InitPciConfigSpace(pDevExt)) {
return STATUS_DEVICE_CONFIGURATION_ERROR;
}
// 2. 视频内存管理器启动
DXGK_VIDMM_INIT vidmmInit = {0};
vidmmInit.Flags.EnableMemoryEviction = TRUE;
pStartInfo->DxgkDdiVidMmInit(&vidmmInit);
// 3. 中断注册(必须最后执行)
NTSTATUS status = IoConnectInterruptEx(
&pDevExt->InterruptObject,
...);
return status;
}
2.2 TDR恢复处理(DxgkDdiResetFromTimeout)
void DxgkDdiResetFromTimeout(_In_ PVOID MiniportDeviceContext) {
// 系统全局TDR锁已由DXGKRNL持有
PDEVICE_CONTEXT pDevExt = (PDEVICE_CONTEXT)MiniportDeviceContext;
// 1. 强制终止所有上下文
VidMmCancelAllocations(pDevExt);
// 2. GPU硬件复位序列
SendResetCommand(pDevExt, RESET_TYPE_FULL);
// 3. 等待50ms复位完成
LARGE_INTEGER interval;
interval.QuadPart = -50 * 10000; // 50ms
KeDelayExecutionThread(KernelMode, FALSE, &interval);
}
三、特殊并发例外处理
3.1 低功耗状态查询(DxgkDdiQueryAdapterInfo)
NTSTATUS DxgkDdiQueryAdapterInfo(
_In_ CONST HANDLE hAdapter,
_Inout_ DXGKARG_QUERYADAPTERINFO* pArgs)
{
if (pArgs->Type == DXGKQAITYPE_UMDRIVERPRIVATE) {
// 需要与SetPowerState同步
ExAcquireFastMutex(&pDevExt->PowerMutex);
NTSTATUS status = QueryPowerStateInfo(pDevExt, pArgs);
ExReleaseFastMutex(&pDevExt->PowerMutex);
return status;
}
// 其他查询类型无需同步...
}
3.2 子设备枚举(DxgkDdiQueryChildRelations)
NTSTATUS DxgkDdiQueryChildRelations(
_In_ PVOID MiniportDeviceContext,
_Inout_ DXGK_CHILD_DESCRIPTOR* pChildRelations)
{
// 动态检测显示器热插拔
ExAcquireFastMutex(&pDevExt->ChildLock);
if (pDevExt->bHotplugDetectionPending) {
UpdateEdidCache(pDevExt);
pDevExt->bHotplugDetectionPending = FALSE;
}
ExReleaseFastMutex(&pDevExt->ChildLock);
return STATUS_SUCCESS;
}
四、内存逐出协议
4.1 显存回收流程
4.2 关键验证点
void VerifyLevel3Conditions() {
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
ASSERT(IsGpuIdle(pDevExt));
ASSERT(VidMmGetAllocationCount() == 0);
}
五、调试与验证
5.1 WinDbg扩展命令
!dxgkd.synclevel 3 // 显示当前Level3调用栈
!vidmm.eviction // 检查内存逐出状态
5.2 断言检查列表
断言条件 | 错误代码 |
---|---|
KeGetCurrentThread() == pDevExt->Level3OwnerThread | 0xC000000D |
!InterlockedCompareExchange(&pDevExt->DmaActive, 0, 0) | 0xC0000010 |
六、版本差异
WDDM版本 | Level3增强特性 |
---|---|
1.2 | 基础同步保证 |
2.0 | 增加DMA缓冲区状态检查 |
2.5 | 支持PCIe FLR(功能级复位) |
实现要点总结:
- 所有Level 3调用必须包含PAGED_CODE()宏验证
- 硬件寄存器访问前需双重确认GPU空闲状态
- 内存逐出必须等待VidMmEvictAllocations完成回调
- 与Power State/Child Relations的并发需使用FAST_MUTEX保护