Partilhar via


Virtualização aninhada

Virtualização aninhada refere-se ao hipervisor Hyper-V emular extensões de virtualização por hardware. Estas extensões emuladas podem ser usadas por outros softwares de virtualização (por exemplo, um hipervisor aninhado) para funcionar na plataforma Hyper-V.

Esta funcionalidade está disponível apenas para partições convidadas. Deve ser ativado por cada máquina virtual. A virtualização aninhada não é suportada numa partição raiz do Windows.

A seguinte terminologia é usada para definir vários níveis de virtualização aninhada:

Term Definition
Hipervisor L0 O hipervisor Hyper-V a correr em hardware físico.
Raiz L1 O sistema operativo raiz do Windows.
L1 Guest Uma Hyper-V máquina virtual sem hipervisor aninhado.
Hipervisor L1 Um hipervisor aninhado a correr dentro de uma Hyper-V máquina virtual.
Raiz L2 Um sistema operativo Windows raiz, a correr no contexto de uma máquina virtual Hyper-V.
L2 Guest Uma máquina virtual aninhada, a correr no contexto de uma máquina virtual Hyper-V.

Comparados com o bare-metal, os hipervisores podem sofrer uma regressão significativa de desempenho ao serem executados numa VM. Os hipervisores L1 podem ser otimizados para correr numa VM Hyper-V usando interfaces iluminadas fornecidas pelo hipervisor L0.

Esta funcionalidade é atualmente suportada apenas em x64.

VMCS Esclarecido (Intel)

Nas plataformas Intel, o software de virtualização utiliza estruturas de dados de controlo de máquinas virtuais (VMCs) para configurar o comportamento do processador relacionado com a virtualização. Os VMCS devem ser ativados usando uma instrução VMPTRLD e modificados usando instruções VMREAD e VMWRITE. Estas instruções são frequentemente um gargalo significativo para a virtualização aninhada porque têm de ser emuladas.

O hipervisor expõe uma funcionalidade "VMCS iluminada" que pode ser usada para controlar o comportamento do processador relacionado com virtualização usando uma estrutura de dados na memória física convidada. Esta estrutura de dados pode ser modificada usando instruções normais de acesso à memória, pelo que não há necessidade do hipervisor L1 executar instruções VMREAD, VMWRITE ou VMPTRLD.

O hipervisor L1 pode optar por usar VMCS iluminados escrevendo 1 no campo correspondente na Página de Assistência ao Processador Virtual. Outro campo na página de assistência ao VP controla o VMCS iluminado atualmente ativo. Cada VMCS iluminado tem exatamente uma página (4 KB) de tamanho e deve ser inicialmente zerado. Nenhuma instrução VMPTRLD deve ser executada para tornar um VMCS iluminado ativo ou atual.

Depois de o hipervisor L1 realizar uma entrada VM com um VMCS iluminado, o VMCS é considerado ativo no processador. Um VMCS iluminado só pode estar ativo num único processador ao mesmo tempo. O hipervisor L1 pode executar uma instrução VMCLEAR para transitar um VMCS iluminado do estado ativo para o não ativo. Qualquer instrução VMREAD ou VMWRITE enquanto um VMCS iluminado está ativo não é suportada e pode resultar em comportamentos inesperados.

A estrutura HV_VMX_ENLIGHTENED_VMCS define a disposição do VMCS iluminado. Todos os campos não sintéticos correspondem a uma codificação física VMCS da Intel.

Campos Limpos

O hipervisor L0 pode optar por armazenar em cache partes do VMCS iluminado. Os campos limpos do VMCS iluminado controlam quais as partes do VMCS iluminado que são recarregadas a partir da memória de convidados numa entrada de VM aninhada. O hipervisor L1 deve limpar os campos limpos VMCS correspondentes sempre que modifica o VMCS iluminado, caso contrário o hipervisor L0 pode usar uma versão obsoleta.

A iluminação dos campos limpos é controlada através do campo sintético "Campos Limpos" do VMCS iluminado. Por defeito, todos os bits são definidos de modo que o hipervisor L0 tenha de recarregar os campos VMCS correspondentes para cada entrada aninhada da VM.

Descoberta de funcionalidades

