Freigeben über


GPU-Paravirtualisierung

In diesem Artikel wird die GPU-Paravirtualisierung in WDDM beschrieben. Dieses Feature ist ab Windows 10, Version 1803 (WDDM 2.4) verfügbar.

Informationen zur GPU-Virtualisierung

GPU-Virtualisierung ist ein wichtiges Feature für Windows Client und Windows Server. Es gibt viele Szenarien, die eine effektive Verwendung von GPU-Ressourcen auf einem virtuellen Computer erfordern.

Serverszenarien (in denen das Hostbetriebssystem keine Benutzeranwendungen ausführt) umfassen:

  • Desktopvirtualisierung
  • Compute (KI, ML usw.)

Clientszenarien (in denen das Hostbetriebssystem die GPU zwischen VMs und Benutzeranwendungen gemeinsam verwendet) umfassen:

  • Entwickeln und Testen von Grafikanwendungen (bei denen Tests auf einem virtuellen Computer ausgeführt werden)
  • Ausführen von Anwendungen in einem virtuellen Computer für Sicherheitszwecke
  • Ausführen von Linux in einer VM mit GPU-Beschleunigung

GPU-Paravirtualisierung in WDDM

Paravirtualization (PV) stellt eine Schnittstelle zu virtuellen Computern (VMs) bereit, die ihrer zugrunde liegenden Hardware ähneln. In PV portieren Sie das Gastbetriebssystem explizit, bevor Sie einen virtuellen Computer installieren, da ein nicht maßgeschneidertes Gastbetriebssystem nicht über einem virtuellen Computermonitor (VMM) ausgeführt werden kann.

Vorteile:

  • Mehrere VMs teilen die Hardwareressourcen.
  • Im Treibercode müssen nur wenige Änderungen vorgenommen werden.

Die folgende Abbildung zeigt verschiedene Komponenten, die am paravirtualisierten Design von WDDM beteiligt sind.

Diagramm, das die komponenten zeigt, die am paravirtualisierten Entwurf beteiligt sind.

Die D3D-Laufzeiten in der Gast-VM werden nicht geändert. Die Schnittstellen mit der Runtime im Benutzermodus und mit KMT-Kernel-Thunks bleiben gleich.

Für die Treiberkomponenten sind nicht viele Änderungen erforderlich:

  • Die UMD in der Gast-VM muss folgendes ausführen:

    • Beachten Sie, dass die Kommunikation mit dem Host kernelmodustreiber (KMD) über die VM-Grenze hinweg erfolgt.
    • Verwenden Sie die hinzugefügten Dxgkrnl--Dienste, um auf Registrierungseinstellungen zuzugreifen.
  • Im Gast ist kein KMD vorhanden, nur UMD. Der KMD (Virtual Render Device, VRD) ersetzt den KMD. Der Zweck des VRD besteht darin, das Laden von Dxgkrnl zu erleichtern.

  • Im Gast in kein Videospeicher-Manager (VidMm) oder Scheduler (VidSch) vorhanden.

  • Dxgkrnl in einer VM erhält Thunk-Aufrufe und leitet sie über VM-Bus-Kanäle an die Hostpartition weiter. Dxgkrnl im Gast erstellt auch lokale Objekte für Zuteilungen, Prozesse, Geräte und andere Ressourcen, wodurch der Datenverkehr mit dem Host reduziert wird.

Virtuelles Rendergerät (VIRTUAL Render Device, VRD)

Wenn eine paravirtualisierte GPU nicht in einer VM vorhanden ist, zeigt der Geräte-Manager des virtuellen Computers den Adapter "Microsoft Hyper-V Video" an. Dieser Anzeigeadapter ist standardmäßig mit dem BasicRender-Adapter zum Rendern verbunden.

Wenn Sie einer VM eine paravirtualisierte GPU hinzufügen, zeigt der Geräte-Manager des virtuellen Computers zwei Adapter an:

  • Microsoft Hyper-V-Grafikkarte oder Microsoft-Remoteanzeigeadapter
  • Microsoft Virtual Render Driver (Der tatsächliche Name ist der Name des GPU-Adapters auf dem Host)

Standardmäßig wird die VRD mit dem Hyper-V Videoadapter gekoppelt, sodass alle UI-Renderings mit dem VRD-Adapter erfolgen.

Wenn Beim Rendern Probleme auftreten, können Sie diese Kopplung mithilfe der GpuVirtualizationFlags Registrierungseinstellung deaktivieren. In diesem Fall wird der Render-Only-Adapter (VRD) verwendet, wenn eine Anwendung ihn speziell auswählt. In einigen DirectX-Beispielen können Sie beispielsweise das Renderinggerät ändern. Die Direct3D-Laufzeiten fügen der VRD eine logische Anzeigeausgabe hinzu, wenn eine Anwendung entscheidet, sie zu verwenden.

Wenn Sie der VM mehrere virtuelle GPUs hinzufügen, können mehrere VRD-Adapter im Gast vorhanden sein. Allerdings kann nur einer davon mit dem Hyper-V-Videoadapter verwendet werden. Es gibt keine Möglichkeit, anzugeben, welche; das Betriebssystem auswäht.

Container und VMs

GPU-Virtualisierung wird für VMs und Container unterstützt. Container sind einfache virtuelle Computer, bei denen die Hostbetriebssystem-Binärdateien der Container-VM zugeordnet sind.

Weitere Informationen zu Containern finden Sie unter Windows und Container.

Sichere virtuelle Computer

Für einen sicheren virtuellen Computer gelten die folgenden Einschränkungen:

  • Treiberescapeaufrufe sind nicht zulässig, mit Ausnahme bekannter Escapes, die mit dem Flag DriverKnownEscape verwendet werden.
  • Die IoMmu-Isolation ist aktiviert. Die VM-Erstellung schlägt fehl, wenn der Treiber die IoMmu-Isolation nicht unterstützt.

Wenn der sichere Modus aktiviert ist:

Es gibt Registrierungseinstellungen, um den sicheren Modus zu erzwingen oder die IoMmu-Isolation während der Entwicklung zu deaktivieren. Weitere Informationen finden Sie unter Registrierungseinstellungen.

Remoting des VM-/Container-Desktops

Sie können den Inhalt eines Desktops auf einem virtuellen Computer (VM) mithilfe von zwei Methoden an den Host remoten:

  • Hyper-V Anzeigeadapter
  • Remoting von Terminalsitzungen

Wenn RDP (Remotedesktop) zum Herstellen einer Verbindung mit einer VM verwendet wird, wird Remoting von Terminalsitzungen verwendet.

Der Hyper-V-Manager verwendet die VMConnect--Anwendung, um einen VM-Desktop anzuzeigen. VMConnect funktioniert in zwei Modi:

  • Erweiterter Modus, der Remoting von Terminalsitzungen verwendet
  • Standardmodus, der den Hyper-V Display-Adapter verwendet.

VM-Arbeitsprozess und VM-Arbeitsspeicher

Wenn Sie einen virtuellen Computer oder Container starten, erstellt das Betriebssystem die folgenden Prozesse auf dem Host:

  • VM-Workerprozess (vmwp.exe)
  • VM-Speicherprozess (vmmem.exe)

VMWP- enthält verschiedene virtuelle Treiber, einschließlich vrdumed.dll, den Treiber für paravirtualisierte Grafikadapter.

Der virtuelle Adressraum des vmmem-Prozesses dient als Unterstützung für den E/A-Bereich der vGPU im Gast. Wenn der Gast auf den E/A-Bereich zugreift, ist die resultierende physische Adresse der Eintrag in die Übersetzung der zweiten Ebene, die die Seitentabellen des vmmem-Prozesses verwendet.

In einer virtualisierten Umgebung werden verschiedene KMD DDI-Aufrufe, die in der Regel im Kontext eines Benutzerprozesses auf dem Host ausgeführt werden, stattdessen im Kontext des vmmem- Prozesses ausgeführt, wenn ein virtueller Computer ausgeführt wird.

Dxgkrnl- erstellt ein einzelnes DXGPROCESS (und das entsprechende KMD-Prozessobjekt) für diese Prozesse, das in diesem Artikel als VM-Arbeitsprozess bezeichnet wird. Der mit dem DXG-VM-Workerprozess verbundene EPROCESS ist vmmem.

VM-Prozesse

Wenn ein DXGPROCESS in der Gast-VM erstellt wird, erstellt Dxgkrnl ein entsprechendes DXGPROCESS-Objekt auf dem Host. Dieser Prozess wird in diesem Artikel als VM-Prozess bezeichnet. Der dem DXGPROCESS zugeordnete EPROCESS ist "vmmem".

Alle Rendering-Vorgänge, die bei der Erstellung einer VM oder einer VM-Zuordnung ausgeführt werden, erfolgen im Kontext des DXGPROCESS des virtuellen Computers.

