Partager via


Signalisation d’un événement d’UC à partir d’un pilote en mode noyau

Il existe des cas où le pilote en mode noyau (KMD) doit signaler un événement de processeur pour informer le pilote en mode utilisateur (UMD) de quelque chose ; par exemple :

  • Quand KMD détecte que l’un de ses objets est dans un état incorrect et doit notifier l’UMD.
  • Pendant le débogage GPU où KMD doit communiquer à l’UMD qu’un événement s’est produit. Pour les IVS avec des panneaux de contrôle pour GPU, la signalisation des événements d’UC par KMD permet à KMD d’informer l’application Panneaux de configuration des événements internes.

En règle générale, UMD peut créer un événement d’UC et passer son handle NT à KMD dans une sortie de données privées d’échappement. Cette méthode ne fonctionne pas dans le scénario de paravirtualisation GPU (GPU-PV), car les handles NT ne peuvent pas être utilisés au-delà des limites des machines virtuelles.

À compter de Windows 11 version 21H2 (WDDM 3.0), l’API WDDM a été étendue pour permettre à l’UMD de créer un objet d’événement processeur qui peut être signalé par KMD. Cette fonctionnalité fonctionne à la fois quand UMD s’exécute sur l’hôte ou sur une machine virtuelle à l’aide de GPU-PV.

Flux de fonctionnalité

L’objet de synchronisation ne peut pas être inséré dans une file d’attente de contexte. Il peut uniquement être signalé par KMD à l’aide de DXGKCB_SIGNALEVENT.

API en mode utilisateur pour gérer les objets de synchronisation des événements du processeur

Création de l’objet d’événement DU PROCESSEUR KMD

L’objet d’événement DU PROCESSEUR KMD est créé en tant qu’objet de synchronisation GPU en appelant D3D12DDICB_CREATESYNCHRONIZATIONOBJECT2 avec :

  • Type défini sur D3DDDI_CPU_NOTIFICATION.

  • Indicateurs définis sur SignalByKmd pour spécifier que l’objet sera signalé par KMD. Cet indicateur ne peut être défini que lorsque le membre Type deD3DDDI_SYNCHRONIZATIONOBJECTINFO2 est D3DDDI_CPU_NOTIFICATION.

Lorsque l’indicateur SignalByKmd est défini, DXGKDDI_CREATECPUEVENT est appelé pour créer l’objet événement du processeur KMD. Notez que le handle d’appareil doit être spécifié lors de la création de l’objet de synchronisation.

L’objet de synchronisation ne peut pas être utilisé dans les API de signal et d’attente (D3DKMTSignalSynchronizationObject, D3DKMTWaitForSynchronizatioObject). Il peut être signalé uniquement par KMD, et l’UMD peut attendre l’événement d’UC correspondant.

Échappement UMD pour définir l’utilisation d’un objet de synchronisation d’événements d’UC KMD

Une échappement connue a été ajoutée à D3DDDI_DRIVERESCAPETYPE. D3DDDI_DRIVERESCAPETYPE_CPUEVENTUSAGE est utilisé pour informer KMD de l’utilisation prévue d’un objet d’événement d’UC KMD. Une échappement connue est définie en définissant DXGKARG_ESCAPE ::Flags.DriverKnownEscape = 1. Les échappements connus sont envoyés à l’hôte même à partir de machines virtuelles sécurisées.

L’extrait de code suivant est un exemple d’utilisation.

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 appelle DXGKDDI_ESCAPE avec les éléments suivants :

  • hDevice défini sur le handle d’appareil miniport utilisé pour créer l’objet de synchronisation
  • pPrivateDriverData pointant vers une structure D3DDDI_DRIVERESCAPE_CPUEVENTUSAGE
  • PrivateDriverDataSize défini sur sizeof(D3DDDI_DRIVERESCAPE_CPUEVENTUSAGE)

Création et destruction d’un objet d’événement d’UC KMD

Les DDIs suivants sont utilisés pour créer et détruire des objets de synchronisation d’événements de processeur KMD :

Signalisation d’un objet d’événement d’UC à partir de KMD

Pour signaler un objet d’événement processeur, KMD appelle DXGKCB_SIGNALEVENT à IRQL <= DISPATCH_LEVEL et avec les valeurs de structure DXGKARGCB_SIGNALEVENT définies comme suit :

  • hDxgkProcess est égal à 0.

  • hEvent égal au handle d’objet d’événement du processeur Dxgkrnl passé à DXGKDDI_CREATECPUEVENT.

  • CpuEventObject doit avoir la valeur 1.

  • Réservé doit être 0.