Поделиться через


Отправка сигнала о событии ЦПУ из драйвера в режиме ядра

Существуют случаи, когда драйвер в режиме ядра (KMD) должен сигнализировать о событии ЦП, чтобы уведомить драйвер пользовательского режима (UMD) о чем-то; Например:

  • Когда KMD обнаруживает, что один из его объектов находится в плохом состоянии и должен уведомлять UMD.
  • Во время отладки GPU, когда KMD должен сообщить UMD о произошедшем событии. Для независимых производителей оборудования (IHV) с панелями управления для GPU, KMD, сигнализируя о событиях процессора, позволяет уведомлять приложение панели управления GPU о внутренних событиях.

Как правило, UMD может создать событие ЦП и передать его дескриптор NT в KMD, используя приватные данные. Этот метод не работает в сценарии паравиртуализации GPU (GPU-PV), так как дескрипторы NT нельзя использовать между границами виртуальных машин.

Начиная с Windows 11 версии 21H2 (WDDM 3.0), API WDDM был расширен, чтобы разрешить UMD создать объект события ЦП, который может быть сигналирован KMD. Эта функция работает как при запуске UMD на узле, так и в виртуальной машине с помощью GPU-PV.

Поток функций

Объект синхронизации нельзя вставить в очередь контекста. Сигнал о нем может передаваться только KMD через DXGKCB_SIGNALEVENT.

API пользовательского режима для обработки объектов синхронизации событий ЦП

Создание объекта события KMD CPU

Объект события KMD для ЦП создается как объект синхронизации GPU посредством вызова D3D12DDICB_CREATESYNCHRONIZATIONOBJECT2 с:

Когда установлен флаг SignalByKmd, будет вызвана функция DXGKDDI_CREATECPUEVENT для создания объекта события ЦП KMD. Обратите внимание, что при создании объекта синхронизации необходимо указать дескриптор устройства.

Объект синхронизации нельзя использовать в API сигнала и ожидания (D3DKMTSignalSynchronizationObject, D3DKMTWaitForSynchronizatioObject). Сигнал может быть подан только KMD, а UMD может ожидать соответствующего события ЦП.

UMD escape для задания использования объекта синхронизации событий на центральном процессоре KMD

В D3DDDI_DRIVERESCAPETYPE добавлен известный escape-экран. D3DDDI_DRIVERESCAPETYPE_CPUEVENTUSAGE используется для уведомления KMD о предполагаемом использовании объекта события центрального процессора 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

Следующие DDIs используются для создания и уничтожения объектов синхронизации событий ЦП KMD:

Сигнализация объекта события процессора из KMD

Чтобы сигнализировать объект события ЦП, KMD вызывает DXGKCB_SIGNALEVENT на IRQL <= DISPATCH_LEVEL с значениями структуры DXGKARGCB_SIGNALEVENT, установленными следующим образом:

  • hDxgkProcess равно 0.

  • hEvent равно дескриптору события ЦП Dxgkrnl , переданной в DXGKDDI_CREATECPUEVENT.

  • CpuEventObject должен иметь значение 1.

  • Зарезервировано должно быть равно 0.