Memberi sinyal peristiwa CPU dari driver mode kernel

Ada beberapa kasus ketika driver mode kernel (KMD) perlu memberi sinyal peristiwa CPU untuk memberi tahu driver mode pengguna (UMD) tentang sesuatu; misalnya:

  • Ketika KMD mendeteksi bahwa salah satu objeknya dalam keadaan buruk dan perlu memberi tahu UMD.
  • Selama penelusuran kesalahan GPU di mana KMD perlu berkomunikasi dengan UMD bahwa beberapa peristiwa terjadi. Untuk IHV dengan Panel Kontrol untuk GPU, memberi sinyal peristiwa CPU oleh KMD memungkinkan KMD untuk memberi tahu aplikasi Panel Kontrol tentang peristiwa internal.

Biasanya, UMD dapat membuat peristiwa CPU dan meneruskan handel NT-nya ke KMD dalam data privat escape. Metode ini tidak berfungsi dalam skenario paravirtualisasi GPU (GPU-PV) karena handel NT tidak dapat digunakan di seluruh batas komputer virtual.

Mulai Windows 11 versi 21H2 (WDDM 3.0), WDDM API diperluas untuk memungkinkan UMD membuat objek peristiwa CPU yang dapat diberi sinyal oleh KMD. Fitur ini berfungsi baik ketika UMD berjalan pada host atau di komputer virtual menggunakan GPU-PV.

Alur fitur

Objek sinkronisasi tidak dapat dimasukkan ke antrean konteks. Ini hanya dapat disinyalir oleh KMD menggunakan DXGKCB_SIGNALEVENT.

API mode pengguna untuk menangani objek sinkronisasi peristiwa CPU

Pembuatan objek peristiwa CPU KMD

Objek peristiwa CPU KMD dibuat sebagai objek sinkronisasi GPU dengan memanggil D3D12DDICB_CREATESYNCHRONIZATIONOBJECT2 dengan:

Ketika bendera SignalByKmd diatur, DXGKDDI_CREATECPUEVENT akan dipanggil untuk membuat objek peristiwa CPU KMD. Perhatikan bahwa handel perangkat harus ditentukan saat membuat objek sinkronisasi.

Objek sinkronisasi tidak dapat digunakan dalam API sinyal dan tunggu (D3DKMTSignalSynchronizationObject, D3DKMTWaitForSynchronizatioObject). Ini hanya dapat disinyalir oleh KMD, dan UMD dapat menunggu pada peristiwa CPU yang sesuai.

Pelarian UMD untuk menentukan penggunaan untuk objek sinkronisasi peristiwa CPU KMD

Escape yang diketahui ditambahkan ke D3DDDI_DRIVERESCAPETYPE. D3DDDI_DRIVERESCAPETYPE_CPUEVENTUSAGE digunakan untuk memberi tahu KMD tentang penggunaan objek peristiwa CPU KMD yang dimaksudkan. Escape yang diketahui ditentukan dengan mengatur DXGKARG_ESCAPE::Flags.DriverKnownEscape = 1. Pelarian yang diketahui dikirim ke host bahkan dari komputer virtual yang aman.

Cuplikan berikut adalah contoh penggunaan.

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 akan memanggil DXGKDDI_ESCAPE dengan yang berikut:

  • hDevice diatur ke handel perangkat miniport yang digunakan untuk membuat objek sinkronisasi
  • pPrivateDriverData menunjuk ke struktur D3DDDI_DRIVERESCAPE_CPUEVENTUSAGE
  • PrivateDriverDataSize diatur ke sizeof(D3DDDI_DRIVERESCAPE_CPUEVENTUSAGE)

Membuat dan menghancurkan objek peristiwa CPU KMD

DDI berikut digunakan untuk membuat dan menghancurkan objek sinkronisasi peristiwa CPU KMD:

Memberi sinyal objek peristiwa CPU dari KMD

Untuk memberi sinyal objek peristiwa CPU, KMD memanggil DXGKCB_SIGNALEVENT di IRQL <= DISPATCH_LEVEL dan dengan nilai struktur DXGKARGCB_SIGNALEVENT ditetapkan sebagai berikut:

  • hDxgkProcess sama dengan 0.

  • hEvent sama dengan handel objek peristiwa CPU Dxgkrnl yang diteruskan ke DXGKDDI_CREATECPUEVENT.

  • CpuEventObject harus 1.

  • Yang dipesan harus 0.