Partilhar via


Comunicação Inter-Partition

O hipervisor fornece dois mecanismos simples para que uma partição comunique com outra: mensagens e eventos. Em ambos os casos, a notificação é sinalizada através do SynIC (controlador sintético de interrupções).

Mensagens SynIC

O hipervisor fornece uma funcionalidade simples de comunicação entre partições que permite que uma partição envie uma mensagem parametrizada para outra partição. (Como a mensagem é enviada de forma assíncrona, diz-se que foi publicada.) A partição de destino pode ser notificada da chegada desta mensagem através de uma interrupção. As mensagens podem ser enviadas explicitamente através da hiperchamada HvCallPostMessage ou implicitamente pelo hipervisor.

Messages

Quando uma mensagem é enviada, o hipervisor seleciona um buffer de mensagens livre. O conjunto de buffers de mensagens disponíveis depende do evento que desencadeou o envio da mensagem.

O hipervisor marca o buffer da mensagem como "em uso" e preenche o cabeçalho da mensagem com o tipo de mensagem, o tamanho da carga útil e informações sobre o remetente. Finalmente, preenche a carga útil da mensagem. O conteúdo da carga útil depende do evento que desencadeou a mensagem.

O hipervisor então adiciona o buffer de mensagens a uma fila de mensagens recetoras. A fila de mensagens recetoras depende do evento que desencadeou o envio da mensagem. Para todos os tipos de mensagens, o SINTx é ou implícito (no caso de mensagens de interceção), explícito (no caso de mensagens temporizadoras) ou especificado por um ID de porta (no caso de mensagens convidadas). O processador virtual alvo é explicitamente especificado ou escolhido pelo hipervisor quando a mensagem é enfileirada. Processadores virtuais cuja página SynIC ou SIM esteja desativada não serão considerados como potenciais alvos. Se não houver alvos disponíveis, o hipervisor termina a operação e devolve um erro ao chamador.

O hipervisor determina então se o slot de mensagem SINTx especificado dentro da página SIM para o processador virtual alvo está vazio. Se o tipo de mensagem no slot de mensagem for igual a HvMessageTypeNone (ou seja, zero), assume-se que o slot de mensagem está vazio. Neste caso, o hipervisor remove o buffer de mensagens e copia o seu conteúdo para o slot de mensagem dentro da página do SIM. O hipervisor pode copiar apenas o número de bytes de carga útil associados à mensagem. O hipervisor também tenta gerar uma interrupção desencadeada por arestas para o SINTx especificado. Se o APIC for desativado por software ou o SINTx estiver mascarado, a interrupção é perdida. A chegada desta interrupção notifica o convidado de que chegou uma nova mensagem. Se a página do SIM estiver desativada ou o slot de mensagem dentro da página SIM não estiver vazio, a mensagem permanece em fila e não é gerada qualquer interrupção.

Como em qualquer interrupção de prioridade fixa, a interrupção não é reconhecida pelo processador virtual até que o PPR (registo de prioridade de processo) seja inferior ao vetor especificado no registo SINTx e as interrupções não sejam mascaradas pelo processador virtual (rFLAGS[IF] está definido para 1).

Múltiplos buffers de mensagens com o mesmo SINTx podem ser enfileirados para um processador virtual. Neste caso, o hipervisor entregará a primeira mensagem (ou seja, escreve-a na página do SIM) e deixará as outras na fila até ocorrer um de três eventos:

  • Outro buffer de mensagens está em fila.
  • O convidado indica o "fim da interrupção" escrevendo no registo EOI do APIC.
  • O convidado indica o "fim da mensagem" escrevendo para o registo EOM do SynIC.

Em todos os três casos, o hipervisor irá analisar uma ou mais filas de buffer de mensagens e tentar entregar mensagens adicionais. O hipervisor também tenta gerar uma interrupção desencadeada pela borda, indicando que chegou uma nova mensagem.

Página SIM

A página SIM consiste num array de 16 elementos de mensagens de 256 bytes (ver HV_MESSAGE estrutura de dados). Cada elemento do array (também conhecido como slot de mensagem) corresponde a uma única fonte sintética de interrupção (SINTx). Diz-se que um slot de mensagem está "vazio" se o tipo de mensagem na slot for igual a HvMessageTypeNone.

