Compartilhar via


Paravirtualização de GPU

Este artigo descreve a paravirtualização da GPU no WDDM. Esse recurso está disponível a partir do Windows 10, versão 1803 (WDDM 2.4).

Sobre a virtualização de GPU

A virtualização de GPU é um recurso importante para o Cliente Windows e o Windows Server. Há muitos cenários que exigem o uso efetivo de recursos de GPU em uma máquina virtual.

Os cenários de servidor (em que o sistema operacional host não executa aplicativos de usuário) incluem:

  • Virtualização da área de trabalho
  • Computação (IA, ML etc.)

Os cenários do cliente (em que o sistema operacional host compartilha a GPU entre VMs e aplicativos de usuário) incluem:

  • Desenvolvendo e testando aplicativos gráficos (em que o teste é executado em uma VM)
  • Executando aplicativos em uma VM para fins de segurança
  • Executando o Linux em uma VM com aceleração de GPU

Paravirtualização de GPU no WDDM

A paravirtualização (PV) fornece uma interface para VMs (máquinas virtuais) semelhantes ao hardware subjacente. No PV, você porta explicitamente o sistema operacional convidado antes de instalar uma VM porque um sistema operacional convidado não personalizado não pode ser executado em cima de um VMM (monitor de máquina virtual).

Vantagens:

  • Várias VMs compartilham os recursos de hardware.
  • Poucas alterações precisam ser feitas no código do driver.

A figura a seguir mostra os diversos componentes envolvidos no design paravirtualizado do WDDM.

Diagrama que mostra os componentes envolvidos no design paravirtualizado.

Os runtimes D3D na VM convidada não são alterados. As interfaces com o runtime do modo de usuário e com os kernel thunks KMT permanecem as mesmas.

Os componentes do driver não exigem muitas alterações:

  • O UMD na VM convidada precisa:

    • Lembre-se de que as comunicações com o driver do modo kernel do host (KMD) atravessam a fronteira da VM.
    • Use os serviços adicionados Dxgkrnl para acessar as configurações do registro.
  • Não há KMD no convidado, apenas UMD. O KMD do VRD (Dispositivo de Renderização Virtual) substitui o KMD. A finalidade do VRD é facilitar o carregamento de Dxgkrnl.

  • Não há nenhum gerenciador de memória de vídeo (VidMm) ou agendador (VidSch) no convidado.

  • Dxgkrnl em uma VM recebe chamadas thunk e as leva para a partição de host por meio de canais de barramento de VM. Dxgkrnl no convidado também cria objetos locais para alocações, processos, dispositivos e outros recursos, o que reduz o tráfego com o host.

Dispositivo de renderização virtual (VRD)

Quando uma GPU paravirtualizada não está presente em uma VM, o Gerenciador de Dispositivos da VM mostra o adaptador "Microsoft Hyper-V Video". Esse adaptador somente exibição é emparelhado por padrão com o adaptador BasicRender para renderização.

Quando você adiciona uma GPU paravirtualizada a uma VM, o Gerenciador de Dispositivos da VM mostra dois adaptadores:

  • Adaptador de Vídeo do Microsoft Hyper-V ou Adaptador de Exibição Remota da Microsoft
  • Microsoft Virtual Render Driver (o nome real é o nome do adaptador de GPU no host)

Por padrão, o VRD é emparelhado com o adaptador de vídeo Hyper-V, portanto, toda a renderização da interface do usuário ocorre com o adaptador VRD.

Se você encontrar problemas de renderização, poderá desabilitar esse emparelhamento usando a configuração de registro GpuVirtualizationFlags. Nesse caso, o adaptador somente para renderização (VRD) é utilizado quando um aplicativo o seleciona especificamente. Por exemplo, alguns exemplos do DirectX permitem alterar o dispositivo de renderização. Os runtimes do Direct3D adicionam uma saída de exibição lógica ao VRD quando um aplicativo decide usá-lo.

Quando você adiciona várias GPUs virtuais à VM, pode haver vários adaptadores VRD no sistema convidado. No entanto, apenas um deles pode ser emparelhado com o adaptador de vídeo Hyper-V. Não há como especificar qual; o sistema operacional escolhe.

Contêineres e VMs

Há suporte para virtualização de GPU para VMs e contêineres. Os contêineres são VMs leves, em que os binários do sistema operacional host são mapeados para a VM do contêiner.

Para obter mais informações sobre contêineres, consulte Windows e contêineres.

VMs seguras

As seguintes limitações existem para uma VM segura:

  • As chamadas de fuga do motorista não são permitidas, exceto escapes conhecidos, que são usados com o sinalizador DriverKnownEscape.
  • O isolamento do IoMmu está habilitado. A criação da VM falhará se o driver não oferecer suporte ao isolamento IoMmu.

Quando o modo de segurança está habilitado:

Há configurações do Registro para forçar o modo seguro ou desabilitar o isolamento do IoMmu durante o desenvolvimento. Para obter mais informações, confira Configurações modificadas do Registro.

Acesso remoto da área de trabalho de VM/contêiner

Você pode transferir remotamente o conteúdo da área de trabalho de uma máquina virtual (VM) para o host usando dois métodos:

  • Hyper-V adaptador de exibição
  • Sessão remota do terminal