Zu Debuggingzwecken benachrichtigt Dxgkrnl KMD darüber, welcher Prozess ein VM-Workerprozess oder ein VM-Prozess in DxgkDdiCreateProcess ist. Mithilfe dieser Informationen kann der Treiber einen VM-Prozess mit dem VM-Arbeitsprozess verknüpfen. Diese Informationen helfen beim Debuggen in Szenarien, in denen mehr als eine VM ausgeführt wird.

Treiberanforderungen

Eine KMD, die GPU-Paravirtualisierung unterstützt, muss die Funktion DXGK_VIDMMCAPS::ParavirtualizationSupported festlegen.

Der Benutzermodustreiber (USER-Mode Driver, UMD) sollte keine prozesskontextbezogenen Daten in den privaten Treiberdaten (Zeiger, Handle usw.) verwenden. Stattdessen ruft die KMD die privaten Daten im Host in einem anderen Prozesskontext ab.

Die UMD im Gast kann den Arbeitsspeicher nicht mit der KMD im Host teilen. Sie muss die in Registrierungszugriff von UMD beschriebenen Funktionen verwenden, um auf die Registrierung zuzugreifen.

Die aktuelle Paravirtualisierungsimplementierung verwendet den VM-Bus, um zwischen dem Gast und dem Host zu kommunizieren. Die maximale Nachrichtengröße beträgt 128 KB. Derzeit teilt Dxgkrnl Nachrichten nicht auf, um sie in Blöcken zu senden. Daher muss der Treiber die Größe privater Daten einschränken, die mit der Objekterstellung übergeben werden. Wenn z. B. Pfnd3dddiAllocatecb verwendet wird, um viele Zuordnungen zu erstellen, enthält die Gesamtnachrichtengröße eine Kopfzeile, globale private Daten sowie die Größe der pro Zuordnung privaten Daten multipliziert mit der Anzahl der Zuordnungen. Diese Informationen müssen alle in eine einzelne Nachricht passen.

Ausführen von Anwendungen im emulierten Vollbildmodus

Der Adapter für indirekte Anzeige muss für Remoting aktiviert sein (ist standardmäßig aktiviert). Führen Sie zum Deaktivieren die folgenden Schritte aus.

  • Starten Sie die Bearbeitung der Gruppenrichtlinie.
  • Navigieren Sie zu Computerkonfiguration–>Administrative Vorlagen->Windows-Komponenten->Remotedesktopdienste->Remotedesktopsitzungshost->Remotesitzungsumgebung
  • Öffnen Sie das Element „WDDM-Grafikanzeigetreiber für Remotedesktopverbindungen verwenden“.
  • Wählen Sie "Deaktivieren" und dann "OK" aus.
  • Neustart

Die DXGI-Unterstützung für Vollbildanwendungen in VMs ist standardmäßig aktiviert. Verwenden Sie StagingTool.exe /disable 19316777, um sie zu deaktivieren.

Vollbildanwendungen müssen im emulierten Vollbildmodus ausgeführt werden.

Aktivieren Sie eFSE für alle DXGI-Anwendungen, und legen Sie die mindeste WDDM-Version für den Swapeffektübergang auf WDDM 2.0 fest:

  • D3DEnableFeature.exe /enable DXGI_eFSE_Enablement_Policy
  • D3DEnableFeature.exe /setvariant DXGI_eFSE_Enablement_Policy 7

eFSE ist für D3D9-Anwendungen standardmäßig aktiviert.

DriverStore im virtuellen Computer

Treiberbinärdateien auf dem Host befinden sich in einem Treiberspeicher %windir%\system32\drivers\DriverStore\FileRepository<DriverDirectory>.

Für die Paravirtualisierung wird erwartet, dass die BIN-Dateien von UMD in einer VM in %windir%\system32\drivers\HostDriverStore\FileRepository<DriverDirectory>liegen.

Der Host-KMD meldet die Namen der UMD-DLLs, die den vollständigen Pfad zum Treiberspeicher enthalten. Beispiel: c:\windows\system32\DriverStore\FileRepository\DriverSpecificDirectory\d3dumd.dll.

Wenn der virtuelle Computer einen UMD-Namen anfragt, wird der Name in <VmSystemDrive>:\windows\system32\HostDriverStore\FileRepository\DriverSpecificDirectory\d3dumd.dllübersetzt.

Hosten von „DriverStore“ für Container

Für Container ordnet Hyper-V das vollständige Verzeichnis des Hosttreiberspeichers im Host dem Verzeichnis <%windir%\HostDriverStore im Container zu.

Host DriverStore für vollständige VMs

Die Treiberspeicherdateien werden auf den virtuellen Computer kopiert, wenn der virtuelle GPU-Adapter im virtuellen Computer gestartet wird. Dieses Feature ist in der veröffentlichten Version des Betriebssystems deaktiviert.

Der folgende Registrierungsschlüssel und mögliche Werte steuern den Kopiervorgang. Der Schlüssel ist standardmäßig nicht vorhanden.

DWORD RTL_REGISTRY_CONTROL\GraphicsDrivers\DriverStoreCopyMode
Wert Beschreibung
0 Kopieren des Treiberspeichers deaktivieren
1 Normaler Vorgang (Kopieren der Treiberspeicherdateien aktivieren und vorhandene Dateien nicht überschreiben).
2 Aktivieren Sie das Kopieren des Treiberspeichers und überschreiben Sie vorhandene Dateien.

Zugriff auf die Registrierung über UMD

Die KMD-Registrierungsschlüssel sind auf dem Host vorhanden und werden nicht auf die VM übertragen. Daher kann die UMD diese Treiberregistrierungsschlüssel nicht direkt lesen. Der pfnQueryAdapterInfoCb2-Rückruf wird der D3DDDI_ADAPTERCALLBACKS-Struktur der D3D-Runtime hinzugefügt. UMD kann pfnQueryAdapterInfoCb2 mit folgender Festlegung von D3DDDICB_QUERYADAPTERINFO2 aufrufen, um bestimmte Registrierungsschlüssel zu lesen:

  • D3DDDICB_QUERYADAPTERINFO2::QueryType auf D3DDDI_QUERYADAPTERTYPE_QUERYREGISTRY festgelegt.
  • pPrivateDriverData- verweist auf einen Puffer mit einer D3DDDI_QUERYREGISTRY_INFO Struktur, in der die Registrierungsinformationen zurückgegeben werden sollen. UMD besetzt die folgenden Mitglieder:
  • PrivateDriverDataSize ist sizeof(D3DDDI_QUERYREGISTRY_INFO) plus die Größe des Puffers für den Ausgabewert mit dynamischer Größe.

UMD kann D3DKMTQueryAdapterInfo auch direkt aufrufen. Dieser Aufruf ist für UMD im Gast nützlich, da er an den Host gemarshallt wird und eine Möglichkeit bietet, bestimmte Namen in den Gastnamensraum zu übersetzen.

D3DKMTQueryAdapterInfo wird aufgerufen, wobei D3DKMT_QUERYADAPTERINFO wie folgt festgelegt wird, um bestimmte Registrierungsschlüssel zu lesen:

  • Typ ist auf KMTQAITYPE_QUERYREGISTRY festgelegt.
  • pPrivateDriverData verweist auf eine D3DKMT_ADAPTERREGISTRYINFO Struktur
  • PrivateDriverDataSize ist sizeof(D3DKMT_ADAPTERREGISTRYINFO) plus die Größe des Puffers für den Ausgabewert mit dynamischer Größe.

Beispiel 1: Lesen eines Werts aus dem Dienstschlüssel


WCHAR ValueName = L"EnableDebug";
    D3DDDI_QUERYREGISTRY_INFO Args = {};
    Args.QueryType = D3DDDI_QUERYREGISTRY_SERVICEKEY;
    Args.QueryFlags.TranslatePath = FALSE or TRUE;
    Args.ValueType = Supported registry value type;
    wcscpy_s(Args.ValueName, ARRAYSIZE(Args.ValueName), ValueName);

    D3DKMT_QUERYADAPTERINFO Args1 = {};
    Args1.hAdapter = hAdapter;
    Args1.Type = KMTQAITYPE_QUERYREGISTRY;
    Args1.pPrivateDriverData = &Args;
    Args1.PrivateDriverDataSize = sizeof(Args);
    NTSTATUS Status = D3DKMTQueryAdapterInfo(&Args1);
    if (NT_SUCCESS(Status) &&
        Args.Status == D3DDDI_QUERYREGISTRY_STATUS_SUCCESS)
    {
       if (ValueType == REG_SZ || ValueType == REG_EXPAND_SZ) {

wprintf(L"Value: \"%s\"\n", Args.OutputString);
       } else
       if (ValueType == REG_MULTI_SZ) {
          wprintf(L"Value: ");
          for (UINT i = 0; i < Args.OutputValueSize; i++) {
             if (Args.OutputString[i] == 0) {
                wprintf(L" ");
             } else {
                wprintf(L"%c", Args.OutputString[i]);
             }
          }
          wprintf(L"\n");
       } else
       if (ValueType == REG_DWORD) {
          wprintf(L"Value: %d\n", Args.OutputDword);
       } else
       if (ValueType == REG_QWORD) {
          wprintf(L"Value: 0x%I64x\n", Args.OutputQword);
       } else
       if (ValueType == REG_BINARY) {
          wprintf(L"Num bytes: %d\n", Args.OutputValueSize);

for (UINT i = 0; i < Args.OutputValueSize; i++) {
             wprintf(L"%d ", Args.OutputBinary[i]);
          }
          wprintf(L"\n");
       }
    }

