Compartilhar via


Interface de hiperchamada

O hipervisor fornece um mecanismo de chamada para convidados. Essas chamadas são conhecidas como hiperchamadas. Cada hiperchamada define um conjunto de parâmetros de entrada e/ou saída. Esses parâmetros são especificados em termos de uma estrutura de dados baseada em memória. Todos os elementos das estruturas de dados de entrada e saída são adicionados a limites naturais de até 8 bytes (ou seja, elementos de dois bytes devem estar em limites de dois bytes e assim por diante).

Opcionalmente, uma segunda convenção de chamada de hiperchamada pode ser usada para um subconjunto de hiperchamas– em particular, aquelas que têm dois ou menos parâmetros de entrada e nenhum parâmetro de saída. Ao usar essa convenção de chamada, os parâmetros de entrada são passados em registros de uso geral.

Opcionalmente, uma terceira convenção de chamada de hiperchamada pode ser usada para um subconjunto de hiperchamas em que o bloco de parâmetro de entrada é de até 112 bytes. Ao usar essa convenção de chamada, os parâmetros de entrada são passados em registros, incluindo os registros voláteis do XMM.

As estruturas de dados de entrada e saída devem ser colocadas na memória em um limite de 8 bytes e adicionadas a um múltiplo de 8 bytes de tamanho. Os valores dentro das regiões de preenchimento são ignorados pelo hipervisor.

Para a saída, o hipervisor tem permissão para (mas não é garantido) substituir regiões de preenchimento. Se substituir regiões de preenchimento, ele gravará zeros.

Classes de hiperchamada

Há duas classes de hiperchamas: simples e rep (abreviação de "repeat"). Uma hiperchamada simples executa uma única operação e tem um conjunto de tamanho fixo de parâmetros de entrada e saída. Uma hiperchamada de representante age como uma série de hiperchamas simples. Além de um conjunto de tamanho fixo de parâmetros de entrada e saída, as hiperchamadas de rep envolvem uma lista de elementos de entrada e/ou saída de tamanho fixo.

Quando um chamador inicialmente invoca uma hiperchamada de representante, ele especifica uma contagem de representantes que indica o número de elementos na lista de parâmetros de entrada e/ou saída. Os chamadores também especificam um índice de início de rep que indica o próximo elemento de entrada e/ou saída que deve ser consumido. O hipervisor processa parâmetros de representante na ordem de lista, ou seja, aumentando o índice de elementos.

Para invocações subsequentes da hiperchamada de rep, o índice de início do rep indica quantos elementos foram concluídos – e, em conjunto com o valor de contagem de representantes – quantos elementos restam. Por exemplo, se um chamador especificar uma contagem de representantes de 25 e apenas 20 iterações forem concluídas dentro das restrições de tempo, a hiperchamada retornará o controle para o processador virtual de chamada depois de atualizar o índice de início do rep para 20. Quando a hiperchamada for executada novamente, o hipervisor será retomado no elemento 20 e concluirá os 5 elementos restantes.

Se um erro for encontrado ao processar um elemento, um código de status apropriado será fornecido juntamente com uma contagem concluída de representantes, indicando o número de elementos que foram processados com êxito antes do erro ser encontrado. Supondo que a palavra de controle de hiperchamada especificada seja válida (veja o seguinte) e as listas de parâmetros de entrada/saída estiverem acessíveis, o hipervisor tem a garantia de tentar pelo menos um representante, mas não é necessário processar toda a lista antes de retornar o controle de volta ao chamador.

Continuação de Hiperchamada

Uma hiperchamada pode ser considerada como uma instrução complexa que leva muitos ciclos. O hipervisor tenta limitar a execução de hiperchamada a 50μs ou menos antes de retornar o controle para o processador virtual que invocou a hiperchamada. Algumas operações de hiperchamada são suficientemente complexas que uma garantia de 50μs é difícil de fazer. Portanto, o hipervisor depende de um mecanismo de continuação de hiperchamada para algumas hiperchamas, incluindo todos os formulários de hiperchamada de representante.

O mecanismo de continuação de hiperchamada é principalmente transparente para o chamador. Se uma hiperchamada não for capaz de ser concluída dentro do limite de tempo prescrito, o controle será retornado para o chamador, mas o ponteiro de instrução não será avançado após a instrução que invocou a hiperchamada. Isso permite que interrupções pendentes sejam tratadas e outros processadores virtuais sejam agendados. Quando o thread de chamada original retomar a execução, ele executará novamente a instrução de hiperchamada e avançará para concluir a operação.

