Hypercall Interface
O hipervisor fornece um mecanismo de chamada para convidados. Essas chamadas são chamadas chamadas 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 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 adicionadas a um múltiplo de 8 bytes de tamanho. Os valores dentro das regiões de preenchimento são ignorados pelo hipervisor.
Para saída, o hipervisor tem permissão para substituir (mas não é garantido) regiões de preenchimento de substituição. Se substituir regiões de preenchimento, ele gravará zeros.
Hypercall Classes
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 rep atua 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 rep, 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 rep 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 da 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 junto 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 rep.
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 de volta 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 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 hiperchamas usam a continuação de hiperchamada de maneira semelhante às hiperchamas 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 de estados internos intermediários são descritos.
Hipercham atomicidade e ordenação
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.
Hiperchamas simples que usam a continuação de hiperchamada podem envolver vários estados internos que são externamente visíveis. Essas chamadas compõem 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 criação da hiperchada e antes da execução da ação. 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 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.
Ambientes de Hiperchamada Legal
As hiperchamas só podem ser invocadas do modo de processador convidado mais privilegiado. Em platfoms x64, isso significa modo protegido com um CPL (nível de privilégio) atual de zero. Embora o código do 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 em um modo de processador ilegal gerará uma exceção #UD (operação indefinida).
Todas as hiperchamas devem ser invocadas por meio da interface de hiperchamada definida pela arquitetura (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). O hipervisor não tem garantia de entregar 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 gpa devem estar alinhados por 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 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 ser lida 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 ser gravada 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 hipercham
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 variável, em 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 de Início do Rep | 59-48 | O índice inicial (para chamada de representante, deve ser zero caso contrário) |
RsvdZ | 63-60 | Deve ser zero |
Para hiperchamações de rep, o campo de contagem de representantes indica o número total de representantes. O índice de início do rep indica a repetição específica em relação 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 do que o índice de início do rep.
Registre o mapeamento para entradas de hiperchamada quando o sinalizador Rápido for zero:
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.
No x64, 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.
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, especificada implicitamente pelo código de hiperchamada e não precisa ser especificada separadamente. No entanto, algumas hipercalls exigem uma quantidade variável de dados de cabeçalho. Normalmente, essas hiperchamações 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 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 está 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 HeaderSize = 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, 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 de tamanho variável dê suporte adicional à semântica de rep. Nesse caso, os elementos de rep ficam após o cabeçalho da forma 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 estar alinhado a 8 bytes.
Entrada de hiperchamada rápida do XMM
Em plataformas 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 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 do 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.
Saídas de hiperchamada
Todas as hiperchamações retornam um valor de 64 bits chamado de valor de resultado de hiperchamada. Ele é formatado da seguinte maneira:
Campo | Bits | Comentário |
---|---|---|
Result | 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 hipercalls de rep, o campo completo de reps é o número total de reps 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 rep de 5 e uma contagem de representantes de 10, o campo completo dos reps indicaria 10 após a conclusão bem-sucedida.
O valor do resultado da hiperchamada é passado de volta nos registros. O mapeamento de registro depende se o chamador está em execução 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 Fornecidas |
---|---|---|
RAX | EDX:EAX | Valor do resultado da hiperchamada |
Saída de hiperchamada rápida do XMM
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 de "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é o bloco alinhado de 16 bytes mais próximo), 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).
Registros voláteis
As hiperchamadas modificarão apenas os valores de registro especificados nas seguintes condições:
- RAX (x64) e EDX:EAX (x86) são sempre substituídos com os parâmetros de resultado de hiperchamada e parâmetros de saída, se houver.
- As hiperchamadas de rep modificarão RCX (x64) e EDX:EAX (x86) com o novo índice de início de rep.
- HvCallSetVpRegisters pode modificar todos os registros com suporte com essa hiperchamada.
- RDX, R8 e XMM0 a XMM5, quando usados para entrada rápida de hiperchamada, permanecem não modificados. No entanto, os registros usados para saída de hiperchamada rápida podem ser modificados, incluindo RDX, R8 e XMM0 por meio de XMM5. O Hyper-V modificará apenas esses registros para saída de hiperchamada rápida, que é limitada a x64.
Restrições de hiperchamada
As hiperchamas podem ter restrições associadas a elas 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 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 hiperchamas com falha
A menos que explicitamente declarado o contrário, 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. Entre elas estão as seguintes:
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 reps não zero é passada para uma chamada não rep 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 dentro da partição deve identificar-se ao hipervisor escrevendo sua assinatura e versão em um MSR (HV_X64_MSR_GUEST_OS_ID
) antes de poder invocar hiperchamamentos. Essa MSR é de todo o particionamento e é compartilhada entre todos os processadores virtuais.
O valor desse registro é inicialmente zero. Um valor não 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). Se esse registro for posteriormente zerado, a página de código de hiperchamada será desabilitada.
#define HV_X64_MSR_GUEST_OS_ID 0x40000000
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 | Descrição |
---|---|---|
15:0 | Número de build | 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, número do "service pack") |
31:24 | Versão Secundária | 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 de so convidado. Um valor de 0 é reservado. Veja a lista de fornecedores abaixo. |
63 | Tipo de sistema operacional | Indica os tipos de sistema operacional. Um valor 0 indica um sistema operacional de origem fechado proprietário. Um valor de 1 indica um sistema operacional código aberto. |
Os valores do fornecedor são alocados pela Microsoft. Para solicitar um novo fornecedor, registre um problema no GitHub repositório de documentação de virtualização (https://aka.ms/VirtualizationDocumentationIssuesTLFS).
Fornecedor | Valor |
---|---|
Microsoft | 0x0001 |
HPE | 0x0002 |
LANCOM | 0x0200 |
MSR de identidade do sistema operacional convidado para sistemas operacionais de software livre
A codificação a seguir é oferecida como diretriz para código aberto fornecedores do sistema operacional que pretendem estar em conformidade com essa especificação. Sugere-se que código aberto sistemas operacionais adaptem a convenção a seguir.
Bits | Campo | Descrição |
---|---|---|
15:0 | Número de build | Informações adicionais |
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 conhecidos do sistema operacional abaixo |
63 | Software livre | Um valor de 1 indica um sistema operacional código aberto. |
Os valores de tipo de sistema operacional são alocados pela Microsoft. Para solicitar um novo tipo de sistema operacional, registre um problema no GitHub repositório de documentação de virtualização (https://aka.ms/VirtualizationDocumentationIssuesTLFS).
Tipo de sistema operacional | Valor |
---|---|
Linux | 0x1 |
FreeBSD | 0x2 |
Xen | 0x3 |
Illumos | 0x4 |
Estabelecendo a interface hypercall
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 do Hypercall Convidado.
#define HV_X64_MSR_HYPERCALL 0x40000001
Bits | Descrição | Atributos |
---|---|---|
63:12 | Hypercall GPFN – Indica o número da página de página física de 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 | Bloqueadas. Indica se a MSR é imutável. Se definido, essa MSR será bloqueada impedindo assim a realocação da página de hiperchamada. Depois de 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 ser 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 hiperchamento seja habilitada, o sistema operacional 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 sistema operacional convidado tiver sido especificada, as tentativas de habilitar a hiperchamada falharão. O bit habilitar permanecerá zero mesmo se um for gravado nele. Além disso, se a identidade do sistema operacional convidado for desmarcada para zero depois que a página de hiperchamento tiver sido habilitada, ela será desabilitada.
A página de hiperchamada aparece como uma "sobreposição" para o espaço GPA; ou seja, cobre o que mais for 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:
- O convidado lê a folha 1 da CPUID e determina se um hipervisor está presente verificando o bit 31 do ECX de registro.
- O convidado lê folha CPUID 0x40000000 para determinar a folha de CPUID máxima do hipervisor (retornada no registro EAX) e 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_ID
HV_X64_MSR_HYPERCALL
eHV_X64_MSR_VP_INDEX
é implementada. - O convidado gravará sua identidade do sistema operacional no MSR
HV_X64_MSR_GUEST_OS_ID
se esse registro for zero. - O convidado lê a MSR do Hypercall (
HV_X64_MSR_HYPERCALL
). - 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.
- O convidado encontra uma página dentro de seu espaço gpa, preferencialmente uma que não é ocupada por RAM, MMIO e assim por diante. Se a página estiver ocupada, o convidado deverá evitar usar a página subjacente para outras finalidades.
- O convidado grava um novo valor no MSR do Hypercall (
HV_X64_MSR_HYPERCALL
) que inclui o GPA da etapa 6 e define o bit Habilitar Página de Hiperchamada para habilitar a interface. - O convidado cria um mapeamento de VA executável para o GPA da página de hiperchamada.
- 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.
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 parecem idênticas da perspectiva de uma VM convidada. As hiperchamas estendidas são tratadas internamente de forma diferente dentro do hipervisor hyper-V.
Recursos de hiperchamada estendidos podem ser consultados com HvExtCallQueryCapabilities.