Beispiel 2: Lesen des Treiberspeicherpfads

    D3DDDI_QUERYREGISTRY_INFO Args = {};
    Args.QueryType = D3DDDI_QUERYREGISTRY_DRIVERSTOREPATH;

    D3DKMT_QUERYADAPTERINFO Args1 = {};
    Args1.hAdapter = hAdapter;
    Args1.Type = KMTQAITYPE_QUERYREGISTRY;
    Args1.pPrivateDriverData = &Args;
    Args1.PrivateDriverDataSize = sizeof(Args);
    NTSTATUS Status = D3DKMTQueryAdapterInfo(&Args1);
    if (NT_SUCCESS(Status) &&
        Args.Status == D3DDDI_QUERYREGISTRY_STATUS_SUCCESS)
    {
        Args.OutputString holds the output NULL terminated string.
        Args.OutputValueSize holds the number of characters in the string
    }

Kopieren von Dateien in %windir%\system32 und %windir%\syswow64- auf dem virtuellen Computer

In einigen Fällen müssen die Treiberbenutzermodus-DLLs in den Verzeichnissen %windir%\system32 und %windir%\syswow64 vorhanden sein.

Das Betriebssystem bietet dem Treiber eine Möglichkeit, Dateien anzugeben, die aus dem Treiberspeicher auf dem Host in %windir%\system32 oder %windir%\syswow64 im Gast kopiert werden sollen.

In der Installation inF kann der Treiber mehrere Werte in den folgenden Unterschlüsseln im Registrierungsschlüssel des Grafikadapters definieren:

  1. CopyToVmOverwrite
  2. CopyToVmWhenNewer
  3. CopyToVmOverwriteWow64
  4. CopyToVmWhenNewerWow64

Die CopyToVmOverwrite und CopyToVmWhenNewer Unterschlüssel werden verwendet, um Dateien in das %windir%\system32 Verzeichnis zu kopieren.

Die CopyToVmOverwriteWow64 und CopyToVmWhenNewerWow64 Unterschlüssel werden verwendet, um Dateien in das %windir%\syswow64 Verzeichnis zu kopieren.

Die Dateien unter CopyToVmOverwrite und CopyToVmOverwriteWow64 überschreiben immer die Dateien am Zielort.

Die Dateien unter CopyToVmWhenNewer und CopyToVmWhenNewerWow64 überschreiben die Dateien im Ziel nur, wenn das Änderungsdatum einer Datei neuer ist. Die "neueren" Kriterien vergleichen zwei Informationsabschnitte:

  • FileVersion
  • Letzte Schreibzeit

Wenn die Zieldatei mit dem .dll- oder .exe-Suffix endet, wird fileVersion als der wichtigste Vergleichswert verwendet, bei dem die größte Version als "neuer" gilt. Wenn die Zieldatei nicht mit dem .dll oder .exe Suffix endet oder die beiden FileVersion gleich sind, wird LastWriteTime als die am wenigsten signifikanten Vergleichswerte verwendet, bei denen das spätere Datum/die spätere Uhrzeit als "neuer" gilt.

Jeder Werttyp unter einem Unterschlüssel muss REG_MULTI_SZ oder REG_SZ sein. Wenn der Werttyp REG_MULTI_SZ ist, sollte der Wert maximal zwei Zeichenfolgen enthalten. Diese Anforderung bedeutet, dass jeder Wert eine einzelne Zeichenfolge oder ein Paar Zeichenfolgen definiert, wobei die zweite Zeichenfolge leer sein könnte.

Der Vorname in einem Paar ist ein Pfad zu einer Datei im Treiberspeicher. Der Pfad ist relativ zum Stamm des Treiberspeichers und kann Unterverzeichnisse enthalten.

Der zweite Name in einem Paar ist der Name der Datei, wie sie im verzeichnis %windir%\system32 oder %windir%\syswow64 angezeigt werden soll. Der zweite Name sollte nur der Dateiname sein, nicht einschließlich Pfad. Wenn der zweite Name leer ist, entspricht der Dateiname dem im Treiberspeicher (mit Ausnahme von Unterverzeichnissen).

Dieser Ansatz ermöglicht es dem Treiber, im Hosttreiberspeicher und im Gast unterschiedliche Namen zu haben.

Beispiel 1

Das folgende Beispiel zeigt, wie man das Betriebssystem dazu bringt, <DriverStorePath>\CopyToVm\softgpu1.dll nach %windir%\system32\softgpu2.dllzu kopieren.

INF [DDInstall] section
HKR,"softgpukmd\CopyToVmOverwrite",SoftGpuFiles,%REG_MULTI_SZ%,"CopyToVm\softgpu1.dll”, “softgpu2.dll”
The directive creates the registry key in the software (adapter) key:
"HKLM\SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\<number>\CopyToVmOverwrite”, SoftGpuFiles = REG_MULTI_SZ, “CopyToVm\softgpu1.dll”, “softgpu2.dll"

Beispiel 2

Das folgende Beispiel zeigt, wie Sie das Betriebssystem dazu bringen, <DriverStorePath>\softgpu1.dll nach %windir%\system32\softgpu.dll und <DriverStorePath>\softgpu2.dll nach %windir%\system32\softgpu2.dllzu kopieren.

INF [DDInstall] section:
HKR,"CopyToVmOverwrite",SoftGpuFiles1,%REG_MULTI_SZ%,"softgpu1.dll”,”softgpu.dll"
HKR,"CopyToVmOverwrite",SoftGpuFiles2,%REG_SZ%, “softgpu2.dll"
The directive creates the registry key in the software (adapter) key:
“HKLM\SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\<number>\CopyToVmOverwrite”,  SoftGpuFiles1 = REG_MULTI_SZ, “softgpu1.dll”, “softgpu.dll"

“HKLM\SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\<number>\CopyToVmOverwrite”,  SoftGpuFiles2 = REG_SZ, “softgpu2.dll””

Beispiel 3

Das folgende Beispiel zeigt, wie Sie das Betriebssystem dazu bringen, <DriverStorePath>\Subdir1\Subdir2\softgpu2wow64.dll in %windir%\syswow64\softgpu.dll und <DriverStorePath>\softgpu.dll zu %windir%\syswow64\softgpu2wow64.dllzu kopieren.

INF [DDInstall] section:
HKR,"CopyToVmOverwriteWow64",SoftGpuFiles,%REG_MULTI_SZ%,“Subdir1\Subdir2\softgpu2wow64.dll”,”softgpu.dll”.
The directive creates the registry key in the software (adapter) key:
“HKLM\SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\<number>\CopyToVmOverwriteWow64”,  SoftGpuFiles = REG_MULTI_SZ, “Subdir1\Subdir2\softgpu2wow64.dll”,”softgpu.dll

Änderungen an DxgkDdiCreateProcess

Die DxgkDdiCreateProcess--Funktion von KMD muss aktualisiert werden, um VM-Arbeitsprozesse und VM-Prozesse zu unterstützen. Die folgenden Felder werden der DXGKARG_CREATEPROCESS Struktur hinzugefügt:

  • hKmdVmWorkerProcess
  • ProcessNameLength
  • pProcessName

Die folgenden Flags werden DXGK_CREATEPROCESSFLAGS hinzugefügt, um VM-Workerprozesse und VM-Prozesse zu unterstützen:

  • VirtualMachineProcess
  • VirtualMachineWorkerProcess

DxgkDdiSetVirtualMachineData

DxgkDdiSetVirtualMachineData wird für Dxgkrnl hinzugefügt, um Informationen über einen virtuellen Computer an den KMD zu übergeben.

Asynchrone VM-Busnachrichten an den Host

Einige Nachrichten von Dxgkrnl im Gastbetriebssystem zur Host-Maschine sind asynchron. Dieser Ansatz verbessert die Leistung sehr häufiger Dxgkrnl-API-Aufrufe im Gast. Der Aufwand jeder synchronen VM-Busnachricht an den Host kann hoch sein.

Zu den asynchronen Nachrichten gehören:

LDA-Unterstützung in GPU-PV

