La virtualizzazione dei sistemi operativi – Capitolo 3.2.1.1
Nella full virtualization la traduzione degli indirizzi virtuali è una delle attività che causano un elevato overhead di elaborazione per garantire alle macchine virtuali la visione e l’accesso a uno spazio di indirizzi contiguo e zero-based. Come abbiamo visto nel capitolo precedente, VMware utilizza la tecnica delle shadow page tables per soddisfare questa esigenza.
La paravirtualizzazione di Xen non impone questo compito all’hypervisor. Infatti Xen è coinvolto solamente nella verifica che un sistema operativo guest non apporti modifiche inaccettabili alle page table.
La figura seguente illustra la gestione della memoria virtuale nell’architettura x86 per facilitare la comprensione del funzionamento di Xen che, anche se non è argomento del presente documento, tenterò di descrivere. Per ulteriori approfondimenti si rimanda alla bibliografia.
Fig. 3.7: schema della gestione della memoria virtuale nell’architettura x86
L’architettura x86 si avvale di uno spazio degli indirizzi segmentato nel quale la memoria è divisa in segmenti da 64KB, e di un registro dei segmenti che punta alla base del segmento utilizzato in quel momento.
La traduzione da indirizzi virtuali a fisici avviene in due fasi. La prima, detta segmentazione (segmentation), traduce i logical address in linear address, la seconda, paginazione (paging), traduce i linear address in phisical address.
L’idea alla base della segmentazione è che la memoria virtuale sia divisa in un insieme di segmenti dotati di uno spazio di indirizzamento autonomo. Un segmento consiste di alcuni componenti tra cui il base address, che contiene l’indirizzo di partenza di una porzione di memoria e un limit, che ne specifica la dimensione. Dal logical address si estraggono i 16 bit più significativi per ottenere il segment selector che identifica un segment descriptor di 64 bit ed un offset per individuare il linear address. Questi segment descriptor sono immagazzinati in una Global Description Table (GDT) nel caso siano accessibili da tutti i processi in esecuzione o in una Local Description Table (LDT) nel caso siano riservati ad un singolo processo.
Un insieme di linear addresses sono raggruppati assieme a formare una page. Una page mappa un corrispondente insieme di indirizzi di memoria contigui chiamato page frame. La struttura dati di queste pagine è chiamata page table (PT). Le page table sono inizializzate dal kernel del sistema operativo e salvate nella memoria centrale prima che inizi il processo di gestione della paginazione.
La traduzione da linear address in phisical address avviene in due fasi. Inizialmente si converte una parte del linear address, avvalendosi di una tabella chiamata page directory (PD), si ottiene la page table (PT). Successivamente dalla page table, utilizzando la parte del linear address che individua l’offset, si ricava il corrispondente page frame.
Xen fa uso principalmente della paginazione. Tutti i segment descriptor utilizzano lo stesso linear address space minimizzando in questo modo la necessità di utilizzare la segmentazione per convertire i logical addresses in linear addresses. Grazie alla paginazione piuttosto che alla segmentazione, Xen semplifica la gestione della memoria da parte dell’hypervisor e dei sistemi operativi guest paravirtualizzati.
Precedentemente abbiamo visto che il ruolo del Xen è quello di validare gli aggiornamenti della page table per garantire sicurezza e isolamento dei DomU. Per ottemperare a questo compito, Xen associa a ogni page frame un identificatore del tipo di dato contenuto. Ciascun page frame può essere solamente di uno di questi tipi:
- Page Directory (PD)
- Page Table (PT)
- Local Descriptor Table (LDT)
- Global Descriptor Table (GDT)
- Writable (RW)
Dato che il coinvolgimento di Xen è limitato alle operazioni di scrittura, i guest possono mappare e accedere a tutti i propri page frame senza che l’hypervisor intervenga, indipendentemente dal tipo. Comunque, un frame non può essere riallocato per un altro uso utilizzando l’hypercall mmu_update prima che sia azzerato l’identificatore del tipo. I frame possono essere poi marcati come PD o PT dopo che l’hypervisor ha completato il processo di validazione, concedendone l’utilizzo al sistema guest.
Attraverso questo meccanismo Xen dà l’illusione al sistema guest di essere in grado di scrivere direttamente sulle pagine di memoria. Quando una DomU PV vuole scrivere una pagina di memoria di tipo PT o PD, chiede di renderla scrivibile attraverso l’hypercall vm_assist e la mmu_update. Xen accetta l’operazione che genera una trap. La pagina viene temporaneamente rimossa dalla page table, validata da Xen e riconnessa. Anche se questo sistema può apparire dispendioso di risorse, lo si mantiene efficiente raggruppando le hypercall ed eseguendole contemporaneamente.
Nell’architettura x86 esiste una cache hardware per immagazzinare una parte delle entry della page table. Questa cache viene chiamata Translation Lookaside Buffer (TLB). Per raggiungere le migliori performance bisogna massimizzare il numero di traduzioni ottenibili direttamente dal TLB e questo può essere ottenuto operando una pulizia completa del TLB al momento del cambiamento dello spazio di indirizzamento dovuto all’utilizzo di un diverso DomU. Gli sviluppatori di Xen hanno affrontato il problema secondo due metodi: demandando al sistema guest l’allocazione e la gestione delle page table sul TLB così da ridurre il carico sull’hypervisor e riservando, come già visto, un’area di memoria all’hypervisor evitando la pulizia del TLB ogni qual volta si verifica un’entrata o un’uscita di contesto dell’hypervisor stesso.
Nella tabella seguente riporto le Xen memory Hypercall.
Categoria |
Hypercall |
Descrizione |
Page Table Management | mmu_update | Aggiorna la page table dei domU, tipicamente in batch |
update_va_mapping | Aggiorna un singola riga della page table per un specifico indirizzo di memoria virtuale. Utilizzabile anche in batch | |
mmuexp_op | Esegue operazioni estese sulla memoria, come pulizia della cache o rassegnazione della proprietà di una pagina | |
vm_assist | Attiva o disattiva le varie modalità di gestione delle pagine di memoria | |
Virtual Address Translation | set_gdt | Crea un nuovo GDT per un domU |
update_descriptor | Aggiorna il GDT o il LDT |