Quando o RDP (Protocolo de Desktop Remoto) é utilizado para se conectar a uma VM, a remotização da sessão do terminal é empregada.

O gerenciador Hyper-V usa o aplicativo VMConnect para exibir uma área de trabalho de VM. O VMConnect funciona em dois modos:

  • Modo aprimorado, que usa o acesso remoto da sessão do terminal.
  • Modo básico, que usa o adaptador de exibição Hyper-V.

Processo de trabalho de VM e memória de VM

Quando você inicia uma VM ou contêiner, o sistema operacional cria os seguintes processos no host:

  • Processo de trabalho da Máquina Virtual (vmwp.exe)
  • Processo de memória da VM (vmmem.exe)

Vmwp contém vários drivers de dispositivo virtual, incluindo vrdumed.dll, que é o driver para adaptadores gráficos paravirtualizados.

O processo de espaço de endereço virtual vmmem serve de apoio para o espaço de E/S do vGPU na máquina virtual hóspede. Quando o sistema hóspede acessa o espaço de E/S, o endereço físico resultante é a entrada para a tradução de segundo nível, que usa as tabelas de página do processo vmmem.

Em um ambiente virtualizado, várias chamadas DDI KMD, que normalmente são executadas no contexto de um processo de usuário no host, são executadas no contexto do processo do vmmem quando uma máquina virtual está em execução.

Dxgkrnl cria um único DXGPROCESS (e o objeto de processo KMD correspondente) para esses processos, que é chamado de processo de trabalho de VM neste artigo. O EPROCESS associado ao processo de trabalho da VM DXG é vmmem.

Processos de VM

Quando um DXGPROCESS é criado na VM convidada, Dxgkrnl cria um objeto DXGPROCESS correspondente no host. Isso é chamado de processo de VM neste artigo. O EPROCESS associado ao DXGPROCESS é vmmem.

Todas as operações de renderização de uma VM ou de criação de alocação de VM são feitas no contexto do DXGPROCESS da VM.

Para fins de depuração, Dxgkrnl notifica KMD sobre qual processo é um processo de trabalho de VM ou processo de VM no DxgkDdiCreateProcess. Usando essas informações, o driver pode vincular um processo de VM ao processo de trabalho da VM. Essas informações ajudam a depurar em cenários em que mais de uma VM está em execução.

Requisitos do motorista

Um KMD que dá suporte à paravirtualização de GPU precisa definir a capacidade DXGK_VIDMMCAPS::ParavirtualizationSupported.

O UMD (driver de modo de usuário) não deve usar nenhum dado relacionado ao contexto do processo nos dados do driver privado (ponteiros, identificador, etc.). Em vez disso, o KMD obtém os dados privados no host em um contexto de processo diferente.

O UMD no convidado não pode compartilhar memória com o KMD no host. Ele deve usar as funções descritas em acesso ao Registro a partir de UMD para acessar o Registro.

A implementação de paravirtualização atual usa o barramento de VM para se comunicar entre o convidado e o host. O tamanho máximo da mensagem é de 128 KB. No momento, Dxgkrnl não divide mensagens para enviá-las em partes. Portanto, o driver precisa limitar o tamanho dos dados privados passados com a criação do objeto. Por exemplo, quando Pfnd3dddiAllocatecb é usado para criar muitas alocações, o tamanho total da mensagem inclui um cabeçalho, dados privados globais, além do tamanho de dados privados por alocação multiplicados pelo número de alocações. Todas essas informações precisam se encaixar em uma única mensagem.

Executando aplicativos no modo emulado de tela inteira

O adaptador de Exibição Indireta deve ser habilitado para transmissão remota (ele está habilitado por padrão). Para desabilitá-lo, execute as etapas a seguir.

  • Iniciar Edição de Política de Grupo
  • Navegue até Configuração do Computador->Modelos Administrativos->Componentes do Windows->Serviços de Área de Trabalho Remota->Host de Sessão de Área de Trabalho Remota->Ambiente de Sessão Remota
  • Abra o item "Usar driver de exibição de elementos gráficos do WDDM para Conexão de Área de Trabalho Remota"
  • Selecione Desabilitar e selecionar OK
  • Reinicializar

O suporte de DXGI para aplicativos de tela inteira em VMs está habilitado por padrão. Para desabilitá-lo, use StagingTool.exe /disable 19316777.

Os aplicativos de tela inteira devem estar em execução no modo de tela inteira emulado.

Habilite o eFSE para todos os aplicativos DXGI e defina a versão mínima do WDDM para a transição de efeito de troca para o WDDM 2.0:

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

O eFSE está habilitado por padrão para aplicativos D3D9.

DriverStore na VM

Os binários de driver no host estão localizados em um repositório de driver %windir%\system32\drivers\DriverStore\FileRepository<DriverDirectory>.

Para paravirtualização, espera-se que os binários da UMD em uma VM estejam em %windir%\system32\drivers\HostDriverStore\FileRepository<DriverDirectory>.

O host KMD relata os nomes das DLLs UMD que têm o caminho completo para o repositório de drivers. Por exemplo, c:\windows\system32\DriverStore\FileRepository\DriverSpecificDirectory\d3dumd.dll.

Quando a VM solicita um nome UMD, o nome é traduzido para <>VmSystemDrive:\windows\system32\HostDriverStore\FileRepository\DriverSpecificDirectory\d3dumd.dll.