O endereço da página SIM é especificado no registo SIM. O endereço da página SIM deve ser único para cada processador virtual. Programar estas páginas para se sobreporem a outras instâncias das páginas SIEF ou SIM ou qualquer outra página de sobreposição (por exemplo, a página de hiperchamada) resultará num comportamento indefinido.

Os acessos de leitura e escrita de um processador virtual à página SIM comportam-se como acessos de leitura e escrita à RAM. No entanto, a implementação SynIC do hipervisor também escreve nas páginas em resposta a certos eventos.

Após a criação e reinício do processador virtual, a página do SIM é apagada até zero.

O mecanismo de entrega de mensagens SynIC foi concebido para acomodar a entrega e receção eficiente de mensagens dentro de uma partição alvo. Recomenda-se que a ISR (rotina de serviço de interrupções) que trata mensagens dentro da partição de destino execute os seguintes passos:

  • Examina a mensagem que foi depositada no slot da mensagem SIM.
  • Copie o conteúdo da mensagem para outro local e defina o tipo de mensagem dentro do slot para HvMessageTypeNone.
  • Indique o fim da interrupção para o vetor escrevendo no registo EOI do APIC.
  • Realize quaisquer ações implícitas na mensagem.

Fontes da Mensagem

As classes de eventos que podem desencadear o envio de uma mensagem são as seguintes:

  • Interceções: Qualquer interceção num processador virtual fará com que uma mensagem seja enviada para a partição principal ou para um VTL superior.
  • Temporizadores: Os mecanismos do temporizador fazem com que as mensagens sejam enviadas. Associados a cada processador virtual estão quatro buffers dedicados de mensagens temporizadoras, um para cada temporizador. A fila de mensagens recetora pertence ao SINTx do processador virtual cujo temporizador desencadeou o envio da mensagem.
  • Mensagens de convidados: O hipervisor suporta a passagem de mensagens como um mecanismo de comunicação entre partições entre convidados. As interfaces definidas nesta secção permitem que um convidado envie mensagens a outro convidado. Os buffers de mensagens usados para mensagens desta classe são retirados do pool de buffers de mensagens convidados por porta do recetor.

Buffers de Mensagens

Um buffer de mensagens é usado internamente no hipervisor para armazenar uma mensagem até que esta seja entregue ao destinatário. O hipervisor mantém vários conjuntos de buffers de mensagens.

Buffers de Mensagens de Convidados

O hipervisor mantém um conjunto de buffers de mensagens de convidados para cada porta. Estes buffers são usados para mensagens enviadas explicitamente de uma partição para outra por um convidado. Quando uma porta é criada, o hipervisor aloca dezasseis (16) buffers de mensagens do pool de memória do proprietário da porta. Estes buffers de mensagens são devolvidos ao pool de memória quando a porta é eliminada.

Filas de Buffer de Mensagens

Para cada partição e cada processador virtual na partição, o hipervisor mantém uma fila de buffers de mensagens para cada SINTx (fonte sintética de interrupções) no SynIC do processador virtual. Todas as filas de mensagens de um processador virtual ficam vazias aquando da criação ou reinício do processador virtual.

Fiabilidade e Sequência dos Buffers de Mensagens de Convidados

Mensagens publicadas com sucesso por um convidado foram enfileiradas para entrega pelo hipervisor. A entrega e receção efetivas pela partição alvo dependem do seu funcionamento correto. As partições podem desabilitar a entrega de mensagens a determinados processadores virtuais, desativando o seu SynIC ou desativando o SIMP.

A quebra de uma ligação não afeta as mensagens não entregues (em fila). A eliminação da porta de destino libertará sempre todos os buffers de mensagens da porta, estejam disponíveis ou contenham mensagens não entregues (em fila).

As mensagens chegam pela ordem em que foram publicadas com sucesso. Se a porta recetora estiver associada a um processador virtual específico, as mensagens chegam na mesma ordem em que foram publicadas. Se a porta recetora estiver associada a HV_ANY_VP, então as mensagens não têm garantia de chegar em nenhuma ordem específica.

Flags de Eventos SynIC