Verknüpfte Grafikkarten (Linked Display Adapter, LDA) werden in GPU-PV unterstützt. Um eine konsistente Implementierung und die Unterstützung möglicher zukünftiger Rückportierungen der LDA-Unterstützung auf ältere Windows-Versionen sicherzustellen, muss die KMD die LDA-Unterstützung in GPU-PV überprüfen, indem sie DxgkCbIsFeatureEnabled(DXGK_FEATURE_LDA_GPUPV)aufruft. Die Unterstützung ist aktiviert, wenn die Funktion erfolgreich ist und Enabledzurückgibt. Wenn der KMD diesen Rückruf nicht aufruft, geht Dxgkrnl davon aus, dass der KMD LDA in GPU-PV nicht unterstützt.

Wenn das Betriebssystem das Feature unterstützt, liegt es bei dem Treiber, LDA im Benutzermodus zu aktivieren. Wenn der Treiber LDA im Benutzermodus aktiviert, sollte dies wie folgt ausgeführt werden.

Laufzeit LDA state
Laufzeit vor D3D12 Aktivieren, wenn DXGK_FEATURE_LDA_GPUPV unterstützt wird und das Gastbetriebssystem Windows 11, Version 22H2 (WDDM 3.1) oder höher ist.
Nicht-DX-Runtimes (Windows) Aktivieren, wenn DXGK_FEATURE_LDA_GPUPV unterstützt wird und das Gastbetriebssystem Windows 11, Version 22H2 (WDDM 3.1) oder höher ist. Anstatt die Betriebssystemversion zu überprüfen, konnte die UMD D3DKMTQueryAdapterInfo(KMTQAITYPE_PHYSICALADAPTERCOUNT) aufrufen und LDA aktivieren, wenn sie die Anzahl der physischen Adapter zurückgibt, die größer als 1 sind.
D3D12-Runtime (Windows) Aktivieren Siehe Festlegen des LDA-Status für die D3D12-Runtime.
Linux (d3d12 und Nicht-DX-Runtime) Aktivieren, wenn DXGK_FEATURE_LDA_GPUPV unterstützt wird.

Treiber, die mit einer Schnittstellenversion unter DXGKDDI_INTERFACE_VERSION_WDDM3_0 kompiliert wurden, überprüfen DXGK_FEATURE_LDA_GPUPV nicht. Diese Treiber können weiterhin LDA für Linux-Runtimes aktivieren.

Festlegen des LDA-Status für die D3D12-Runtime

Wenn LDA für die D3D12-Laufzeitumgebung ein- oder ausgeschaltet wird, muss die UMD die korrekten Stufen- und Knotenzuordnungsinformationen an die Laufzeitumgebung zurückgeben. Der Codefluss lautet wie folgt:

  • D3D12 ruft die D3D12_CROSS_NODE_SHARING_TIER-Obergrenze von UMD ab.

  • D3D12 ruft D3DKMTQueryAdapterInfo(KMTQAITYPE_PHYSICALADAPTERCOUNT) auf, um die Anzahl der physischen Adapter von Dxgkrnl zu ermitteln.

  • D3D12 ruft pfnQueryNodeMap(PhysicalAdapterCount, &map) auf, um die Zuordnung logischer Knotenindizes zu physischen Knoten abzurufen. Mit Knoten ist in diesem Fall ein physischer Adapter gemeint. Der UMD muss den tatsächlichen physischen Adapterindex in der Zuordnung oder D3D12DDI_NODE_MAP_HIDE_NODE festlegen, um einen Knoten zu deaktivieren.

  • Basierend auf den pfnQueryNodeMap- Ergebnissen berechnet D3D12 die effektive physische Adapteranzahl, indem die ausgeblendeten Knoten nicht gezählt werden.

  • Wenn der Status der Ebene und die tatsächliche Anzahl der physischen Adapter nicht übereinstimmen, schlägt die Geräteerstellung in D3D12 fehl. In folgenden Fällen tritt ein Konflikt auf:

    • Die Ebene ist D3D12DDI_CROSS_NODE_SHARING_TIER_NOT_SUPPORTED, und die Adapteranzahl ist größer als 1.
    • Die Ebene ist nicht D3D12DDI_CROSS_NODE_SHARING_TIER_NOT_SUPPORTED, und die Adapteranzahl ist 1.

Um LDA zu deaktivieren, muss der UMD die Ebene D3D12DDI_CROSS_NODE_SHARING_TIER_NOT_SUPPORTED zurückgeben und nur einen physischen Adapter in der Knotenzuordnung aktiviert lassen.

D3DKMTQueryAdapterInfo(KMTQAITYPE_PHYSICALADAPTERCOUNT)

Eine KMTQAITYPE_PHYSICALADAPTERCOUNT-Abfrage für die Anzahl der physischen Adapter gibt dem Gast immer die korrekte Anzahl der physischen Adapter zurück:

  • Bei Gästen vor Windows 11 Version 22H2 wird 1 zurückgegeben. Dieser Wert ist im Gastcode hartcodiert. Es könnte sich in Zukunft ändern, wenn die LDA-Unterstützung zu älteren Betriebssystemversionen portiert wird.
  • Unter Windows 11, Version 22H2 und höher, wird Folgendes zurückgegeben:

Aktivieren der Paravirtualisierung

Aktivieren Sie die Virtualisierungsunterstützung im BIOS (VT-d oder ähnlich). GPU-PV Setup unterscheidet sich für virtuelle VMMS-Computer und die Container.

Aktivieren Sie in PowerShell (als Administrator ausgeführt) die Skriptausführung auf dem Server:

set-executionpolicy unrestricted

Einrichtung des virtuellen VMMS-Computers

Einrichten des Hosts und der VM

