Virtualizzazione nidificata
La virtualizzazione annidata fa riferimento all'hypervisor Hyper-V che emula le estensioni di virtualizzazione hardware. Queste estensioni emulate possono essere usate da altri software di virtualizzazione (ad esempio, un hypervisor annidato) per l'esecuzione nella piattaforma Hyper-V.
Questa funzionalità è disponibile solo per le partizioni guest. Deve essere abilitato per ogni macchina virtuale. La virtualizzazione annidata non è supportata in una partizione radice di Windows.
La terminologia seguente viene usata per definire vari livelli di virtualizzazione annidata:
Termine | Definizione |
---|---|
L0 Hypervisor | Hypervisor Hyper-V in esecuzione su hardware fisico. |
L1 Radice | Sistema operativo radice di Windows. |
L1 Guest | Una macchina virtuale Hyper-V senza un hypervisor annidato. |
L1 Hypervisor | Hypervisor annidato in esecuzione all'interno di una macchina virtuale Hyper-V. |
L2 Radice | Sistema operativo Windows radice, in esecuzione nel contesto di una macchina virtuale Hyper-V. |
L2 Guest | Una macchina virtuale annidata, in esecuzione nel contesto di una macchina virtuale Hyper-V. |
Rispetto a bare metal, gli hypervisor possono comportare una regressione significativa delle prestazioni durante l'esecuzione in una macchina virtuale. Gli hypervisor L1 possono essere ottimizzati per l'esecuzione in una macchina virtuale Hyper-V usando interfacce abilitate fornite dall'hypervisor L0.
Nelle piattaforme Intel il software di virtualizzazione usa le strutture di dati di controllo delle macchine virtuali (VMCS) per configurare il comportamento del processore correlato alla virtualizzazione. Le VMCS devono essere attivate usando un'istruzione VMPTRLD e modificate usando le istruzioni VMREAD e VMWRITE. Queste istruzioni sono spesso un collo di bottiglia significativo per la virtualizzazione annidata perché devono essere emulate.
L'hypervisor espone una funzionalità "VMCS con riconoscimento dei dati" che può essere usata per controllare il comportamento del processore correlato alla virtualizzazione usando una struttura di dati nella memoria fisica guest. Questa struttura di dati può essere modificata usando le normali istruzioni di accesso alla memoria, pertanto non è necessario che l'hypervisor L1 eseseguono istruzioni VMREAD o VMWRITE o VMPTRLD.
L'hypervisor L1 può scegliere di usare le macchine virtuali abilitate scrivendo 1 nel campo corrispondente nella pagina Virtual Processor Assist .The L1 hypervisor may choose to use enlightened VMCSs by writing 1 to the corrispondente field in the Virtual Processor Assist Page. Un altro campo nella pagina di assist VP controlla il vmCS attualmente attivato. Ogni VMCS con riconoscimento dei dati con riconoscimento dei dati è di una sola pagina (4 KB) di dimensioni e deve essere inizialmente zero. Non è necessario eseguire alcuna istruzione VMPTRLD per rendere attivo o aggiornato un VMCS con riconoscimento dei dati.
Dopo che l'hypervisor L1 esegue una voce di macchina virtuale con un VMCS con riconoscimento dei dati con riconoscimento dei dati, il vmCS viene considerato attivo nel processore. Un VMCS con riconoscimento dei dati con riconoscimento dei dati può essere attivo solo in un singolo processore contemporaneamente. L'hypervisor L1 può eseguire un'istruzione VMCLEAR per eseguire la transizione di un VMCS con riconoscimento dei dati aziendali dallo stato attivo allo stato non attivo. Qualsiasi istruzione VMREAD o VMWRITE mentre un VMCS con riconoscimento dei dati è attivo non è supportato e può comportare un comportamento imprevisto.
La struttura HV_VMX_ENLIGHTENED_VMCS definisce il layout del vmCS con riconoscimento dei dati con riconoscimento dei dati. Tutti i campi non sintetici eseguono il mapping a una codifica VMCS fisica Intel.
L'hypervisor L0 può scegliere di memorizzare nella cache parti del vmCS con riconoscimento dei dati con riconoscimento dei dati. I campi puliti VMCS con riconoscimento dei dati con riconoscimento dei dati abilitati controllano quali parti del vmCS con riconoscimento dei dati sono ricaricati dalla memoria guest in una voce di macchina virtuale nidificata. L'hypervisor L1 deve cancellare i campi di pulizia VMCS corrispondenti ogni volta che modifica vmCS con riconoscimento dei dati con riconoscimento dei dati, altrimenti l'hypervisor L0 potrebbe usare una versione non aggiornata.
L'illuminazione dei campi puliti viene controllata tramite il campo sintetico "CleanFields" del VMCS con riconoscimento dei dati con riconoscimento dei dati. Per impostazione predefinita, tutti i bit vengono impostati in modo che l'hypervisor L0 debba ricaricare i campi VMCS corrispondenti per ogni voce di macchina virtuale nidificata.
Il supporto per un'interfaccia VMCS con riconoscimento dei dati viene segnalato con 0x40000004 foglia CPUID.
La struttura VMCS con riconoscimento dei dati con riconoscimento dei dati è con controllo delle versioni per tenere conto delle modifiche future. Ogni struttura VMCS con riconoscimento dei dati con riconoscimento dei dati contiene un campo di versione, riportato dall'hypervisor L0.
L'unica versione di VMCS attualmente supportata è 1.
Per la maggior parte dei campi VMCS, il campo VMCS con supporto per la macchina virtuale corrispondente è supportato per una macchina virtuale se il campo VMCS è supportato per la macchina virtuale, come determinato tramite meccanismi di individuazione delle funzionalità architetturali. Le eccezioni vengono segnalate nel 0x4000000A foglia CPUID.
Nei casi in cui i meccanismi di individuazione delle funzionalità architetturali indicano il supporto per un campo VMCS per cui non è definito alcun campo VMCS con riconoscimento dei dati, l'hypervisor L1 non deve abilitare la funzionalità se sceglie di usare VMCS con riconoscimento dei dati abilitati.
L'hypervisor Hyper-V L0 non indicherà il supporto per un campo VMCS per il quale non è definito alcun campo o eccezione VMCS con riconoscimento dei dati. Se un altro hypervisor L0 necessita di un nuovo campo VMCS con riconoscimento dei dati o di un'eccezione da definire, contattare Microsoft.
AMD ha spazio riservato in VMCB per l'uso dell'hypervisor, nonché un bit pulito associato. I byte riservati si trovano nella sezione di controllo, offset 0x3E0-3FF, di VMCB. Il bit pulito è bit 31 (il bit pulito deve essere invalidato ogni volta che l'hypervisor modifica l'area "enlightenments" di VMCB).
Hyper-V usa l'area VMCB riservata per configurare i servizi di riconoscimento dei dati. La struttura HV_SVM_ENLIGHTENED_VMCB_FIELDS documenta il formato.
L'hypervisor L0 emula i controlli "MSR-Bitmap" su piattaforme Intel e AMD che consentono al software di virtualizzazione di controllare quali accessi MSR generano intercettazioni.
L'hypervisor L1 può collaborare con l'hypervisor L0 per rendere gli accessi MSR più efficienti. Può abilitare bitmap MSR abilitate per il riconoscimento dei dati impostando il campo corrispondente nei campi VMCS/VMCB con riconoscimento dei dati su 1. Se abilitato, l'hypervisor L0 non monitora le bitmap MSR per le modifiche. L'hypervisor L1 deve invece invalidare il campo pulito corrispondente dopo aver apportato modifiche a una delle bitmap MSR.
Il supporto per la bitmap MSR con riconoscimento dei dati con riconoscimento dei dati viene segnalato nella 0x4000000A foglia CPUID.
Hyper-V ha la possibilità di eseguire la migrazione in tempo reale di una partizione figlio da un host a un altro host. Le migrazioni in tempo reale sono in genere trasparenti per la partizione figlio. Tuttavia, nel caso della virtualizzazione annidata, l'hypervisor L1 potrebbe dover essere a conoscenza delle migrazioni.
Un hypervisor L1 può richiedere di ricevere una notifica quando viene eseguita la migrazione della partizione. Questa funzionalità viene enumerata in CPUID come privilegio "AccessReenlightenmentControls". L'hypervisor L0 espone un msr sintetico (HV_X64_MSR_REENLIGHTENMENT_CONTROL) che può essere usato dall'hypervisor L1 per configurare un vettore di interrupt e un processore di destinazione. L'hypervisor L0 inietta un interrupt con il vettore specificato dopo ogni migrazione.
#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;
Il vettore specificato deve corrispondere a un interrupt APIC fisso. TargetVp specifica l'indice del processore virtuale.
È possibile eseguire la migrazione in tempo reale di una partizione guest tra due computer con frequenze TSC diverse. In questi casi, potrebbe essere necessario ricompilare il valore TscScale della pagina TSC di riferimento .
L'hypervisor L0 emula facoltativamente tutti gli accessi TSC dopo una migrazione fino a quando l'hypervisor L1 non ha avuto la possibilità di ricompilare il valore TscScale. L'hypervisor L1 può acconsentire esplicitamente all'emulazione TSC scrivendo nel HV_X64_MSR_TSC_EMULATION_CONTROL MSR. Se si è scelto, l'hypervisor L0 emula gli accessi TSC dopo che viene eseguita una migrazione.
L'hypervisor L1 può eseguire una query se gli accessi TSC sono attualmente emulati usando il HV_X64_MSR_TSC_EMULATION_STATUS MSR. Ad esempio, l'hypervisor L1 potrebbe sottoscrivere le notifiche di Live Migration ed eseguire una query sullo stato del TSC dopo la ricezione dell'interruzione della migrazione. Può anche disattivare l'emulazione TSC (dopo aver aggiornato il valore TscScale) usando questo 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;
Il bilanciamento del carico di rete virtuale esposto dall'hypervisor può essere esteso alle traduzioni della cache da GPA L2 ad oggetti Criteri di gruppo. Come per il bilanciamento del carico di rete su un processore logico, il bilanciamento del carico di rete virtuale è una cache non coerente e questa non coerenza è visibile agli utenti guest. L'hypervisor espone le operazioni per gestire il bilanciamento del carico di rete.
L'hypervisor espone hypercalls (HvCallFlushVirtualAddressSpace, HvCallFlushVirtualAddressSpaceEx, HvCallFlushVirtualAddressList e HvCallFlushVirtualAddressListEx) che consentono ai sistemi operativi di gestire in modo più efficiente il TLB virtuale. L'hypervisor L1 può scegliere di consentire al guest di usare tali hypercall e delegare la responsabilità di gestirli all'hypervisor L0. Ciò richiede l'uso di una pagina di supporto per le partizioni e di una macchina virtuale VMCS nelle piattaforme Intel.
Quando in uso, il TLB virtuale taga tutti i mapping memorizzati nella cache con un identificatore del contesto annidato (VMCS o VMCB) che li ha creati. In risposta a un hypercall di scaricamento virtuale diretto da un guest L2, l'hypervisor L0 invalida tutti i mapping memorizzati nella cache creati da contesti nidificati in cui
- VmId è lo stesso del chiamante VmId
- Il VpId è contenuto nel processore specificato o nel HV_FLUSH_ALL_PROCESSORS specificato
Il supporto per gli scaricamenti virtuali diretti viene segnalato in 0x4000000A foglia CPUID.
La gestione diretta delle hypercall di scaricamento virtuale è abilitata da:
- Impostazione del campo NestedEnlightenmentsControl.Features.DirectHypercall della pagina Assistenza processore virtuale su 1.
- Impostazione del campo EnlightenmentsControl.NestedFlushVirshVirtualHypercall di una vmCS o vmCB illuminata su 1.
Prima di abilitarlo, l'hypervisor L1 deve configurare i seguenti campi aggiuntivi della vmCS/VMCB illuminata:
- VpId: ID del processore virtuale che controlla VMCS/VMCB con illuminazione.
- VmId: ID della macchina virtuale a cui appartiene vmCS/VMCB illuminata.
- PartitionAssistPage: indirizzo fisico guest della pagina di assistenza della partizione.
L'hypervisor L1 deve esporre anche le funzionalità seguenti ai propri guest tramite CPUID.
- UseHypercallForLocalFlush
- UseHypercallForRemoteFlush
La pagina di assistenza per le partizioni è un'area di memoria allineata a pagine allineata alle dimensioni della pagina che l'hypervisor L1 deve allocare e zero prima che sia possibile usare hypercall a scarica diretta. L'oggetto Criteri di gruppo deve essere scritto nel campo corrispondente nel vmCS/VMCB illuminato.
struct
{
UINT32 TlbLockCount;
} VM_PARTITION_ASSIST_PAGE;
Se la pagina di assistenza della partizione del chiamante TlbLockCount non è zero, l'hypervisor L0 fornisce un VM-Exit con un motivo di uscita sintetica per l'hypervisor L1 dopo aver gestito una hypercall di scaricamento virtuale diretto.
Nelle piattaforme Intel viene recapitato un VM-Exit con motivo HV_VMX_SYNTHETIC_EXIT_REASON_TRAP_AFTER_FLUSH
di uscita. Nelle piattaforme AMD un VM-Exit con codice HV_SVM_EXITCODE_ENL
di uscita viene recapitato e ExitInfo1 è impostato su 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)
Quando la virtualizzazione annidata è abilitata per una partizione guest, l'unità di gestione della memoria (MMU) esposta dalla partizione include il supporto per la conversione degli indirizzi a secondo livello. La traduzione degli indirizzi di secondo livello è una funzionalità che può essere usata dall'hypervisor L1 per virtualizzare la memoria fisica. Quando in uso, alcuni indirizzi che verranno trattati come indirizzi fisici guest (GpA) vengono considerati come indirizzi fisici guest L2 (GpA) e tradotti in criteri di gruppo attraversando un set di strutture di paging.
L'hypervisor L1 può decidere come e dove usare spazi indirizzi di secondo livello. Ogni spazio di indirizzi di secondo livello viene identificato da un valore ID a 64 bit definito dal guest. Nelle piattaforme Intel questo valore è uguale al puntatore EPT. Nelle piattaforme AMD il valore è uguale al campo vmCB nCR3.
La funzionalità di traduzione degli indirizzi di secondo livello esposta dall'hypervisor è in genere compatibile con il supporto vmX o SVM per la traduzione degli indirizzi. Esistono tuttavia le differenze osservabili guest seguenti:
- Internamente, l'hypervisor può usare tabelle di pagina shadow che convertono gli oggetti Criteri di gruppo L2 in spA. In tali implementazioni, queste tabelle di pagina shadow sembrano essere software come TLB di grandi dimensioni. Tuttavia, diverse differenze possono essere osservabili. Prima di tutto, le tabelle della pagina shadow possono essere condivise tra due processori virtuali, mentre le TLB tradizionali sono strutture per processore e sono indipendenti. Questa condivisione può essere visibile perché un accesso di pagina da un processore virtuale può riempire una voce di tabella della pagina shadow che viene successivamente usata da un altro processore virtuale.
- Alcune implementazioni dell'hypervisor possono usare la protezione interna per la scrittura interna delle tabelle delle pagine guest per scaricare i mapping MMU dalle strutture dati interne(ad esempio, tabelle di pagine shadow). Ciò è invisibile in modo architettonico al guest perché le scritture in queste tabelle verranno gestite in modo trasparente dall'hypervisor. Tuttavia, le scritture eseguite nelle pagine criteri di gruppo sottostanti da altre partizioni o da dispositivi potrebbero non attivare lo scaricamento TLB appropriato.
- In alcune implementazioni dell'hypervisor, un errore di pagina di secondo livello potrebbe non invalidare i mapping memorizzati nella cache.
L'hypervisor supporta anche un set di miglioramenti che consentono a un guest di gestire il TLB di secondo livello in modo più efficiente. Queste operazioni avanzate possono essere usate in modo intercambiabile con operazioni di gestione TLB legacy.
L'hypervisor supporta le hypercall seguenti per invalidare le TLB:
Hypercall | Descrizione |
---|---|
HvCallFlushGuestPhysicalAddressSpace | invalida i mapping dell'oggetto Criteri di gruppo L2 memorizzati nella cache in uno spazio indirizzi a livello di secondo livello. |
HvCallFlushGuestPhysicalAddressList | invalida i mapping di GVA/L2 memorizzati nella cache a criteri di gruppo all'interno di una parte di uno spazio indirizzi di secondo livello. |
Nelle piattaforme AMD tutte le voci TLB vengono contrassegnate in modo architetturale con un ASID (identificatore dello spazio degli indirizzi). L'invalidazione dell'ASID causa l'invalidazione di tutti gli interi TLB associati all'ASID. L'hypervisor annidato può facoltativamente acconsentire a un TLB "illuminato" impostando EnlightenedNptTlb su "1" in HV_SVM_ENLIGHTENED_VMCB_FIELDS. Se l'hypervisor annidato opta per l'illuminazione, ASID invalida solo l'intero TLB derivato dalla traduzione degli indirizzi di primo livello (ad esempio lo spazio indirizzi virtuale). Per scaricare le voci TLB derivate dalla tabella di pagina annidata (NPT) e forzare l'hypervisor L0 per ricompilare le tabelle della pagina shadow, è necessario usare HvCallFlushGuestPhysicalAddressSpace o HvCallFlushGuestPhysicalAddressList hypercall.
Nelle piattaforme Intel. l'hypervisor L1 può acconsentire esplicitamente alla combinazione di eccezioni di virtualizzazione nella classe di eccezione di errore della pagina. L'hypervisor L0 annuncia il supporto per questa illuminazione nel foglia CPUID della virtualizzazione annidata di Hypervisor.
Questa illuminazione può essere abilitata impostando VirtualizationException su "1" nella struttura di dati HV_NESTED_ENLIGHTENMENTS_CONTROL nella pagina Assistenza processore virtuale.
L'hypervisor L1 espone un msr che segnala l'indice VP sottostante del processore corrente.
Indirizzo MSR | Nome registrazione | Descrizione |
---|---|---|
0x40001002 | HV_X64_MSR_NESTED_VP_INDEX | In una partizione radice annidata segnala l'indice VP sottostante del processore corrente. |
In una partizione radice nidificata, gli msr seguenti consentono l'accesso agli msr SynIC corrispondenti dell'hypervisor di base.
Per trovare l'indice del processore sottostante, i chiamanti devono prima usare HV_X64_MSR_NESTED_VP_INDEX.
Indirizzo MSR | Nome registrazione | MSR sottostante |
---|---|---|
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 |