A maioria das hiperchamadas simples tem a garantia de ser concluída dentro do limite de tempo prescrito. No entanto, um pequeno número de hiperchamas simples pode exigir mais tempo. Essas hiperchamações usam a continuação de hiperchamada de maneira semelhante às hiperchamações de rep. Nesses casos, a operação envolve dois ou mais estados internos. A primeira invocação coloca o objeto (por exemplo, a partição ou processador virtual) em um estado e, após invocações repetidas, o estado finalmente faz a transição para um estado terminal. Para cada hiperchamada que segue esse padrão, os efeitos colaterais visíveis dos estados internos intermediários são descritos.

Atomicidade e ordenação de hiperchamada

Exceto quando observado, a ação executada por uma hiperchamada é atômica em relação a todas as outras operações de convidado (por exemplo, instruções executadas dentro de um convidado) e todas as outras hiperchamadas que estão sendo executadas no sistema. Uma hiperchamada simples executa uma única ação atômica; uma hiperchamada de rep executa várias ações atômicas independentes.

Hiperchamações simples que usam a continuação de hiperchamada podem envolver vários estados internos que são visíveis externamente. Essas chamadas compreendem várias operações atômicas.

Cada ação de hiperchamada pode ler parâmetros de entrada e/ou gravar resultados. As entradas para cada ação podem ser lidas em qualquer granularidade e a qualquer momento após a hiperchamada ser feita e antes que a ação seja executada. Os resultados (ou seja, os parâmetros de saída) associados a cada ação podem ser gravados em qualquer granularidade e a qualquer momento após a execução da ação e antes do retorno da hiperchamada.

O convidado deve evitar o exame e/ou a manipulação de quaisquer parâmetros de entrada ou saída relacionados a uma hiperchamada em execução. Embora um processador virtual executando uma hiperchamada seja incapaz de fazer isso (já que sua execução de convidado é suspensa até que a hiperchamada retorne), não há nada que impeça outros processadores virtuais de fazê-lo. Os convidados que se comportam dessa maneira podem falhar ou causar corrupção dentro de sua partição.

As hiperchamas só podem ser invocadas no modo de processador convidado mais privilegiado. Em plataformas x64, isso significa modo protegido com um CPL (nível de privilégio) atual de zero. Embora o código em modo real seja executado com uma CPL efetiva de zero, as hiperchamas não são permitidas no modo real. Uma tentativa de invocar uma hiperchamada dentro de um modo de processador ilegal gerará uma exceção #UD (operação indefinida) no x64 e uma exceção de instrução indefinida no ARM64.