Der Betriebssystembuild auf dem virtuellen Computer kann älter oder neuer sein als der Betriebssystembuild auf dem Host.

  1. Aktivieren Sie die Hyper-V-Funktion in den Serverrollen oder das feature Hyper-V auf dem Client. Wenn Sie dieses Feature auf dem Server aktivieren, wählen Sie die Option aus, um den Netzwerkadapter als externen Switch zu verwenden.

  2. (optional) Aktivieren Sie die Testsignierung (bcdedit -set TESTSIGNING ON).

  3. Neustart.

  4. Installieren Sie einen GPU-Treiber, der die Paravirtualisierung unterstützt.

  5. (optional) Einige Treiber setzen die legen die ParavirtualizationSupported-Obergrenze nicht fest. Fügen Sie in diesem Fall den folgenden Registry-Eintrag hinzu, bevor Sie den Treiber installieren, oder deaktivieren und aktivieren Sie das Gerät erneut, nachdem das Flag gesetzt wurde.

    DWORD HKLM\System\CurrentControlSet\Control\GraphicsDrivers\GpuVirtualizationFlags = 1   
    
  6. Um zu überprüfen, ob das Betriebssystem die paravirtualisierte GPU erkennt, führen Sie den folgenden PowerShell-Befehl aus:

    Get-VMPartitionableGpu
    
    # Example output from running the command
    Name                    : \\?\PCI#VEN_10DE&DEV_1C02&SUBSYS_11C210DE&REV_A1#4&275d7527&0&0010#{064092b3-625e-43bf-9eb5-d
                              c845897dd59}\GPUPARAV
    ValidPartitionCounts    : {32}
    PartitionCount          : 32
    TotalVRAM               : 1,000,000,000
    AvailableVRAM           : 1,000,000,000
    MinPartitionVRAM        : 0
    MaxPartitionVRAM        : 1,000,000,000
    OptimalPartitionVRAM    : 1,000,000,000
    TotalEncode             : 18,446,744,073,709,551,615
    AvailableEncode         : 18,446,744,073,709,551,615
    MinPartitionEncode      : 0
    MaxPartitionEncode      : 18,446,744,073,709,551,615
    
    OptimalPartitionEncode  : 18446744073709551615
    TotalDecode             : 1000000000
    AvailableDecode         : 1000000000
    MinPartitionDecode      : 0
    MaxPartitionDecode      : 1000000000
    OptimalPartitionDecode  : 1000000000
    TotalCompute            : 1000000000
    AvailableCompute        : 1000000000
    MinPartitionCompute     : 0
    MaxPartitionCompute     : 1000000000
    OptimalPartitionCompute : 1000000000
    CimSession              : CimSession: .
    ComputerName            : MYCOMPUTER-TEST2
    IsDeleted               : False
    
  7. Führen Sie die folgenden Befehle in PowerShell aus, um einen virtuellen Computer mit GPU zu erstellen. Eine VM namens TEST wird erstellt.

    $vm = “TEST“
    New-VM -VMName $vm -Generation 2
    Set-VM -GuestControlledCacheTypes $true -VMName $vm
    
  8. Legen Sie den E/A-Speicherplatz für den virtuellen Computer fest. GPU-PV verwendet E/A-Speicherplatz, um CPU-sichtbare Zuweisungen zu verarbeiten. Mindestens 8 GB E/A-Speicherplatz sind erforderlich.

    Set-VM -LowMemoryMappedIoSpace 1GB -VMName $vm
    Set-VM -HighMemoryMappedIoSpace 16GB -VMName $vm
    
  9. [optional] Standardmäßig ist die Basisadresse für den E/A-Speicherplatz mit hohem Arbeitsspeicher auf (64 GB - 512 MB) festgelegt. Auf Haswell-Chipsatzen mit 36-Bit-Physischer Speicheradressierung muss die Endadresse der E/A-Raumregion unter 64 GB liegen, sodass die Startadresse entsprechend festgelegt werden muss. Das folgende Skript mit dem Namen SetHighMmioBase.ps1legt die Startadresse bei ausführung mit den folgenden Parametern auf 47 GB fest:

    SetHightMmioBase.ps1 “TEST” 48128
    
    # SetHighMmioBase.ps1
    
    param( [string]$VmName, $BaseInMB)
    
    function Get-WMIVM
    {
        [CmdletBinding()]
        param(
            [parameter(Mandatory=$true)]
            [ValidateNotNullOrEmpty()]
            [string]$VmName = ""
            )
    
        gwmi -namespace root\virtualization\v2 -query "select * from Msvm_ComputerSystem where ElementName = '$VmName'"
    }
    function Get-WMIVmSettingData
    {
        [CmdletBinding()]
        param(
            [parameter(Mandatory=$true)]
            [ValidateNotNullOrEmpty()]
            [string]$VmName = ""
            )
        $vm = Get-WMIVM $VmName
    
        return $vm.GetRelated ("Msvm_VirtualSystemSettingData","Msvm_SettingsDefineState",$null,$null, "SettingData", "ManagedElement", $false, $null)
    }
    
    Write-Host "Setting HighMmioGapBase to $BaseInMB for VmName $VmName"
    $vssd = Get-WMIVmSettingData $VmName
    $vmms = Get-WmiObject -Namespace "root\virtualization\v2" -Class Msvm_VirtualSystemManagementService
    $vssd.HighMmioGapBase = $BaseInMB
    $settingsText = $vssd.PSBase.GetText("CimDtd20")
    $ret=$vmms.ModifySystemSettings($settingsText).ReturnValue
    if ($ret -eq 0)
    {
       Write-Host "Successfully set" $vssd.HighMmioGapBase
    } else
    {
       Write-Host "Error $ret"
    }
    
  10. Fügen Sie der VM eine virtuelle GPU hinzu, und deaktivieren Sie Prüfpunkte.

    Add-VMGpuPartitionAdapter -VMName $vm
    Set-VM -CheckpointType Disabled -VMName $vm
    
  11. Führen Sie den folgenden Befehl aus, um zu überprüfen, ob der virtuelle Computer über eine paravirtualisierte GPU verfügt:

    Get-VMGpuPartitionAdapter -VMName $vm in PowerShell. The output should show the adapter.
    
    
    # Example output from running the command
    
    MinPartitionVRAM        :
    MaxPartitionVRAM        :
    OptimalPartitionVRAM    :
    MinPartitionEncode      :
    MaxPartitionEncode      :
    OptimalPartitionEncode  :
    MinPartitionDecode      :
    MaxPartitionDecode      :
    OptimalPartitionDecode  :
    MinPartitionCompute     :
    MaxPartitionCompute     :
    OptimalPartitionCompute :
    Name                    : GPU Partition Settings
    Id                      : Microsoft:9ABB95E2-D12D-43C3-B840-6F4A9CFB217B\929890BC-BB33-4687-BC1A-F72A4F1B3B3F
    VMId                    : 9abb95e2-d12d-43c3-b840-6f4a9cfb217b
    VMName                  : TEST
    VMSnapshotId            : 00000000-0000-0000-0000-000000000000
    VMSnapshotName          :
    
    CimSession              : CimSession: .
    ComputerName            : MYCOMPUTER-TEST2
    IsDeleted               : False
    VMCheckpointId          : 00000000-0000-0000-0000-000000000000
    VMCheckpointName        :
    
  12. Kopieren Sie das VHDX-Image desselben Clientbuilds, den Sie in der VM verwenden, auf ein Hostverzeichnis. Beispiel: d:\VM\os.vhdx.

  13. Öffnen Sie Hyper-V Manager, und ändern Sie VM-Parameter (wählen Sie "VM" und dann "Einstellungen" aus):

    • Sicherheit: Deaktivieren Sie Sicheren Start aktivieren.
    • Arbeitsspeicher: Aktivieren Sie Dynamischen Arbeitsspeicher aktivieren. Legen Sie die Arbeitsspeichermenge auf 1.024 MB oder mehr fest.
    • Prozessor – Legen Sie Anzahl virtueller Prozessoren auf 2 oder 4 fest.
    • Netzwerkadapter – Wählen Sie den Netzwerkadapter aus, der im Dropdownfeld mit dem virtuellen Computer verwendet werden soll. Wenn das Netzwerkdebugging aktiviert ist, stellen Sie sicher, dass Sie den Microsoft Debugging NET-Adapter auswählen.
    • SCSI-Controller - Festplatte - Hinzufügen – virtuelle Festplatte – Durchsuchen – d:\VM\os.vhdx auswählen
  14. Das Betriebssystem kopiert die Dateien aus dem Hosttreiberspeicher in das HostDriverStore-Verzeichnis im Gast, wenn der Adapter im Gast initialisiert wird.

    • Binden Sie die VHDX der VM ein. Zum Beispiel auf der Festplatte f:.
    • Erstellen Sie auf der bereitgestellten VM ein Verzeichnis namens f:\%windir%\system32\HostDriverStore\FileRepository.
    • Replizieren Sie Treiberdateien aus %windir%\system32\DriverStore- im Host auf die VM. Es sollte f:\%windir%\system32\HostDriverStore\FileRepository\YourDriverDirectory\* auf dem virtuellen Computer vorhanden sein.
  15. Wenn der Treiber von %windir%\system32 oder %windir%\syswow64auf Dateien zugreifen muss, kopieren Sie die Dateien manuell auf den virtuellen Computer.

  16. Aktivieren Sie die Testanmeldung auf dem virtuellen Computer, wenn die Treiber nicht von Microsoft signiert sind. Führen Sie im CMD-Administratorfenster den folgenden Befehl aus:

    bcdedit /store <VM drive>:\EFI\Microsoft\Boot\BCD -set {bootmgr} testsigning on
    

    Heben Sie die Einbindung der VHDX der VM auf.

  17. Starten Sie den virtuellen Computer.

  18. Stellen Sie eine Verbindung mit dem virtuellen Computer mithilfe der Option Hyper-V Manager Connect her.

INNERHALB DER VM

Überprüfen Sie, ob ein virtuelles Rendergerät im Geräte-Manager des virtuellen Computers vorhanden ist. Das gesamte Rendering innerhalb des virtuellen Computers durchläuft virtuelle GPU.

PowerShell-Skript zum Einrichten einer VM

Das folgende PowerShell-Skript ist ein Beispiel für das Einrichten eines virtuellen Computers von Grund auf. Ändern Sie sie entsprechend Ihren Anforderungen.


Param(
   [string]$VMName,
   [string]$VHDPath,
   [string]$SwitchName,
   [switch]$CreateVm,
   [switch]$InitDebug,
   [switch]$CopyRegistry,
   [switch]$CopyDriverStore,
   [switch]$CreateSwitch,
   [switch]$AddGpu,
   [switch]$All
)

if($All)
{
   $CreateVm = $True
   $CreateInitDebug = $True
   $CopyRegistry = $True
   $CopyDriverStore = $True
   $CreateSwitch = $True
   $AddGpu = $True
   $InitDebug = $True
}

   $vm = $VMName

#
# Validate parameters
#
if ($CreateSwitch -or $CreateVM)
{
    if ($SwitchName -eq "")
    {
        write "SwitchName is not set"
        exit
    }
}

if ($AddGpu -or $CreateVM)
{
    if ($VMName -eq "")
    {
        write "VMName is not set"
        exit
    }
}

if ($InitDebug -or $CreateVM -or $CopyDriverStore -or $CopyRegistry)
{
    if ($VHDPath -eq "")
    {
        write "VHDPath is not set"
        exit
    }
}

enable-windowsoptionalfeature -FeatureName Microsoft-Hyper-V-All -online

#
# Create a network switch for the VM
#
if ($CreateSwitch)
{
    New-VMSwitch $SwitchName -NetAdapterName "Ethernet (Kernel Debugger)"
}

#
# Create a VM and assign VHD to it
#
if ($CreateVm)
{
   New-VM -VMName $vm -Generation 2
   Set-VM -GuestControlledCacheTypes $true -VMName $vm


Set-VM -LowMemoryMappedIoSpace 1Gb -VMName $vm
   Set-VM -HighMemoryMappedIoSpace 32GB -VMName $vm
   Set-VMProcessor -VMname $vm -count 4
   Set-VMMemory -VMName $vm -DynamicMemoryEnabled $true -MinimumBytes 1024MB -MaximumBytes 4096MB -StartupBytes 1024MB -Buffer 20
   Add-VMHardDiskDrive -VMName $vm -Path $VHDPath
   Connect-VMNetworkAdapter -VMName $vm -Name "Network Adapter" -SwitchName $SwitchName
   Set-VMFirmware -VMName $vm -EnableSecureBoot off
   Set-VMFirmware -VMName $vm -FirstBootDevice (Get-VMHardDiskDrive -VMName $vm)
}