O suporte para uma interface VMCS iluminada é reportado com 0x40000004 CPUID leaf.

A estrutura VMCS iluminada é versionada para ter em conta mudanças futuras. Cada estrutura VMCS iluminada contém um campo de versão, que é reportado pelo hipervisor L0.

A única versão VMCS atualmente suportada é a 1.

Considerações de Implementação do Hipervisor

Para a maioria dos campos VMCS, o campo VMCS iluminado correspondente é suportado para uma VM se o campo VMCS for suportado para a VM, conforme determinado através dos mecanismos de descoberta de características arquitetónicas. Exceções são reportadas no CPUID leaf 0x4000000A.

Em casos em que os mecanismos de descoberta de características arquitetónicas indicam suporte a um campo VMCS para o qual não está definido um campo VMCS iluminado, o hipervisor L1 não deve ativar a funcionalidade se optar por usar VMCS iluminado.

O hipervisor L0 Hyper-V não indicará suporte a um campo VMCS para o qual não esteja definido nenhum campo ou exceção VMCS iluminado. Se outro hipervisor L0 precisar de definir um novo campo VMCS esclarecido ou exceção, por favor contacte a Microsoft.

Campos VMCB ligados (AMD)

A AMD reservou espaço no VMCB para uso do hipervisor, bem como um bit limpo associado. Os bytes reservados encontram-se na secção de controlo, deslocados 0x3E0-3FF, do VMCB. O bit limpo é o bit 31 (o bit limpo deve ser invalidado sempre que o hipervisor modifica a área de "iluminação" do VMCB).

Hyper-V utiliza a área reservada VMCB para configurar iluminações. A estrutura HV_SVM_ENLIGHTENED_VMCB_FIELDS documenta o formato.

Bitmap MSR Iluminado

O hipervisor L0 emula os controlos "MSR-Bitmap" tanto nas plataformas Intel como AMD, que permitem ao software de virtualização controlar quais os acessos MSR que geram interceções.

O hipervisor L1 pode colaborar com o hipervisor L0 para tornar os acessos MSR mais eficientes. Pode permitir bitmaps MSR iluminados definindo o campo correspondente nos campos VMCS / VMCB iluminados para 1. Quando ativado, o hipervisor L0 não monitoriza os bitmaps MSR para alterações. Em vez disso, o hipervisor L1 deve invalidar o campo limpo correspondente após fazer alterações a um dos bitmaps MSR.

O suporte ao bitmap MSR iluminado é reportado em CPUID leaf 0x4000000A.

Compatibilidade com a Migração ao Vivo

Hyper-V tem a capacidade de migrar em tempo real uma partição filha de um host para outro. As migrações vivas são tipicamente transparentes para a partição filha. No entanto, no caso da virtualização aninhada, o hipervisor L1 pode precisar de estar atento às migrações.

Notificação de Migração em Direto

Um hipervisor L1 pode pedir para ser notificado quando a sua partição for migrada. Esta capacidade é enumerada no CPUID como privilégio "AccessReenlightenmentControls". O hipervisor L0 expõe um MSR sintético (HV_X64_MSR_REENLIGHTENMENT_CONTROL) que pode ser usado pelo hipervisor L1 para configurar um vetor de interrupção e um processador alvo. O hipervisor L0 irá injetar uma interrupção com o vetor especificado após cada migração.

#define HV_X64_MSR_REENLIGHTENMENT_CONTROL (0x40000106)

typedef union
{
    UINT64 AsUINT64;
    struct
    {
        UINT64 Vector :8;
        UINT64 RsvdZ1 :8;
        UINT64 Enabled :1;
        UINT64 RsvdZ2 :15;
        UINT64 TargetVp :32;
    };
} HV_REENLIGHTENMENT_CONTROL;

O vetor especificado deve corresponder a uma interrupção APIC fixa. O TargetVp especifica o índice do processador virtual.

Emulação TSC

Uma partição de convidados pode ser migrada em tempo real entre duas máquinas com frequências TSC diferentes. Nesses casos, o valor TscScale da página de referência do TSC pode precisar de ser recalculado.