Para além das mensagens, o SynIC suporta um segundo tipo de mecanismo de notificação de partição cruzada chamado flags de evento. Os flags de evento podem ser definidos explicitamente usando a hiperchamada HvCallSignalEvent ou implicitamente pelo hipervisor.

Flags de Evento versus Mensagens

Os flags de evento são mais leves do que as mensagens e, por isso, têm menos sobrecarga. Além disso, as flags de evento não requerem qualquer alocação de buffer ou fila dentro do hipervisor, pelo que o HvCallSignalEvent nunca falhará devido à falta de recursos.

Entrega da Bandeira do Evento

Quando uma partição chama HvCallSignalEvent, especifica um número de flag de evento. O hipervisor responde definindo atomicamente um bit dentro da página SIEF do processador virtual receptor. Processadores virtuais cuja página SynIC ou SIEF esteja desativada não serão considerados como potenciais alvos. Se não houver alvos disponíveis, o hipervisor termina a operação e devolve um erro ao chamador.

Se a flag de evento foi previamente apagada, o hipervisor tenta notificar a partição recetora de que a flag está agora definida, gerando uma interrupção desencadeada pela borda. O processador virtual de destino, juntamente com o SINTx de destino, é especificado como parte da criação de uma porta. Se o SINTx estiver mascarado, o HvSignalEvent devolve HV_STATUS_INVALID_SYNIC_STATE.

Tal como em qualquer interrupção externa de prioridade fixa, a interrupção não é reconhecida pelo processador virtual até que o registo de prioridade do processo (PPR) seja inferior ao vetor especificado no registo SINTx e as interrupções não sejam mascaradas pelo processador virtual (rFLAGS[IF] é definido para 1).

Página do SIEF

A página SIEF consiste num array de 16 elementos com flags de evento de 256 bytes (ver HV_SYNIC_EVENT_FLAGS). Cada elemento do array corresponde a uma única fonte sintética de interrupção (SINTx).

O endereço da página SIEF é especificado no registo SIEF. O endereço da página SIEF deve ser único para cada processador virtual. Programar estas páginas para se sobreporem a outras instâncias das páginas SIEF ou SIM ou qualquer outra página de sobreposição (por exemplo, a página de hiperchamada) resultará num comportamento indefinido.

Os acessos de leitura e escrita por um processador virtual à página SIEF comportam-se como acessos de leitura e escrita à RAM. No entanto, a implementação SynIC do hipervisor também escreve nas páginas em resposta a certos eventos.

Após a criação e reinício do processador virtual, a página SIEF é limpa até zero.

Recomenda-se que a rotina de serviço de interrupção de flag de evento (ISR) dentro da partição de destino execute os seguintes passos:

  • Examine os flags de eventos e determine quais, se algum, estão definidos.
  • Elimine uma ou mais flags de evento usando uma operação bloqueada (atómica) como LOCK AND ou LOCK CMPXCHG.
  • Indique o fim da interrupção para o vetor escrevendo no registo EOI do APIC.
  • Realize quaisquer ações implícitas pelas bandeiras de evento que foram definidas.

Portos e Ligações

Uma mensagem ou evento enviado de um convidado para outro deve ser enviado através de uma ligação pré-alocada. Uma ligação, por sua vez, deve estar associada a um porto de destino.

Uma porta é atribuída a partir do pool de memória do recetor e especifica qual processador virtual e SINTx a direcionar. As portas de evento têm um "número de flag base" e uma "contagem de flags" que permitem ao chamador especificar um intervalo de flags de evento válidos para essa porta.

As ligações são alocadas a partir do pool de memória do remetente. Quando uma ligação é criada, esta deve estar associada a uma porta válida. Esta ligação cria um canal de comunicação simples e unidirecional. Se uma porta for subsequentemente eliminada, a sua ligação, enquanto permanecer, torna-se inútil.

Registos SynIC

Cada processador virtual tem a sua própria cópia destes registos, pelo que podem ser programados de forma independente.

Em plataformas x64, estes registos são acedidos como registos específicos de modelo (MSRs) usando instruções RDMSR e WRMSR:

Endereço MSR Nome do Registo Função
0x40000080 SCONTROL Controlo SynIC
0x40000081 VERSÃO Versão SynIC
0x40000082 SIEFP Página de Flags de Eventos de Interrupção
0x40000083 SIMP Página de Mensagem de Interrupção
0x40000084 EOM Fim da mensagem
0x40000090 SINT0 Fonte de interrupção 0 (hipervisor)
0x40000091 SINT1 Fonte de interrupção 1
0x40000092 SINT2 Fonte de interrupção 2
0x40000093 SINT3 Fonte de interrupção 3
0x40000094 SINT4 Fonte de interrupção 4
0x40000095 SINT5 Fonte de interrupção 5
0x40000096 SINT6 Fonte de interrupção 6
0x40000097 SINT7 Fonte de interrupção 7
0x40000098 SINT8 Fonte de interrupção 8
0x40000099 SINT9 Fonte de interrupção 9
0x4000009A SINT10 Fonte de interrupção 10
0x4000009B SINT11 Fonte de interrupção 11
0x4000009C SINT12 Fonte de interrupção 12
0x4000009D SINT13 Fonte de interrupção 13
0x4000009E SINT14 Fonte de interrupção 14
0x4000009F SINT15 Fonte de interrupção 15

Nas plataformas ARM64, estes registos são acedidos usando chamadas de hiperchamadas HvCallGetVpRegisters e HvCallSetVpRegisters com os seguintes nomes de registos:

Nome do Registo HvT Função
HvRegisterScontrol Controlo SynIC
HvRegisterSversion Versão SynIC
HvRegisterSifp Página de Flags de Eventos de Interrupção
HvRegisterSipp Página de Mensagem de Interrupção
HvRegisterEom Fim da mensagem
HvRegisterSirbp Página do Buffer de Resposta a Interrupções
HvRegisterSint0 Fonte de interrupção 0 (hipervisor)
HvRegisterSint1 Fonte de interrupção 1
HvRegisterSint2 Fonte de interrupção 2
HvRegisterSint3 Fonte de interrupção 3
HvRegisterSint4 Fonte de interrupção 4
HvRegisterSint5 Fonte de interrupção 5
HvRegisterSint6 Fonte de interrupção 6
HvRegisterSint7 Fonte de interrupção 7
HvRegisterSint8 Fonte de interrupção 8
HvRegisterSint9 Fonte de interrupção 9
HvRegisterSint10 Fonte de interrupção 10
HvRegisterSint11 Fonte de interrupção 11
HvRegisterSint12 Fonte de interrupção 12
HvRegisterSint13 Fonte de interrupção 13
HvRegisterSint14 Fonte de interrupção 14
HvRegisterSint15 Fonte de interrupção 15

Registo SCONTROL

Este registo é usado para controlar o comportamento SynIC do processador virtual.

No momento da criação do processador virtual e após o reset do processador, o valor deste SCONTROL (registo de controlo SynIC) é 0x0000000000000000. Assim, a fila de mensagens e as notificações de flags de eventos serão desativadas.

Bits Campo Description Attributes
63:1 RsvdP O valor deve ser preservado Lê / escreve
0 Enable Quando definido, este processador virtual permite que a fila de mensagens e notificações de flags de eventos sejam publicadas no seu SynIC. Quando limpo, as notificações de fila de mensagens e de flag de eventos não podem ser direcionadas para este processador virtual. Lê / escreve

Registo SVERSION

Este é um registo de apenas leitura e devolve o número de versão do SynIC. As tentativas de escrever neste registo resultam numa falha #GP.

Bits Campo Description Attributes
63:32 RsvdP Leitura
31:0 Versão SynIC Número de versão do SynIc Leitura

Registo SIEFP

No momento da criação do processador virtual e após o reset do processador, o valor deste registo SIEFP (página de flags sintéticos de eventos de interrupção) é 0x0000000000000000. Assim, o SIEFP está desativado por defeito. O convidado deve ativá-lo definindo o bit 0. Se o endereço base especificado estiver para além do limite do espaço GPA da partição, a página SIEFP não será acessível ao convidado. Ao modificar o registo, os hóspedes devem preservar o valor dos bits reservados (1 a 11) para compatibilidade futura.