Todas as hiperchamações devem ser invocadas por meio da interface de hiperchamada definida arquitetônica (veja abaixo). Uma tentativa de invocar uma hiperchamada por qualquer outro meio (por exemplo, copiar o código da página de código de hiperchamada para um local alternativo e executá-lo a partir daí) pode resultar em uma exceção de operação indefinida (#UD). Não há garantia de que o hipervisor forneça essa exceção.

Requisitos de alinhamento

Os chamadores devem especificar o GPA (endereço físico convidado) de 64 bits dos parâmetros de entrada e/ou saída. Os ponteiros de GPA devem estar alinhados com 8 bytes. Se a hiperchamada não envolver parâmetros de entrada ou saída, o hipervisor ignorará o ponteiro DE GPA correspondente.

As listas de parâmetros de entrada e saída não podem sobrepor ou cruzar limites de página. Espera-se que as páginas de entrada e saída de hiperchamada sejam páginas GPA e não páginas de "sobreposição". Se o processador virtual gravar os parâmetros de entrada em uma página de sobreposição e especificar um GPA nesta página, o acesso do hipervisor à lista de parâmetros de entrada será indefinido.

O hipervisor validará que a partição de chamada pode ler na página de entrada antes de executar a hiperchamada solicitada. Essa validação consiste em duas verificações: o GPA especificado é mapeado e o GPA é marcado como legível. Se um desses testes falhar, o hipervisor gerará uma mensagem de interceptação de memória. Para hiperchamas que têm parâmetros de saída, o hipervisor validará que a partição pode gravar na página de saída. Essa validação consiste em duas verificações: o GPA especificado é mapeado e o GPA é marcado como gravável.

Entradas de hiperchamada

Os chamadores especificam uma hiperchamada por um valor de 64 bits chamado de valor de entrada de hiperchamada. Ele é formatado da seguinte maneira:

Campo Bits Informações fornecidas
Código de chamada 15-0 Especifica qual hiperchamada é solicitada
Rápido 16 Especifica se a hiperchamada usa a convenção de chamada baseada em registro: 0 = baseada em memória, 1 = baseada em registro
Tamanho do cabeçalho variável 26-17 O tamanho de um cabeçalho de variável, em QWORDS.
RsvdZ 30-27 Deve ser zero
Está aninhado 31 Especifica que a hiperchamada deve ser tratada pelo hipervisor L0 em um ambiente aninhado.
Contagem de representantes 43-32 O número total de representantes (para chamada de representante, deve ser zero caso contrário)
RsvdZ 47-44 Deve ser zero
Índice de Início do Rep 59-48 Índice inicial (para chamada de representante, deve ser zero caso contrário)
RsvdZ 63-60 Deve ser zero

Para hiperchamações de representante, o campo contagem de representantes indica o número total de representantes. O índice de início do rep indica a repetição específica relativa ao início da lista (zero indica que o primeiro elemento na lista deve ser processado). Portanto, o valor da contagem de representantes deve ser sempre maior que o índice de início do rep.

Convenções de Registro de Hiperchamada (x86/x64)

No x86/x64, registre o mapeamento para entradas de hiperchamada quando o sinalizador Rápido for zero da seguinte maneira:

x64 x86 Informações fornecidas
RCX EDX:EAX Valor de entrada de hiperchamada
RDX EBX:ECX GPA de parâmetros de entrada
R8 EDI:ESI GPA de parâmetros de saída

O valor de entrada de hiperchamada é passado em registros junto com um GPA que aponta para os parâmetros de entrada e saída.

Os mapeamentos de registro dependem se o chamador está em execução no modo de 32 bits (x86) ou 64 bits (x64). O hipervisor determina o modo do chamador com base no valor de EFER. LMA e CS.L. Se ambos os sinalizadores estiverem definidos, o chamador será considerado um chamador de 64 bits.

Registre o mapeamento para entradas de hiperchamada quando o sinalizador Rápido for um:

x64 x86 Informações fornecidas
RCX EDX:EAX Valor de entrada de hiperchamada
RDX EBX:ECX Parâmetro de entrada
R8 EDI:ESI Parâmetro de saída

O valor de entrada de hiperchamada é passado em registros junto com os parâmetros de entrada.

Convenções de Registro de Hiperchamada (ARM64 SMCCC)

No ARM64, as hiperchamadas são executadas usando a instrução "HVC #0". As chamadas aderem ao ARM64 SMCCC (Convenção de Chamada do SMC).

O mapeamento de registro de entradas de hiperchamada é o seguinte:

Registrar-se Informações fornecidas
X0 Identificador de função SMCCC
X1 Valor de entrada de hiperchamada
X2 GPA de parâmetros de entrada
X3 GPA de parâmetros de saída

O Identificador de Função SMCCC em X0 segue este formato:

Bits Campo Value Description
31 Chamada de rendimento 0 Sempre 0
30 Convenção de chamada 1 1 para convenções de chamada HVC64
29:24 Tipo de Chamada de Serviço 6 6 para chamadas de serviço de hipervisor específicos do fornecedor
23:16 Reservado 0 Reservado, deve ser zero (Res0)
15:0 Número da função 1 1 indica que o código de chamada HV está definido em X1

O formato completo do Identificador de Função: 0x46000001

Convenções de Registro de Hiperchamada (ARM64 HVC #1)

Por motivos históricos, a interface do hipervisor ARM64 também dá suporte a uma convenção de chamada diferente. As hiperchamadas são executadas com a instrução "HVC #1". É recomendável usar a convenção de chamada SMCCC para novo código.

O mapeamento de registro de entradas de hiperchamada é o seguinte:

Registrar-se Informações fornecidas
X0 Valor de entrada de hiperchamada
X1 GPA de parâmetros de entrada
X2 GPA de parâmetros de saída

Cabeçalhos de entrada de hiperchamada de tamanho variável

A maioria dos cabeçalhos de entrada de hiperchamada tem tamanho fixo. A quantidade de dados de cabeçalho que estão sendo passados do convidado para o hipervisor é, portanto, implicitamente especificada pelo código de hiperchamada e não precisam ser especificadas separadamente. No entanto, algumas hiperchamas exigem uma quantidade variável de dados de cabeçalho. Essas hiperchamas normalmente têm um cabeçalho de entrada de tamanho fixo e entrada de cabeçalho adicional de tamanho variável.

Um cabeçalho de tamanho variável é semelhante a uma entrada de hiperchamada fixa (alinhada a 8 bytes e dimensionada a um múltiplo de 8 bytes). O chamador deve especificar quantos dados ele está fornecendo como cabeçalhos de entrada. Esse tamanho é fornecido como parte do valor de entrada de hiperchamada (consulte "Tamanho do cabeçalho variável" na tabela acima).

Como o tamanho do cabeçalho fixo é implícito, em vez de fornecer o tamanho total do cabeçalho, somente a parte variável é fornecida nos controles de entrada:

Variable Header Bytes = {Total Header Bytes - sizeof(Fixed Header)} rounded up to nearest multiple of 8

Variable Header Size = Variable Header Bytes / 8

É ilegal especificar um tamanho de cabeçalho de variável diferente de zero para uma hiperchamada que não está explicitamente documentada como aceitando cabeçalhos de entrada de tamanho variável. Nesse caso, a hiperchamada resultará em um código de retorno de HV_STATUS_INVALID_HYPERCALL_INPUT.

É possível que para uma determinada invocação de uma hiperchamada que aceite cabeçalhos de entrada de tamanho variável que toda a entrada de cabeçalho se ajuste inteiramente dentro do cabeçalho de tamanho fixo. Nesses casos, o cabeçalho de entrada de tamanho variável é de tamanho zero e os bits correspondentes na entrada de hiperchamada devem ser definidos como zero.

Em todos os outros aspectos, as hiperchamadas que aceitam cabeçalhos de entrada de tamanho variável são semelhantes às hiperchamadas de cabeçalho de entrada de tamanho fixo em relação às convenções de chamada. Também é possível que uma hiperchamada de cabeçalho com tamanho variável dê suporte adicional à semântica de rep. Nesse caso, os elementos de rep residem após o cabeçalho da maneira usual, exceto que o tamanho total do cabeçalho inclui as partes fixas e variáveis. Todas as outras regras permanecem as mesmas, por exemplo, o primeiro elemento rep deve ser alinhado a 8 bytes.

Entrada de hiperchamada rápida do XMM (x86/x64)

Em plataformas x86/x64, o hipervisor dá suporte ao uso de hiperchamadas rápidas do XMM, o que permite que algumas hiperchamadas aproveitem o desempenho aprimorado da interface de hiperchamada rápida, embora exijam mais de dois parâmetros de entrada. A interface de hiperchamada rápida do XMM usa seis registros XMM para permitir que o chamador passe um bloco de parâmetro de entrada de até 112 bytes de tamanho.

A disponibilidade da interface de hiperchamada rápida do XMM é indicada por meio da Folha de CPUID "Identificação de Recursos do Hipervisor" (0x40000003):

  • Bit 4: o suporte para passar entrada de hiperchamada por meio de registros XMM está disponível.

Observe que há um sinalizador separado para indicar suporte para saída rápida do XMM. Qualquer tentativa de usar essa interface quando o hipervisor não indicar disponibilidade resultará em uma falha de #UD.

Mapeamento de registro (somente entrada)

x64 x86 Informações fornecidas
RCX EDX:EAX Valor de entrada de hiperchamada
RDX EBX:ECX Bloco de parâmetro de entrada
R8 EDI:ESI Bloco de parâmetro de entrada
XMM0 XMM0 Bloco de parâmetro de entrada
XMM1 XMM1 Bloco de parâmetro de entrada
XMM2 XMM2 Bloco de parâmetro de entrada
XMM3 XMM3 Bloco de parâmetro de entrada
XMM4 XMM4 Bloco de parâmetro de entrada
XMM5 XMM5 Bloco de parâmetro de entrada

O valor de entrada de hiperchamada é passado em registros junto com os parâmetros de entrada. Os mapeamentos de registro dependem se o chamador está em execução no modo de 32 bits (x86) ou 64 bits (x64). O hipervisor determina o modo do chamador com base no valor de EFER. LMA e CS.L. Se ambos os sinalizadores estiverem definidos, o chamador será considerado um chamador de 64 bits. Se o bloco de parâmetro de entrada for menor que 112 bytes, todos os bytes extras nos registros serão ignorados.

Registrar entrada de chamada rápida (ARM64 SMCCC)

Nas plataformas ARM64, o hipervisor dá suporte ao uso de hiperchamadas rápidas de registro, o que permite que algumas hiperchamadas aproveitem o desempenho aprimorado da interface de hiperchamada rápida, embora exijam mais de dois parâmetros de entrada. A interface de hiperchamada rápida de registro usa 16 registros de finalidade geral para permitir que o chamador passe um bloco de parâmetro de entrada de até 128 bytes de tamanho.

Mapeamento de registro (somente entrada)

Registrar-se Informações fornecidas
X0 Identificador de função SMCCC
X1 Valor de entrada de hiperchamada
X2 – X17 Bloco de parâmetro de entrada

Se o bloco de parâmetro de entrada for menor que 128 bytes, todos os bytes extras nos registros serão ignorados.

Registrar entrada de chamada rápida (ARM64 HVC #1)

A interface de hiperchamada rápida de registro usa dezesseis registros de finalidade geral para permitir que o chamador passe um bloco de parâmetro de entrada de até 128 bytes de tamanho.

Mapeamento de registro (somente entrada)

Registrar-se Informações fornecidas
X0 Valor de entrada de hiperchamada
X1 – X17 Bloco de parâmetro de entrada

Se o bloco de parâmetro de entrada for menor que 128 bytes, todos os bytes extras nos registros serão ignorados.

Saídas de hiperchamada

Todas as hiperchamas retornam um valor de 64 bits chamado de valor de resultado de hiperchamada. Ele é formatado da seguinte maneira:

Campo Bits Comment
Resultado 15-0 HV_STATUS código que indica êxito ou falha
Rsvd 31-16 Os chamadores devem ignorar o valor nesses bits
Representantes concluídos 43-32 Número de representantes concluídos com êxito
RsvdZ 63-40 Os chamadores devem ignorar o valor nesses bits

Para hiperchamações de rep, o campo de reps complete é o número total de representantes concluído e não relativo ao índice de início do rep. Por exemplo, se o chamador especificasse um índice de início de repositório de 5 e uma contagem de representantes de 10, o campo completo dos representantes indicaria 10 após a conclusão bem-sucedida.

O valor do resultado da hiperchamada é passado novamente nos registros.

No x64, o mapeamento de registro depende se o chamador está em execução no modo de 32 bits (x86) ou 64 bits (x64) (consulte acima). O mapeamento de registro para saídas de hiperchamada é o seguinte:

x64 x86 Informações fornecidas
RAX EDX:EAX Valor do resultado da hiperchamada

No ARM64, o mapeamento de registro para saídas de hiperchamada é o seguinte:

Registrar-se Informações fornecidas
X0 Valor do resultado da hiperchamada

Saída de hiperchamada rápida do XMM (x86/x64)

Semelhante a como o hipervisor dá suporte a entradas de hiperchamada rápidas do XMM, os mesmos registros podem ser compartilhados para retornar a saída. Isso só tem suporte em plataformas x64.

A capacidade de retornar a saída por meio de registros XMM é indicada por meio da Folha de CPUID "Identificação de Recursos do Hipervisor" (0x40000003):

  • Bit 15: o suporte para retornar a saída de hiperchamada por meio de registros XMM está disponível.

Observe que há um sinalizador separado para indicar suporte para entrada rápida do XMM. Qualquer tentativa de usar essa interface quando o hipervisor não indicar disponibilidade resultará em uma falha de #UD.

Mapeamento de registro (entrada e saída)

Os registros que não estão sendo usados para passar parâmetros de entrada podem ser usados para retornar a saída. Em outras palavras, se o bloco de parâmetro de entrada for menor que 112 bytes (arredondado até a parte alinhada de 16 bytes mais próxima), os registros restantes retornarão a saída de hiperchamada.

x64 Informações fornecidas
RDX Bloco de entrada ou saída
R8 Bloco de entrada ou saída
XMM0 Bloco de entrada ou saída
XMM1 Bloco de entrada ou saída
XMM2 Bloco de entrada ou saída
XMM3 Bloco de entrada ou saída
XMM4 Bloco de entrada ou saída
XMM5 Bloco de entrada ou saída

Por exemplo, se o bloco de parâmetro de entrada tiver 20 bytes de tamanho, o hipervisor ignorará os 12 bytes a seguir. Os 80 bytes restantes conterão saída de hiperchamada (se aplicável).

Registrar saída de chamada rápida (ARM64 SMCCC)

Em plataformas ARM64, semelhante à forma como o hipervisor dá suporte ao registro de entradas de hiperchamada rápidas, os mesmos registros podem ser compartilhados para retornar a saída.

Mapeamento de registro (entrada e saída)

Os registros que não estão sendo usados para passar parâmetros de entrada podem ser usados para retornar a saída. Em outras palavras, se o bloco de parâmetro de entrada for menor que 128 bytes (arredondado até a parte alinhada de 8 bytes mais próxima), os registros restantes retornarão a saída de hiperchamada.

Registrar-se Informações fornecidas
X2 – X17 Bloco de entrada ou saída

Por exemplo, se o bloco de parâmetro de entrada tiver 20 bytes de tamanho, o hipervisor ignorará os 4 bytes a seguir. Os 104 bytes restantes conterão saída de hiperchamada (se aplicável).

Registrar saída de chamada rápida (ARM64 HVC #1)

Semelhante às versões do SMCCC, a interface HVC nº 1 usa os mesmos registros para retornar a saída.

Mapeamento de registro (entrada e saída)

Os registros que não estão sendo usados para passar parâmetros de entrada podem ser usados para retornar a saída. Em outras palavras, se o bloco de parâmetro de entrada for menor que 128 bytes (arredondado até a parte alinhada de 8 bytes mais próxima), os registros restantes retornarão a saída de hiperchamada.

Registrar-se Informações fornecidas
X1 – X17 Bloco de entrada ou saída

Por exemplo, se o bloco de parâmetro de entrada tiver 20 bytes de tamanho, o hipervisor ignorará os 4 bytes a seguir. Os 104 bytes restantes conterão saída de hiperchamada (se aplicável).

Registros voláteis (x86/x64)

As hiperchamadas modificarão apenas os valores de registro especificados nas seguintes condições:

  1. RAX (x64) e EDX:EAX (x86) são sempre substituídos com os parâmetros de saída e valor de resultado de hiperchamada, se houver.
  2. As hiperchamadas de rep modificarão RCX (x64) e EDX:EAX (x86) com o novo índice de início de rep.
  3. HvCallSetVpRegisters pode modificar todos os registros com suporte com essa hiperchamada.
  4. RDX, R8 e XMM0 a XMM5, quando usados para entrada de hiperchamada rápida, permanecem não modificados. No entanto, os registros usados para saída de hiperchamada rápida podem ser modificados, incluindo RDX, R8 e XMM0 a XMM5. Hyper-V modificará apenas esses registros para uma saída de hiperchamada rápida, que é limitada a x64.

Registros Voláteis (ARM64 SMCCC)

As hiperchamadas modificarão apenas os valores de registro especificados nas seguintes condições:

  1. X0 é sempre substituído com o valor do resultado da hiperchamada e parâmetros de saída, se houver.
  2. As hiperchamações de rep modificarão X1 com o novo índice de início de rep.
  3. HvCallSetVpRegisters pode modificar todos os registros com suporte com essa hiperchamada.
  4. X2 – X17, quando usado para entrada de hiperchamada rápida, permanece não modificado. No entanto, os registros usados para saída de hiperchamada rápida podem ser modificados, incluindo X2 - X17. Hyper-V modificará apenas esses registros para uma saída de hiperchamada rápida.

Registros voláteis (ARM64 HVC #1)

As hiperchamadas modificarão apenas os valores de registro especificados nas seguintes condições:

  1. X0 é sempre substituído com o valor do resultado da hiperchamada e parâmetros de saída, se houver.
  2. As hiperchamações de rep modificarão X0 com o novo índice de início do rep.
  3. HvCallSetVpRegisters pode modificar todos os registros com suporte com essa hiperchamada.
  4. X1 – X17, quando usado para entrada de hiperchamada rápida, permanece não modificado. No entanto, os registros usados para saída de hiperchamada rápida podem ser modificados, incluindo X1 - X17. Hyper-V modificará apenas esses registros para uma saída de hiperchamada rápida.

Restrições de hiperchamada

As hiperchamas podem ter restrições associadas que devem ser satisfeitas para que elas executem a função pretendida. Se todas as restrições não forem atendidas, a hiperchamada terminará com um erro apropriado. As seguintes restrições serão listadas, se houver alguma aplicação:

  • A partição de chamada deve ter um privilégio específico
  • A partição que está sendo executada deve estar em um estado específico (por exemplo, "Ativo")

Códigos de status de hiperchamada

Cada hiperchamada é documentada como retornando um valor de saída que contém vários campos. Um campo de valor de status (do tipo HV_STATUS) é usado para indicar se a chamada foi bem-sucedida ou falhou.

Validade do parâmetro de saída em hiperchamações com falha

A menos que explicitamente declarado de outra forma, quando uma hiperchamada falha (ou seja, o campo de resultado do valor do resultado da hiperchamada contém um valor diferente HV_STATUS_SUCCESS), o conteúdo de todos os parâmetros de saída é indeterminado e não deve ser examinado pelo chamador. Somente quando a hiperchamada for bem-sucedida, todos os parâmetros de saída apropriados conterão resultados válidos e esperados.

Ordenação de condições de erro

A ordem na qual as condições de erro são detectadas e relatadas pelo hipervisor é indefinida. Em outras palavras, se houver vários erros, o hipervisor deverá escolher qual condição de erro relatar. A prioridade deve ser dada a esses códigos de erro que oferecem maior segurança, a intenção é impedir que o hipervisor revele informações aos chamadores sem privilégio suficiente. Por exemplo, o código HV_STATUS_ACCESS_DENIED de status é o código de status preferencial em vez de um que revelaria algumas informações de contexto ou estado puramente com base no privilégio.

Códigos comuns de status de hiperchamada

Vários códigos de resultado são comuns a todas as hiperchamadas e, portanto, não são documentados para cada hiperchamada individualmente. Estes incluem o seguinte:

Código de status Condição de erro
HV_STATUS_SUCCESS A chamada foi bem-sucedida.
HV_STATUS_INVALID_HYPERCALL_CODE O código de hiperchamada não é reconhecido.
HV_STATUS_INVALID_HYPERCALL_INPUT A contagem de representantes está incorreta (por exemplo, uma contagem de representantes diferente de zero é passada para uma chamada não representante ou uma contagem de representante zero é passada para uma chamada de representante).
O índice de início do rep não é menor que a contagem de representantes.
Um bit reservado no valor de entrada de hiperchamada especificado não é zero.
HV_STATUS_INVALID_ALIGNMENT O ponteiro GPA de entrada ou saída especificado não está alinhado a 8 bytes.
As listas de parâmetros de entrada ou saída especificadas abrangem páginas.
O ponteiro GPA de entrada ou saída não está dentro dos limites do espaço gpa.

O código HV_STATUS_SUCCESS de retorno indica que nenhuma condição de erro foi detectada.

Relatando a identidade do sistema operacional convidado

O sistema operacional convidado em execução na partição deve identificar-se ao hipervisor gravando sua assinatura e versão em um MSR (HV_X64_MSR_GUEST_OS_ID/HvRegisterGuestOsId) antes de poder invocar hiperchamamentos. Essa MSR é de todo o particionamento e é compartilhada entre todos os processadores virtuais.

O valor desse registro é inicialmente zero.

No x86/x64, um valor diferente de zero deve ser gravado no MSR da ID do so convidado antes que a página de código de hiperchamada possa ser habilitada (consulte Estabelecendo a interface de hiperchamada (x86/x64)). Se esse registro for posteriormente zerado, a página de código de hiperchamada será desabilitada.

No ARM64, um valor diferente de zero deve ser gravado no MSR da ID do so convidado antes que os códigos de hiperchamada possam ser invocados. A exceção é as hiperchamadas HvCallSetVpRegisters/HvCallGetVpRegisters . Consulte a respectiva documentação para obter mais informações.

#define HV_X64_MSR_GUEST_OS_ID 0x40000000
#define HvRegisterGuestOsId 0x00090002

No ARM64, há suporte apenas para HvRegisterGuestOsId, que deve ser gravado usando a hiperchamada HvCallSetVpRegisters no processador de inicialização.

Identidade do sistema operacional convidado para sistemas operacionais proprietários

Veja a seguir a codificação recomendada para essa MSR. Alguns campos podem não se aplicar a alguns OSs convidados.

Bits Campo Description
15:0 Número da Compilação Indica o número de build do sistema operacional
23:16 Versão do serviço Indica a versão do serviço (por exemplo, o número do "service pack")
31:24 Versão Menor Indica a versão secundária do sistema operacional
39:32 Versão Principal Indica a versão principal do sistema operacional
47:40 ID do sistema operacional Indica a variante do sistema operacional. A codificação é exclusiva do fornecedor. Os sistemas operacionais da Microsoft são codificados da seguinte maneira: 0=Indefinido, 1=MS-DOS®, 2=Windows® 3.x, 3=Windows® 9x, 4=Windows® NT (e derivados), 5=Windows® CE
62:48 ID do Fornecedor Indica o fornecedor convidado do sistema operacional. Um valor de 0 é reservado. Veja a lista de fornecedores abaixo.
63 Tipo de sistema operacional Indica o tipo de sistema operacional. Um valor de 0 representa um sistema operacional proprietário (de origem fechada). Um valor de 1 representa um sistema operacional de software livre.

Os valores do fornecedor são alocados pela Microsoft. Para solicitar um novo fornecedor, registre um problema no repositório de documentação de virtualização do GitHub (https://aka.ms/VirtualizationDocumentationIssuesTLFS).

Fornecedor Value
Microsoft 0x0001
HPE 0x0002
BlackBerry 0x0003
LANCOM 0x0200

MSR de identidade do sistema operacional convidado para sistemas operacionais de software livre

A codificação a seguir é oferecida como orientação para fornecedores de sistema operacional de software livre que pretendem estar em conformidade com essa especificação. Sugere-se que os sistemas operacionais de software livre adotem a convenção a seguir.

Bits Campo Description
15:0 Número da Compilação Informações específicas da distribuição (por exemplo, número de build).
47:16 Versão Informações de versão do kernel upstream.
55:48 ID do sistema operacional Informações adicionais do fornecedor
62:56 Tipo de sistema operacional Tipo de sistema operacional (por exemplo, Linux, FreeBSD etc.). Veja a lista de tipos de sistema operacional conhecidos abaixo
63 Software livre Um valor de 1 indica um sistema operacional de software livre.

Os valores de tipo do sistema operacional são alocados pela Microsoft. Para solicitar um novo tipo de sistema operacional, registre um problema no repositório de documentação de virtualização do GitHub (https://aka.ms/VirtualizationDocumentationIssuesTLFS).

Tipo de sistema operacional Value
Linux 0x1
FreeBSD 0 x 2
Xen 0x3
Illumos 0x4

Estabelecendo a interface de hiperchamada (x86/x64)

No x86/x64, as Hiperchamas são invocadas usando um opcode especial. Como esse opcode difere entre as implementações de virtualização, é necessário que o hipervisor abstraa essa diferença. Isso é feito por meio de uma página de hiperchamada especial. Esta página é fornecida pelo hipervisor e aparece dentro do espaço GPA do convidado. O convidado é necessário para especificar o local da página programando o MSR de Hiperchamada de Convidado.

#define HV_X64_MSR_HYPERCALL 0x40000001
Bits Description Attributes
63:12 GPFN de Hiperchamada – Indica o Número da Página Física do Convidado da página de hiperchamada Leitura/gravação
11:2 RsvdP. Os bits devem ser ignorados em leituras e preservados em gravações. Reservado
1 Trancado. Indica se o MSR é imutável. Se definido, esse MSR será bloqueado, impedindo a realocação da página de hiperchamada. Uma vez definido, somente uma redefinição do sistema pode limpar o bit. Leitura/gravação
0 Habilitar página de hiperchamada Leitura/gravação

A página de hiperchamada pode ser colocada em qualquer lugar dentro do espaço GPA do convidado, mas deve estar alinhada à página. Se o convidado tentar mover a página de hiperchamada para além dos limites do espaço gpa, uma falha #GP resultará quando o MSR for gravado.

Essa MSR é uma MSR em toda a partição. Em outras palavras, ele é compartilhado por todos os processadores virtuais na partição. Se um processador virtual gravar com êxito no MSR, outro processador virtual lerá o mesmo valor.

Antes que a página de hiperchamada esteja habilitada, o sistema operacional convidado deve relatar sua identidade gravando sua assinatura de versão em um MSR separado (HV_X64_MSR_GUEST_OS_ID). Se nenhuma identidade do sistema operacional convidado tiver sido especificada, as tentativas de habilitar a hiperchamada falharão. O bit de habilitação permanecerá zero mesmo ao gravar um nele. Além disso, se a identidade do sistema operacional convidado for desmarcada para zero depois que a página de hiperchamada tiver sido habilitada, ela será desabilitada.

A página de hiperchamada aparece como uma "sobreposição" para o espaço gpa; ou seja, abrange o que mais estiver mapeado para o intervalo de GPA. Seu conteúdo é legível e executável pelo convidado. As tentativas de gravar na página de hiperchamada resultarão em uma exceção de proteção (#GP). Depois que a página de hiperchamada tiver sido habilitada, invocar uma hiperchamada simplesmente envolve uma chamada para o início da página.

Veja a seguir uma lista detalhada das etapas envolvidas no estabelecimento da página de hiperchamada:

  1. O convidado lê a folha 1 da CPUID e determina se um hipervisor está presente verificando o bit 31 do registro ECX.
  2. O convidado lê a folha CPUID 0x40000000 para determinar a folha CPUID máxima do hipervisor (retornada no registro EAX) e a folha CPUID 0x40000001 para determinar a assinatura da interface (retornada no registro EAX). Ele verifica se o valor máximo da folha é pelo menos 0x40000005 e que a assinatura da interface é igual a "Hv#1". Essa assinatura implica isso HV_X64_MSR_GUEST_OS_IDHV_X64_MSR_HYPERCALL e HV_X64_MSR_VP_INDEX é implementada.
  3. O convidado gravará sua identidade do sistema operacional no MSR HV_X64_MSR_GUEST_OS_ID se esse registro for zero.
  4. O convidado lê o MSR de Hiperchamada (HV_X64_MSR_HYPERCALL).
  5. O convidado verifica o bit Habilitar Página de Hiperchamada. Se estiver definido, a interface já estará ativa e as etapas 6 e 7 deverão ser omitidas.
  6. O convidado encontra uma página dentro de seu espaço gpa, de preferência uma que não esteja ocupada por RAM, MMIO e assim por diante. Se a página estiver ocupada, o convidado deverá evitar o uso da página subjacente para outras finalidades.
  7. O convidado grava um novo valor no MSR de Hiperchamada (HV_X64_MSR_HYPERCALL) que inclui o GPA da etapa 6 e define o bit Habilitar Página de Hiperchamada para habilitar a interface.
  8. O convidado cria um mapeamento de VA executável para o GPA da página de hiperchamada.
  9. O convidado consulta a folha CPUID 0x40000003 para determinar quais instalações de hipervisor estão disponíveis para ele. Depois que a interface for estabelecida, o convidado poderá iniciar uma hiperchamada. Para fazer isso, ele preenche os registros de acordo com o protocolo de hiperchamada e emite uma CHAMADA para o início da página de hiperchamada. O convidado deve assumir que a página de hiperchamada executa o equivalente a um retorno próximo (0xC3) para retornar ao chamador. Dessa forma, a hiperchamada deve ser invocada com uma pilha válida.

Estabelecendo a interface de hiperchamada (ARM64)

Como o ARM64 dá suporte nativo à instrução HVC, o hipervisor não precisa de configuração adicional para habilitar as hiperchamas.

Interface de Hiperchamada Estendida

As hiperchamas com códigos de chamada acima 0x8000 são conhecidas como hiperchamas estendidas. As hiperchamas estendidas usam a mesma convenção de chamada que as hiperchamas normais e aparecem idênticas da perspectiva de uma VM convidada. As hiperchamas estendidas são tratadas internamente de forma diferente no hipervisor Hyper-V.

Os recursos de hiperchamação estendida podem ser consultados com HvExtCallQueryCapabilities.