O hipervisor L0 emula opcionalmente todos os acessos TSC após uma migração até que o hipervisor L1 tenha tido oportunidade de recalcular o valor TscScale. O hipervisor L1 pode optar pela Emulação TSC escrevendo no MSR HV_X64_MSR_TSC_EMULATION_CONTROL. Se optar por aderir, o hipervisor L0 emula os acessos TSC após a migração.

O hipervisor L1 pode consultar se os acessos TSC estão atualmente a ser emulados usando o HV_X64_MSR_TSC_EMULATION_STATUS MSR. Por exemplo, o hipervisor L1 poderia subscrever as notificações de Migração ao Vivo e consultar o estado do TSC após receber a interrupção de migração. Também pode desligar a emulação TSC (após atualizar o valor TscScale) usando este MSR.

#define HV_X64_MSR_TSC_EMULATION_CONTROL (0x40000107)
#define HV_X64_MSR_TSC_EMULATION_STATUS (0x40000108)

typedef union
{
    UINT64 AsUINT64;
    struct
    {
        UINT64 Enabled :1;
        UINT64 RsvdZ :63;
    };
 } HV_TSC_EMULATION_CONTROL;

typedef union
{
    UINT64 AsUINT64;
    struct
    {
        UINT64 InProgress : 1;
        UINT64 RsvdP1 : 63;
    };
} HV_TSC_EMULATION_STATUS;

Virtual TLB

O TLB virtual exposto pelo hipervisor pode ser estendido para traduções em cache de GPAs L2 para GPAs. Assim como o TLB em um processador lógico, o TLB virtual é um cache não coerente, e essa não coerência é visível para os convidados. O hipervisor expõe operações para gerir o TLB.

Flush Virtual Direto

O hipervisor expõe hiperchamadas (HvCallFlushVirtualAddressSpace, HvCallFlushVirtualAddressSpaceEx, HvCallFlushVirtualAddressList e HvCallFlushVirtualAddressListEx) que permitem aos sistemas operativos gerir o TLB virtual de forma mais eficiente. O hipervisor L1 pode optar por permitir que o seu convidado use essas chamadas e delegar a responsabilidade de as tratar ao hipervisor L0. Isto requer o uso de uma página de assistência de partição (e um VMCS virtual nas plataformas Intel).

Quando em uso, o TLB virtual etiqueta todos os mapeamentos em cache com um identificador do contexto aninhado (VMCS ou VMCB) que os criou. Em resposta a uma hiperchamada de flush virtual direta de um convidado L2, o hipervisor L0 invalida todos os mapeamentos em cache criados por contextos aninhados onde

  • O VmId é o mesmo que o VMID do chamador
  • Ou o VpId está contido na Máscara de Processador especificada ou HV_FLUSH_ALL_PROCESSORS é especificado

O suporte a flushes virtuais diretos é reportado em CPUID leaf 0x4000000A.

Configuração

O tratamento direto das hiperchamadas de flush virtual é possibilitado por:

  1. Definindo o campo NestedEnlightenmentsControl.Features.DirectHypercall da Página de Assistência do Processador Virtual para 1.
  2. Definir o campo EnlightenmentsControl.NestedFlushVirtualHypercall de um VMCS ou VMCB iluminado para 1.

Antes de o ativar, o hipervisor L1 deve configurar os seguintes campos adicionais do VMCS / VMCB iluminado:

  • VpId: ID do processador virtual que o VMCS / VMCB iluminado controla.
  • VmId: ID da máquina virtual à qual pertence o VMCS / VMCB iluminado.
  • PartitionAssistPage: Endereço físico convidado da página de assistência de partição.

O hipervisor L1 deve também expor as seguintes capacidades aos seus convidados via CPUID.

  • UseHypercallForLocalFlush
  • UseHypercallForRemoteFlush

Página de Assistência de Partição

A página de assistência de partição é uma região de memória alinhada ao tamanho da página que o hipervisor L1 deve alocar e zerar antes de poderem ser usadas chamadas de flush direto. A sua média deve ser escrita para a área correspondente no VMCS / VMCB iluminado.

struct
{
    UINT32 TlbLockCount;
} VM_PARTITION_ASSIST_PAGE;

Sintético VM-Exit