Hospedar DriverStore para contêineres

Para contêineres, Hyper-V mapeia o diretório completo do repositório de driver de host no host para <%windir%\HostDriverStore no contêiner.

Hospedar DriverStore para VMs completas

Os arquivos do repositório de driver são copiados para a VM quando o adaptador de GPU virtual é iniciado na VM. Esse recurso está desabilitado na versão lançada do sistema operacional.

A chave do Registro a seguir e os valores possíveis controlam a operação de cópia. A chave não existe por padrão.

DWORD RTL_REGISTRY_CONTROL\GraphicsDrivers\DriverStoreCopyMode
Valor Descrição
0 Desabilitar a cópia do repositório de driver
1 Operação normal (habilitar a cópia dos arquivos do repositório de driver e não substituir arquivos existentes).
2 Habilite a cópia do repositório de driver e substitua os arquivos existentes.

Acesso ao Registro do UMD

As chaves do registro KMD existem no host e não são refletidas para a VM. Portanto, a UMD não pode ler essas chaves do Registro de Driver diretamente. A chamada de retorno pfnQueryAdapterInfoCb2 é adicionada à estrutura D3DDDI_ADAPTERCALLBACKS do runtime D3D. O UMD pode chamar pfnQueryAdapterInfoCb2 com D3DDDICB_QUERYADAPTERINFO2 definido da seguinte maneira para ler determinadas chaves do registro:

  • D3DDDICB_QUERYADAPTERINFO2::QueryType definido como D3DDDI_QUERYADAPTERTYPE_QUERYREGISTRY.
  • pPrivateDriverData aponta para um buffer com uma estrutura D3DDDI_QUERYREGISTRY_INFO para retornar as informações do registro. O UMD preenche os seguintes membros:
  • PrivateDriverDataSize é sizeof(D3DDDI_QUERYREGISTRY_INFO) mais o tamanho do buffer para o valor de saída de tamanho dinâmico.

O UMD também pode chamar D3DKMTQueryAdapterInfo diretamente. Essa chamada é útil para o UMD no ambiente do convidado porque ela é transferida para o host e fornece uma maneira de traduzir determinados nomes para o espaço de nomes do convidado.

D3DKMTQueryAdapterInfo é chamado com D3DKMT_QUERYADAPTERINFO configurado da seguinte forma para ler algumas chaves específicas do Registro:

  • Type está definido como KMTQAITYPE_QUERYREGISTRY
  • pPrivateDriverData aponta para uma estrutura de D3DKMT_ADAPTERREGISTRYINFO
  • PrivateDriverDataSize é sizeof(D3DKMT_ADAPTERREGISTRYINFO) mais o tamanho do buffer para o valor de saída de tamanho dinâmico.

Exemplo 1: Lendo um valor da chave de serviço


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");
       }
    }

Exemplo 2: ler o caminho do repositório de driver

    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
    }

Copiar arquivos para %windir%\system32 e %windir%\syswow64 na VM

Em alguns casos, as DLLs do modo de usuário do driver precisam estar presentes nos diretórios %windir%\system32 e %windir%\syswow64.

O sistema operacional fornece uma maneira para o driver especificar arquivos que devem ser copiados do repositório de driver no host para %windir%\system32 ou %windir%\syswow64 no convidado.

No INF de instalação, o driver pode definir vários valores nas seguintes subchaves na chave do registro do adaptador gráfico:

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

As subchaves CopyToVmOverwrite e CopyToVmWhenNewer são usadas para copiar arquivos para o diretório %windir%\system32.

As subchaves CopyToVmOverwriteWow64 e CopyToVmWhenNewerWow64 são usadas para copiar arquivos para o diretório %windir%\syswow64.

Os arquivos em CopyToVmOverwrite e CopyToVmOverwriteWow64 sempre substituem os arquivos no destino.

Os arquivos em CopyToVmWhenNewer e CopyToVmWhenNewerWow64 substituem os arquivos no destino somente se a data de alteração do arquivo for mais recente. Os critérios "mais recentes" comparam duas informações:

  • FileVersion
  • LastWriteTime

Quando o arquivo de destino termina com o sufixo .dll ou .exe, o FileVersion é usado como o valor de comparação mais significativo em que a versão maior é considerada "mais recente". Quando o arquivo de destino não termina com o sufixo .dll ou .exe ou os dois FileVersion são iguais, o LastWriteTime é usado como os valores de comparação menos significativos em que a data/hora posterior é considerada "mais recente".

Cada tipo de valor em uma subchave deve ser REG_MULTI_SZ ou REG_SZ. Se o tipo de valor for REG_MULTI_SZ, deverá haver um máximo de duas cadeias de caracteres no valor. Esse requisito significa que cada valor define uma única cadeia de caracteres ou um par de cadeias de caracteres, em que a segunda cadeia de caracteres pode estar vazia.

O primeiro nome em um par é um caminho para um arquivo no repositório do driver. O caminho é relativo à raiz do repositório de driver e pode conter subdiretórios.

O segundo nome em um par é o nome do arquivo, pois ele deve aparecer no diretório %windir%\system32 ou %windir%\syswow64. O segundo nome deve ser apenas o nome do arquivo, não incluindo o caminho. Se o segundo nome estiver vazio, o nome do arquivo será o mesmo que no repositório de driver (excluindo subdiretórios).

