從內核模式驅動程式發出 CPU 事件的訊號

在某些情況下,核心模式驅動程式 (KMD) 需要發出 CPU 事件的訊號,以通知使用者模式驅動程式 (UMD) 相關專案;例如:

  • 當 KMD 偵測到其中一個對象處於不良狀態,且需要通知 UMD 時。
  • 在 GPU 偵錯期間,KMD 需要與 UMD 通訊,因為發生某些事件。 對於具有 GPU 控制面板的 IHV,KMD 發出 CPU 事件的訊號可讓 KMD 通知控制面板應用程式有關內部事件。

一般而言,UMD 可以建立 CPU 事件,並將其 NT 句柄傳遞至逸出私人數據中的 KMD。 此方法無法在 GPU 參數化 (GPU-PV) 案例中運作,因為 NT 句柄無法跨虛擬機界限使用。

從 Windows 11 21H2 版 (WDDM 3.0) 開始,WDDM API 已擴充為允許 UMD 建立可由 KMD 發出訊號的 CPU 事件物件。 當UMD在主機上或使用 GPU-PV 的虛擬機上執行時,此功能都適用。

功能流程

同步處理物件無法插入內容佇列。 它只能透過 KMD 使用 DXGKCB_SIGNALEVENT來發出訊號。

處理 CPU 事件同步物件的使用者模式 API

建立 KMD CPU 事件物件

KMD CPU 事件物件會藉由呼叫 D3D12DDICB_CREATESYNCHRONIZATIONOBJECT2下列專案來 建立為 GPU 同步處理物件:

設定 SignalByKmd 旗標時,將會呼叫 DXGKDDI_CREATECPUEVENT 來建立 KMD CPU 事件物件。 請注意,建立同步處理物件時,必須指定裝置句柄。

同步處理物件不能用於訊號和等候 API (D3DKMTSignalSynchronizationObjectD3DKMTWaitForSynchronizatioObject) 。 它只能由 KMD 發出訊號,UMD 可以等候對應的 CPU 事件。

UMD 逸出以定義 KMD CPU 事件同步物件的使用方式

已知逸出已新增至 D3DDDI_DRIVERESCAPETYPED3DDDI_DRIVERESCAPETYPE_CPUEVENTUSAGE 用來通知 KMD 有關 KMD CPU 事件物件之預定使用方式的 KMD。 已知逸出是藉由設定 DXGKARG_ESCAPE::Flags.DriverKnownEscape = 1 來定義。 已知逸出會從安全的虛擬機傳送至主機。

下列代碼段是使用範例。

D3DDDI_DRIVERESCAPE_CPUEVENTUSAGE Command = {};
Command.EscapeType = D3DDDI_DRIVERESCAPETYPE_CPUEVENTUSAGE;
Command.hSyncObject = SyncObjectHandle;
Command.Usage[0] = 1;

D3DKMT_ESCAPE Args = {};
Args.hAdapter = AdapterHandle;
Args.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
Args.Flags.DriverKnownEscape = 1;
Args.Flags.NoAdapterSynchronization = 1; // Prevent waking up the device from D3
Args.pPrivateDriverData = &Command;
Args.PrivateDriverDataSize = sizeof(Command);

NTSTATUS Status = D3DKMTEscape(&Args);

Dxgkrnl 會使用下列命令 呼叫DXGKDDI_ESCAPE

  • hDevice 設定為用來建立同步處理物件的迷你埠裝置句柄
  • pPrivateDriverData 指向 D3DDDI_DRIVERESCAPE_CPUEVENTUSAGE 結構
  • PrivateDriverDataSize 設為 sizeof(D3DDDI_DRIVERESCAPE_CPUEVENTUSAGE)

建立和終結 KMD CPU 事件物件

下列 DIS 可用來建立和終結 KMD CPU 事件同步物件:

從 KMD 發出 CPU 事件對象的訊號

若要發出 CPU 事件對象的訊號,KMD 會在 IRQL <= DISPATCH_LEVEL 呼叫 DXGKCB_SIGNALEVENT,並將 DXGKARGCB_SIGNALEVENT 結構值設定如下:

  • hDxgkProcess 等於 0。

  • hEvent 等於傳入至 DXGKDDI_CREATECPUEVENTDxgkrnl CPU 事件物件句柄。

  • CpuEventObject 必須是 1。

  • 保留 必須是 0。