Se o TlbLockCount da página de assistência de partição do chamador for diferente de zero, o hipervisor L0 fornece um VM-Exit com uma razão sintética de saída para o hipervisor L1 após gerir uma hiperchamada de flush virtual direta.

Nas plataformas Intel, é entregue um VM-Exit com razão HV_VMX_SYNTHETIC_EXIT_REASON_TRAP_AFTER_FLUSH de saída. Nas plataformas AMD, é entregue um VM-Exit com código HV_SVM_EXITCODE_ENL de saída e o ExitInfo1 é definido para HV_SVM_ENL_EXITCODE_TRAP_AFTER_FLUSH.

#define HV_VMX_SYNTHETIC_EXIT_REASON_TRAP_AFTER_FLUSH 0x10000031

#define HV_SVM_EXITCODE_ENL 0xF0000000
#define HV_SVM_ENL_EXITCODE_TRAP_AFTER_FLUSH   (1)

Tradução de Endereços de Segundo Nível

Quando a virtualização aninhada é ativada para uma partição convidada, a unidade de gestão de memória (MMU) exposta pela partição inclui suporte para tradução de endereços de segundo nível. A tradução de endereços de segundo nível é uma capacidade que pode ser usada pelo hipervisor L1 para virtualizar memória física. Quando em uso, certos endereços que seriam tratados como endereços físicos de convidados (GPAs) são tratados como endereços físicos de convidados L2 (GPAs L2) e traduzidos para GPAs através de um conjunto de estruturas de paginação.

O hipervisor L1 pode decidir como e onde usar espaços de endereçamento de segundo nível. Cada espaço de endereçamento de segundo nível é identificado por um valor de ID de 64 bits definido por convidado. Nas plataformas Intel, este valor é o mesmo do ponteiro EPT. Nas plataformas AMD, o valor é igual ao campo nCR3 VMCB.

Compatibility

A capacidade de tradução de endereços de segundo nível exposta pelo hipervisor é geralmente compatível com o suporte VMX ou SVM para tradução de endereços. No entanto, existem as seguintes diferenças observáveis por visitas:

  • Internamente, o hipervisor pode usar tabelas de páginas sombra que traduzem GPAs L2 para SPAs. Nessas implementações, estas tabelas de páginas sombra aparecem ao software como grandes TLBs. No entanto, podem ser observadas várias diferenças. Primeiro, as tabelas de páginas sombra podem ser partilhadas entre dois processadores virtuais, enquanto as TLBs tradicionais são estruturas por processador e independentes. Esta partilha pode ser visível porque um acesso à página por um processador virtual pode preencher uma entrada de tabela de páginas sombra que é posteriormente usada por outro processador virtual.
  • Algumas implementações de hipervisores podem usar proteção interna de escrita de tabelas de páginas convidadas para limpar preguiçosamente mapeamentos MMU de estruturas de dados internas (por exemplo, tabelas de páginas sombra). Isto é arquitetonicamente invisível para o convidado porque as escritas nestas tabelas serão tratadas de forma transparente pelo hipervisor. No entanto, escritas feitas nas páginas GPA subjacentes por outras partições ou dispositivos podem não acionar o flush TLB apropriado.
  • Em algumas implementações de hipervisores, uma falha de página de segundo nível pode não invalidar mapeamentos em cache.

Flushes TLB de Segundo Nível Iluminado

O hipervisor também suporta um conjunto de melhorias que permitem a um convidado gerir o TLB de segundo nível de forma mais eficiente. Essas operações aprimoradas podem ser usadas de forma intercambiável com operações de gerenciamento de TLB legadas.

O hipervisor suporta as seguintes hiperchamadas para invalidar TLBs:

Hiperchamada Description
HvCallFlushConvidadoFísicoEndereçoEspaço invalida os mapeamentos de GPA L2 para GPA em cache dentro de um espaço de endereçamento de segundo nível.
HvChamadaFlushConvidadosFísicaEndereçosListas invalida os mapeamentos em cache de GVA / GPA L2 para GPA dentro de uma parte de um espaço de endereçamento de segundo nível.