Essa abordagem permite que o driver tenha nomes diferentes no repositório de drivers do host e no convidado.

Exemplo 1

O exemplo a seguir mostra como fazer com que o sistema operacional copie <DriverStorePath>\CopyToVm\softgpu1.dll para %windir%\system32\softgpu2.dll.

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"

Exemplo 2

O exemplo a seguir mostra como fazer com que o sistema operacional copie <DriverStorePath>\softgpu1.dll para %windir%\system32\softgpu.dll e <DriverStorePath>\softgpu2.dll para %windir%\system32\softgpu2.dll.

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””

Exemplo 3

O exemplo a seguir mostra como fazer com que o sistema operacional copie <DriverStorePath>\Subdir1\Subdir2\softgpu2wow64.dll para %windir%\syswow64\softgpu.dll e <DriverStorePath>\softgpu.dll para %windir%\syswow64\softgpu2wow64.dll.

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

Alterações no DxgkDdiCreateProcess

A função DxgkDdiCreateProcess do KMD precisa ser atualizada para dar suporte a processos de trabalho de VM e processos de VM. Os campos a seguir são adicionados à estrutura DXGKARG_CREATEPROCESS:

  • hKmdVmWorkerProcess
  • ProcessNameLength
  • pProcessName

Os sinalizadores a seguir são adicionados a DXGK_CREATEPROCESSFLAGS para dar suporte a processos de trabalho de máquinas virtuais e processos de VM:

  • VirtualMachineProcess
  • VirtualMachineWorkerProcess

DxgkDdiSetVirtualMachineData

DxgkDdiSetVirtualMachineData é adicionado ao Dxgkrnl para passar informações sobre uma máquina virtual para o KMD.

Mensagens de barramento de VM assíncronas para o host

Algumas mensagens de Dxgkrnl no sistema operacional convidado para o host são assíncronas. Essa abordagem melhora o desempenho de chamadas de API de Dxgkrnl de alta frequência no convidado. A sobrecarga de cada mensagem síncrona do barramento de VM para o host pode ser alta.

As mensagens assíncronas incluem:

Suporte ao LDA no GPU-PV

O LDA (adaptador de exibição vinculado) tem suporte no GPU-PV. Para garantir uma implementação consistente e dar suporte a possíveis futuras retrocompatibilidades com suporte a LDA para versões mais antigas do Windows, o KMD precisa verificar o suporte de LDA em GPU-PV chamando DxgkCbIsFeatureEnabled(DXGK_FEATURE_LDA_GPUPV). O suporte será habilitado se a função tiver êxito e retornar Habilitado. Se o KMD não fizer esse retorno de chamada, Dxgkrnl pressupõe que o KMD não dá suporte ao LDA no GPU-PV.

Se o sistema operacional der suporte ao recurso, cabe ao driver habilitar o LDA no modo de usuário. Se o driver habilitar o LDA no modo de usuário, ele deverá fazer isso da seguinte maneira.

Tempo de Execução Estado da LDA
Runtime pré-D3D12 Habilite se DXGK_FEATURE_LDA_GPUPV tiver suporte e o sistema operacional convidado for Windows 11, versão 22H2 (WDDM 3.1) ou posterior.
Runtimes não DirectX (Windows) Habilite se DXGK_FEATURE_LDA_GPUPV tiver suporte e o sistema operacional convidado for Windows 11, versão 22H2 (WDDM 3.1) ou posterior. Em vez de verificar a versão do sistema operacional, o UMD pode chamar D3DKMTQueryAdapterInfo(KMTQAITYPE_PHYSICALADAPTERCOUNT) e habilitar o LDA quando retornar o número de adaptadores físicos maior que 1.
Runtime D3D12 (Windows) Habilitar. Consulte Definir o estado do LDA para o runtime D3D12.
Linux (runtime d3d12 e não DX) Habilite se houver suporte para DXGK_FEATURE_LDA_GPUPV.

Os drivers compilados com uma versão de interface inferior à DXGKDDI_INTERFACE_VERSION_WDDM3_0 não verificam DXGK_FEATURE_LDA_GPUPV. Esses drivers ainda podem habilitar o LDA para runtimes do Linux.

Definir o estado do LDA para o runtime D3D12

Ao habilitar ou desabilitar o LDA para o runtime D3D12, o UMD precisa retornar as informações de mapa de camada e nó corretas para o runtime. O fluxo de código é o seguinte:

  • D3D12 obtém o limite de D3D12_CROSS_NODE_SHARING_TIER do UMD.

  • D3D12 obtém a contagem de adaptadores físicos de Dxgkrnl chamando D3DKMTQueryAdapterInfo(KMTQAITYPE_PHYSICALADAPTERCOUNT).

  • D3D12 chama pfnQueryNodeMap(PhysicalAdapterCount, &map) para obter o mapeamento de índices de nós lógicos para nós físicos. Neste contexto, "nó" significa "adaptador físico". O UMD precisa definir o índice do adaptador físico real no mapa ou D3D12DDI_NODE_MAP_HIDE_NODE para desabilitar um nó.

  • Baseado nos resultados do pfnQueryNodeMap, o D3D12 calcula a contagem efetiva do adaptador físico sem contar os nós ocultos.

  • Se o estado da camada e a contagem efetiva do adaptador físico não corresponderem, D3D12 falha na criação do dispositivo. A incompatibilidade acontece quando:

    • A camada é D3D12DDI_CROSS_NODE_SHARING_TIER_NOT_SUPPORTED e a contagem de adaptadores é maior que 1.
    • A camada não é D3D12DDI_CROSS_NODE_SHARING_TIER_NOT_SUPPORTED e a contagem de adaptadores é 1.

