Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
O hipervisor fornece um mecanismo de chamada para os convidados. Essas chamadas são chamadas de 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 acolchoados em limites naturais de até 8 bytes (ou seja, elementos de dois bytes devem estar em limites de dois bytes e assim por diante).
Uma segunda convenção de chamada de hiperchamada pode opcionalmente ser usada para um subconjunto de hiperchamadas – 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.
Uma terceira convenção de chamada de hiperchamada pode opcionalmente ser usada para um subconjunto de hiperchamadas onde o bloco de parâmetros 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 registradores XMM voláteis.
As estruturas de dados de entrada e saída devem ser colocadas na memória em um limite de 8 bytes e acolchoadas 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 (mas não é garantido) substituir regiões de preenchimento. Se ele sobrescrever regiões de preenchimento, ele gravará zeros.
Hypercall Classes
Existem duas classes de hiperchamadas: simple 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 funciona como uma série de hiperchamadas simples. Além de um conjunto de parâmetros de entrada e saída de tamanho fixo, as hiperchamadas de representantes envolvem uma lista de elementos de entrada e/ou saída de tamanho fixo.
Quando um chamador invoca inicialmente 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 representante que indica o próximo elemento de entrada e/ou saída que deve ser consumido. O hipervisor processa os parâmetros de representação em ordem de lista – ou seja, aumentando o índice de elementos.
Para invocações subsequentes da hiperchamada rep, o índice de início de rep indica quantos elementos foram concluídos e, em conjunto com o valor de rep count, 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 de volta ao processador virtual de chamada depois de atualizar o índice de início do representante para 20. Quando a hiperchamada for reexecutada, o hipervisor será retomado no elemento 20 e completará os 5 elementos restantes.
Se for encontrado um erro ao processar um elemento, um código de status apropriado é fornecido junto com uma contagem de representantes concluídos, 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 (consulte o seguinte) e as listas de parâmetros de entrada/saída estejam 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 do Hypercall
Uma hiperchamada pode ser pensada como uma instrução complexa que leva muitos ciclos. O hipervisor tenta limitar a execução da 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 para que uma garantia de 50μs seja difícil de fazer. Portanto, o hipervisor depende de um mecanismo de continuação de hiperchamada para algumas hiperchamadas – incluindo todos os formulários de hiperchamada de representante.
O mecanismo de continuação da hiperchamada é principalmente transparente para o chamador. Se uma hiperchamada não puder ser concluída dentro do limite de tempo prescrito, o controle será retornado ao 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 hypercall e avançará em direção à conclusão da operação.
A maioria das hiperchamadas simples são garantidas para serem concluídas dentro do prazo prescrito. No entanto, um pequeno número de hiperchamadas simples pode exigir mais tempo. Essas hiperchamadas usam a continuação de hiperchamada de maneira semelhante às hiperchamadas de repetição. Nesses casos, a operação envolve dois ou mais estados internos. A primeira invocação coloca o objeto (por exemplo, a partição ou o processador virtual) em um estado e, após invocações repetidas, o estado finalmente transita para um estado terminal. Para cada hiperchamada que segue este padrão, os efeitos colaterais visíveis de estados internos intermediários são descritos.
Atomicidade e Encomenda de Hiperchamadas
Exceto onde indicado, a ação executada por uma hiperchamada é atômica tanto em relação a todas as outras operações de convidado (por exemplo, instruções executadas dentro de um convidado) quanto a todas as outras hiperchamadas que estão sendo executadas no sistema. Uma simples hiperchamada executa uma única ação atômica; Um hypercall de representante executa várias ações atômicas independentes.
Hiperchamadas simples que usam a continuação de hiperchamada podem envolver vários estados internos que são visíveis externamente. Tais chamadas compreendem múltiplas 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 depois que a hiperchamada é 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 que a hiperchamada retorne.
O hóspede deve evitar o exame e/ou manipulação de quaisquer parâmetros de entrada ou saída relacionados a uma hiperchamada em execução. Embora um processador virtual que execute uma hypercall seja incapaz de fazê-lo (já que sua execução de convidado é suspensa até que a hypercall retorne), não há nada que impeça outros processadores virtuais de fazê-lo. Os hóspedes que se comportam desta forma podem falhar ou causar corrupção na sua partição.
Ambientes Legais de Hypercall
As hiperchamadas só podem ser invocadas a partir do modo de processador convidado mais privilegiado. Em plataformas x64, isso significa modo protegido com um nível de privilégio atual (CPL) de zero. Embora o código em modo real seja executado com uma CPL efetiva de zero, as hiperchamadas 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) em x64 e uma exceção de instrução indefinida em ARM64.
Todas as hiperchamadas devem ser invocadas através da interface de hiperchamada definida arquitetonicamente (veja abaixo). Uma tentativa de invocar uma hiperchamada por qualquer outro meio (por exemplo, copiar o código da página de código da hiperchamada para um local alternativo e executá-la a partir daí) pode resultar em uma exceção de operação indefinida (#UD). Não é garantido que o hipervisor forneça essa exceção.
Requisitos de alinhamento
Os chamadores devem especificar o endereço físico convidado (GPA) de 64 bits dos parâmetros de entrada e/ou saída. Os ponteiros 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 GPA correspondente.
As listas de parâmetros de entrada e saída não podem se sobrepor ou cruzar os limites da página. Espera-se que as páginas de entrada e saída do Hypercall 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 nessa página, o acesso do hipervisor à lista de parâmetros de entrada será indefinido.
O hipervisor validará se a partição chamadora pode ler a partir da 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 intercetação de memória. Para hiperchamadas com 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 valor de entrada de hiperchamada. Está formatado da seguinte forma:
| Campo | Bits | Informações Prestadas |
|---|---|---|
| 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 variável do cabeçalho | 26-17 | O tamanho de um cabeçalho variável, no QWORDS. |
| RsvdZ | 30-27 | Deve ser zero |
| Está aninhado | 31 | Especifica que a hiperchamada deve ser manipulada pelo hipervisor L0 em um ambiente aninhado. |
| Contagem de representantes | 43-32 | Número total de representantes (para chamada de representante, deve ser zero caso contrário) |
| RsvdZ | 47-44 | Deve ser zero |
| Índice Rep Start | 59-48 | Índice inicial (para chamada de representante, deve ser zero caso contrário) |
| RsvdZ | 63-60 | Deve ser zero |
Para hiperchamadas de representantes, o campo de contagem de representantes indica o número total de representantes. O índice de início de rep indica a repetição específica em relação ao início da lista (zero indica que o primeiro elemento da lista deve ser processado). Portanto, o valor da contagem de representantes deve ser sempre maior do que o índice de início do rep.
Convenções de Registro Hypercall (x86/x64)
Em x86/x64, o mapeamento de registro para entradas de hiperchamada quando o sinalizador Fast é zero é o seguinte:
| x64 | x86 | Informações Prestadas |
|---|---|---|
| RCX | EDX: EAX | Valor de entrada do Hypercall |
| RDX | EBX:ECX | Parâmetros de entrada GPA |
| R8 | EDI:ESI | Parâmetros de saída GPA |
O valor de entrada de hiperchamada é passado em registradores junto com um GPA que aponta para os parâmetros de entrada e saída.
Os mapeamentos de registro dependem se o chamador está sendo executado no modo de 32 bits (x86) ou 64 bits (x64). O hipervisor determina o modo do chamador com base no valor do EFER. LMA e CS.L. Se ambos os sinalizadores estiverem definidos, presume-se que o chamador seja um chamador de 64 bits.
Registre o mapeamento para entradas de hiperchamada quando o sinalizador Fast for um:
| x64 | x86 | Informações Prestadas |
|---|---|---|
| RCX | EDX: EAX | Valor de entrada do Hypercall |
| RDX | EBX:ECX | Parâmetro de entrada |
| R8 | EDI:ESI | Parâmetro de saída |
O valor de entrada de hiperchamada é passado em registradores junto com os parâmetros de entrada.
Convenções de registro Hypercall (ARM64 SMCCC)
No ARM64, as hiperchamadas são executadas usando a instrução "HVC #0". As chamadas aderem ao ARM64 SMCCC (SMC Calling Convention).
O mapeamento de registro para entradas de hiperchamada é o seguinte:
| Register | Informações Prestadas |
|---|---|
| X0 | Identificador de função SMCCC |
| X1 | Valor de entrada do Hypercall |
| X2 | Parâmetros de entrada GPA |
| X3 | Parâmetros de saída GPA |
O identificador de função SMCCC em X0 segue este formato:
| Bits | Campo | Valor | Description |
|---|---|---|---|
| 31 | Render chamada | 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íficas 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 razões históricas, a interface do hipervisor ARM64 também suporta uma convenção de chamada diferente. As hiperchamadas são executadas com a instrução "HVC #1". Recomendamos o uso da convenção de chamada SMCCC para o novo código.
O mapeamento de registro para entradas de hiperchamada é o seguinte:
| Register | Informações Prestadas |
|---|---|
| X0 | Valor de entrada do Hypercall |
| X1 | Parâmetros de entrada GPA |
| X2 | Parâmetros de saída GPA |
Cabeçalhos de entrada Hypercall 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 precisa ser especificada separadamente. No entanto, algumas hiperchamadas exigem uma quantidade variável de dados de cabeçalho. Essas hiperchamadas normalmente têm um cabeçalho de entrada de tamanho fixo e uma 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 a quantidade de dados que 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 fixo do cabeçalho está implícito, em vez de fornecer o tamanho total do cabeçalho, apenas 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 variável diferente de zero para uma hiperchamada que não esteja 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, toda a entrada de cabeçalho se encaixe 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 aspetos, 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 de tamanho variável suporte adicionalmente a semântica de representante. Nesse caso, os elementos rep ficam após o cabeçalho da maneira usual, exceto que o tamanho total do cabeçalho inclui as partes fixa e variável. Todas as outras regras permanecem as mesmas, por exemplo, o primeiro elemento rep deve estar alinhado com 8 bytes.
Entrada rápida de hiperchamada XMM (x86/x64)
Em plataformas x86/x64, o hipervisor suporta o uso de hiperchamadas rápidas XMM, o que permite que algumas hiperchamadas aproveitem o desempenho aprimorado da interface de hiperchamada rápida, mesmo que exijam mais de dois parâmetros de entrada. A interface de hiperchamada rápida XMM usa seis registradores XMM para permitir que o chamador passe um bloco de parâmetros de entrada de até 112 bytes de tamanho.
A disponibilidade da interface de hiperchamada rápida XMM é indicada através da folha CPUID "Hypervisor Feature Identification" (0x40000003):
- Bit 4: suporte para passar a entrada de hiperchamada através de registradores XMM está disponível.
Observe que há um sinalizador separado para indicar o suporte para saída rápida XMM. Qualquer tentativa de usar essa interface quando o hipervisor não indicar disponibilidade resultará em uma falha de #UD.
Registrar mapeamento (somente entrada)
| x64 | x86 | Informações Prestadas |
|---|---|---|
| RCX | EDX: EAX | Valor de entrada do Hypercall |
| RDX | EBX:ECX | Bloco de parâmetros de entrada |
| R8 | EDI:ESI | Bloco de parâmetros de entrada |
| XMM0 | XMM0 | Bloco de parâmetros de entrada |
| XMM1 | XMM1 | Bloco de parâmetros de entrada |
| XMM2 | XMM2 | Bloco de parâmetros de entrada |
| XMM3 | XMM3 | Bloco de parâmetros de entrada |
| XMM4 | XMM4 | Bloco de parâmetros de entrada |
| XMM5 | XMM5 | Bloco de parâmetros de entrada |
O valor de entrada de hiperchamada é passado em registradores junto com os parâmetros de entrada. Os mapeamentos de registro dependem se o chamador está sendo executado no modo de 32 bits (x86) ou 64 bits (x64). O hipervisor determina o modo do chamador com base no valor do EFER. LMA e CS.L. Se ambos os sinalizadores estiverem definidos, presume-se que o chamador seja um chamador de 64 bits. Se o bloco de parâmetros de entrada for menor que 112 bytes, quaisquer bytes extras nos registradores serão ignorados.
Registrar entrada de chamada rápida (ARM64 SMCCC)
Nas plataformas ARM64, o hipervisor suporta o uso de hiperchamadas rápidas de registro, o que permite que algumas hiperchamadas aproveitem o melhor desempenho da interface de hiperchamada rápida, mesmo que exijam mais de dois parâmetros de entrada. A interface de hiperchamada rápida de registos utiliza 16 registos de uso geral para permitir ao chamador passar um bloco de parâmetros de entrada com até 128 bytes.
Registrar mapeamento (somente entrada)
| Register | Informações Prestadas |
|---|---|
| X0 | Identificador de função SMCCC |
| X1 | Valor de entrada do Hypercall |
| X2 - X17 | Bloco de parâmetros de entrada |
Se o bloco de parâmetros de entrada for menor que 128 bytes, quaisquer bytes extras nos registradores serão ignorados.
Registrar entrada de chamada rápida (ARM64 HVC #1)
A interface de hiperchamada rápida de registro usa dezesseis registradores de uso geral para permitir que o chamador passe um bloco de parâmetros de entrada de até 128 bytes de tamanho.
Registrar mapeamento (somente entrada)
| Register | Informações Prestadas |
|---|---|
| X0 | Valor de entrada do Hypercall |
| X1 - X17 | Bloco de parâmetros de entrada |
Se o bloco de parâmetros de entrada for menor que 128 bytes, quaisquer bytes extras nos registradores serão ignorados.
Saídas Hypercall
Todas as hiperchamadas retornam um valor de 64 bits chamado valor de resultado de hiperchamada. Está formatado da seguinte forma:
| Campo | Bits | Comment |
|---|---|---|
| Result | 15-0 |
HV_STATUS código que indica sucesso 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 hiperchamadas de representantes, o campo reps complete é o número total de repetições concluídas e não relativo ao índice de início de rep. Por exemplo, se o chamador especificou um índice de início de representante de 5 e uma contagem de representantes de 10, o campo de representantes completos indicará 10 após a conclusão bem-sucedida.
O valor do resultado da hiperchamada é passado de volta nos registros.
Em x64, o mapeamento do registro depende se o chamador está sendo executado no modo de 32 bits (x86) ou 64 bits (x64) (veja acima). O mapeamento de registro para saídas de hiperchamada é o seguinte:
| x64 | x86 | Informações Prestadas |
|---|---|---|
| RAX | EDX: EAX | Valor do resultado da hiperchamada |
No ARM64, o mapeamento de registro para saídas de hiperchamada é o seguinte:
| Register | Informações Prestadas |
|---|---|
| X0 | Valor do resultado da hiperchamada |
Saída rápida de hiperchamada XMM (x86/x64)
Semelhante a como o hipervisor suporta entradas de hiperchamada rápidas XMM, os mesmos registradores podem ser compartilhados para retornar a saída. Isso só é suportado em plataformas x64.
A capacidade de retornar a saída através de registradores XMM é indicada através da folha CPUID "Hypervisor Feature Identification" (0x40000003):
- Bit 15: suporte para retornar saída de hiperchamada via registradores XMM está disponível.
Observe que há um sinalizador separado para indicar o suporte para entrada rápida 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 registradores 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âmetros de entrada for menor que 112 bytes (arredondado para o bloco alinhado de 16 bytes mais próximo), os registradores restantes retornarão a saída de hiperchamada.
| x64 | Informações Prestadas |
|---|---|
| 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âmetros de entrada tiver 20 bytes de tamanho, o hipervisor ignorará os 12 bytes a seguir. Os 80 bytes restantes conteriam saída de hiperchamada (se aplicável).
Registrar saída de chamada rápida (ARM64 SMCCC)
Em plataformas ARM64, semelhante a como o hipervisor suporta entradas de hiperchamada rápidas de registro, os mesmos registros podem ser compartilhados para retornar a saída.
Mapeamento de Registro (Entrada e Saída)
Os registradores 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âmetros de entrada for menor que 128 bytes (arredondado para o bloco alinhado de 8 bytes mais próximo), os registradores restantes retornarão a saída de hiperchamada.
| Register | Informações Prestadas |
|---|---|
| X2 - X17 | Bloco de entrada ou saída |
Por exemplo, se o bloco de parâmetros de entrada tiver 20 bytes de tamanho, o hipervisor ignorará os 4 bytes a seguir. Os 104 bytes restantes conteriam saída de hiperchamada (se aplicável).
Registrar saída de chamada rápida (ARM64 HVC #1)
Semelhante às versões SMCCC, a interface HVC #1 usa os mesmos registradores para retornar a saída.
Mapeamento de Registro (Entrada e Saída)
Os registradores 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âmetros de entrada for menor que 128 bytes (arredondado para o bloco alinhado de 8 bytes mais próximo), os registradores restantes retornarão a saída de hiperchamada.
| Register | Informações Prestadas |
|---|---|
| X1 - X17 | Bloco de entrada ou saída |
Por exemplo, se o bloco de parâmetros de entrada tiver 20 bytes de tamanho, o hipervisor ignorará os 4 bytes a seguir. Os 104 bytes restantes conteriam saída de hiperchamada (se aplicável).
Registos voláteis (x86/x64)
As hiperchamadas só modificarão os valores de registro especificados nas seguintes condições:
- RAX (x64) e EDX:EAX (x86) são sempre substituídos pelo valor do resultado da hiperchamada e pelos parâmetros de saída, se houver.
- As hiperchamadas de representantes modificarão RCX (x64) e EDX:EAX (x86) com o novo índice de início de representante.
- HvCallSetVpRegisters pode modificar quaisquer registros suportados com essa hiperchamada.
- RDX, R8 e XMM0 a XMM5, quando usados para entrada rápida de hiperchamada, permanecem inalterados. No entanto, os registradores usados para saída rápida de hiperchamada podem ser modificados, incluindo RDX, R8 e XMM0 a XMM5. Hyper-V modificará apenas esses registradores para saída de hiperchamada rápida, que é limitada a x64.
Registos voláteis (ARM64 SMCCC)
As hiperchamadas só modificarão os valores de registro especificados nas seguintes condições:
- X0 é sempre substituído pelo valor do resultado da hiperchamada e pelos parâmetros de saída, se houver.
- As hiperchamadas de representantes modificarão o X1 com o novo índice de início de representante.
- HvCallSetVpRegisters pode modificar quaisquer registros suportados com essa hiperchamada.
- X2 - X17, quando usado para entrada rápida de hiperchamada, permanece inalterado. No entanto, os registradores usados para saída de hiperchamada rápida podem ser modificados, incluindo X2 - X17. Hyper-V só modificará esses registradores para saída rápida de hiperchamada.
Registos voláteis (ARM64 HVC #1)
As hiperchamadas só modificarão os valores de registro especificados nas seguintes condições:
- X0 é sempre substituído pelo valor do resultado da hiperchamada e pelos parâmetros de saída, se houver.
- As hiperchamadas de representantes modificarão X0 com o novo índice de início de representante.
- HvCallSetVpRegisters pode modificar quaisquer registros suportados com essa hiperchamada.
- X1 - X17, quando usado para entrada rápida de hiperchamada, permanece inalterado. No entanto, os registradores usados para saída de hiperchamada rápida podem ser modificados, incluindo X1 - X17. Hyper-V só modificará esses registradores para saída rápida de hiperchamada.
Restrições de hiperchamada
As hiperchamadas podem ter restrições associadas que devem ser satisfeitas para que elas desempenhem a função pretendida. Se todas as restrições não forem atendidas, a hiperchamada será encerrada com um erro apropriado. As seguintes restrições serão listadas, se forem aplicáveis:
- A partição chamadora deve possuir 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 hiperchamadas com falha
A menos que explicitamente indicado de outra forma, quando uma hiperchamada falha (ou seja, o campo de resultado do valor de resultado da hiperchamada contém um valor diferente de HV_STATUS_SUCCESS), o conteúdo de todos os parâmetros de saída são indeterminados e não devem ser examinados 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 em que as condições de erro são detetadas e relatadas pelo hipervisor é indefinida. Em outras palavras, se existirem vários erros, o hipervisor deve escolher qual condição de erro relatar. Deve ser dada prioridade aos códigos de erro que ofereçam maior segurança, com a intenção de impedir que o hipervisor revele informações a pessoas que não tenham privilégios suficientes. Por exemplo, o código HV_STATUS_ACCESS_DENIED de status é o código de status preferido em vez de um que revelaria alguma informação de contexto ou estado puramente baseada em privilégio.
Códigos de status comuns 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 estado | 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 que não é de representante ou uma contagem de representantes zero é passada para uma chamada de representante). |
| O índice de início de rep não é inferior à contagem de rep. | |
| Um bit reservado no valor de entrada de hiperchamada especificado é diferente de zero. | |
HV_STATUS_INVALID_ALIGNMENT |
O ponteiro GPA de entrada ou saída especificado não está alinhado a 8 bytes. |
| O parâmetro de entrada ou saída especificado lista páginas de extensão. | |
| 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 detetada.
Relatando a identidade do SO convidado
O SO convidado em execução na partição deve identificar-se para o hipervisor escrevendo sua assinatura e versão em um MSR (HV_X64_MSR_GUEST_OS_ID/HvRegisterGuestOsId) antes de poder invocar hiperchamadas. Este MSR é de toda a partição e é compartilhado entre todos os processadores virtuais.
O valor deste registo é inicialmente zero.
Em x86/x64, um valor diferente de zero deve ser gravado no MSR do ID do SO convidado antes que a página de código de hiperchamada possa ser habilitada (consulte Estabelecendo a interface Hypercall (x86/x64)). Se esse registro for zerado posteriormente, a página de código de hiperchamada será desativada.
No ARM64, um valor diferente de zero deve ser gravado no ID do SO convidado MSR antes que os códigos de hiperchamada possam ser invocados. A exceção são as hiperchamadas HvCallSetVpRegisters/HvCallGetVpRegisters . Consulte a respetiva documentação para obter mais informações.
#define HV_X64_MSR_GUEST_OS_ID 0x40000000
#define HvRegisterGuestOsId 0x00090002
No ARM64, apenas HvRegisterGuestOsId é suportado, que deve ser escrito usando a hiperchamada HvCallSetVpRegisters no processador de inicialização.
Identidade do SO convidado para sistemas operativos proprietários
A seguir está a codificação recomendada para este MSR. Alguns campos podem não se aplicar a alguns SOs convidados.
| Bits | Campo | Description |
|---|---|---|
| 15:0 | Número de compilação | Indica o número de compilação do SO |
| 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 SO |
| 39:32 | Versão principal | Indica a versão principal do SO |
| 47:40 | ID do SO | Indica a variante do SO. A codificação é exclusiva do fornecedor. Os sistemas operacionais Microsoft são codificados da seguinte forma: 0=Undefined, 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 do SO convidado. Um valor de 0 é reservado. Veja a lista de fornecedores abaixo. |
| 63 | Tipo de SO | Indica o tipo de SO. Um valor de 0 representa um sistema operacional proprietário (de código fechado). Um valor de 1 representa um SO de código aberto. |
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 | Valor |
|---|---|
| Microsoft | 0x0001 |
| HPE | 0x0002 |
| BlackBerry | 0x0003 |
| LANCOM | 0x0200 |
MSR de identidade do SO convidado para sistemas operacionais de código aberto
A codificação a seguir é oferecida como orientação para fornecedores de sistemas operacionais de código aberto que pretendem estar em conformidade com esta especificação. Sugere-se que os sistemas operacionais de código aberto adotem a seguinte convenção.
| Bits | Campo | Description |
|---|---|---|
| 15:0 | Número de compilação | Informações específicas da distribuição (por exemplo, número de compilação). |
| 47:16 | Versão | Informações de versão do kernel upstream. |
| 55:48 | ID do SO | Informações adicionais do fornecedor |
| 62:56 | Tipo de SO | Tipo de sistema operacional (por exemplo, Linux, FreeBSD, etc.). Veja a lista de tipos de SO conhecidos abaixo |
| 63 | Código aberto | Um valor de 1 indica um SO de código aberto. |
Os valores de Tipo de SO 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 SO | Valor |
|---|---|
| Linux | 0x1 |
| FreeBSD | 0x2 |
| Xen | 0x3 |
| Illumos | 0x4 |
Estabelecendo a interface Hypercall (x86/x64)
Em x86/x64, as Hypercalls são invocadas usando um opcode especial. Como esse opcode difere entre as implementações de virtualização, é necessário que o hipervisor abstraia essa diferença. Isso é feito através de uma página de hiperchamada especial. Esta página é fornecida pelo hipervisor e aparece dentro do espaço GPA do convidado. O convidado é obrigado a especificar o local da página programando o Guest Hypercall MSR.
#define HV_X64_MSR_HYPERCALL 0x40000001
| Bits | Description | Attributes |
|---|---|---|
| 63:12 | Hypercall GPFN - Indica o número da página física do convidado da página de hiperchamada | Leitura/escrita |
| 11:2 | RsvdP. Os bits devem ser ignorados nas leituras e preservados nas gravações. | Reservado |
| 1 | Bloqueado. Indica se a REM é imutável. Se definido, este MSR é bloqueado, impedindo assim a realocação da página de hiperchamada. Uma vez definido, apenas uma redefinição do sistema pode limpar o bit. | Leitura/escrita |
| 0 | Ativar página de hiperchamada | Leitura/escrita |
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 além dos limites do espaço GPA, uma falha de #GP ocorrerá quando o MSR for gravado.
Este MSR é um MSR de 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 seja habilitada, o SO convidado deve relatar sua identidade escrevendo sua assinatura de versão em um MSR (HV_X64_MSR_GUEST_OS_ID) separado. Se nenhuma identidade do SO convidado tiver sido especificada, as tentativas de ativar a hiperchamada falharão. O bit de ativação permanecerá zero mesmo ao escrever um para ele. Além disso, se a identidade do SO convidado for limpa para zero depois que a página de hiperchamada for ativada, ela será desativada.
A página de hiperchamada aparece como uma "sobreposição" ao espaço GPA; ou seja, cobre o que mais estiver mapeado para o intervalo GPA. O 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 hypercall for habilitada, invocar uma hypercall simplesmente envolve uma chamada para o início da página.
A seguir está uma lista detalhada das etapas envolvidas no estabelecimento da página de hiperchamada:
- O convidado lê CPUID folha 1 e determina se um hipervisor está presente verificando o bit 31 do registro ECX.
- 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 se a assinatura da interface é igual a "Hv#1". Esta assinatura implica que
HV_X64_MSR_GUEST_OS_ID,HV_X64_MSR_HYPERCALLeHV_X64_MSR_VP_INDEXsão implementados. - O convidado grava sua identidade do sistema operacional no MSR
HV_X64_MSR_GUEST_OS_IDse esse registro for zero. - O convidado lê o Hypercall MSR (
HV_X64_MSR_HYPERCALL). - O convidado verifica o bit Ativar página Hypercall. Se estiver definida, a interface já está ativa e as etapas 6 e 7 devem ser omitidas.
- 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 hóspede deve evitar usar a página subjacente para outros fins.
- O convidado grava um novo valor no Hypercall MSR (
HV_X64_MSR_HYPERCALL) que inclui o GPA da etapa 6 e define o bit Enable Hypercall Page para habilitar a interface. - O convidado cria um mapeamento VA executável para o GPA da página de hiperchamada.
- O convidado consulta o 0x40000003 folha CPUID para determinar quais recursos 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 hypercall e emite um CALL para o início da página hypercall. O convidado deve assumir que a página de hiperchamada executa o equivalente a um quase retorno (0xC3) para retornar ao chamador. Como tal, a hiperchamada deve ser invocada com uma pilha válida.
Estabelecendo a interface Hypercall (ARM64)
Como o ARM64 suporta nativamente a instrução HVC, o hipervisor não precisa de configuração adicional para habilitar hiperchamadas.
Interface Hypercall estendida
As hiperchamadas com códigos de chamada acima 0x8000 são conhecidas como hiperchamadas estendidas. As hiperchamadas estendidas usam a mesma convenção de chamada que as hiperchamadas normais e parecem idênticas da perspetiva de uma VM convidada. As hiperchamadas estendidas são tratadas internamente de forma diferente dentro do Hyper-V hipervisor.
Os recursos estendidos de hiperchamada podem ser consultados com HvExtCallQueryCapabilities.