Nas plataformas AMD, todas as entradas do TLB são arquitetonicamente marcadas com um ASID (identificador de espaço de endereçamento). A invalidação do ASID faz com que todas as entradas TLB associadas ao ASID sejam invalidadas. O hipervisor aninhado pode, opcionalmente, optar por um "TLB iluminado" definindo EnlightenedNptTlb como "1" em HV_SVM_ENLIGHTENED_VMCB_FIELDS. Se o hipervisor aninhado optar por aderir ao iluminamento, as invalidações do ASID simplesmente eliminam entradas TLB derivadas da tradução de endereços de primeiro nível (ou seja, o espaço de endereçamento virtual). Para limpar as entradas do TLB derivadas da tabela de páginas aninhadas (NPT) e forçar o hipervisor L0 a reconstruir as tabelas de páginas sombra, devem ser usadas as chamadas HvCallFlushGuestPhysicalAddressSpace ou HvCallFlushGuestPhysicalAddressList.

Exceções de Virtualização Aninhada

Nas plataformas da Intel. o hipervisor L1 pode optar por combinar exceções de virtualização na classe de exceção de falha de página. O hipervisor L0 anuncia suporte para esta iluminação na folha CPUID das Características de Virtualização Aninhada do Hipervisor.

Este esclarecimento pode ser ativado definindo o VirtualizationException como "1" na HV_NESTED_ENLIGHTENMENTS_CONTROL estrutura de dados na Página de Assistência ao Processador Virtual.

MSRs de virtualização aninhada

Registo de Índice VP aninhado

O hipervisor L1 expõe um MSR que reporta o índice VP subjacente do processador atual.

Endereço MSR Nome do Registo Description
0x40001002 HV_X64_MSR_NESTED_VP_INDEX Numa partição raiz aninhada, reporta o índice VP subjacente do processador atual.

MSRs SynIC aninhados

Numa partição raiz aninhada, os seguintes MSRs permitem o acesso aos registos SynIC correspondentes do hipervisor base.

Para encontrar o índice do processador subjacente, os que chamam devem primeiro usar HV_X64_MSR_NESTED_VP_INDEX.

Endereço MSR Nome do Registo MSR subjacente
0x40001080 HV_X64_MSR_NESTED_SCONTROL HV_X64_MSR_SCONTROL
0x40001081 HV_X64_MSR_NESTED_SVERSION HV_X64_MSR_SVERSION
0x40001082 HV_X64_MSR_NESTED_SIEFP HV_X64_MSR_SIEFP
0x40001083 HV_X64_MSR_NESTED_SIMP HV_X64_MSR_SIMP
0x40001084 HV_X64_MSR_NESTED_EOM HV_X64_MSR_EOM
0x40001090 HV_X64_MSR_NESTED_SINT0 HV_X64_MSR_SINT0
0x40001091 HV_X64_MSR_NESTED_SINT1 HV_X64_MSR_SINT1
0x40001092 HV_X64_MSR_NESTED_SINT2 HV_X64_MSR_SINT2
0x40001093 HV_X64_MSR_NESTED_SINT3 HV_X64_MSR_SINT3
0x40001094 HV_X64_MSR_NESTED_SINT4 HV_X64_MSR_SINT4
0x40001095 HV_X64_MSR_NESTED_SINT5 HV_X64_MSR_SINT5
0x40001096 HV_X64_MSR_NESTED_SINT6 HV_X64_MSR_SINT6
0x40001097 HV_X64_MSR_NESTED_SINT7 HV_X64_MSR_SINT7
0x40001098 HV_X64_MSR_NESTED_SINT8 HV_X64_MSR_SINT8
0x40001099 HV_X64_MSR_NESTED_SINT9 HV_X64_MSR_SINT9
0x4000109A HV_X64_MSR_NESTED_SINT10 HV_X64_MSR_SINT10
0x4000109B HV_X64_MSR_NESTED_SINT11 HV_X64_MSR_SINT11
0x4000109C HV_X64_MSR_NESTED_SINT12 HV_X64_MSR_SINT12
0x4000109D HV_X64_MSR_NESTED_SINT13 HV_X64_MSR_SINT13
0x4000109E HV_X64_MSR_NESTED_SINT14 HV_X64_MSR_SINT14
0x4000109F HV_X64_MSR_NESTED_SINT15 HV_X64_MSR_SINT15