#
# Enable debugger and testsiging
#
if ($InitDebug)

```powershell
{
   Mount-vhd $VHDPath
   Add-PartitionAccessPath  -DiskNumber (Get-DiskImage -ImagePath $VHDPath | Get-Disk).Number -PartitionNumber 1 -AssignDriveLetter
   $efidrive = (Get-DiskImage -ImagePath $VHDPath | Get-Disk | Get-Partition -PartitionNumber 1).DriveLetter
   bcdedit /store ${efidrive}:\EFI\Microsoft\Boot\BCD -set '{bootmgr}' testsigning on
   bcdedit /store ${efidrive}:\EFI\Microsoft\Boot\BCD -set '{default}' debug on
   bcdedit /store ${efidrive}:\EFI\Microsoft\Boot\BCD /dbgsettings net port:50052 key:a.b.c.d hostip:10.131.18.133
   Dismount-VHD $VHDPath
}

#

# Now boot the VM without vGPU to verify that it's initialized correctly
# If everything is OK, turn off the VM
#
if ($CreateVm)
{
   Write-Output "Boot the VM and turn it OFF after it's initialized"
   pause
}

#
# Add virtual GPU
#
if($AddGpu)
{
   Add-VMGpuPartitionAdapter -VMName $vm
   Get-VMGpuPartitionAdapter -VMName $vm
}

#
# Copy the driver store to the VM
#
if ($CopyDriverStore)
{
   Write "Copying driver store"
   Mount-vhd $VHDPath
   $drive = (Get-DiskImage -ImagePath $VHDPath | Get-Disk | Get-Partition -PartitionNumber 3).DriveLetter
   xcopy /s $Env:windir\system32\driverstore\* ${drive}:\windows\system32\hostdriverstore\


Dismount-VHD $VHDPath
}

#
# Export driver registry settings
#
if ($CopyRegistry)
{
   Write "Copying registry"
   Mount-vhd $VHDPath
   $drive = (Get-DiskImage -ImagePath $VHDPath | Get-Disk | Get-Partition -PartitionNumber 3).DriveLetter
   reg load HKLM\VMSettings ${drive}:\Windows\System32\config\SYSTEM
   reg copy "HKLM\System\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\0000" "HKLM\VmSettings\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\0000" /s /f
   reg unload "HKLM\VmSettings"
   Dismount-VHD $VHDPath
}

Debuggen des virtuellen Computers

Konfigurieren Sie den VM-Debugger auf dieselbe Weise wie das Netzwerkdebugging auf einem normalen Clientcomputer.

Wenn der virtuelle Computer nicht gestartet wird oder ein schwarzer Bildschirm angezeigt wird:

  • Deaktivieren Sie den virtuellen Computer, und entfernen Sie die virtuelle GPU mit den folgenden Befehlen:

    $vm = “TEST“
    remove-VMGpuPartitionAdapter  -VMName $vm -AdapterId “<Id from Get-VMGpuPartitionAdapter>”
    

    Zum Beispiel:

    remove-VMGpuPartitionAdapter  -VMName $vm -AdapterId “Microsoft:9ABB95E2-D12D-43C3-B840-6F4A9CFB217B\929890BC-BB33-4687-BC1A-F72A4F1B3B3F”
    
  • Starten Sie den virtuellen Computer. Wenn sie erfolgreich gestartet wird, stellen Sie sicher, dass die Treiberdateien ordnungsgemäß in den HostDriverStore auf dem virtuellen Computer kopiert werden.

  • Fügen Sie der VM mithilfe des Befehls Add-VMGpuPartitionAdapter vGPU hinzu.

  • Starten Sie den virtuellen Computer erneut.

Weitere Informationen finden Sie unter Problembehandlung.

Containereinrichtung

Der Unterschied zwischen Containern (auch als Host Compute System (HCS)-VMs bezeichnet) und dem vollständigen virtuellen Computer besteht darin, dass die Binärdateien des Betriebssystems und treiberspeicherdateien dem Container zugeordnet werden. Es ist also nicht erforderlich, die Treiberdateien in den Container zu kopieren, es sei denn, sie sind im windows\system32 Verzeichnis erforderlich.

Für sichere Container:

  • Treiberescapes sind deaktiviert.
  • Der Treiber muss die IOMMU-Isolation unterstützen, um in einem sicheren Container aktiviert zu werden.

Wenn Sie den Treiber auf dem Host aktualisieren und die Host-GPU starten oder beenden, werden die Änderungen im Container wiedergegeben.

Windows-Sandkasten

Dieser Containertyp wird verwendet, um riskante Anwendungen auszuprobieren. Das vollständige Desktopimage wird per Remoting an den Host übertragen. Zum Remoting wir der Treiber für indirekte Anzeige verwendet. Grafik-VAIL wird nicht verwendet, sodass das Desktopimage langsam auf den Host übertragen wird.

Virtuelle GPU ist in der Windows-Sandbox standardmäßig deaktiviert. Erstellen Sie zum Aktivieren eine WSB-Konfigurationsdatei (z. B. config.wsb), und legen Sie die virtuelle GPU-Option fest. Starten Sie den Sandkasten, indem Sie auf die Konfigurationsdatei klicken.

Beispiel für eine Konfigurationsdatei:

<Configuration>
    <VGpu>Enable</VGpu>
</Configuration>

Standardmäßig sind die Treiberescapes für die vGPU im Container deaktiviert. Es gibt eine Konfigurationsoption, um Treiberescapes zu aktivieren. Mit dem folgenden Beispiel für eine WSB-Datei werden sowohl vGPU in der Sandbox als auch Treiberescapes aktiviert:

<Configuration>
    <VGpu>EnableVendorExtensions</VGpu>
</Configuration>

Die Windows-Sandbox unterstützt den GPU-Adapter "Hot Plug".

VAIL-Container (Virtual Application Integrated Locally)

Verwenden Sie diesen Containertyp, um Win32-Anwendungen innerhalb eines WCOS-basierten Hosts (Windows Core Operated System) auszuführen. Das Image jeder Anwendung im Container wird per Remoting an den Host übertragen. Grafik-VAIL ist aktiviert, um jede Anwendungs-Swapchain fernzusteuern. Treiberescapes sind aktiviert.

Allgemeine Containeranforderungen

Computeranforderungen sind:

  • Sowohl Vtx als auch Vtd müssen im BIOS (oder deren Entsprechungen: AMD-V, AMD-IOMMU) aktiviert sein.
  • Mindestens 8 GB RAM.
  • Mehr als 5 GB Systemspeicherplatz.

Einrichten des Kerneldebuggers für Windows-Sandbox

Verwenden von CMDIAG

Ein Container-Manager-Dienst (cmservice) steuert Hyper-V isolierte Container. CMDIAG.EXE ist eine Anwendung, die verfügbar ist, wenn Sie die Hyper-V- und Container-Features installieren. Es ermöglicht das Debuggen im Kernelmodus für Container, ermöglicht die Testsignierung und vieles mehr.

Der Container-Manager unterstützt das serielle und NET-Debugging.

Führen Sie cmdiag.exe Debug aus, um die Optionen anzuzeigen.

CMDIAG ändert Debuggereinstellungen im Containerbasisimage. Es sollte nur eine Instanz eines Containers vorhanden sein, der ausgeführt wird, wenn der Kerneldebugger aktiviert ist.

Beenden Sie den HVSICS-Dienst, bevor Sie die Debuggereinstellungen ändern.


# Example 1:

C:\Windows\system32>sc stop hvsics
SERVICE_NAME: HVSICS
        TYPE               : 30  WIN32
        STATE              : 3  STOP_PENDING
                                (STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x1
        WAIT_HINT          : 0xbb8

C:\Windows\system32>cmdiag debug -on -Serial  -Force
Debugging successfully enabled. Connection string: -k com:pipe,port=\\.\pipe\debugpipe,reconnect -v

# Example 2:

C:\Windows\system32>cmdiag debug -on -net -port 51000 -key a.b.c.d -hostip 10.131.18.34

Ausführen des Debuggers auf einem anderen Computer

Wenn Sie den seriellen Debugger verwenden, sollten Sie ihn auf einem anderen Computer ausführen. Verwenden Sie kdsrv.exe, um den Debugger auf einem anderen Computer auszuführen. Weitere Informationen finden Sie unter KD-Verbindungsserver.

Um Timeouts während des Kerneldebuggings zu deaktivieren, legen Sie die folgenden Registrierungsschlüssel fest:

reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\Containers\UtilityVm" /v BridgeTransactionTimeout /t REG_DWORD /d 0xffffffff /f
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\Containers\UtilityVm" /v BridgeServerConnectTimeout /t REG_DWORD /d 0xffffffff /f
reg add "HKLM\SOFTWARE\Microsoft\HVSI" /f /v DisableResetContainer /t REG_DWORD /d 1
reg add "HKLM\SOFTWARE\Microsoft\HVSI" /f /v AppLaunchTimeoutInSeconds /t REG_DWORD /d 0x7fffffff
reg add "HKLM\Software\Microsoft\Terminal Server Client" /f /v ConnectionHealthMonitoringSupported /t REG_DWORD /d 0

reg add "HKLM\Software\Microsoft\Terminal Server Client" /f /v DisableUDPTransport /t REG_DWORD /d 1
reg add "HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client" /f /v ConnectionHealthMonitoringSupported /t REG_DWORD /d 0
reg add "HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client" /f /v DisableUDPTransport /t REG_DWORD /d 1

Einrichten des Kerneldebuggers für VAIL-Container

  • Stellen Sie mithilfe von Telnet eine Verbindung mit dem Host her. Sie können die IP-Adresse des Hosts aus den Netzwerkeinstellungen im Hostbetriebssystem abrufen.
  • Verwenden Sie cmdiag.exe, um den Debugger zu konfigurieren.

Einrichten des Hypervisor-Debuggers

bcdedit /hypervisorsettings NET port:50000 key:a.b.c.d hostip:1.1.1.1
bcdedit /set {hypervisorsettings} hypervisorbusparams 0.0.0 (if needed)
bcdedit /set hypervisordebug on
reboot host

Fehlerbehebung

Dieser Abschnitt enthält Informationen zum Behandeln von Problemen mit GPU-PV.

Get-VMHostPartitionableGpu

Rufen Sie Get-VMHostPartitionableGpu auf, um festzustellen, ob eine virtualisierte GPU vorhanden ist. Wenn die Ausgabe leer ist, gibt es irgendwo einen Fehler (Treiber hat die Virtualisierungscap nicht festgelegt, Virtualisierung ist nicht aktiviert usw.).

Get-VMHostPartitionableGpu

# Example output from running the command

Name                    : \\?\PCI#VEN_10DE&DEV_1188&SUBSYS_095B10DE&REV_A1#6&cfd27c8&0&00400008#{064092b3-625e-43bf-9eb5-dc845897dd59}\PARAV
ValidPartitionCounts    : {32, 4}
PartitionCount          : 32
TotalVRAM               : 2,000,000
AvailableVRAM           : 1,800,000
MinPartitionVRAM        : 100,000
MaxPartitionVRAM        : 1,000,000
OptimalPartitionVRAM    : 1,000,000
TotalEncode             : 20
AvailableEncode         : 20
MinPartitionEncode      : 1
MaxPartitionEncode      : 5
OptimalPartitionEncode  : 4
TotalDecode             : 40
AvailableDecode         : 30
MinPartitionDecode      : 2


MaxPartitionDecode      : 20
OptimalPartitionDecode  : 15
TotalCompute            : 100
AvailableCompute        : 100
MinPartitionCompute     : 1
MaxPartitionCompute     : 50
OptimalPartitionCompute : 30
CimSession              : CimSession: .
ComputerName            : WIN-T3H0LVHJJ59
IsDeleted               : False

Verwenden von ETW-Ereignissen

Dxgkrnl verfügt über Administrator- und Betriebskanäle für ETW-Ereignisse. Die Ereignisse werden in der Windows-Ereignisanzeige angezeigt: Anwendungs- und Dienstprotokoll - Microsoft - Windows - Dxgkrnl.

Die Ereignisanzeige verfügt über Ereignisse aus anderen Komponenten, die an der Erstellung eines virtuellen Computers mit GPU-PV teilnehmen (Hyper-V-Compute, Hyper-V-Worker, Hyper-V-VID usw.).

Verwenden von Add-VMGpuPartitionAdapter

Bei Verwendung von Add-VMGpuPartitionAdapter geben Sie eine Fähigkeit (z. B. Dekodieren) nicht an, wenn diese nicht benötigt wird. Verwenden Sie 0 nicht für diese Funktion.

Verwenden von Remove-VMGpuPartitionAdapter

Wenn ein virtueller Computer Fehler beim Starten oder Rendering-Probleme hat, versuchen Sie, die virtuelle GPU mithilfe von Remove-VMGpuPartitionAdapteraus dem virtuellen Computer zu entfernen.

remove-VMGpuPartitionAdapter  -VMName $vm -AdapterId "Microsoft:9ABB95E2-D12D-43C3-B840-6F4A9CFB217B\929890BC-BB33-4687-BC1A-F72A4F1B3B3F"

Verhindern des Startens des virtuellen Computers während des Starts

set-vm -AutomaticStartAction Nothing -VmName TEST

Ereignisse der Ereignisanzeige

Fügen Sie dem Ereignisanzeigekanal Ereignisse hinzu, um Probleme beim vGPU-Start zu identifizieren. Die Ereignisse finden Sie unter "Anwendungs- und Dienstprotokolle\Microsoft\Windows\Dxgkrnl". Die Ereigniskanäle sind "Admin" und "Operational".

Ereignisse werden ausgegeben, wenn:

  • vGPU erstellt wird
  • vGPU wird zerstört
  • Der Gast öffnet einen virtuellen Adapter.

Die Ereignisdateien sind in:

  • c:\Windows\System32\winevt\Logs\Microsoft-Windows-DxgKrnl-Admin.evtx
  • c:\Windows\System32\winevt\Logs\Microsoft-Windows-DxgKrnl-Operational.evtx

Überprüfen Sie, ob eine vGPU erstellt wurde und ob Fehler vorhanden sind.

Registrierungseinstellungen

GpuVirtualizationFlags

Der GpuVirtualizationFlags-Registrierungsschlüssel wird verwendet, um das Verhalten von paravirtualisierten GPUs festzulegen. Der Schlüssel befindet sich in:

DWORD HKLM\System\CurrentControlSet\Control\GraphicsDrivers\GpuVirtualizationFlags

Die folgenden Bits sind definiert:

Bit Beschreibung
0x1 Erzwingen Sie die ParavirtualizationSupported-Obergrenze für alle Hardwareadapter. Verwenden Sie dieses Bit im Host.
0x2 Erzwingen Sie die ParavirtualizationSupported-Obergrenze für BasicRender. Verwenden Sie dieses Bit im Host.
0x4 Erzwingen Sie den modus "Sicherer virtueller Computer", in dem alle virtuellen Computer als sicher behandelt werden. In diesem Modus gibt es Einschränkungen für den Benutzermodustreiber. Beispielsweise kann der Treiber keine Escapeaufrufe verwenden, sodass diese fehlschlagen. Verwenden Sie dieses Bit im Host.
0x8 Aktivieren Sie die Kopplung von paravirtualisierten Adaptern mit dem ausschließlich für die Anzeige vorgesehenen Adapter. Verwenden Sie dieses Bit in der Gast-VM. Die Kopplung ist standardmäßig aktiviert.

GuestIoSpaceSizeInMb

Der Registrierungsschlüssel "GuestIoSpaceSizeInMb" wird verwendet, um die Größe des Gast-E/A-Raums für virtuelle GPUs in Megabyte festzulegen. Der Standardwert ist 1.000 MB (1 GB). Der Schlüssel befindet sich unter:

DWORD HKLM\System\CurrentControlSet\Control\GraphicsDrivers\Paravirtualization\GuestIoSpaceSizeInMb

Der Gast-E/A-Bereich führt derzeit CPU-sichtbare Zuweisungen durch. Ein CPU-sichtbarer Zuweisungssicherungsspeicher im Host wird im Speicher angeheftet und dem Gast-E/A-Bereich zugeordnet. Im Gast wird die virtuelle Adresse der Zuweisung im Benutzermodus in den E/A-Bereich rotiert. Auf einigen Haswell-Systemen verfügt die CPU über 36-Bit-physische Adressen. Hyper-V in solchen Systemen hat eine begrenzte E/A-Bereichsgröße.

Deaktivieren der IOMMU-Isolierung für sichere virtuelle Computer

Wenn ein Treiber die IoMmu-Isolation nicht unterstützt, verwenden Sie während der Entwicklung die folgende Registrierungseinstellung, um die IoMmu-Isolation zu deaktivieren.

`DWORD HKLM\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\IoMmuFlags = 8`

Begrenzen Sie die Anzahl der virtuellen Funktionen

Standardmäßig ist die Anzahl der virtuellen Funktionen, die von einem Adapter verfügbar gemacht werden, der GPU-Paravirtualisierung unterstützt, 32. Diese Zahl bedeutet, dass der Adapter zu 32 virtuellen Computern hinzugefügt werden kann, vorausgesetzt, jede VM verfügt über einen Adapter.

Sie können die folgende Registrierungseinstellung verwenden, um die Anzahl der verfügbar gemachten virtuellen Funktionen einzuschränken.

DWORD HKLM\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\NumVirtualFunctions

Wenn Sie z. B. NumVirtualFunctions auf 1 festlegen, kann der Adapter nur einmal einer GPU hinzugefügt werden. Diese Einstellung ist nützlich, wenn ein Computer über mehrere GPU-Adapter verfügt, die GPU-PV unterstützen, und Sie jeden Adapter einem virtuellen Computer zuweisen möchten. Add-VMGpuPartitionAdapter lässt nicht zu, dass Sie angeben, welcher Adapter hinzugefügt werden soll. Wenn also zwei Adapter zu einem virtuellen Computer hinzugefügt werden, könnten beide den gleichen GPU-PV Adapter vom Host abrufen.

WDDM 2.4 DDI-Updates

Die folgenden DDI-Updates werden zur Unterstützung der GPU-Paravirtualisierung in WDDM 2.4 vorgenommen.

DXGK_VIDMMCAPS-Obergrenze hinzugefügt

Die ParavirtualizationSupported-Funktion wird der DXGK_VIDMMCAPS-Struktur hinzugefügt. Der Host-KMD legt diese Obergrenze fest, wenn alle in diesem Abschnitt beschriebenen DDIs implementiert werden.

Private Treiberdaten, die über DDI übergeben werden

Die UMD verwendet verschiedene DDIs, um private Informationen mit dem entsprechenden KMD auszutauschen. Wenn die UMD auf der Gast-VM ausgeführt wird, erfolgt der entsprechende KMD DDI-Aufruf in der Hostpartition. Daher gilt für den UMD Folgendes:

  1. Es können keine Zeiger in den privaten Daten übergeben werden.
  2. Es können keine Handles in den privaten Daten übergeben werden.
  3. Sollte die KMD nicht anweisen, globale Änderungen des GPU-Zustands vorzunehmen, da sich diese Änderung auf andere ausgeführte VMs auswirken könnte.

VirtualMachineProcess-Flag für DxgkDdiCreateProcess hinzugefügt

Das Betriebssystem erstellt einen VM-Arbeitsprozess für jeden ausgeführten virtuellen Computer. Dxgkrnl erstellt einen entsprechenden DXGPROCESS und ruft DxgkDdiCreateProcess auf, wobei das VirtualMachineWorkerProcess-Flag festgelegt ist. In diesem Prozesskontext gibt es keine Rendering- oder Treiberressourcenerstellung. Der Treiber kann also die Zuordnung bestimmter Ressourcen überspringen.

Das Betriebssystem erstellt einen DXGPROCESS im Host für jeden Prozess in einem Gastcomputer, der eine GPU verwendet. Dxgkrnl ruft DxgkDdiCreateProcess auf, wobei das VirtualMachineProcess-Flag festgelegt ist. Jeder VM DXG-Prozess gehört zum gleichen EPROCESS-Prozess wie der VM-Arbeitsprozess.

DxgkDdiQueryAdapterInfo-Updates

Die DXGKARG_QUERYADAPTERINFO Struktur wird aktualisiert, um die folgenden Felder für die Unterstützung der Paravirtualisierung einzuschließen:

  • Das Flags-Element wird hinzugefügt, wodurch Dxgkrnl Folgendes angeben kann:

    • Es legt VirtualMachineData- fest, um anzugeben, dass der Aufruf von einer VM stammt.
    • Es legt SecureVirtualMachine fest, um anzugeben, dass der virtuelle Computer im abgesicherten Modus ausgeführt wird.
  • hKmdProcessHandle hinzugefügt wird, wodurch der Treiber den richtigen Prozesskontext auf der Hostseite identifizieren und verwenden kann, wenn es um Abfragen geht, die von einer Gast-VM stammen.

DxgkDdiEscape-Aktualisierungen

Das hKmdProcessHandle-Element wird der DXGKARG_ESCAPE-Struktur hinzugefügt, damit der Treiber den korrekten Prozesskontext auf der Hostseite identifizieren und verwenden kann, wenn es um Escapesequenzen geht, die von einer Gast-VM stammen.

Das VirtualMachineData-Flag wird der D3DDDI_ESCAPEFLAGS-Struktur hinzugefügt, um anzugeben, dass DxgkDdiEscape von einem virtuellen Computer aufgerufen wird.

Physischer Zugriff auf GPU-Zuordnungen

Derzeit implementiert der Treiber keinen physischen Zugriff auf die Zuordnungen. Der Treiber muss GpuMmu unterstützen.

WDDM 2.5 DDI-Updates

Für WDDM 2.5 sind auch die folgenden DDI-Änderungen für die Unterstützung der Paravirtualisierung erforderlich.

Signalisierung von Gastveranstaltungen durch den Host-KMD

Es gibt Szenarien, die ohne Virtualisierung vorhanden sind, wenn die KMD ein ereignis signalisieren muss, das von einer UMD erstellt wurde. Um solche Szenarien zu verarbeiten, wenn Paravirtualisierung verwendet wird, muss der KMD auf dem Host ein im Gast erstelltes Ereignis signalisieren. Der DxgkCbSignalEvent-Rückruf wird zu diesem Zweck hinzugefügt. KMD kann diesen Rückruf auch verwenden, um Ereignisse der Hostprozesse zu signalisieren.

Unterstützung für UMD-bereitgestellte Handles in einer VM

Bestimmte Treiberrückrufe akzeptieren eine Dxgkrnl-Zuweisung oder ein Ressourcenhandle, das der UMD übergibt, wie zum Beispiel:

Die Aufrufe des Hosts müssen sich im Kontext desselben Threads befinden, der eine DxgkDdi-Xxx--Funktion aufgerufen hat.

Beispiel: Angenommen, ohne Virtualisierung ruft der KMD DxgkCbAcquireHandleData im Kontext des Benutzermodusthreads auf, der D3DKMTEscape aufruft, das wiederum DxgkDdiEscape aufruft.

Wenn UMD auf einem virtuellen Computer ausgeführt wird, kennt sie nur die Gastzuweisungshandles und kann solche Handles nicht an die KMD übergeben, da KMD auf dem Host ausgeführt wird. Der UMD im Gast ruft D3DKMTEscape auf, und der KMD im Host empfängt den entsprechenden DxgkDdiEscape-Aufruf. Der KMD muss DxgkCbAcquireHandleData im Kontext dieses Threads aufrufen.

Um die Gastzuweisung/das Ressourcenhandle in das entsprechende Hosthandle übersetzen zu können, wird das Treiberescapeflag D3DDDI_ESCAPEFLAGS::DriverKnownEscape hinzugefügt.

Wenn Sie D3DKMTEscape mit festgelegtem DriverKnownEscape-Flag aufrufen:

  • Legen Sie D3DKMT_ESCAPE::Type auf D3DKMT_ESCAPE_DRIVERPRIVATEfest.

  • Legen Sie D3DKMT_ESCAPE::pPrivateDriverData so fest, dass es auf eine bekannte Treiberescapestruktur verweist, die im folgenden Abschnitt definiert ist. Jede Struktur beginnt mit einem D3DDDI_DRIVERESCAPETYPE Wert.

Wenn die Virtualisierung nicht verwendet wird, entspricht das übersetzte Handle dem Eingabehandle.

Die folgenden bekannten Treiberescapes sind definiert.

Der folgende Codeausschnitt veranschaulicht die Verwendung des DriverKnownEscape- Flags.

D3DDDI_DRIVERESCAPE_TRANSLATEALLOCATIONEHANDLE Command = {};
    Command.EscapeType = D3DDDI_DRIVERESCAPETYPE_TRANSLATEALLOCATIONHANDLE;
    Command.hAllocation = hAlloc;
    D3DKMT_ESCAPE Args = {};
    Args.hAdapter = hAdapter;
    Args.Flags.DriverKnownEscape = TRUE;
    Args.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
    Args.pPrivateDriverData = &Command;
    Args.PrivateDriverDataSize = sizeof(Command);
    Status = D3DKMTEscape(&Args);

WDDM 2.6 DDI-Updates

Ab WDDM 2.6 (Windows 10, Version 1903) wurden die folgenden Updates für die Unterstützung der Paravirtualisierung vorgenommen:

  • Der Treiber kann das DXGK_ALLOCATIONINFOFLAGS::ACCESSEDPHYSICALLY-Flag auf einem virtuellen Computer verwenden. Vor WDDM 2.6 konnte der Treiber dieses Kennzeichen nicht in einem virtuellen Computer verwenden, und die Zuordnungserstellung mit diesem Flag ist fehlgeschlagen.

  • UMD kann Pfnd3dkmtUpdateallocationproperty in einem virtuellen Computer verwenden. Vor WDDM 2.6 schlägt dieser Aufruf fehl.