Para desabilitar o LDA, o UMD precisa retornar a camada D3D12DDI_CROSS_NODE_SHARING_TIER_NOT_SUPPORTED e manter apenas um adaptador físico habilitado no mapa de nós.

D3DKMTQueryAdapterInfo(KMTQAITYPE_PHYSICALADAPTERCOUNT)

Uma consulta a KMTQAITYPE_PHYSICALADAPTERCOUNT para a contagem do adaptador físico sempre retorna a contagem correta do adaptador físico para o convidado:

  • Em convidados pré-Windows 11 versão 22H2, ele retorna 1. Esse valor é codificado de forma fixa no código do convidado. Isso poderá mudar no futuro se o suporte ao LDA for portado para versões mais antigas do sistema operacional.
  • No Windows 11, versão 22H2 e sistemas posteriores, ele retorna:

Inicialização da paravirtualização

Habilite o suporte à virtualização no BIOS (VT-d ou similar). A configuração de GPU-PV é diferente para as máquinas virtuais do VMMS e para os contêineres.

No PowerShell (em execução como Administrador), habilite a execução de script no servidor:

set-executionpolicy unrestricted

Configuração da máquina virtual do VMMS

Configurando o host e a VM

O build do sistema operacional na VM pode ser mais antigo ou mais recente do que o build do sistema operacional no host.

  1. Habilite o recurso Hyper-V nas funções de servidor ou no recurso Hyper-V no cliente. Ao habilitar esse recurso no servidor, selecione a opção para usar o adaptador de rede como o comutador Externo.

  2. (opcional) Habilitar a assinatura de teste (bcdedit -set TESTSIGNING ON)

  3. Reinicializar.

  4. Instale um driver de GPU que dê suporte à para virtualização.

  5. (opcional) Alguns drivers não definem o limite de ParavirtualizationSupported. Nesse caso, adicione o registro a seguir antes de instalar o driver ou desabilitar/habilitar o dispositivo depois que o sinalizador for definido.

    DWORD HKLM\System\CurrentControlSet\Control\GraphicsDrivers\GpuVirtualizationFlags = 1   
    
  6. Para verificar se o sistema operacional reconhece a GPU paravirtualizada, execute o seguinte comando do PowerShell:

    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. Execute os comandos a seguir no PowerShell para criar uma VM com GPU. Uma VM chamada TEST é criada.

    $vm = “TEST“
    New-VM -VMName $vm -Generation 2
    Set-VM -GuestControlledCacheTypes $true -VMName $vm
    
  8. Defina o espaço de E/S para a VM. GPU-PV usa espaço de entrada/saída para lidar com alocações que são visíveis pela CPU. Pelo menos 8 GB de espaço de E/S são necessários.

    Set-VM -LowMemoryMappedIoSpace 1GB -VMName $vm
    Set-VM -HighMemoryMappedIoSpace 16GB -VMName $vm
    
  9. [opcional] Por padrão, o endereço base do espaço de E/S de memória alta é definido como (64 GB - 512 MB). Em chipsets Haswell com endereçamento de memória física de 36 bits, o endereço final da região de espaço de E/S precisa estar abaixo de 64 GB, portanto, o endereço inicial precisa ser definido adequadamente. O script a seguir, chamado SetHighMmioBase.ps1, define o endereço inicial como 47 GB quando executado com os seguintes parâmetros:

    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. Adicione uma GPU virtual à VM e desabilite os pontos de verificação.

    Add-VMGpuPartitionAdapter -VMName $vm
    Set-VM -CheckpointType Disabled -VMName $vm
    
  11. Para verificar se a VM tem uma GPU paravirtualizada, execute o seguinte comando:

    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. Copie o VHDX do mesmo build de cliente que você usa na VM para um diretório de host. Por exemplo, d:\VM\os.vhdx.

  13. Abra Hyper-V gerenciador e modifique os parâmetros da VM (selecione VM e selecione Configurações):

    • Segurança - Desmarque a opção habilitar inicialização segura.
    • Memória – Marque Habilitar Memória Dinâmica. Defina a quantidade de memória como 1.024 MB ou mais.
    • Processador – Defina Número de processadores virtuais como 2 ou 4.
    • Adaptador de rede – Selecione o adaptador de rede a ser usado com a VM na caixa de saída. Se a depuração de rede estiver habilitada, escolha o adaptador de Depuração NET da Microsoft.
    • Controlador SCSI – Disco Rígido – Adicionar – Disco Rígido Virtual – Procurar – Selecionar d:\VM\os.vhdx
  14. O sistema operacional copia os arquivos do armazenamento de driver do host para o diretório HostDriverStore na máquina convidada quando o adaptador é inicializado na máquina convidada.

    • Monte o VHDX da VM. Por exemplo, para o disco f:.
    • Na VM montada, crie um diretório chamado f:\%windir%\system32\HostDriverStore\FileRepository.
    • Replique arquivos de driver de %windir%\system32\DriverStore no host para a VM. Deve haver f:\%windir%\system32\HostDriverStore\FileRepository\YourDriverDirectory\* na VM.
  15. Se o driver precisar acessar arquivos de %windir%\system32 ou %windir%\syswow64, copie manualmente os arquivos para a VM.

  16. Habilite a assinatura de teste na VM se os drivers não estiverem assinados pela Microsoft. Na janela administrador do CMD, execute o seguinte comando:

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

    Desmonte o VHDX da VM.

  17. Inicie a VM.

  18. Conecte-se à VM usando a opção Hyper-V manager Connect.