Bits Campo Description Attributes
63:12 Morada Base Endereço base (no espaço GPA) do SIEFP (12 bits baixos assumidos como desativados) Ler / Escrever
11:1 RsvdP Reservado, o valor deve ser preservado Ler / Escrever
0 Enable Habilitar o SIEFP Ler / Escrever

Registo SIMP

No momento da criação do processador virtual e após o reset do processador, o valor deste registo SIMP (página sintética de interrupção de mensagens) é 0x0000000000000000. Assim, o SIMP está desativado por defeito. O convidado deve ativá-lo definindo o bit 0. Se o endereço base especificado estiver para além do limite do espaço GPA da partição, a página SIMP não será acessível ao convidado. Ao modificar o registo, os hóspedes devem preservar o valor dos bits reservados (1 a 11) para compatibilidade futura.

Bits Campo Description Attributes
63:12 Morada Base Endereço base (no espaço GPA) do SIMP (12 bits baixos assumidos como desativados) Ler / Escrever
11:1 RsvdP Reservado, o valor deve ser preservado Ler / Escrever
0 Enable Ativação SIMP Ler / Escrever

Registos SINTx

No momento da criação do processador virtual, o valor padrão de todos os registos SINTx (fonte sintética de interrupções) é 0x0000000000010000. Assim, todas as fontes sintéticas de interrupção são mascaradas por defeito. O convidado deve desmascará-los programando um vetor apropriado e limpando o bit 16.

Definir o bit de sondagem terá o efeito de desmascarar uma fonte de interrupção, exceto que uma interrupção real não é gerada.

A bandeira AutoEOI indica que um EOI implícito deve ser realizado pelo hipervisor quando uma interrupção é entregue ao processador virtual. Além disso, o hipervisor limpa automaticamente a correspondente bandeira no "registo em serviço" (ISR) do API virtual. Se o convidado ativar este comportamento, então não deve realizar uma EOI na sua rotina de serviço de interrupção. A flag AutoEOI pode ser ativada a qualquer momento, embora o convidado tenha de realizar um EOI explícito numa interrupção durante o voo. A consideração de temporização dificulta saber se uma interrupção específica necessita de EOI ou não, pelo que recomenda-se que, uma vez desmascarado o SINT, as suas definições não sejam alteradas. Da mesma forma, a bandeira AutoEOI pode ser desligada a qualquer momento, embora se apliquem as mesmas preocupações sobre interrupções em voo

Os valores válidos para vetor são 16-255 inclusive. Especificar um número de vetor inválido resulta em #GP.

Bits Campo Description Attributes
63:19 RsvdP Reservado, o valor deve ser preservado Ler / Escrever
18 Votação Ativa o modo de sondagem Ler / Escrever
17 AutoEOI Definir se uma EOI implícita deve ser realizada após a entrega da interrupção Ler / Escrever
16 Mascarado Definir se o SINT estiver mascarado Ler / Escrever
15:8 RsvdP Reservado, o valor deve ser preservado Ler / Escrever
7:0 Vector Vetor de interrupção Ler / Escrever

Registo EOM

Uma escrita no registo de fim de mensagem (EOM) pelo convidado faz com que o hipervisor escaneie a(s) fila(s) interna(s) do buffer de mensagens associadas ao processador virtual. Se uma fila de buffer de mensagens contiver um buffer de mensagens em fila, o hipervisor tenta entregar a mensagem. A entrega de mensagens é bem-sucedida se a página SIM estiver ativada e o slot de mensagem correspondente ao SINTx estiver vazio (ou seja, o tipo de mensagem no cabeçalho for definido como HvMessageTypeNone). Se uma mensagem for entregue com sucesso, o seu correspondente buffer interno de mensagens é retirado da fila e marcado como livre. Se o SINTx correspondente não estiver mascarado, é entregue uma interrupção acionada por arestas (ou seja, o bit correspondente no IRR é definido).

Este registo pode ser usado pelos convidados para "sondarem" mensagens. Também pode ser usado como forma de drenar a fila de mensagens de um SINTx que foi desativado (ou seja, mascarado).

Se as filas de mensagens estiverem todas vazias, uma escrita no registo EOM é uma no-op.

As leituras do registo EOM devolvem sempre zeros.

Bits Campo Description Attributes
63:0 RsvdZ Gatilho apenas de escrita Escreve