Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
La virtualisation imbriquée fait référence à l’hyperviseur Hyper-V émulant des extensions de virtualisation matérielle. Ces extensions émulées peuvent être utilisées par d’autres logiciels de virtualisation (par exemple, un hyperviseur imbriqué) pour s’exécuter sur la plateforme Hyper-V.
Cette fonctionnalité est disponible uniquement pour les partitions invitées. Elle doit être activée par machine virtuelle. La virtualisation imbriquée n’est pas prise en charge dans une partition racine Windows.
La terminologie suivante permet de définir différents niveaux de virtualisation imbriquée :
| Terme | Definition |
|---|---|
| Hyperviseur L0 | Hyperviseur Hyper-V s’exécutant sur du matériel physique. |
| Racine L1 | Système d’exploitation racine Windows. |
| Invité L1 | Une machine virtuelle Hyper-V sans hyperviseur imbriqué. |
| Hyperviseur L1 | Hyperviseur imbriqué s’exécutant dans une machine virtuelle Hyper-V. |
| Racine L2 | Un système d’exploitation Windows racine s’exécutant dans le contexte d’une machine virtuelle Hyper-V. |
| Invité L2 | Une machine virtuelle imbriquée s’exécutant dans le contexte d’une machine virtuelle Hyper-V. |
Par rapport aux hyperviseurs nus, les hyperviseurs peuvent entraîner une régression significative des performances lors de l’exécution dans une machine virtuelle. Les hyperviseurs L1 peuvent être optimisés pour s’exécuter dans une machine virtuelle Hyper-V à l’aide d’interfaces compatibles fournies par l’hyperviseur L0.
Cette fonctionnalité est actuellement prise en charge uniquement sur x64.
VMCS (Intel) éclairé
Sur les plateformes Intel, le logiciel de virtualisation utilise des structures de données de contrôle de machine virtuelle (VMCS) pour configurer le comportement du processeur lié à la virtualisation. Les VMCS doivent être actifs à l’aide d’une instruction VMPTRLD et modifiées à l’aide des instructions VMREAD et VMWRITE. Ces instructions sont souvent un goulot d’étranglement important pour la virtualisation imbriquée, car elles doivent être émulées.
L’hyperviseur expose une fonctionnalité « vmCS compatible » qui peut être utilisée pour contrôler le comportement du processeur lié à la virtualisation à l’aide d’une structure de données dans la mémoire physique invitée. Cette structure de données peut être modifiée à l’aide d’instructions normales d’accès à la mémoire. Il n’est donc pas nécessaire que l’hyperviseur L1 exécute des instructions VMREAD ou VMWRITE ou VMPTRLD.
L1 hyperviseur peut choisir d’utiliser des VMCS compatibles en écrivant 1 dans le champ correspondant dans la page d’assistance du processeur virtuel. Un autre champ de la page d’assistance VP contrôle le VMCS actuellement activé. Chaque VMCS éclairé est exactement une page (4 Ko) de taille et doit être initialement zéro. Aucune instruction VMPTRLD ne doit être exécutée pour rendre un VMCS actif ou actif compatible.
Une fois que l’hyperviseur L1 effectue une entrée de machine virtuelle avec un VMCS éclairé, le VMCS est considéré comme actif sur le processeur. Un VMCS compatible ne peut être actif que sur un seul processeur en même temps. L’hyperviseur L1 peut exécuter une instruction VMCLEAR pour passer d’un VMCS éclairé de l’état actif à l’état non actif. Toutes les instructions VMREAD ou VMWRITE lorsqu’un VMCS éclairé est actif n’est pas pris en charge et peut entraîner un comportement inattendu.
La structure HV_VMX_ENLIGHTENED_VMCS définit la disposition du VMCS éclairé. Tous les champs non synthétiques sont mappés à un encodage VMCS physique Intel.
Nettoyer les champs
L’hyperviseur L0 peut choisir de mettre en cache des parties de vmCS compatibles. Les champs de nettoyage VMCS éclairés contrôlent les parties de VMCS compatibles qui sont rechargées à partir de la mémoire invité sur une entrée de machine virtuelle imbriquée. L’hyperviseur L1 doit effacer les champs de nettoyage VMCS correspondants chaque fois qu’il modifie le VMCS éclairé, sinon l’hyperviseur L0 peut utiliser une version obsolète.
L’éclairage des champs propres est contrôlé via le champ synthétique « CleanFields » du VMCS éclairé. Par défaut, tous les bits sont définis de sorte que l’hyperviseur L0 doit recharger les champs VMCS correspondants pour chaque entrée de machine virtuelle imbriquée.
Découverte des fonctionnalités
La prise en charge d’une interface VMCS compatible est signalée avec le 0x40000004 feuille CPUID.
La structure VMCS compatible est versionnée pour tenir compte des modifications futures. Chaque structure VMCS compatible contient un champ de version, qui est signalé par l’hyperviseur L0.
La seule version de VMCS actuellement prise en charge est 1.
Considérations relatives à l’implémentation de l’hyperviseur
Pour la plupart des champs VMCS, le champ VMCS compatible correspondant est pris en charge pour une machine virtuelle si le champ VMCS est pris en charge pour la machine virtuelle, comme déterminé par le biais de mécanismes de découverte de fonctionnalités architecturales. Les exceptions sont signalées dans la feuille UCID 0x4000000A.
Dans les cas où les mécanismes de découverte de fonctionnalités architecturales indiquent la prise en charge d’un champ VMCS pour lequel aucun champ VMCS compatible n’est défini, l’hyperviseur L1 ne doit pas activer la fonctionnalité si elle choisit d’utiliser vmCS compatible.
L’hyperviseur Hyper-V L0 n’indique pas la prise en charge d’un champ VMCS pour lequel aucun champ VMCS ou exception éclairé n’est défini. Si un autre hyperviseur L0 a besoin d’un nouveau champ VMCS ou d’une exception compatible à définir, contactez Microsoft.
Champs VMCB enlighendés (AMD)
AMD dispose d’un espace réservé dans vmCB pour l’utilisation de l’hyperviseur, ainsi qu’un bit propre associé. Les octets réservés se trouvent dans la section de contrôle, offset 0x3E0-3FF, du VMCB. Le bit propre est bit 31 (le bit propre doit être invalidé chaque fois que l’hyperviseur modifie la zone « illuminations » du VMCB).
Hyper-V utilise la zone VMCB réservée pour configurer des éclairages. La structure HV_SVM_ENLIGHTENED_VMCB_FIELDS documente le format.
Bitmap MSR compatible
L0 hyperviseur émule les contrôles « MSR-Bitmap » sur les plateformes Intel et AMD qui permettent au logiciel de virtualisation de contrôler les accès MSR qui génèrent des intercepts.
L’hyperviseur L1 peut collaborer avec l’hyperviseur L0 pour rendre les accès MSR plus efficaces. Il peut activer les bitmaps MSR compatibles en définissant le champ correspondant dans les champs VMCS / VMCB éclairés sur 1. Lorsqu’il est activé, l’hyperviseur L0 ne surveille pas les bitmaps MSR pour les modifications. Au lieu de cela, l’hyperviseur L1 doit invalider le champ propre correspondant après avoir apporté des modifications à l’une des bitmaps MSR.
La prise en charge de la bitmap MSR compatible est signalée dans le 0x4000000A feuille CPUID.
Compatibilité avec la migration dynamique
Hyper-V a la possibilité de migrer une partition enfant d’un hôte vers un autre hôte. Les migrations dynamiques sont généralement transparentes vers la partition enfant. Toutefois, dans le cas de la virtualisation imbriquée, l’hyperviseur L1 peut avoir besoin de connaître les migrations.
Notification de migration dynamique
Un hyperviseur L1 peut demander d’être averti lorsque sa partition est migrée. Cette fonctionnalité est énumérée dans CPUID en tant que privilège « AccessReenlightenmentControls ». L’hyperviseur L0 expose un MSR synthétique (HV_X64_MSR_REENLIGHTENMENT_CONTROL) qui peut être utilisé par l’hyperviseur L1 pour configurer un vecteur d’interruption et un processeur cible. L’hyperviseur L0 injecte une interruption avec le vecteur spécifié après chaque migration.
#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;
Le vecteur spécifié doit correspondre à une interruption APIC fixe. TargetVp spécifie l’index du processeur virtuel.
Émulation TSC
Une partition d’invité peut être migrée en direct entre deux machines avec des fréquences TSC différentes. Dans ces cas, la valeur TscScale de la page TSC de référence peut avoir besoin d’être recomputée.
L’hyperviseur L0 émule éventuellement tous les accès TSC après une migration jusqu’à ce que l’hyperviseur L1 ait eu la possibilité de recompiler la valeur TscScale. L’hyperviseur L1 peut opter pour l’émulation TSC en écrivant dans la HV_X64_MSR_TSC_EMULATION_CONTROL MSR. S’il est choisi, l’hyperviseur L0 émule les accès TSC après une migration.
L’hyperviseur L1 peut interroger si les accès TSC sont actuellement émulés à l’aide du MSR HV_X64_MSR_TSC_EMULATION_STATUS. Par exemple, l’hyperviseur L1 peut s’abonner aux notifications de migration dynamique et interroger l’état TSC après avoir reçu l’interruption de migration. Il peut également désactiver l’émulation TSC (après avoir mis à jour la valeur TscScale) à l’aide de ce 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;
TLB virtuel
L’équilibrage de charge de charge virtuel exposé par l’hyperviseur peut être étendu pour mettre en cache les traductions des objets de stratégie de groupe L2 vers des objets de stratégie de groupe. Comme pour le TLB sur un processeur logique, le TLB virtuel est un cache non cohérent et cette non-cohérence est visible pour les invités. L’hyperviseur expose les opérations pour gérer l’équilibrage de charge réseau.
Vidage virtuel direct
L’hyperviseur expose des hypercalls (HvCallFlushVirtualAddressSpace, HvCallFlushVirtualAddressSpaceEx, HvCallFlushVirtualAddressList et HvCallFlushVirtualAddressListEx) qui permettent aux systèmes d’exploitation de gérer plus efficacement le TLB virtuel. L1 hyperviseur peut choisir de permettre à son invité d’utiliser ces hypercalls et de déléguer la responsabilité de les gérer à l’hyperviseur L0. Cela nécessite l’utilisation d’une page d’assistance de partition (et d’une machine virtuelle VMCS sur les plateformes Intel).
En cas d’utilisation, le TLB virtuel étiquette tous les mappages mis en cache avec un identificateur du contexte imbriqué (VMCS ou VMCB) qui les a créés. En réponse à un hypercall de vidage virtuel direct à partir d’un invité L2, l’hyperviseur L0 invalide tous les mappages mis en cache créés par des contextes imbriqués où
- VmId est identique à vmId de l’appelant
- Le VpId est contenu dans le processeurMask spécifié ou HV_FLUSH_ALL_PROCESSORS est spécifié.
La prise en charge des vidages virtuels directs est signalée dans la feuille UCID 0x4000000A.
Paramétrage
La gestion directe des hypercalls de vidage virtuel est activée par :
- Définition du champ NestedEnlightenmentsControl.Features.DirectHypercall de la page d’assistance du processeur virtuel sur 1.
- Définition du champ EnlightenmentsControl.NestedFlushVirtualHypercall d’un VMCS ou VMCB éclairé sur 1.
Avant de l’activer, l’hyperviseur L1 doit configurer les champs supplémentaires suivants du VMCS / VMCB éclairé :
- VpId : ID du processeur virtuel que les contrôles VMCS / VMCB éclairés.
- VmId : ID de la machine virtuelle à laquelle appartient vmCS / VMCB éclairé.
- PartitionAssistPage : adresse physique de l’invité de la page d’assistance de partition.
L1 hyperviseur doit également exposer les fonctionnalités suivantes à ses invités via CPUID.
- UseHypercallForLocalFlush
- UseHypercallForRemoteFlush
Partition Assist Page
La page d’assistance de partition est une région de mémoire alignée sur la taille de page que l’hyperviseur L1 doit allouer et zéro avant que les hypercalls de vidage direct puissent être utilisés. Son GPA doit être écrit dans le champ correspondant dans le VMCS / VMCB éclairé.
struct
{
UINT32 TlbLockCount;
} VM_PARTITION_ASSIST_PAGE;
VM-Exit synthétique
Si le TlbLockCount de la page d’assistance de partition de l’appelant n’est pas égal à zéro, l’hyperviseur L0 remet un VM-Exit avec une raison de sortie synthétique à l’hyperviseur L1 après avoir géré un hypercall de vidage virtuel direct.
Sur les plateformes Intel, une VM-Exit avec raison HV_VMX_SYNTHETIC_EXIT_REASON_TRAP_AFTER_FLUSH de sortie est fournie. Sur les plateformes AMD, un VM-Exit avec le code HV_SVM_EXITCODE_ENL de sortie est remis et ExitInfo1 a la valeur 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)
Traduction d’adresses de deuxième niveau
Lorsque la virtualisation imbriquée est activée pour une partition invitée, l’unité de gestion de mémoire (MMU) exposée par la partition inclut la prise en charge de la traduction d’adresses de deuxième niveau. La traduction d’adresses de deuxième niveau est une fonctionnalité qui peut être utilisée par l’hyperviseur L1 pour virtualiser la mémoire physique. En cas d’utilisation, certaines adresses qui seraient traitées comme des adresses physiques invitées (GPA) sont traitées comme des adresses physiques invitées L2 (GPO) et traduites en objets de stratégie de groupe en parcourant un ensemble de structures de pagination.
L’hyperviseur L1 peut décider comment et où utiliser des espaces d’adressage de deuxième niveau. Chaque espace d’adressage de deuxième niveau est identifié par une valeur d’ID 64 bits définie par l’invité. Sur les plateformes Intel, cette valeur est identique au pointeur EPT. Sur les plateformes AMD, la valeur est égale au champ VMCB nCR3.
Compatibilité
La fonctionnalité de traduction d’adresses de deuxième niveau exposée par l’hyperviseur est généralement compatible avec la prise en charge de VMX ou SVM pour la traduction d’adresses. Toutefois, les différences observables par l’invité suivantes existent :
- En interne, l’hyperviseur peut utiliser des tables de pages d’ombres qui traduisent les comptes de stratégie de groupe L2 en autorités de service. Dans ces implémentations, ces tables de pages fantômes semblent être logicielles comme des TLB volumineuses. Toutefois, plusieurs différences peuvent être observables. Tout d’abord, les tables de pages fantômes peuvent être partagées entre deux processeurs virtuels, tandis que les TLB traditionnelles sont des structures par processeur et sont indépendantes. Ce partage peut être visible, car un accès à la page par un processeur virtuel peut remplir une entrée de table d’ombres qui est ensuite utilisée par un autre processeur virtuel.
- Certaines implémentations d’hyperviseur peuvent utiliser la protection en écriture interne des tables de pages invitées pour vider les mappages MMU à partir de structures de données internes (par exemple, les tables de pages fantômes). Cela est architecturalement invisible pour l’invité, car les écritures dans ces tables seront gérées de manière transparente par l’hyperviseur. Toutefois, les écritures effectuées dans les pages GPA sous-jacentes par d’autres partitions ou par les appareils peuvent ne pas déclencher le vidage TLB approprié.
- Dans certaines implémentations d’hyperviseur, une erreur de page de deuxième niveau peut ne pas invalider les mappages mis en cache.
Vidages TLB de deuxième niveau éclairés
L’hyperviseur prend également en charge un ensemble d’améliorations qui permettent à un invité de gérer plus efficacement le TLB de second niveau. Ces opérations améliorées peuvent être utilisées de façon interchangeable avec les opérations de gestion de LLB héritées.
L’hyperviseur prend en charge les hypercalls suivants pour invalider les TLB :
| Hypercall | Descriptif |
|---|---|
| HvCallFlushGuestPhysicalAddressSpace | invalide les mappages GPA L2 mis en cache dans un espace d’adressage de deuxième niveau. |
| HvCallFlushGuestPhysicalAddressList | invalide les mappages GVA /L2 GPA mis en cache dans une partie d’un espace d’adressage de deuxième niveau. |
Sur les plateformes AMD, toutes les entrées TLB sont étiquetées de manière architecturale avec un ASID (identificateur d’espace d’adressage). L’invalidation de l’ASID entraîne l’invalidation de tous les ensembles TLB associés à l’ASID. L’hyperviseur imbriqué peut éventuellement opter pour un « TLB éclairé » en définissant EnlightenedNptTlb sur « 1 » dans HV_SVM_ENLIGHTENED_VMCB_FIELDS. Si l’hyperviseur imbriqué opte dans l’éclairage, les invalidations ASID vident simplement les entiers TLB dérivés de la traduction d’adresses de premier niveau (c’est-à-dire l’espace d’adressage virtuel). Pour vider les entrées TLB dérivées de la table de pages imbriquée (CF) et forcer l’hyperviseur L0 à reconstruire les tables de pages fantômes, les hypercalls HvCallFlushGuestPhysicalAddressSpace ou HvCallFlushGuestPhysicalAddressList doivent être utilisés.
Exceptions de virtualisation imbriquées
Sur les plateformes Intel. l’hyperviseur L1 peut choisir de combiner des exceptions de virtualisation dans la classe d’exception d’erreur de page. L’hyperviseur L0 annonce la prise en charge de cet éclairage dans la feuille CPUID des fonctionnalités de virtualisation imbriquées hyperviseur.
Cet éclairage peut être activé en définissant VirtualizationException sur « 1 » dans HV_NESTED_ENLIGHTENMENTS_CONTROL structure de données dans la page d’assistance du processeur virtuel.
MSR de virtualisation imbriquée
Registre d’index VP imbriqué
L1 hyperviseur expose un MSR qui signale l’index VP sous-jacent du processeur actuel.
| Adresse MSR | Nom de l’inscription | Descriptif |
|---|---|---|
| 0x40001002 | HV_X64_MSR_NESTED_VP_INDEX | Dans une partition racine imbriquée, signale l’index VP sous-jacent du processeur actuel. |
MSR SynIC imbriqués
Dans une partition racine imbriquée, les MSR suivants autorisent l’accès aux registres SynIC correspondants de l’hyperviseur de base.
Pour rechercher l’index du processeur sous-jacent, les appelants doivent d’abord utiliser HV_X64_MSR_NESTED_VP_INDEX.
| Adresse MSR | Nom de l’inscription | MSR sous-jacent |
|---|---|---|
| 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 |