DENTRO DA VM

Verifique se há um Dispositivo de Renderização Virtual no gerenciador de dispositivos da VM. Toda a renderização dentro da VM passa pela GPU virtual.

Script do PowerShell para configurar uma VM

O script do PowerShell a seguir é um exemplo de como configurar uma VM do zero. Modifique-o para atender às suas necessidades.


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
}

Depurar a Máquina Virtual

Configure o depurador de VM da mesma maneira que a depuração de rede em um computador cliente regular.

Se a VM não for iniciada ou você vir uma tela preta:

  • Desative a VM e remova a GPU virtual dela usando os seguintes comandos:

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

    Por exemplo:

    remove-VMGpuPartitionAdapter  -VMName $vm -AdapterId “Microsoft:9ABB95E2-D12D-43C3-B840-6F4A9CFB217B\929890BC-BB33-4687-BC1A-F72A4F1B3B3F”
    
  • Inicie a VM. Se ele for iniciado com êxito, verifique se os arquivos de driver são copiados corretamente para o HostDriverStore na VM.

  • Adicione vGPU à VM usando o comando Add-VMGpuPartitionAdapter.

  • Inicie a VM novamente.

Consulte Solução de Problemas para obter informações adicionais.

Configuração do contêiner

A diferença entre contêineres (também chamados VMs do HCS (Host Compute System) e a VM completa é que os binários do sistema operacional e os arquivos do repositório de driver são mapeados para o contêiner. Portanto, não é necessário copiar os arquivos de driver para o contêiner, a menos que sejam necessários no diretório windows\system32.

Para contêineres seguros:

  • Os escapes do driver estão desabilitados.
  • O driver deve dar suporte ao isolamento IOMMU para que seja habilitado dentro de um contêiner seguro.

Quando você atualiza o driver no host e inicia ou interrompe a GPU do host, as alterações são refletidas no contêiner.

Área Restrita do Windows

Esse tipo de contêiner é usado para experimentar aplicativos arriscados. A imagem completa da área de trabalho é transmitida remotamente para o host. O Driver de Exibição Indireto é usado para comunicação remota. O Graphics VAIL não é usado, portanto, a transferência da imagem da área de trabalho para o host é lenta.

A GPU virtual está desabilitada por padrão na Área Restrita do Windows. Para habilitá-lo, crie um arquivo de configuração do WSB (por exemplo, config.wsb) e defina a opção gpu virtual. Inicie o Sandbox clicando no arquivo de configuração.

Exemplo do arquivo de configuração:

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

Por padrão, a vGPU no contêiner tem escapes de driver desabilitados. Há uma opção de configuração para habilitar escapes do driver. O seguinte exemplo de arquivo WSB habilita tanto a vGPU na área restrita quanto os escapes do driver:

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

O Windows Sandbox oferece suporte ao adaptador de GPU 'hot plug'.

Contêiner VAIL (Virtual Application Integrated Locally)

Use esse tipo de contêiner para executar aplicativos Win32 dentro de um host baseado em WCOS (Windows Core Operated System). A imagem de cada aplicativo no contêiner é remota para o host. A funcionalidade VAIL para gráficos está ativada para permitir a troca remota de cada cadeia de troca de aplicativo. Os escapes de driver estão habilitados.

Requisitos comuns de contêiner

Os requisitos do computador são:

  • O Vtx e o Vtd devem ser habilitados no BIOS (ou seus equivalentes: AMD-V, AMD-IOMMU).
  • Pelo menos 8 GB de RAM.
  • Mais de 5 GB de espaço em disco do sistema.

Configurando o depurador de kernel para o Windows Sandbox

Usar o CMDIAG

Um serviço do Gerenciador de Contêineres (cmservice) controla contêineres Hyper-V isolados. CMDIAG.EXE é um aplicativo que está disponível quando você instala as funcionalidades Hyper-V e Contêineres. Ele habilita a depuração no modo kernel para contêineres, habilita a assinatura de teste e muito mais.

O Gerenciador de Contêineres suporta a depuração serial e de rede.

Execute cmdiag.exe Debug para ver as opções.

CMDIAG modifica as configurações do depurador na imagem base do contêiner. Deve haver apenas uma instância de um contêiner em execução quando o depurador de kernel estiver habilitado.

Interrompa o serviço HVSICS antes de alterar as configurações do depurador.


# 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

Executar o depurador em um computador diferente

Ao usar o depurador serial, pode ser interessante executá-lo em outro computador. Use kdsrv.exe para executar o depurador em um computador diferente. Para obter mais informações, consulte Servidores de Conexão KD.

Para desabilitar os tempos limite durante a depuração do kernel, defina as seguintes chaves de registro:

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

Configurar o depurador de kernel para o contêiner VAIL

  • Conecte-se ao host usando telnet. Você pode obter o endereço IP do host nas Configurações de Rede no sistema operacional host.
  • Use cmdiag.exe para configurar o depurador.

Configurando o depurador do Hipervisor

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

Solução de Problemas

Esta seção fornece informações sobre como solucionar problemas com GPU-PV.

Get-VMHostPartitionableGpu

Chame Get-VMHostPartitionableGpu para ver se há uma GPU virtualizada. Se a saída estiver vazia, haverá um erro em algum lugar (o driver não definiu o limite de virtualização, a virtualização não está habilitada etc.).

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

Usando eventos ETW

Dxgkrnl tem canais de administração e operacionais para eventos ETW. Os eventos são mostrados no Visualizador de Eventos do Windows: Log de Aplicativos e Serviços – Microsoft – Windows – Dxgkrnl.

O Visualizador de Eventos tem eventos de outros componentes que participam da criação de uma VM com GPU-PV (Hyper-V-Compute, Hyper-V-Worker, Hyper-V-VID etc.).

Usar Add-VMGpuPartitionAdapter

Ao usar Add-VMGpuPartitionAdapter, não especifique um recurso (por exemplo, decodificar) se não for necessário. Não use 0 para essa funcionalidade.

Usar Remove-VMGpuPartitionAdapter

Se uma VM não for iniciada ou tiver problemas de renderização, tente remover a GPU virtual da VM usando Remove-VMGpuPartitionAdapter.

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

Impedir o início da VM durante a inicialização

set-vm -AutomaticStartAction Nothing -VmName TEST

Eventos do visualizador de eventos

Adicione eventos ao canal do visualizador de eventos para ajudar a identificar problemas com a inicialização do vGPU. Você pode encontrar os eventos em "Logs de Aplicativos e Serviços\Microsoft\Windows\Dxgkrnl". Os canais de eventos são Administração e Operacional.

Os eventos são emitidos quando:

  • a vGPU é criada
  • vGPU é destruído
  • O convidado abre um adaptador virtual

Os arquivos de evento estão em:

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

Verifique se um vGPU foi criado e se houve erros.

Configurações do Registro

GpuVirtualizationFlags

A chave do registro GpuVirtualizationFlags é usada para definir o comportamento de GPUs paravirtualizadas. A chave está localizada em:

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

Os bits a seguir são definidos:

bit Descrição
0x1 Force o limite de ParavirtualizationSupported para todos os adaptadores de hardware. Use esse bit neste host.
0x2 Force o limite ParavirtualizationSupported para BasicRender. Use esse bit neste host.
0x4 Force o modo de máquina virtual seguro, em que todas as máquinas virtuais serão tratadas como seguras. Nesse modo, há restrições no driver do modo de usuário. Por exemplo, o driver não pode usar chamadas Escape, por isso elas falharão. Use esse bit neste host.
0x8 Habilite o emparelhamento de adaptadores paravirtualizados com o adaptador apenas para exibição. Use esse bit na máquina virtual convidada. O emparelhamento está habilitado por padrão.

GuestIoSpaceSizeInMb

A chave do Registro GuestIoSpaceSizeInMb é usada para definir o tamanho do espaço de E/S convidado para GPUs virtuais, em megabytes. O valor padrão é 1.000 MB (1 GB). A chave está localizada em:

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

O espaço de E/S convidado atualmente implementa alocações visíveis à CPU. Um repositório de backup de alocação visível à CPU no host é fixado na memória e mapeado para o espaço de E/S convidado. No convidado, o endereço virtual do modo de usuário de alocação é girado para a região de espaço de E/S. Em alguns sistemas Haswell, a CPU tem endereços físicos de 36 bits. Hyper-V nesses sistemas tem espaço de E/S limitado.

Desabilitar o isolamento de IOMMU para máquinas virtuais seguras

Se um driver não oferecer suporte ao isolamento IOMMU, use a seguinte configuração de registro durante o desenvolvimento para desativar o isolamento do IOMMU.

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

Limitar o número de funções virtuais

Por padrão, o número de funções virtuais expostas por um adaptador que dá suporte à paravirtualização de GPU é 32. Esse número significa que o adaptador pode ser adicionado a 32 máquinas virtuais, supondo que cada VM tenha um adaptador.

Você pode usar a seguinte configuração do Registro para limitar o número de funções virtuais expostas.

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

Por exemplo, se você definir NumVirtualFunctions como 1, o adaptador poderá ser adicionado a apenas uma GPU uma vez. Essa configuração é útil quando um computador tem vários adaptadores de GPU que dão suporte a GPU-PV e você deseja atribuir cada adaptador a uma VM. Add-VMGpuPartitionAdapter não permite especificar qual adaptador adicionar. Portanto, se dois adaptadores forem adicionados a uma VM, ambos poderão obter o mesmo adaptador GPU-PV do host.

Atualizações de DDI do WDDM 2.4

As seguintes atualizações de DDI são feitas para dar suporte à paravirtualização de GPU no WDDM 2.4.

Limite de DXGK_VIDMMCAPS adicionado

A capacidade de ParavirtualizationSupported é adicionada à estrutura DXGK_VIDMMCAPS. O KMD do host definirá esse limite se implementar todos os DDIs descritos nesta seção.

Dados privados do driver passados pela DDI

O UMD usa vários DDIs para trocar informações privadas com seu KMD correspondente. Quando o UMD é executado na VM convidada, a chamada KMD DDI correspondente ocorre na partição do anfitrião. Portanto, o UMD:

  1. Não é possível passar ponteiros nos dados privados.
  2. Não é possível passar identificadores nos dados privados.
  3. Não deve instruir o KMD a fazer alterações globais do estado da GPU, pois essa alteração pode afetar outras VMs em execução.

Sinalizador VirtualMachineProcess adicionado para DxgkDdiCreateProcess

O sistema operacional cria um processo de trabalho de VM para cada VM em execução. Dxgkrnl cria um DXGPROCESS correspondente e chama DxgkDdiCreateProcess com o sinalizador VirtualMachineWorkerProcess definido. Não há nenhuma renderização ou criação de recursos de driver neste contexto de processo. Portanto, o driver pode ignorar a alocação de determinados recursos.

O sistema operacional cria um DXGPROCESS no host para cada processo em uma VM convidada que usa uma GPU. Dxgkrnl chama DxgkDdiCreateProcess com o sinalizador VirtualMachineProcess definido. Cada processo DXG da VM pertence ao mesmo EPROCESS que o processo de trabalho da VM.

Atualizações do DxgkDdiQueryAdapterInfo

A estrutura DXGKARG_QUERYADAPTERINFO é atualizada para incluir os seguintes campos para suporte à paravirtualização:

  • O membro Flags é adicionado, o que permite que o Dxgkrnl indique o seguinte:

    • Ele define VirtualMachineData para indicar que a chamada vem de uma VM.
    • Ele define SecureVirtualMachine para indicar que a VM é executada no modo seguro.
  • hKmdProcessHandle é adicionado, o que permite que o driver identifique e use o contexto de processo correto no lado do host ao lidar com consultas originadas de uma VM convidada.

Atualizações do DxgkDdiEscape

O membro hKmdProcessHandle é adicionado à estrutura DXGKARG_ESCAPE para permitir que o driver identifique e use o contexto de processo correto no lado do host ao manipular escapes provenientes de uma máquina virtual convidada.

O sinalizador VirtualMachineData é adicionado à estrutura D3DDDI_ESCAPEFLAGS para indicar que DxgkDdiEscape é chamado de uma máquina virtual.

Acesso físico a alocações de GPU

Atualmente, o driver não implementa o acesso físico às alocações. O driver deve dar suporte a GpuMmu.

Atualizações de DDI do WDDM 2.5

Para o WDDM 2.5, as seguintes alterações de DDI também são necessárias para suporte à paravirtualização.

Sinalização de eventos de convidados pelo KMD do host

Há cenários que existem sem virtualização quando o KMD precisa sinalizar um evento criado por um UMD. Para lidar com esses cenários quando a paravirtualização está sendo usada, o KMD no host precisa sinalizar um evento criado no convidado. O retorno de chamada DxgkCbSignalEvent é adicionado para essa finalidade. O KMD também pode usar esse retorno de chamada para sinalizar eventos dos processos do host.

Suporte para identificadores fornecidos por UMD em uma VM

Determinados retornos de chamada de driver aceitam um identificador de alocação ou recurso do Dxgkrnl que o UMD passa, tal como:

As chamadas no host devem estar no contexto do mesmo thread que chamou uma função DxgkDdixxx.

Por exemplo, suponha que, sem virtualização, o KMD chame DxgkCbAcquireHandleData no contexto do thread em modo de usuário que chama D3DKMTEscape, que chama DxgkDdiEscape.

Quando o UMD é executado em uma máquina virtual, ele sabe apenas os identificadores de alocação de convidado e não pode passar esses identificadores para o KMD porque o KMD é executado no host. O UMD nas chamadas de convidado D3DKMTEscape e o KMD no host recebe a chamada DxgkDdiEscape correspondente. O KMD precisa chamar DxgkCbAcquireHandleData no contexto desse thread.

Para traduzir o identificador de alocação/recurso de convidado para o identificador de host correspondente, é adicionado o sinalizador de escape do driver D3DDDI_ESCAPEFLAGS::DriverKnownEscape.

Quando você chama D3DKMTEscape com o sinalizador DriverKnownEscape definido:

  • Defina D3DKMT_ESCAPE::Type como D3DKMT_ESCAPE_DRIVERPRIVATE.

  • Defina D3DKMT_ESCAPE::pPrivateDriverData para apontar para uma estrutura de escape de driver conhecida, definida na seção a seguir. Cada estrutura começa com um valor D3DDDI_DRIVERESCAPETYPE.

Quando a virtualização não é usada, o identificador traduzido é o mesmo que o identificador de entrada.

Os escapes de driver conhecidos a seguir são definidos.

O trecho de código a seguir mostra como usar o sinalizador DriverKnownEscape.

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);

Atualizações de DDI do WDDM 2.6

A partir do WDDM 2.6 (Windows 10, versão 1903), foram feitas as seguintes atualizações para suporte à paravirtualização: