Uno strumento per l’emulazione di fallimenti hardware in sistemi … · 2018-03-12 · ad una...
Transcript of Uno strumento per l’emulazione di fallimenti hardware in sistemi … · 2018-03-12 · ad una...
Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica
tesi di laurea magistrale
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Anno Accademico 2012/2013 relatore Ch.mo prof. Marcello Cinque Ing. Antonio Pecchia correlatore Ing. Anna Lanzaro candidato Giovanni Fierro matr. M63/40
Alla mia famiglia e ad Annarita
III
Indice
Introduzione 5
Capitolo 1. Contesto 8
1 Virtualizzazione 8
1.1 Xen hypervisor 11
1.1.1 Xen e meccanismi di protezione architettura IA32 13
1.1.2 Gestione memoria 15
1.1.3 Hypercalls 16
1.1.4 Eventi ed interupt 18
1.1.5 Grant Tables 18
1.1.6 XenStore 19
1.2 Error Detection 20
1.2.1 Machine Check Architecture 20
Capitolo 2. Xen: gestione errori hardware 24
2.1 Architettura MCA 24
2.1.1 Hypercall: interfaccia MCA 26
2.2 Telemetria 27
2.3 vMCE 28
2.4 Intel handler 30
2.5 Shared handler 37
Capitolo 3. Tool di emulazione di errori hardware 41
3.1 Descrizione del tool 41
3.1.1 Dettagli implementativi 43
3.1.2 Modifiche al codice Xen 49
3.1.3 Esempio di utilizzo 58
3.2 Architettura framework 61
3.2.1 MCE generatori 62
Capitolo 4. Sperimentazione 66
4 Framework di iniezione 66
4.1 Campagna 1: Xen error handling 68
IV
4.1.1 Scelta degli errori 69
4.1.2 Monitoring 71
4.1.3 Configurazione del framework 73
4.2 Handler: intel_machine_check 76
4.2.1 Risultati 84
4.3 Handler: mcheck_cmn_check 86
4.3.1 Risultati 86
4.3.2 Errori inoltrati al guest 88
4.3.2.1 Filtraggio degli errori 88
4.3.2.2 Scelta degli errori 91
4.3.2.3 Configurazione Guest 92
4.3.2.4 Script di iniezione 92
4.3.2.5 Risultati 96
4.4 Campagna 2: Linux kernel 3.6.11 98
4.4.1 Scelta degli errori 98
4.4.2 Script di iniezione 98
4.4.3 Risultati 99
4.5 Problema HVM 101
Conclusioni e Sviluppi futuri 102
Bibliografia 103
Inserire il titolo della tesi di laurea come intestazione
5
Introduzione
I moderni sistemi software richiedono sempre maggiore capacità elaborative per lo
sviluppo di nuove funzionalità. I processori single-core, a causa di limiti tecnologici, non
riescono a mantenere il passo con la crescente richiesta di maggiori prestazioni. Per cui
sempre più sistemi sono orientanti verso soluzioni multi-core, cioè processori che
dispongono di più unità di elaborazione sul medesimo chip. Tali processori garantiscono
elevate capacità di calcolo in combinazione ad una maggiore efficienza in termini sia di
consumo energetico che di occupazione d’area su chip. Infatti, recenti trends di mercato
hanno evidenziato che anche nei sistemi safety-critical e in sistemi embedded in ambito:
avionico [4], [3], automotive [1], [2] e medico [5] optano per soluzioni basate su
architetture multi-core.
I sistemi critici sono sistemi in cui un fallimento può avere conseguenze catastrofiche, ad
esempio danni a persone e a cosa, perdite di vite umane oppure disastri ambientali. Quindi,
tali sistemi prima di poter essere operativi devono essere validati, in base al particolare
dominio di appartenenza, rispetto a determinati standard industriali in modo da poter
certificare che il sistema è in linea con una serie di caratteriste d’affidabilità.
Una delle tecniche più comuni adottate nei sistemi critici per evitare che un errore si
propaghi nel intero sistema (fault-conteinement) è quella di isolare spazialmente e
Inserire il titolo della tesi di laurea come intestazione
6
temporalmente i task critici non, in modo da evitare che un errore da parte di un task non
critico possa interferire con quelli più prioritari. In tal senso i sistemi critici utilizzano
tecniche di virtualizzazione per far sì che task indipendenti siano in esecuzione su core
differenti e per implementare tecniche di tolleranza ai guasti, come la replicazione dei task
su più core [6]. La virtualizzazione consiste in uno strato software intermedio, chiamato
hypervisor, che disciplina l’accesso alla risorse hardware da parte dei sistemi operativi
guest.
Alla luce di tutte le caratteriste descritte in precedenza, l’utilizzo di processori multi-core e
l’uso di virtualizzazione introducono molteplici problematiche legate principalmente
all’isolamento tra task e la condivisione delle risorse, per cui, risulta difficile sviluppare e
validare software in tali sistemi e quindi è necessario realizzare dei nuovi strumenti per la
valutazione delle caratteristiche d’affidabilità. Nel particolare, l’aspetto che si vuole
studiare è come il sistema di comporta in presenza di errori hardware. In letteratura sono
presenti numerose tecniche di fault-injection per l’iniezione di guasti hardware, tra cui la
hardware-based fault injection che permette l’iniezione di errori nell’hardware reale
mediante l’utilizzo di speciali dispositivi oppure interferendo con le unità fisiche (ad
esempio, incrementando la temperatura oppure introducendo delle interferenze
elettromagnetiche). Con questa tecnica è che è possibile riprodurre degli errori hardware
reali ma è costosa e rischiosa da implementare.
Tuttavia, i moderni processori notificano l’occorrenza di un errore al software di base
tramite un’unità hardware di error-reporting, composta da un insieme di registri. Quindi,
l’idea di base è di sfruttare i meccanismi di notifica e gestione implementati
dall’hypervisor per emulare l’occorrenza di un errore hardware senza impattare sul
hardware fisico vero e proprio. Nel particolare, questo lavoro di tesi ha come obiettivo la
realizzazione di un tool di emulazione fallimenti da parte di unità hardware, tramite cui è
possibile condurre campagne sperimentali atte a valutare le caratteristiche di affidabilità di
sistemi virtualizzati su architetture multi-core.
Inserire il titolo della tesi di laurea come intestazione
7
Nel primo capitolo si approfondisce la tematica delle tecniche di virtualizzazione, nel
particolare si illustrerà l’hypervisor Xen, e dei meccanismi di error-reporting implementati
dai moderni processori Intel e AMD.
Nel secondo capitolo sono descritti, in modo approfondito, i meccanismi di gestione di
errori hardware adottati da Xen, mettendo in evidenza tutti gli aspetti dell’interazione tra
hypervisor e macchine virtuali.
Nel terzo capitolo ci si occupa di illustrare nel dettaglio il tool realizzato e le modifiche
apportate all’hypervisor.
Infine, nel quarto capitolo si esaminerà una serie di sperimentazioni effettuate: sia uno
studio degli handler di gestione dell’hypervisor e sia del sistema operativo linux.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
8
Capitolo 1
Contesto
I moderni computer dispongono di sufficiente potenza di calcolo per utilizzare la
virtualizzazione, per offrire l’illusione di avere più macchine virtuali (virtual machine –
VMs), ognuna ospitante una particolare istanza di un sistema operativo. Tale tecnologia
trova spazio anche nell’ambito di sistemi critici e di sistemi embedded per
l’implementazione di meccanismi di fault-tolerance e fault-containment [6].
Inoltre, processori dispongono di un dispositivo di error-reporting per il rilevamento e la
notifica di errori da parte delle unità hardware, come memoria, TLB, bus ed ecc. L’idea
alla base del tool proposto è emulare l’occorrenza di fallimenti hardware sfruttando i
meccanismi di notifica e studiare il comportamento del sistema target.
Nel seguito di questo capitolo si descrive brevemente lo stato dell’arte riguardo le tecniche
di virtualizzazione e si approfondisce nel dettaglio l’hypervisor Xen. A seguire si illustra
l’architettura di error reporting implementata nei processori Intel: la Machine Check
Architecture.
1 Virtualizzazione
Lo scopo della virtualizzazione è quello di eseguire contemporaneamente più istanze di
sistemi operativi «guest» in un'unica macchina fisica chiamata “host”. I diversi sistemi
operativi guest non interagiscono direttamente con l'hardware ma si interfacciano ad esso
attraverso un componente software intermedio chiamato “hypervisor”.
L’utilizzo della virtualizzazione comporta numerosi benefici:
1. Aumento dell’affidabilità del sistema: come già accennato in precedenza è
possibile dedicare una macchina virtuale all’esecuzione di specifici task. Inoltre
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
9
l’hypervisor isolerà le macchine guest in esecuzione sullo stesso host affinché
eventuali problemi che compromettono il funzionamento di una singola macchina,
non influenzino la stabilità delle altre;
2. Consolidamento dei server: molte aziende hanno visto crescere vistosamente il
numero dei server proprio a causa dell’aumento dei servizi da fornire ai propri
utenti. Attraverso la virtualizzazione si possono eseguire più macchine virtuali
nella stessa macchina fisica riducendo il numero dei server di dieci volte o più;
3. Riduzione del total cost of ownership (TCO): un numero di server inferiore
permette una notevole riduzione dei costi legati all’energia utilizzata per
alimentare i server e per mantenere la temperatura ambientale adatta alle sale
server. Inoltre si riducono i costi di acquisto e i canoni di manutenzione dei server
fisici;
4. Disaster recovery: l’intero sistema operativo guest può essere facilmente salvato e
ripristinato riducendo notevolmente i tempi di indisponibilità in caso di guasto;
5. High availability: se è presente una infrastruttura di server fisici con caratteristiche
hardware tra loro compatibili e questi server condividono un’area dati (storage)
sulla quale risiedono le macchine virtuali, sarà possibile spostare l’esecuzione di
una macchina virtuale si un altro host in caso di fallimento. Alcuni sistemi
prevedono lo spostamento automatico delle macchine virtuali tra i vari host in
funzione al carico;
6. Esecuzione di applicazioni legacy: è frequente che alcune aziende utilizzino
applicazioni sviluppate per sistemi operatici che girano su hardware obsoleto, non
supportato o addirittura introvabile. Attraverso la virtualizzazione si possono
continuare ad utilizzare quelle applicazioni che diversamente dovrebbero essere
migrate ad una architettura più attuale affrontando i costi relativi al porting e al
debug.
Esistono diverse tecniche di virtualizzazione:
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
10
Emulazione: L’hypervisor simula l’intero hardware set che permette al sistema
operativo guest di essere eseguito senza alcune modifiche. Il software di
virtualizzazione si occupa di presentare al guest un’architettura hardware completa
a lui nota, indipendentemente dall’architettura hardware presente sulla macchina
host.
Full virtualization: chiamata anche native virtualization, è molto simile
all’emulazione, infatti, i sistemi operativi guest girano senza alcuna modifica in
macchine virtuali ospitate sul sistema host. La differenza rispetto all’emulazione
sta nel fatto che i sistemi operativi guest devono essere compatibili con
l’architettura hardware della macchina fisica. In questo modo molte istruzione
possono essere eseguite direttamente sull’hardware senza bisogno di un software di
traduzione garantendo prestazione superiori all’emulazione. Recentemente Intel ed
AMD hanno sviluppato indipendentemente le estensioni di virtualizzazione
dell'architettura x86 (IVT e AMD-V). Esse non sono tra loro completamente
compatibili, ma supportano grosso modo le stesse istruzioni. Entrambe permettono
ad una macchina virtuale di eseguire un sistema operativo ospite senza incorrere in
grosse perdite prestazionali causate dall'emulazione via software.
Paravirtualization: L’hypervisor presenta alle macchine virtuali una versione
modificata dell’hardware sottostante, mantenendone tuttavia la medesima
architettura. Il sistema operativo in esecuzione sulle macchine virtuali è invece
modificato per evitare alcune particolari chiamate di sistema. Questa tecnica
permette maggiori prestazioni rispetto alle tecniche descritte in precedenza, dato
che le istruzioni provenienti dalle macchine virtuali sono eseguite quasi tutte
direttamente sul processore senza che intervengano modifiche.
Operating system level virtualization: non esiste uno strato software intermedio, ma
più istanze di un sistema operativo guest condividono la stessa immagine del
medesimo kernel. Ogni guest dispone di un proprio fi system, configurazione di
rete e applicazioni. Il vantaggio principale è il miglior utilizzo delle risorse grazie
alla condivisione degli spazi di memoria. Questa tecnica è inadatta se si vogliono
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
11
eseguire sistemi operativi diversi sullo stesso host. Inoltre, l’isolamento tra i guest
non è garantito, infatti, un problema di stabilità o di performance di un solo guest
può influire negativamente sugli altri.
1.1 XEN hypervisor
Xen è un hypervisor di tipo bare-metal open-source nato da un progetto iniziato
dall’università di Cambridge [7]. E’ ampiamente utilizzato in diversi contesti applicativi:
server virtualization, desktop virtualization, Infrastracture as service (IaaS), sistemi
embedded ed è alla base di molti sistemi di Cloud Computing.
Xen crea un livello di astrazione e fornisce un interfaccia di comunicazione tra i sistemi
operativi virtuali e l’hardware sottostante. E’ responsabile della gestione della CPU,
memoria ed interrupt, mentre non si occupa delle normali operazioni di I/O come l’acceso
al disco o alla scheda di rete.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
12
In figura 1 è mostrato il diagramma dell’architettura di XEN. Oltre all’hypervisor vero e
proprio si possono distinguere ulteriori componenti:
The Control Domain (o Dom0): È l'unica macchina virtuale in esecuzione su Xen
che gode di speciali privilegi di accesso alle risorse di I/O ed ha, inoltre, la
possibilità di interagire con le altre macchine virtuali (DomU) in esecuzione. Un
qualsiasi ambiente di virtualizzazione basato su Xen richiede la presenza di un
Domain 0 prima che qualsiasi altra macchina ospite possa essere avviata. Utilizza
due driver per supportare le richieste di accesso allo storage e alla rete da parte dei
DomU-PV: il Network backend driver e il Block Backend Driver. Il primo processa
tutte le richieste di accesso alla rete provenienti dai domini non privilegiati, mentre
il secondo gestisce le operazioni di I/O con i dischi locali.
Guest/Virtual Machine (DomU): chiamati anche domini, sono ambienti
virtualizzati ed ognuno di essi ospita il proprio sistema operativo. I guest sono
completamente isolati, non hanno alcun privilegio di accesso alle risorse hardware
o a periferiche di I/O e per questo vengono chiamati unpriviliged domain (o
DomU). Si distinguono principalmente due tipi di domini: paravirtualized (PV) e
fully virtualized (HVM) ed entrambi possono coesistere sul medesimo kernel
Figura 1 Architettura XEN
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
13
XEN. I domini PV sono coscienti che stanno operando in ambiente virtualizzato
con altri guest, infatti, sono macchine virtuali con sistemi operativi il cui kernel è
stato modificato per ottimizzare l’esecuzione sull’hypervisor; sono dotati di due
driver per gestire le loro operazioni sulla rete e sullo storage che si interfacciano
con i driver back-end presenti sul Dom0. Diversamente, i domini HVM non hanno
questi driver e la comunicazione con le risorse di I/O avviene invece attraverso un
processo speciale chiamato Qemu-dm che viene istanziato su Dom0. Ad ogni
dominio HVM dispone di una sua istanza del processo sul Dom0. All’avvio della
macchina virtuale è caricato un strato software chiamato Xen Virtual Firmware. In
questo modo il guest può effettuare la procedura di boot come se avesse a
disposizione l’hardware fisico.
Toolstack e Console: il Dom0 contiene uno stack di controllo (o Toolstack) che
consente agli utenti di gestire la creazione, la distruzione e la configurazione delle
macchina virtuali. Il Toolstack espone un interfaccia che può essere sia da riga di
comando tramite console (es, xl) oppure tramite interfaccia grafica (es, libvirt).
1.1.1 Xen e meccanismi di protezione architettura IA32
L’architettura IA32 prevede quattro livelli di privilegio, denominati ring. Il ring a più alta
priorità è quello 0 mentre, il ring 3 corrisponde al livello più basso. Tipicamente nel ring 0
è eseguito il codice kernel dell’sistema operativo (SuperVisor Mode) mentre le
applicazione utente (User mode) sono eseguite nel ring a minore privilegio. L’esecuzione
di istruzione “privilegiate” nel ring tre comporta la generazione dell’eccezione general
protection fault. Il ring uno e due non sono stati usati negli anni (ad eccezione di OS/2).
L'introduzione di un hypervisor al di sotto del sistema operativo viola il principio per cui il
sistema operativo deve essere eseguito con il privilegio maggiore. Per proteggere
l’hypervisor da comportamenti inaspettati dei sistemi operativi guest e per garantire
isolamento tra le macchine virtuali, essi devono essere eseguiti con privilegi inferiori. In
architetture diverse da IA32 (ad esempio IA64) l'assenza dei ring uno e due imponeva una
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
14
modifica all'hypervisor Xen (che eseguiva nel ring zero) con il con il conseguente
“spostamento” del sistema operativo nel ring tre (insieme alle applicazioni utente). Il tutto
è mostrato in figura 2.
La presenza di quattro ring (IA32) semplifica l'introduzione di Xen; infatti, basterà
“spostare” il sistema operativo nel ring 1 lasciando il ring 0 all'hypervisor (figura 3).
Figura 2 IA 64 protection ring
Figura 3 IA 32 protection rings
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
15
1.1.2 Gestione memoria
Per quel che concerne la virtualizzazione della memoria, i progettisti di Xen hanno preso
due decisioni:
1. I sistemi operativi guest sono responsabili dell'allocazione e della gestione
delle tabelle delle pagine hardware, con un minimo coinvolgimento di Xen
che garantisce sicurezza e isolamento;
2. Xen occupa una porzione ben definita dello spazio di indirizzamento in modo
da evitare il ricorso alla pulizia del Translation Lookaside Buffer (TLB) ogni
volta che l'hypervisor è interessato da un cambiamento di contesto.
In figura 4 sono proposti alcuni scenari che prevedono una diversa gestione della memoria
a seconda dell’architettura disponibile:
1. In presenza di un’architettura a 32 bit, Xen occupa i primi 64MB dello spazio
Figura 4 Gestione memoria Xen
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
16
di indirizzamento a 4GB;
2. Se l’architettura della macchina prevede Physical Address Extension (PAE),
Xen avrà a disposizione i primi 168MB.
3. Non tutte le CPU supportano meccanismi di segmentazione, come ad esempio
l’architettura x86-64. Per cui la protezione della memoria è implementata a
livello di pagina.
Ogni volta che il sistema operativo guest necessita di una pagina di memoria esso la alloca
e la inizializza dalla propria zona di memoria e la comunica a Xen.
1.1.3 Hypercalls
Nei comuni sistemi operativi le applicazioni in contesto userspace (ring 3) non possono
accedere direttamente alla risorse hardware e quindi per eseguire operazioni come la
stampa a video o la lettura di un input la tastiera richiedono al kernel (ring 0) tramite
system calls di svolgere operazioni privilegiate. Le system call lavorano tutte allo stesso
modo, indipendentemente dal sistema operativo o piattaforma:
1. Effettuano il push dei parametri nei registri o nello stack;
2. Generano un interrupt software (trap) specifico;
3. La generazione dell'interrupt comporta il passaggio dal modo di esecuzione
utente (non privilegiato) al modo kernel (privilegiato);
4. Con i privilegi ottenuti viene processata la system call;
5. Si riporta il sistema al modo di funzionamento utente ritornando il controllo al
chiamante.
In generale, l'architettura x86 prevede l'utilizzo dell'interrupt 80h per le system call,
tuttavia, release recenti prevedono l'utilizzo di istruzioni speciali quali
SYSENTER/SYSEXIT o SYSCALL/SYSRET.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
17
Nel caso di Xen, il kernel guest si trova in esecuzione nel ring 1 e non gli è concesso di
effettuare nessuna operazione privilegiata. In modo analogo a quanto avviene per le
system-calls, un sistema guest invoca una hypercall nello stesso modo in cui
un'applicazione chiama un system call con la differenza, nel caso delle hypercall, che
l'interrupt generato è 82h. Il presente meccanismo di funzionamento è stato in uso fino alla
versione 3 di Xen (la versione più recente corrisponde alla 4.2); le successive versioni
prevedono un meccanismo basato sulla creazione di un'hypercall page. Si tratta di un'area
di memoria mappata nello spazio di indirizzamento di un guest e creata all'avvio del
sistema. Una specifica hypercall è eseguita invocandola presso l'indirizzo della hypercall
page in cui risiede l’hypercall.
Figura 5 System calls in sistemi nativi e paravirtualizzati
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
18
1.1.4 Eventi ed interrupt
In un sistema Unix, è possibile utilizzare i segnali per garantire la comunicazione tra due
entità; si tratta di un meccanismo asincrono che permette ad una entità qualsiasi, esterna ad
un processo, di “avvertire” lo stesso processo circa l'occorrenza di un dato evento. L'entità
esterna può essere il kernel o un altro processo. Il meccanismo analogo in Xen è noto
come “event mechanism”. Una delle prime cose che un kernel guest deve fare all'avvio è
di registrare una callback che sarà usata per la notifica di eventi. Quando un guest riceve la
notifica di un evento, vengono settati dei flag per indicare, appunto, che detto evento si è
verificato. Il guest può gestire tale situazione in due modi: può mascherare la notifica
dell'evento e verificare periodicamente se ci sono messaggi pendenti, oppure può utilizzare
un meccanismo di notifica asincrono. Gli eventi possono essere generati direttamente da
Xen e possono rappresentare interruzioni hardware o virtuali, o da altri guest. Gli eventi
Xen possono essere utilizzati per creare un canale tra guest in cui viaggiano informazioni
riguardo, ad esempio, lo stato di risorse condivise.
Gli interrupt hardware sono mappati ad eventi, i quali sono notificati al dominio target
tramite una callback registrata in precedenza ed il kernel del guest associa ognuno di
questi eventi ad uno specifico interrupt handler. Quindi, Xen si occupa solamente di
determinare ogni interrupt fisico a quale dominio si riferisce.
1.1.5 Grant tables
Il modello basato sui segnali di Unix è ottimo per notifica veloce di eventi ma non è
sufficiente per costruire un meccanismo per la comunicazione tra processi (IPC). A tale
scopo esistono svariati approcci quali code di messaggi o ancora memoria condivisa. In
ambiente Xen la comunicazione interdominio avviene mediante le “grant tables”. Si tratta
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
19
di un meccanismo che prevede la condivisione di aree di memoria tra domini. La tecnica
dello “split driver” è realizzata proprio grazie alle grant tables. Come accennato nei
precedenti paragrafi, un dominio non privilegiato s’interfaccia con un driver virtuale che a
sua volta comunica, tramite memoria condivisa, con il driver reale residente nel dom0.
Ciascun dominio ha la propria grant table; è una struttura dati condivisa con Xen che
permette a ciascun dominio di comunicare all'hypervisor quali permessi possiedono gli
altri domini sulle sue pagine. Le voci presenti nella grant table, note come “grant
reference”, sono degli interi che indicano i privilegi che un concessionario mette a
disposizione sull'area di memoria che intende condividere. Un “grant reference” incapsula,
inoltre, altre informazioni che esentano un dominio dal conoscere il reale indirizzo della
pagina condivisa. Questo offre la possibilità di condivisione della memoria anche tra
domini “fully virtualized”.
1.1.6 XenStore
XenStore è uno spazio di memorizzazione d’informazioni condivise tra i domini. È
pensato per le notifiche di informazioni di configurazione e di stato, piuttosto che per
grandi trasferimenti di dati. Ogni dominio possiede una sorta di pseudo file system
analogo a procfs dei sistemi Unix like. Quando sono modificati i valori dello store, i driver
corrispondenti vengono avvertiti. Lo store conta tre percorsi principali:
/vm – memorizza le informazioni di configurazione dei domini, ad esempio il nome
simbolico del dominio (ssidref), il numero di cpu dedicate (vpcpu_avail), la
memoria disponibile (memory). Altri tipi di informazioni presenti riguardano il
comportamento da assumere in corrispondenza di un determinato stato della
macchina, cioè: le azioni da eseguire quando il dominio riceve una richiesta di
reboot (destroy o restart), le azioni da svolgere quando il dominio riceve una
richiesta di halt (destroy o restart) e le azioni da compiere quando il dominio va in
crash (destroy o restart);
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
20
/local/domain – contiene le informazioni sul dominio correntemente in esecuzione.
/tool – contempla informazioni riguardo I tool di supporto.
1.2 Error detection
Il numero di transistor nei comuni processori e nelle memoria crescono di anno in anno. I
bus hardware sono sempre più veloci. Questo incrementa la probabilità che i dati siano
corrotti da errori hardware di tipo bit-flips (cioè, la commutazione di un bit). Le moderne
architetture possono rilevare e qualche volte correggere questi eventi utilizzando varie
tecniche, ad esempio uso di checksum, ma ci sono casi in cui l’hardware non riesce a
nascondere completamente questi problemi ed è responsabilità del software gestirli. Questi
eventi sono chiamati machine check (MC) ed rappresentano il modo con cui l’hardware
comunica con il sistema sovrastante che qualcosa è andato storto [8].
1.2.1 Machine Check Architecture
La machine check architecture (MCA) è un componente hardware, implementato sia su
precessori Intel e sia AMD, che fornisce meccanismo di detection e reporting di errori
hardware. Consiste in un insieme di registri, chiamati Model Specific Register (MSR),
utilizzati per il report di errori hardware, come: cache, TLB, errori al bus di sistema
oppure errori di parità.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
21
La MCA è organizzata in banchi (il numero varia a seconda dell’architettura), replicati su
ogni core (figura 6), ed ognuno di essi corrisponde ad uno specifico componente hardware
(es, QPI Controller) e contiene cinque registri: due di controllo (MCi_CTL e MCi_CTL2),
un registro di controllo (MCi_STATUS), un registro indirizzo (MCi_ADDR) e un registro
miscellaneus (MCi_MISC). In aggiunta, ogni processore ha tre MSR globali:
MCG_STATUS, MCG_CAP e MCG_CTL. Il primo fornisce informazioni aggiuntive
sullo stato del processore; mentre, il secondo fornisce informazioni sulle funzionalità della
MCA implementate dal processore.
In base ai valori assunti dai registri gli errori si possono classificare in:
Uncorrected errors (UC): errori non corretti dal processore;
Uncorrected recoverable errors (UCR): errori non corretti dal processore ma per i
quali è possibile eseguire azioni di recupero software. Le operazioni di recovery
Figura 6 architettura MCA
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
22
possono essere obbligatorie (required – SRAR), opzionali (SRAO) o non richieste
(UCNA);
Corrected errors: sono errori corretti dal processore senza influenzare i processi in
esecuzione.
Il processore segnala il rilevamento di un errore non corretto sollevando l’eccezione:
Machine Check Exception (MCE). L’handler MCE del sistema operativo legge i valori dei
registri MSR e può intraprendere azioni di recupero.
Quando il processore rileva una condizione di errore scrive nei 16 bit meno significativi
del registro MCi_STATUS un codice di errore in cui sono codificate informazioni sulla
tipologia dell’errore, esempio: “0000 0000 0000 1101” specifica un errore generico nella
cache di primo livello. In tabella 2 sono riportati alcuni formati di error code.
Tipo Formato
Generic cache hierarchy 0001 0000 0000 11LL
TLB 0001 0000 0001 TTLL
Memory Controller 0001 1MMM 11LL CCCC
Cache hierarchy 0001 0001 RRRR TTLL
Bus and interconenctios 0001 1PPT RRRR IILL
*TT - Type of transaction
LL - Level in the memory hierarchy
RRRR - Type of action associated with the error
MMM and CCCC - Memory transaction type and Channel
PP and T - Partecipation
Tabella 2 MCi_Status [15:0]
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
23
Per la conoscenza degli MCE e dei codici di errore si è fatto riferimento alla
documentazione fornita dal produttore del processore [9].
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
24
Capitolo 2
XEN: gestione errori hardware
Nel seguente Capitolo si descrive in modo approfondito l’architettura software
implementata da Xen per la gestione degli errori MCE. Tale studio preliminare è servito
per acquisire un conoscenza dettagliata dei meccanismi relativi la MCA utilizzati poi per
la realizzazione del tool di emulazione argomento di questo lavoro di tesi.
2.1 Architettura MCA
Xen implementa un supporto software per la MCA che fornisce meccanismi di gestione e
di logging degli errori hardware. In figura 7 È mostrata l’architettura MCA di Xen.
Come già accennato nel capitolo precedente, la MCA memorizza nei registri MSR
informazioni sul tipo di errore. Molti di questi errori sono corretti dall’hardware stesso, ed
essi sono loggati nei banchi della machine check senza notificare il sistema soprastante.
Quindi, Xen implementa un meccanismo di polling: ogni trenta secondi sono letti i registri
MSR e nel caso di rilevano errori non segnalati, quest’ultimi vengono loggati. Mentre,
errori non corretti sono segnalati generando un interrupt MCE. L’hypervisor implementa
Figura 7 Architettura MCA Xen
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
25
due handler per MCE:
Intel_machine_check;
mcheck_cmn_handler;
Il primo è specifico per processori intel ed stato introdotto solo nelle ultime versioni di
xen. Il secondo, invece, è un handler generico, implementato già nelle versioni meno
recenti dell’hypervisor ed è utilizzato tipicamente per i processori AMD. Nella fase di init
della MCA, Xen in base al tipo di processore installato sulla macchina registra l’handler
più adatto.
I due handlers saranno descritti in maniera più approfondita nel corso di questo capitolo.
La politica di gestione di Xen in linea generale segue due principi chiave:
Non permette mai ad un sistema corrotto di continuare la propria esecuzione;
E senza violare il punto precedente cerca il più possibile di mantenere “vivo” il
sistema.
Se il primo punto non è garantito, il sistema deve essere riavviato. Comunque, quando
possibile si preferisce uccidere un processo in un guest o distruggere il guest stesso per
preservare l’integrità dell’intero sistema.
Il Dom0 è responsabile di gestire il logging e la notifica degli errori. Xen segnala al dom0
della rilevazione di un nuovo errore tramite VIRQ (se l’evento è abilitato).
Successivamente il dominio raccoglie informazioni sul tipo di errore interrogando il
modulo di telemetria di Xen, tramite hypercall (HYPERVISOR_mca). Le informazioni
raccolte sono quindi loggate e notificate all’amministratore di sistema.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
26
2.1.1 Hypercall: interfaccia MCA
XEN permette di interagire il modulo MCA tramite una specifica hypercall: la
HYPERVISOR_mca, con cui il Dom0 può recuperare informazioni sulla cpu, interrogare i
log o iniettare errori hardware per il testing degli handler MCE.
static inline int HYPERVISOR_mca(struct xen_mc *mc_op) {
mc_op->interface_version = XEN_MCA_INTERFACE_VERSION;
return _hypercall1(int, mca, mc_op);
}
struct xen_mc {
uint32_t cmd;
uint32_t interface_version; /* XEN_MCA_INTERFACE_VERSION */
union {
struct xen_mc_fetch mc_fetch;
struct xen_mc_notifydomain mc_notifydomain;
struct xen_mc_physcpuinfo mc_physcpuinfo;
struct xen_mc_msrinject mc_msrinject;
struct xen_mc_mceinject mc_mceinject;
} u;
};
Tabella 1 - HYPERVISOR_mca
In tabella è mostrato l’interfaccia di programmazione fornita da XEN. La struttura dati
xen_mc, passata come argomento in ingresso, specifica l’operazione da effettuare; tale
informazione è contenuta nel campo cmd. Le operazioni disponibili sono:
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
27
1. Fetch: recupero delle informazioni sugli errori hardware loggati dalla MCA;
2. Notifydomain: notifica a un dominio non privilegiato dell’occorrenza di un
errore, attualmente non implementato;
3. Physcpuinfo: recupero informazioni sulla cpu fisica, esempio: modello, signature,
ecc..
4. Msrinject: il modulo MCA mantiene un’astrazione dei registri MSR, e tale
comando permette di scriverne il valore;
5. Mceinject: tipicamente invocato dopo una serie di comandi di msrinject; solleva
interrupt 18 (MCE) sulla cpu target per attivare gli handler di gestione.
Ad ogni comando è associata una ulteriore struct che specifica i parametri dell’operazione.
Il tool di iniezione proposto in questo lavoro di tesi sfrutta i due comandi di iniezione
(msrinject e mceinject), la cui descrizione più approfondita è illustrata nel capitolo 3.
2.2 Telemetria
Xen comprende un modulo interno di telemetria per il logging degli errori. Ad ogni errore
corrisponde un singolo elemento di telemetria, identificato univocamente da un token. La
tabella mostra nel dettaglio la struct utilizzata.
struct mctelem_ent {
struct mctelem_ent *mcte_next; /* next in chronological order */
struct mctelem_ent *mcte_prev; /* previous in chronological order */
uint32_t mcte_flags; /* See MCTE_F_* below */
uint32_t mcte_refcnt; /* Reference count */
void *mcte_data; /* corresponding data payload */
};
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
28
Il campo mcte_data è un puntatore ad un area di memoria contenente informazioni
dettagliate sul tipo di errore rilevato, ossia il numero di banco e il valore dei registri MSR.
I vari elementi sono organizzati secondo in strutture dati di tipo lista, nel particolare per
ogni processore sono gestite due liste: pending e processing utilizzate nell’elaborazione
della telemetria in differita. La prima lista contiene tutti gli elementi che sono in attesa di
essere elaborati, mentre la seconda quelli attualmente in elaborazione. In aggiunta, c’è un
ulteriore lista globale commit che contiene tutti gli errori gestiti e loggati da Xen; il Dom0
può accedere a tale lista tramite il comando fetch dell’hypercall HYPERVISOR_mca.
2.3 VMCE
Xen fornisce ai guest una virtualizzazione di registri MSR. Generalmente solo al Dom0 e
ai domini HVM è abilitato il supporto per la MCA ma questo limite può essere superato
mediante un opzione di configurazione del dominio. Il guest ha due banchi virtuali, un
singolo banco (Bank 1) è utilizzato per la notifica di tutti gli errori che appartengono al
guest. Mentre, il Bank 0 di solito è inutilizzato poiché alcune distribuzioni di linux su
alcuni processori vecchi AMD ignorano tale banco.
Alcuni errori non sono gestiti direttamente dall’hypervisor ma sono inoltrati ai domini
guest, che a loro volta attivano i propri handler MCE. Tipicamente l’istruction-set dei
moderni processori includono delle istruzioni specifiche per le operazioni di lettura e di
scrittura dei registri MSR, nel particolare per cpu Intel e AMD le istruzioni sono: rdmsr e
wrmsr. Queste istruzioni richiedono un livello di privilegio elevato e generano un general
protection fault (GPF) se eseguite in un livello diverso del ring 0.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
29
Per consentire ai sistemi operativi guest di utilizzare istruzioni privilegiate pur essendo in
ring 1, XEN implementa un meccanismo di emulazione all’interno dell’handler GPF
(figura 8). Nel caso particolare delle istruzioni di rdmsr e wrmsr, la sequenza di passi
eseguiti sono i seguenti:
1. Il guest esegue rdmsr o wrmsr, per esempio in seguito ad una trap MCE da parte di
Xen;
2. Il processore controlla il livello di privilegio, vede che è diverso dal ring 0 e solleva
un GPF;
3. È attivato l’handler di gestione do_genaral_protection; se il codice di errore è pari
a zero significa che l’eccezione è stata sollevata perché si è tentato di eseguire un
istruzione privilegiata ed è richiamata la funzione emulate_priviled_op( );
4. Si esegue l’operazione di lettura o di scrittura del registro MSR, in contesto
hypervisor.
L’ultimo punto è implementato in maniera differente in base al tipo di processore su cui è
installato il sistema. Nel caso AMD, semplicemente sono eseguite le istruzione di read e di
Figura 8 Meccanismo di emulazione di operazioni privilegiate
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
30
write in contesto ring 0. Mentre, nel caso Intel non si accede ai registri MSR fisici ma ai
registri MSR virtuali (vMSR) della VMCE relativa al particolare dominio. Questa
differenza è dovuta al fatto che i processori Intel non permettono la scrittura dei registri
MSR via software.
struct domain_mca_msrs {
uint64_t mcg_status;
uint16_t nr_injection;
struct list_head impact_header;
spinlock_t lock;
};
Figura 9 Astrazione registri MSR
In figura 9 è mostrata la struttura dati utilizzata per rappresentare i registri MSR di un
dominio. Oltre al registro MCG_STATUS, ogni dominio detiene una propria lista,
impact_header, contenente tutti i registri MSR impattati da un errore. Per esempio: se
nella segnalazione di un errore da parte della MCA sono stati modificati i registri
MCi_STATUS e MCi_ADDR, l’hypervisor dovrà aggiungere due elementi nella lista, uno
per ogni registro MSR.
2.4 Handler Intel
Nel seguito è descritto il funzionamento dell’handler MCE specifico per precessori Intel.
L’architettura Intel prevede che errori rilevati dalla MCA siano segnalate in modalità
broadcast. Sui processori multi-core un errore da parte di un unità hardware può
propagarsi su più core. Per evitare che errori critici possano essere ignorati a favore di
errori meno severi si impone che tutte le cpu logiche sollevino un interrupt MCE.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
31
In figura 10 è mostrato il flow chart dell’handler. In linea generale i passi effettuati sono:
1. Riserva una nuova entry nella telemetria. La funzione mcheck_mca_logout( )
legge i registri MSR e verifica che ci siano banchi validi (controlla il bit VAL del
registro MCi_STATUS) e crea una nuova entry nella telemetria.
2. Se sono stati trovati errori:
a. Se l’errore risulta essere non recuperabile oppure il contesto del processore
corrotto (bit PCC di MCi_STATUS) il sistema è riavviato.
b. Se nel registro globale MCG_STATUS i bit RIPV e EIPV (errori
asincroni) sono entrambi zero oppure l’errore appartiene al contesto
hypervisor il sistema è riavviato.
c. Altrimenti si tenta di recuperare l’errore; richiamando opportuni handler
Figura 10 Diagramma di flusso handler Intel
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
32
per il particolare tipo di errore, la cui descrizione è approfondita in seguito.
3. Si solleva un software interrupt per il processing di ulteriori banchi non corretti.
4. Commit dell’errore.
L’MCA su processori Intel può aggregare più errori appartenenti a banchi diversi in una
singola segnalazione. Nell’handler Xen si cerca il primo banco contenente un errore e lo si
processa, mentre, ulteriori errori sono elaborati in “differita”: ogni cpu controlla la propria
lista pending nella telemetria in cerca di entry da processare e per ognuno di essi sono
attivati gli handler di gestione.
In base al particolare tipo di errore sono attivate più procedure di gestione. Ognuna di esse
intraprende azioni di recupero in maniera indipendente dalle altre. Al termine si tiene
conto del risultato peggiore, se per esempio tra tutti gli handlers attivati almeno uno decide
per il panic il sistema è riavviato indipendentemente dall’esito degli altri. Nel particolare,
sono implementati cinque handlers:
1. intel_default_mce_uhandler;
2. intel_default_mce_dhandler ;
3. intel_srao_dhandler
4. intel_srar_dhandler
5. intel_memerr_dhandler;
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
33
I primi due sono equivalenti da un punto di vista funzionale ed è attivato o l’uno o l’altro
in base al contesto di appartenenza delle errore se guest o hypervisor. Sono sempre attivati
per ogni tipo di errore. In tabella è riportato un riassunto delle azioni intraprese dai default
handlers.
VAL PCC UC SER
support
S AR OVER
0 - - - - - -
Continue
1 0 0 - - - -
1 0 1 1 0 - -
1 0 1 1 1 0 -
1 0 1 1 1 1 0
Figura 11 Sequenza attivazione handler
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
34
Altrimenti Panic
Gli handlers: intel_srao_dhandler, intel_srar_dhandler sono attivati rispettivamente per
errori di tipo SRAO e SRAR. Non intraprendono azioni di ripristino vero e proprio ma si
limitano a verificare se l’error-code (ultimi 16 bit di MCi_STATUS) è specifico di alcuni
tipi di errore della memoria e richiamano l’handler intel_memerr_dhandler. In figura è
riportato il codice sorgente dei due handlers.
static void intel_srar_dhandler(
727 struct mca_binfo *binfo,
728 enum mce_result *result,
729 struct cpu_user_regs *regs)
730 {
731 uint64_t status = binfo->mib->mc_status;
732
733 /* For unknown srar error code, reset system */
734 *result = MCER_RESET;
735
736 switch ( status & INTEL_MCCOD_MASK )
737 {
738 case INTEL_SRAR_DATA_LOAD:
739 case INTEL_SRAR_INSTR_FETCH:
740 intel_memerr_dhandler(binfo, result, regs);
741 break;
742 default:
743 break;
744 }
745 }
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
35
752 static void intel_srao_dhandler(
753 struct mca_binfo *binfo,
754 enum mce_result *result,
755 struct cpu_user_regs *regs)
756 {
757 uint64_t status = binfo->mib->mc_status;
758
759 /* For unknown srao error code, no action required */
760 *result = MCER_CONTINUE;
761
762 if ( status & MCi_STATUS_VAL )
763 {
764 switch ( status & INTEL_MCCOD_MASK )
765 {
766 case INTEL_SRAO_MEM_SCRUB:
767 case INTEL_SRAO_L3_EWB:
768 intel_memerr_dhandler(binfo, result, regs);
769 break;
770 default:
771 break;
772 }
773 }
774 }
L’handler intel_memerr_dhandler gestisce errori che coinvolgono la memoria. In tabella
sono riportate le condizioni di attivazione dell’handler.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
36
VA
L
OV
ER
UC
EN
MIS
CV
AD
DR
V
PC
C
S
AR
MCACOD
Errori SRAO
Memory
scrubbling 1 0 1 1 1 1 0 1 0
0xC0-
0xCF
L3 explicit
Writeback 1 0 1 1 1 1 0 1 0 0x17A
Errori SRAR
Data load 1 0 1 1 1 1 0 1 1 0x134
Istr. fetch 1 0 1 1 1 1 0 1 1 0x150
Questi tipi di errori sono gestiti tutti allo stesso modo. L’azione di recupero intrapresa è
quella di rendere offline la pagina corrotta in maniera che non possa essere più utilizzata. I
passi eseguiti dell’handler sono:
1. Lettura del registro MSR MCi_ADDR che contiene l’indirizzo di memoria
dell’errore;
2. Invalida la pagina corrotta: page_offline
3. Se:
a. l’operazione precedente ha esito positivo,
i. Dall’indirizzo si risale a quale guest appartiene la pagina;
ii. Qualora il guest sia HVM verrà notificato, altrimenti si distrugge il
dominio.
b. Altrimenti, il sistema è riavviato.
L’operazione di page_offline può fallire in due casi: se la pagina appartiene al dom0
oppure all’area heap dell’hypervisor.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
37
2.5 Shared handler
Lo shared handler è implementato già nelle versione più vecchie dell’hypervisor (Xen
3.0), è attualmente utilizzato per i processori AMD. In figura 12 è riportato il flow chart.
Figura 12 Diagramma di flusso Shared handler
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
38
I passi seguiti dall’handler:
1. Disabilita gli interrupt verso la vcpu in esecuzione al momento dell’interrupt in
modo da evitare che possa essere rischedulata;
2. Riserva una nova entry nella telemetria;
3. Si determina a quale contesto appartiene l’errore: guest o hypervisor e se esso ne
abbia corrotto lo stato. Nel particolare:
In contesto hypervisor si riavvia il sistema;
In contesto guest si cerca di recuperare l’errore inoltrando una trap MCE al
kernel del guest. Se quest’ultimo non dispone di una callback registarta per
tale evento: nel caso domU il dominio è distrutto, altrimenti, nel caso dom0
il sistema è riavviato;
4. Si riabilitano gli interrupt per la vcpu e si logga lerrore in telemetria.
CS
(context
segment)
Dom ID UC PCC RIPV
- - 1 - - XEN
State lost - - - - 0
0 - - 1 -
Not 0 0 0 1 1 Dom0
State lost
Not 0 Not 0 0 1 1 DomU
State lost
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
39
In figura 13 è mostrato uno schema ad albero che descrive nel dettaglio le azioni intraprese
dall’handler in funzione dei bit dei registri MCG_STATUS e MCi_STATUS.
Tipicamente gli interrupt MCE si riferiscono ad errori UC o PCC, ma è possibile
configurare la machine check per la segnalazione di altre classi di errore.
Gli errori non corretti possono compromettere qualunque dominio o l’hypervisor stesso,
per esempio un errore della memoria durante un operazione di scrittura della cache
potrebbe corrompere dei dati appartenenti a più domini. Poiché non é possibile prevenire
l’utilizzo di questi dati corrotti da parte del sistema l’hypervisor.
Figura 13 Schema ad albero delle azioni di recupero
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
40
Per errori PCC (procesor context corrupted) la criticità dipende dal contesto a cui
appartengono. Se il contesto (registro CS del processore) dell’interrupt è l’hypervisor (ring
0) si ha il riavvio del sistema (panic), altrimenti si cerca di limitare l’impatto dell’errore al
singolo guest.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
41
Capitolo 3
Tool di emulazione di fallimenti hardware
In questo capitolo si propone una descrizione dettagliata del tool di iniezione realizzato e
delle rispettive modifiche apportate all’hypervisor. Successivamente, è illustrata
l’architettura del framework di iniezione sviluppato per la conduzione di esperimenti. Esso
si compone di diversi moduli indipendenti, tra cui un tool di supporto per la generazione
dei faultload (MCE da iniettare) e la cui implementazione è descritta nel dettaglio a fine
capitolo.
3.1 Descrizione del tool
Il tool proposto permette di emulare fallimenti hardware sfruttando i meccanismi di
notifica degli errori hardware al software di base. Infatti, l’approccio utilizzato è quello di
emulare l’occorrenza di un MCE da parte di un’unità del processore scrivendo i registri
MSR dell’hypervisor senza interferire con la macchina fisica vera e propria.
Sono previste due modalità di iniezione degli MCE:
1. In contesto hypervisor: cioè, l’errore è elaborato dalle normali procedure di gestione
di Xen;
2. In contesto guest: l’errore è inoltrato direttamente al dominio target by-passando
completamente la logica di gestione dell’hypervisor.
La seconda modalità permette di testare un singolo sistema operativo guest trascurando
completamente la presenza di uno strato di virtualizzazione intermedio.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
42
Come già accennato nel Capitolo 2 Xen mette a disposizione un specifica hypercall
(HYPERVISOR_mca) come interfaccia per il modulo MCA e fornisce dei comandi per
l’iniezione di errori MCE. Nel particolare il tool sfrutta i comandi mceinjet e msrinject.
I passi effettuati in una singola iniezione (figura 14) sono:
1. Scrittura dei registri MSR, tramite msr_inject
2. Tramite il comando mce_inject, si solleva l’interrupt MCE sulla cpu target.
3. Si attiva l’handler MCE
4. Se l’iniezione è diretta al guest l’Mce è inoltrato direttamente al kernel guest,
altrimenti, è gestito normalmente da Xen.
Figura 14 Interaction diagram tool di iniezione
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
43
Oltre all’implementazione del tool vero e proprio, eseguito in contesto utente sul dom0, è
stato necessario apportare numerose modifiche al codice dell’hypervisor. Entrambi gli
aspetti sono descritti nel dettaglio nel seguito.
3.1.1 Dettagli implementativi
La libreria libxc, su cui è basato anche il toolstack xm, fornisce un insieme di API per
l’interfaccia tra applicazioni e hypervisor. Tale libreria è stata utilizzata dal tool per
l’invocazione delle hypercall.
xc_interface* xc_interface_open ( xentoollog_logger * logger,
xentoollog_logger * dombuild_logger,
unsigned open_flags
)
Nel particolare la API xc_interface_open() crea un handle per interfacciarsi al componente
privcmd, che fornisce funzionalità di invio di hypercall.
int xc_mca_op(xc_interface *xch, struct xen_mc *mc);
struct xen_mc {
uint32_t cmd
uint32_t interface_version
union {
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
44
struct xen_mc_fetch mc_fetch
struct xen_mc_notifydomain mc_notifydomain
struct xen_mc_physcpuinfo mc_physcpuinfo
struct xen_mc_msrinject mc_msrinject
struct xen_mc_mceinject mc_mceinject
}
La funzione xc_mca_op permette l’invocazione di HYPERVISOR_mca, tramite privcmd.
In aggiunta all’interfaccia aperta in precedenza richiede come secondo parametro di
ingresso un puntatore alla struttura dati (xen_mc) che specifica il tipo di operazione da
effettuare.
#define XEN_MC_msrinject 4
#define MC_MSRINJ_MAXMSRS 8
struct xen_mc_msrinject {
/* IN */
uint32_t mcinj_cpunr; /* target processor id */
uint32_t mcinj_flags;
uint32_t mcinj_count;
uint32_t _pad0;
struct mcinfo_msr mcinj_msr[MC_MSRINJ_MAXMSRS];
};
struct mcinfo_msr {
uint64_t reg; /* MSR */
uint64_t value; /* MSR value */
};
Il comando msr_inject prevede i seguenti parametri:
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
45
1. Mcinj_cpunr, cioè il numero della cpu target;
2. Mcinj_flags, è possibile specifcare dei flag per la scrittura dei registri MSR;
3. Mcinj_conut: è possibile aggregare la scrittura di più registri MSR nel medesimo
comando, e tale parametro contiene il numero dei registri da iniettare;
4. Mcinj_msr: è un array di elementi mcinfo_msr, ognuno di essi specifica il registro
MSR e il valore da iniettare.
#define XEN_MC_mceinject 5
struct xen_mc_mceinject {
unsigned int mceinj_cpunr; /* target processor id */
Invece, il commando mce_inject richiede come unico parametro l’numero della cpu target
su cui iniettare l’MCE. Come sarà descritto in seguito è stato necessario modificare
l’interfaccia di questo comando, aggiungendo altri due campi: l’id del dominio target e un
flag che indica l’iniezione verso il guest.
Nella figura mostrata in seguito, è riportato il codice della funzione inject_error () in cui è
implementata la logica di iniezione del tool.
struct xen_mc_msrinject msr_inj;
int inject_error (xc_interface *xc_handle,
uint32_t cpu_nr ,
uint32_t domain,
uint64_t gaddr)
{
uint64_t gpfn, mfn, haddr;
int ret = 0;
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
46
ret = inject_mcg_status(xc_handle, cpu_nr, MCG_STATUS);
if ( ret )
err(xc_handle, "Failed to inject MCG_STATUS MSR\n");
ret = inject_mci_status(xc_handle, cpu_nr,
bank, MCi_STATUS);
if ( ret )
err(xc_handle, "Failed to inject MCi_STATUS MSR\n");
if(misc){ // se il bit MISCV di MCi_STATUS è abilitato
ret = inject_mci_misc(xc_handle, cpu_nr, //inietto il registro MCi_MISC
bank, MCi_MISC);
if ( ret )
err(xc_handle, "Failed to inject MCi_MISC MSR\n");
}
if(addr){ // se il bit ADDR di MCi_STATUS è abilitato
gpfn = gaddr >> PAGE_SHIFT;
mfn = mca_gpfn_to_mfn(xc_handle, domain, gpfn);
if (!mfn_valid(mfn))
err(xc_handle, "The MFN is not valid\n");
haddr = (mfn << PAGE_SHIFT) | (gaddr & (PAGE_SIZE - 1));
ret = inject_mci_addr(xc_handle, cpu_nr, bank, haddr); //inietto il registro
MCi_ADDR
if ( ret )
err(xc_handle, "Failed to inject MCi_ADDR MSR\n");
}
ret = flush_msr_inj(xc_handle); //comando msr_inejct
if ( ret )
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
47
err(xc_handle, "Failed to inject MSR\n");
ret = inject_mce(xc_handle, cpu_nr,domain);
if ( ret )
err(xc_handle, "Failed to inject MCE error\n");
return 0;
Poiché è possibile specificare più operazioni di scrittura in una singola invocazione del
comando msr_inject, per ogni registro MSR coinvolto dell’errore da iniettare si inserisce
nella struct msr_inj (globale) un nuovo elemento; il codice relativo all’inserimento nella
struct dell’hypercall è mostrato nella figura sottostante.
int add_msr_intpose(xc_interface *xc_handle,
uint32_t cpu_nr,
uint32_t flags,
uint64_t msr,
uint64_t val)
{
uint32_t count;
/* se si è raggiunto il numero massimo di registri MSR oppure la cpu target o i
flag di iniezione sono cambiati si effettua il flush dell’iniezione, cioè si invoca
l’hypercall per il comando di msr_inject, altrimenti, si inserisce un nuovo
elemento nell’array*/
if ( (msr_inj.mcinj_count &&
(cpu_nr != msr_inj.mcinj_cpunr || flags != msr_inj.mcinj_flags)) ||
msr_inj.mcinj_count == MC_MSRINJ_MAXMSRS )
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
48
{
flush_msr_inj(xc_handle);
init_msr_inj();
}
count= msr_inj.mcinj_count;
if ( !count )
{
msr_inj.mcinj_cpunr = cpu_nr;
msr_inj.mcinj_flags = flags;
}
msr_inj.mcinj_msr[count].reg = msr;
msr_inj.mcinj_msr[count].value = val;
msr_inj.mcinj_count++;
return 0;
}
La funzione flush_msr_inj(), mostrata nel riquadro sottostante, invia il comando msrinject
all’hypervisor, includendo la struct msr_inj, riempita in precedenza.
static int flush_msr_inj(xc_interface *xc_handle)
{
struct xen_mc mc;
mc.cmd = XEN_MC_msrinject;
mc.interface_version = XEN_MCA_INTERFACE_VERSION;
mc.u.mc_msrinject = msr_inj;
return xc_mca_op(xc_handle, &mc);
}
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
49
Al termine delle operazioni di scrittura dei registri MSR è sollevato l’MCE tramite la
funzione inject_mce(), che invoca il comando mceinject, la cui interfaccia è stata
modificata opportunamente in base ai requisiti di iniezione; una trattazione più
approfondita è affrontata nel seguito di questo capitolo nel paragrafo relativo alle
modifiche apportate al codice dell’hypervisor. Il parametro di ingresso is_guest è un
intero se l’errore deve essere inoltrato direttamente al guest o meno.
static int inject_mce(xc_interface *xc_handle, int cpu_nr, int domid int to_guest)
{
/* to_guest:
0: errore gestito normalemente da xen
1: errore inoltrato direttamente al guest
*/
struct xen_mc mc;
memset(&mc, 0, sizeof(struct xen_mc));
mc.cmd = XEN_MC_mceinject;
mc.interface_version = XEN_MCA_INTERFACE_VERSION;
mc.u.mc_mceinject.mceinj_cpunr = cpu_nr;
mc.u.mc_mceinject.to_guest = to_guest;
mc.u.mc_mceinject.domain_id = domid;
return xc_mca_op(xc_handle, &mc);
}
3.1.2 Modifiche al codice di XEN
Nel seguente paragrafo sono discusse le modifiche necessarie apportate all’hypervisor. Il
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
50
primo passo è stato scegliere quale handler di gestione (discussi nel capitolo 2) utilizzare
per la creazione dell’infrastruttura di iniezione: intel_machine_check, specifico per Intel, o
mcheck_cmd_handler, generico ed implementato nelle versioni di Xen meno recenti. Il
primo non è stato ritenuto adatto per i seguenti motivi:
1. È specifico dei processori Intel e questo limita l’utilizzo del framework di iniezione
su architetture diverse;
2. La gestione dell’errore è implementata quasi completamente nell’hypervisor stesso,
riducendo al minimo l’interazione con il guest, salvo pochi casi;
3. Inoltre, prevede anche la gestione degli errori in “differita”.
Per cui si è optato per l’handler shared la cui logica di gestione risulta essere molto più
lineare e semplice, inoltre, a differenza dall’handler Intel, possibili azioni di recupero sono
demandate ai guest.
La prima modifica è stata apportata al file mce_intel.c
(xen/arch/x86/cpu/mcheck/mce_intel.c) in modo che forzare l’uso dell’handler shared
anche in architetture Intel, come mostrato in figura.
static void intel_machine_check(struct cpu_user_regs * regs, long error_code)
{
/* richiamo l’handler shared */
mcheck_cmn_handler(regs, error_code, mca_allbanks);
}
Un obiettivo del framework di iniezione proposto è la possibilità di valutare i meccanismi
di error-handling di un sistema operativo guest by-passando completamente l’hypervisor,
questo è tradotto con una modifica dell’handler shared (xen/arch/x86/cpu/mcheck/mce.c)
come riportato in seguito.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
51
void mcheck_cmn_handler(struct cpu_user_regs *regs, long error_code,
struct mca_banks *bankmask)
{
/* init variabili */
vcpu_schedule_lock_irq(v);
irqlocked = 1;
if(to_guest){ //inoltra la gestione al guest
domid = injected_domid;
curdom = get_domain_by_id(domid);
send_guest_trap(curdom, 0,TRAP_machine_check);
goto fine;
}
/*
…….
error-handling logic XEN
…..
*/
fine:
if(irqlocked)
vcpu_schedule_unlock_irq(v);
atomic_dec(&curdom->refcnt);
} // fine handler
Nel caso di iniezione verso il guest (to_guest pari a 1) è sollevato una trap machine check,
tramite la funzione int send_guest_trap (struct domain *d, uint16_t vcpuid, unsigned int
trap_nr), tale funzione prevede tre parametri d’ingresso:
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
52
1. Il primo è un puntatore ad una struct relativa al dominio;
2. L’id della vcpu del dominio da notificare;
3. Il numero della trap da sollevare.
La scelta della vcpu è del tutto ininfluente sull’impatto dell’errore verso il guest e per
questo motivo si è scelto arbitrariamente di inoltrare le trap sempre alla vcpu 0.
Altre modifiche riguardano l’hypercall “HYPERVISOR_do_mca”, descritta nel capitolo 1.
Nel particolare il comando mce_inject prevede come unico parametro d’ingresso
l’identificativo della cpu su cui sollevare l’MCE, ma tale informazione, da sola, è
insufficiente per implementare un meccanismo di iniezione verso un guest target. Per cui
si è resa necessaria una modifica dell’interfaccia del comando (xen-mca.h, sia
nell’hypervisor che nel kernel dom0), nel particolare sono stati aggiunti due parametri:
1. Domid: l’identificativo del dominio target;
2. to_guest: è un intero, se vale 1 l’errore è da inoltrare direttamente al guest,
altrimenti, è gestito normalmente dall’hypervisor.
#define XEN_MC_mceinject 5
struct xen_mc_mceinject {
unsigned int mceinj_cpunr; /* target processor id */
domid_t domain_id; /*target domain*/
int to_guest; /*forward error to guest*/
};
Per ogni hypercall HYPERVISOR_do_mca è invocata la funzione do_mca() (mce.c), che
implementa la logica di gestione dei comandi previsti da tale hypercall. Nel caso
particolare, nel seguito è riportato il codice modificato relativo al comando mceinject.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
53
…
…
case XEN_MC_mceinject:
if (nr_mce_banks == 0)
return x86_mcerr("do_mca #MC", -ENODEV);
mc_mceinject = &op->u.mc_mceinject; //leggo la struct inviata nella
Hypercall
target = mc_mceinject->mceinj_cpunr;
target_domid = mc_mceinject->domain_id;
mcib.mc_domid = target_domid;
if (target >= nr_cpu_ids)
return x86_mcerr("do_mca #MC: bad target", -EINVAL);
if (!cpu_online(target))
return x86_mcerr("do_mca #MC: target offline", -EINVAL);
injected_domid = target_domid;
target_domain = get_domain_by_id(target_domid);
if (injected_domid != DOMID_XEN){
injection_context = 3; //simulo un errore nel ring 3
if ( mc_mceinject->to_guest )
to_guest = 1;
fill_vmsr_data(&mcib, target_domain , injected_gstatus);
}
on_selected_cpus(cpumask_of(target), x86_mc_mceinject,mc_mceinject,
1); // solleva interrupt 18 (MCE)
atomic_dec(&target_domain->refcnt); // decremento il numero di referenze alla
struct
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
54
Inoltre, sono settate due variabili globali: injection_context e to_guest; la prima è
utilizzata per simulare errori in un determinato contesto (ring 0, ring 3), infatti,
l’handler normalmente legge il registro CS (context segment) per capire
nell’istante in cui è stato sollevato l’MCE a quale livello di privilegio appartiene
(ring 0, ring 1, ecc) l’istruzione in esecuzione nella cpu quindi, se si desidera
emulare un errore da parte di applicativo guest bisognerebbe far in modo che
nell’istante in cui è attivato l’handler è in esecuzione codice livello utente. Per
superare questo inconveniente, nel caso di iniezione l’handler non legge il registro
CS ma bensì la variabile injection_context, che nel caso in cui l’errore è relativo ad
un dominio vale tre (ring 3), altrimenti vale zero (ring 0). Mentre, la variabile
to_guest indica all’handler la volontà di iniettare l’errore direttamente al guest by-
passando completamente la normale logica di gestione dell’errore dell’hypervisor.
Come già descritto nel capitolo 2, i registi MSR fisici sono mascherati ai guest ai
quali si fornisce una loro astrazione tramite la vmce. Quindi, prima di inoltrare una
trap MCE al guest devono essere scritti i registri MSR virtuali, questa operazione è
svolta dalla funzione:
int fill_vmsr_data(struct mcinfo_bank *mc_bank, struct domain *d, uint64_t
gstatus);
Che come parametri d’ingresso richiede:
1. Mc_bank: un puntatore ad una struct mcinfo_bank (figura … ), contenente
l’intero stato del banco da iniettare;
2. d: la struct domain relativa al dominio target;
3. gstatus: di tipo uint_64, è il valore del registro MCG_STATUS.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
55
struct mcinfo_bank {
struct mcinfo_common common;
uint16_t mc_bank; /* bank nr */
uint16_t mc_domid;
uint64_t mc_status; /* bank status */
uint64_t mc_addr; /* bank address, only valid
* if addr bit is set in mc_status */
uint64_t mc_misc;
uint64_t mc_ctrl2;
uint64_t mc_tsc;
};
struct mcinfo_common {
uint16_t type; /* structure type */
uint16_t size; /* size of this struct in bytes */
};
La struttura dati mcib, passata nella funzione fill_vmsr_data, contiene i valori dei
registri MSR coinvolti nella segnalazione dell’errore. Tale struttura è riempita nella
prima fase di scrittura dei registri MSR, cioè nel comando msr_inject. Nel seguito
è riportato il codice modificato (evidenziato in verde) della funzione di scrittura dei
registri MSR.
static void x86_mc_msrinject(void *data)
{
struct xen_mc_msrinject *mci = data;
struct mcinfo_msr *msr;
uint64_t hwcr = 0;
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
56
int intpose;
int i;
int bank = 0;
int msr_type = 0;
if (mci->mcinj_flags & _MC_MSRINJ_F_REQ_HWCR_WREN)
hwcr = x86_mc_hwcr_wren();
intpose = (mci->mcinj_flags & MC_MSRINJ_F_INTERPOSE) != 0;
//per forza intpose altrimenti va in gp
for (i = 0, msr = &mci->mcinj_msr[0];
i < mci->mcinj_count; i++, msr++) {
printk("HV MSR INJECT (%s) target %u actual %u MSR 0x%llx "
"<-- 0x%llx\n",
intpose ? "interpose" : "hardware",
mci->mcinj_cpunr, smp_processor_id(),
(unsigned long long)msr->reg,
(unsigned long long)msr->value);
if (intpose)
intpose_add(mci->mcinj_cpunr, msr->reg, msr->value);
else
wrmsrl(msr->reg, msr->value);
if (msr->reg != 0x17a){
if(mcib_valid){
msr_type = (int) (msr->reg & 0x3); //bit 0-1
bank = (int)((msr->reg >> 2) & 0xf); //bit 2-5
switch(msr_type){
case 1:
mcib.mc_status = msr->value;
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
57
break;
case 2:
mcib.mc_addr = msr->value;
break;
case 3:
mcib.mc_misc = msr->value;
break;
default:
printk("No valid msr to insert in mcib\n");
break;
}
mcib.mc_bank = bank;
}
}else{
injected_gstatus = msr->value;
}
}
if (mci->mcinj_flags & _MC_MSRINJ_F_REQ_HWCR_WREN)
x86_mc_hwcr_wren_restore(hwcr);
}
Alcuni processori, come intel, non ammettono la scrittura dei registri MSR al di
fuori del contesto interrupt. La soluzione implementa da Xen prevede l’utilizzo di
un array, chiamato interpose_array: in scrittura è inserito un nuovo elemento,
interpose_ent, nell’array; mentre, in lettura si controlla prima se esiste una entry
nell’array, altrimenti in caso contrario si procede con la lettura del registro fisico.
In verde (riquadro in alto) è evidenziato la parte di codice relativa all’inserimento
dei dati nella struct mcib: in base all’indirizzo del registro MSR si determina il tipo
di registro (MCi_STATUS, MCi_ADRR, ecc..), il banco di appartenenza e si
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
58
scrive il corrispettivo campo della struct. Al termine dell’operazione di scrittura dei
registri MSR la struct mcib conterrà lo stato del banco MCA da iniettare nella
vmce, in modo tale da sincronizzare i registri MSR tra guest ed hypervisor.
3.1.3 Esempio di utilizzo
Tramite il tool realizzato è possibile iniettare qualsiasi tipo di errore MCE. Nella
tabella seguente sono elencati tutte le opzioni di iniezione supportate.
Option Descrizione
s [MSR value] Specifica il valore del registro
MCG_STATUS
S [MSR value] Specifica il valore del registro
MCi_STATUS
p [MSR value] Specifica il valore del registro MCi_ADDR
M [MSR value] Specifica il valore del registro MCi_MISCV
B [Bank number] Specifica il numero di banco
c [CPU value] Cpu target
d [domid] Specifica il dominio target
g
Se specificato l’errore è inoltrato
direttamente al guest, altrimenti è gestito da
xen.
Nel seguito è riportato un esempio di utilizzo. Consideriamo il caso di un errore
nella gerarchia cache inoltrato direttamente al guest. In tabella sono riportati i
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
59
valori dei registri.
In figura 16 è illustrato uno screen del terminale del dom0, in cui si evidenziano gli
argomenti passati al tool di iniezione.
Infine, in figura 17 è mostrato uno spezzone dei log di sistemi sul dominio target
Figura 15 parametri iniezione di esempio
Figura 16 utilizzo tool – screen Console dom0
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
60
che prova l’effettivo inoltro dell’MCE al guest target.
Figura 17 Log MCE – dom target
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
61
3.2 Architettura framework
La figura 18 illustra l’architettura del framework realizzato, in cui sono presenti
due domini:
1. Un dominio privilegiato (dom0) su cui è installato il framework di testing.
2. Un dominio target non privilegiato (domU) che esegue un particolare
workload con lo scopo di simulare condizioni di reali di funzionamento. Inoltre, il
guest è in esecuzione su un determinato “core”, assegnato ad esso in modo
esclusivo.
Inoltre, il framework si compone di diversi moduli aventi specifiche funzioni:
1. MCE generator è l’entità che automatizza la generazione degli errori MCE
da iniettare durante la campagna di test. Il numero di tutte le possibili
combinazione di codici di errori è estremamente elevato. È possibile
Figura 18 Architetura framework di iniezione
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
62
ottimizzare il processo di generazione secondo particolari criteri che
limitano il numero di esperimenti.
2. Injection tool è il componente responsabile dell’iniezione di errori MCE nel
sistema target, tramite l’hypervisor Xen. Il guest target deve essere
completamente isolato dal dom0, su cui è esecuzione il tool. Questo può
essere garantito eseguendo il dominio sotto esame su un particolare core in
modo esclusivo.
3. Coordinator è l’entità responsabile dell’iterazione degli esperimenti di error-
injection e del coordinamento dei vari componenti sopra descritti. Inoltre
esso si occupa di monitorare il comportamento del sistema target e di
memorizzare i dati raccolti.
3.2.1 MCE generator
Una singola campagna di testing può comprendere decine di migliaia di
esperimenti, di conseguenza è necessario automatizzare l’operazione di
generazione dei faultloads, cioè, l’insieme di MCE da iniettare nel sistema.
Ogni errore corrisponde ad una specifica combinazione dei registri MSR, numero
di banco, numero cpu, dominio target e quindi il numero totale di combinazioni
possibili risulta essere estremamente elevato, per cui è necessario poter specificare
dei criteri per ottimizzare il processo di generazione e ridurre il numero di
faultload.
A tal scopo è stato realizzato un apposito tool di supporto per la generazione dei
casi di test (MCE_generator). Il tool riceve in input un file contenente i criteri di
generazione e produce in output un ulteriore file contenente la lista degli MCE da
iniettare, sotto forma di argomenti che a loro volta sono dati in pasto al tool di
iniezione vero e proprio (figura 19).
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
63
I criteri possono essere del tipo:
Un determinato bit deve essere alto o basso;
Il tipo di errore, es. errori della TLB;
Oppure, è possibile specificare la cpu e il banco di appartenenza;
In accordo con i criteri specificati il tool genera tutte le possibili combinazioni di
errori. In seguito è mostrato l’elenco delle opzioni:
MSR bit options
Option (SET/NO_SET) Bit Affected MSR
MCIP/NO_MCIP 2
MCG_STATUS EIPV/NO_EIPV 1
RIPV/NO_RIPV 0
VALID/NO_VALID 63
MCi_STATUS
OVER/NO_OVER 62
UC/NO_UC 61
EN/NO_EN 60
PCC/NO_PCC 57
S/NO_S 56
Figura 19 MCE generator
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
64
MISCR/NO_MISCR 59
ADDV/NO_ADDRV 58
MCA error code option
Error option Description MCAOP binary encoding
NO_ERROR No error 0000 0000 0000 0000
UNCL_ERROR Unclassified error 0000 0000 0000 0001
MRPC_ERROR Microcode Rom
parity error
0000 0000 0000 0010
EXT_ERROR External error 0000 0000 0000 0011
FRC_ERROR
FRC( functional
redundancy check)
error
0000 0000 0000 0100
INT_PAR_ERRO Internal parity error 0000 0000 0000 0101
INT_TIMER_ERROR Internal timer error 0000 0100 0000 0000
GEN_CACHE_HIER_ERROR Generic cache
hierachy error
0000 0000 0000 11LL
TLB_ERROR TLB error 0000 0000 0001 TTLL
MEM_CTNL_ERROR Memory controller
error
0000 0000 1MMM CCCC
CACHE_HIER_ERROR Caache hiearachy
error
0000 0001 RRRR TTLL
BUS_ERROR Bus and
interconnects error
0000 1PPT RRRR IILL
MCAOP [mcaop value] Specific MCAOP passed from user (deafult 0x0)
*TT - Type of transaction
LL - Level in the memory hierarchy
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati
65
RRRR - Type of action associated with the error
MMM and CCCC - Memory transaction type and Channel
PP and T - Partecipation
Other option
Option Description
CPU [cpu number] Cpu target [default 0]
BANK [bank number] Numero del banco impattato [default 0]
NR_RIP [number] Un singolo esperimento pulò essere
ripetuto più volte [default 1]
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
66
Capitolo 4
Sperimentazione
In questo capitolo sono illustrate diverse campagne sperimentali svolte. Un primo studio è
incentrato sull’analisi dei meccanismi di error-handling di Xen. Dalla base dei risultati
ottenuti in precedenza, una seconda sperimentazione è focalizzata sul sottoinsieme di
errori demandati ai sistemi guest. Infine, è svolto un’ulteriore campagna è incentrata sullo
studio di sistema operativo linux.
La versione dell’hypervisor Xen utilizzata è la 4.2.1 rilasciata nel 2012. Inoltre, la
macchina utilizzata per l’esecuzione del framework dispone di un processore multicore
Intel i7-3630QM.
4 Framework di iniezione: coordinator
Come già descritto nel capitolo 3, il framework di iniezione si compone di diversi moduli
indipendenti (figura 20). L’entità coordinator ha la responsabilità di orchestrare le
operazioni tra i diversi moduli in modo da automatizzare il processo di iniezione.
Figura 20 Testbed
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
67
Ogni campagna di iniezione prevede una fase preliminare di creazione degli MCEs da
iniettare:
1. Si definiscono i criteri di generazione; nel particolare si scrive in un file le opzioni
da utilizzare nel tool di generazione. Nel seguito ne è mostrato un esempio.
MCIP NO_EIPV
VALID EN S NO_OVER NO_PCC
MCAOP 0x134
CPU 6 BANK 8
2. Il file così creato è dato in pasto al tool di generazione:
“./test_generator gen_criteria_file”
In output è restituito un file contenete la lista di argomenti da passare al tool di
iniezione vero e proprio.
Il modulo coordinator è uno script bash che la cui implementazione dipende dalla
particolare campagna di testing che si vuole svolgere. In linea generale, ogni
sperimentazione prevede le seguenti fasi:
1. Inizializzazione:
a. Creazione del dominio target, tramite il comando:
“xl create guest.cfg”
dove guest.cfg è il file di confgurazione del dominio;
b. Assegnazione della vcpu ad uno specifica cpu fisica, tramite il comando:
“xl vcpu-pin domid vcpu cpu”
Questo serve per garantire che l’iniezione influenza solo il dominio target;
2. Testing, per ogni errore da iniettare:
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
68
a. Eseguo un workload sul guest in modo che sia sempre in esecuzione all’atto
dell’iniezione; per sistemi operativi linux è disponibile un tool di utility per
lo stressing dei processori, chiamato “stress”, che è utilizzato per generare
un carico di lavoro presso il guest; Il guest è contattato mediante ssh,
tramite il comando:
“sshpass -p $dom_pass ssh $host "nohup stress -c 1 > foo.out 2> foo.err
< /dev/null &"
b. Dalla lista di MCEs si legge il prossimo errore da iniettare, tramite il
comando:
“./inject_mce_error $error_args $dom_arg”
c. Si monitora il sistema, leggendo i log dell’hypervisor:
“xl dmesg”
E i log di sistema del guest:
“sshpass -p $dom_pass ssh $host "dmesg -c"”
3. I log generati nella fase precedente vengono memorizzati e si produce in output un
file di report dell’esperimento.
4.1 Campagna 1: Xen error-handling
Una prima campagna di iniezione è mirata ad un’analisi della gestione degli errori da parte
dell’hypervisor. Nel particolare, sono messi sotto esame i due handler:
Intel_machine_check,, specifico per architetture intel;
Mcheck_cmn_handler, generico, utilizzato nelle versioni meno recenti di Xen
(versione 3) per tutte le architetture.
L’obiettivo principale di questo primo studio è stilare una casistica sul comportamento
degli handler: le azioni di recupero intraprese, quanti errori sono demandati al guest
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
69
4.1.1 Scelta degli errori
L’idea è di analizzare il comportamento di Xen rispetto a qualunque tipo di errore. Se
consideriamo errori appartenenti all’insieme di tutte le possibili combinazioni dei registri
MCG_STATUS, MCi_STATUS e di banco, il numero totale delle combinazioni
risulterebbe estremamente elevato:
2{nr bit MCG_STATUS} x 2
{nr bit MCi_STATUS} x {nr di banchi} = 23 x 264 x 9 > 267!!!
Tuttavia, i primi nove bit più significativi del registro MCi_STATUS caratterizzano la
tipologia di errore (UC, SRAO, SRAR); in aggiunta, i sedici bit meno significativi
contengono un codice specifico dell’unità in cui si è rilevato l’errore; mentre i rimanenti
sono contengono informazioni specifiche in base al modello del processore. Per cui, per
ridurre il numero di errori da iniettare si è pensato di considerare tutte le combinazioni dei
registri come riportate in figura sottostante.
Figura 21 Registri MSR
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
70
Gli MCA error code scelti sono errori “architecturally defined”, cioè sono errori per cui è
consigliato implementare delle azioni di recovery. In tabella sono mostrati gli error-code
per ogni errore.
Error MCACOD
Data Load 0x134 SRAR
Instruction fetch 0x150
L3 explicit cache writeback 0xC0-0xCF SRAO
Memory Scrubbing 0x17A
Unclassified 0x001 //
Per quanto riguarda il numero di banco, si è scelto arbitrariamente il banco otto. In
conclusione il numero di combinazioni è:
23 x 29 x 5 = 20480
Per ogni MCACOD è generato una lista di MCEs (in figura è il file di opzione di
genrazione relativo Data load), successivamente le diverse liste sono aggregate sotto un
unico file.
MCAOP 0x134
CPU 6 BANK 8
Nella seguente figura è presentato un spezzone della lista di MCE generata:
……
……
-s 0x5 -S 0x0180000000000134 -M 0x80 -p 0x180020 -c 6 -B 8
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
71
-s 0x5 -S 0x0200000000000134 -M 0x80 -p 0x180020 -c 6 -B 8
-s 0x5 -S 0x0280000000000134 -M 0x80 -p 0x180020 -c 6 -B 8
-s 0x5 -S 0x0300000000000134 -M 0x80 -p 0x180020 -c 6 -B 8
-s 0x5 -S 0x0380000000000134 -M 0x80 -p 0x180020 -c 6 -B 8
-s 0x5 -S 0x0400000000000134 -M 0x80 -p 0x180020 -c 6 -B 8
-s 0x5 -S 0x0480000000000134 -M 0x80 -p 0x180020 -c 6 -B 8
-s 0x5 -S 0x0500000000000134 -M 0x80 -p 0x180020 -c 6 -B 8
-s 0x5 -S 0x0580000000000134 -M 0x80 -p 0x180020 -c 6 -B 8
-s 0x5 -S 0x0600000000000134 -M 0x80 -p 0x180020 -c 6 -B 8
-s 0x5 -S 0x0680000000000134 -M 0x80 -p 0x180020 -c 6 -B 8
-s 0x5 -S 0x0700000000000134 -M 0x80 -p 0x180020 -c 6 -B 8
-s 0x5 -S 0x0780000000000134 -M 0x80 -p 0x180020 -c 6 -B 8
-s 0x5 -S 0x0800000000000134 -M 0x80 -p 0x180020 -c 6 -B 8
-s 0x5 -S 0x0880000000000134 -M 0x80 -p 0x180020 -c 6 -B 8
…….
…….
Il valore dei registri MISC e ADDR (rispettivamente “-M” e “-p”) se non specificati
assumono valori di default.
4.1.2 Monitoring
Da questo studio preliminare degli handlers, per ogni errore introdotto, si vogliono
ricavare due informazioni:
Lo stack di funzioni e il data flow eseguito;
E quale azione è intrapresa, per esempio: panic, distruzione del dominio, ecc.
Per integrare entrambi i punti, si è deciso di monitorare il sistema introducendo delle
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
72
stampe (printk) nel codice dell’hypervisor. Nel particolare si distinguono due tipologie di
stampe:
DEBUG: sono stampa inserite in ogni ramo del codice di interesse in modo tale da
riuscire a ricostruire il percorso seguito dall’handler;
RESULT: sono stampe inserite nei rami terminali dell’handler, e indicano l’azione
intrapresa (panic, inoltra al guest, ecc);
Per evitare che un errore causi il riavvio della macchina o del guest, in aggiunta sono tutte
le operazioni di panic o di domain_destroy sono state sostituite da stampe di RESULT, in
modo tale da evitare di resettare le macchine durante l’esecuzione della campagna. Nel
seguito è mostrato un esempio relativo all’handler shared.
…..
…..
…..
…..
printk("DEBUG_MCE: CPU%d - mcheck_cmn_handler - Hypervisor state lost
due to machine check "
"exception - panic \n",cpu);
printk("MCE_ACTION: CPU%d - PANIC\n",cpu);
//mc_panic("Hypervisor state lost due to machine check "
//"exception.\n");
goto fine;
}
…..
…..
…..
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
73
4.1.3 Configurazione del framework
Il processore su cui è in esecuzione il framework dispone di otto cpu logiche. Tali core
sono suddivisi tra dom0 e domU. Nel particolare i primi 6 core (da 0 a 5) sono messi a
disposizione del dom0, mentre i rimanenti core (6 e 7) sono utilizzati per i domU.
Nel riquadro successivo è mostrato lo script bash vcpu-pin.sh utilizzato in fase di
inizializzazione del framework per assegnare le 8 vcpu del dom0 sui primi 6 core dal
processore fisico.
#! /bin/bash
xl vcpu-pin 0 0 0
xl vcpu-pin 0 1 1
xl vcpu-pin 0 2 2
xl vcpu-pin 0 3 3
xl vcpu-pin 0 4 4
xl vcpu-pin 0 5 4
xl vcpu-pin 0 6 5
xl vcpu-pin 0 7 5
Nel riquadro sottostante, invece, è mostrato il file di configurazione del dominio target.
File cfg #
# Configuration file for the Xen instance guest2, created
# by xen-tools 4.3.1 on Sat Feb 9 12:15:25 2013.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
74
#
#
# Kernel + memory size
#
#builder = "hvm"
bootloader = 'pygrub'
bootloader_args = "--kernel=/boot/vmlinuz-3.6.11-modified-domU --
ramdisk=/boot/initrd.img-3.6.11-modified-domU"
vcpus = '1'
cpus = '6'
#enable cpu features: VME MCE MCA
cpuid=['1:edx=xxxxxxxxxxxxxxxxx1xxxxxx1xxxxx1x']
memory = '1024'
#
# Disk device(s).
#
root = '/dev/xvda2 ro'
disk = [
'file:/mnt/xen/domains/guest2/disk.img,xvda2,w',
'file:/mnt/xen/domains/guest2/swap.img,xvda1,w',
]
#
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
75
# Physical volumes
#
#
# Hostname
#
name = 'guest2'
#
# Networking
#
dhcp = 'dhcp'
vif = [ 'mac=00:16:3E:79:51:CF,bridge=virbr0' ]
#
# Behaviour
#
on_poweroff = 'coredump-destroy'
on_reboot = 'coredump-restart'
on_crash = 'preserve'
Il guest creato dispone di una sola vcpu in esecuzione sul core 6:
vcpus = '1'
cpus = '6'
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
76
Tipicamente l’hypervisor fornisce un signature del processore con delle features
mascherate. Per forzare Xen ad abilitare il supporto per la scrittura dei registri MSR e per
la MCE, nel file di configurazione è aggiunta un opzione:
#enable cpu features: VME MCE MCA
cpuid=['1:edx=xxxxxxxxxxxxxxxxx1xxxxxx1xxxxx1x']
4.2 Handler: intel_machine_check
Nel seguito è riportato lo script bash test_intel.sh, come argomento prevede la lista dei casi
degli errori da iniettare:
./test_intel.sh test_cases_list.txt
#!/bin/bash
test_logs="test_logs"
summary_file="summary.txt"
results_file="results.txt"
test_prefix="test_"
result_prefix="_log"
fetch_mod_name="fetch_mod.ko"
dom_name="guest2"
dom_cfg="guest2.cfg"
dom_pass="napoli"
if [ $# -ne 1 ]
then
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
77
echo "ERROR: no test_cases file specified"
echo "Usage>> ./test_dom.sh test_cases_file"
exit
else
test_cases_list=$1
fi
./vcpu-pin.sh
xl | grep $dom_name
if [ $? -ne 0 ]
then
echo "creating domain..."
xl create $dom_cfg
echo "domain created..."
xl li | grep guest2
fi
sleep 25
sshpass -p $dom_pass ssh 192.168.122.90 "nohup stress -c 1 > foo.out 2> foo.err
< /dev/null &"
domid=`xl domid ${dom_name}`
dom_arg=" -d $domid "
#dom_arg=" "
if [ -a $results_file ]
then
rm $results_file
fi
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
78
rm -r $test_logs
mkdir $test_logs
if [ -a $summary_file ]
then
rm $summary_file
fi
Lines=`wc -l < $test_cases_list`
count=1
panic_cnt=0
cnt_cnt=0
rec_cnt=0
noerr_cnt=0
domcr_cnt=0
n=1
xl dmesg -c > /dev/null
dmesg -c > /dev/null
while [ $count -le $Lines ]
do
arg=`head -n $count $test_cases_list | tail -1`
echo "$n of $Lines"
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
79
./inject_mce_error $arg $dom_arg > "./"${test_logs}"/"${test_prefix}${n}".txt"
xl dmesg | grep DEBUG_MCE >
"./"${test_logs}"/"${test_prefix}_dmesg_${n}".txt"
xl dmesg -c | grep MCE_ACTION >> "./"${test_logs}"/"${test_prefix}${n}".txt"
more "./"${test_logs}"/"${test_prefix}${n}".txt" | grep -q CONTINUE
if [ $? -eq 0 ]
then
echo "test_$n $arg $dom_arg continue">> ${results_file}
let cnt_cnt++
else
more "./"${test_logs}"/"${test_prefix}${n}".txt" | grep -q RECOVERED
if [ $? -eq 0 ]
then
echo "test_$n $arg $dom_arg recovered">> ${results_file}
let rec_cnt++
else
more "./"${test_logs}"/"${test_prefix}${n}".txt" | grep -q DOMAIN_CRASH
if [ $? -eq 0 ]
then
echo "test_$n $arg $dom_arg domain_crash">> ${results_file}
let domcr_cnt++
else
more "./"${test_logs}"/"${test_prefix}${n}".txt" | grep -q PANIC
if [ $? -eq 0 ]
then
echo "test_$n $arg $dom_arg panic">> ${results_file}
let panic_cnt++
else
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
80
echo "test_$n $arg $dom_arg no_error">> ${results_file}
let noerr_cnt++
fi
fi
fi
fi
insmod $fetch_mod_name
rmmod $fetch_mod_name
let count++
n=$((n+1))
done
n=$((n-1))
echo "Summary generated"
echo `date` > ${summary_file}
echo "panic: $panic_cnt /$n" >> ${summary_file}
echo "recovered: $rec_cnt /$n" >> ${summary_file}
echo "continue: $cnt_cnt /$n" >> ${summary_file}
echo "domain_crash: $domcr_cnt" >> ${summary_file}
echo "no error: $noerr_cnt /$n" >> ${summary_file}
more ${summary_file}
echo "END TEST"
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
81
In una prima fase di init si cancellano eventuali log appartenenti a esperimenti precedenti,
si crea il dominio guest e si assegnano le cpu come già descritto nei paragrafi precedenti.
La cpu target è la 6, dove è in esecuzione il guest.
Per ogni errore sono salvati (nella cartella test_logs) due tipi di log:
1. Uno relativo al iniezione: registri MSR iniettati ed esito dell’esperimento. Il nome
del file è pari a:
test_{numero iniezione}.txt
nel seguito è riportato un esempio di log:
get domain 9 max gpa is: 0x40000400
get gaddr of error inject is: 0x180020
Domain: 9 - CPU: 6 - Bank: 8
MCG_STATUS: 0
MCi_STATUS: 0x600000000000134
MCi_MISC: 0x80
MCi_ADDR: 0x180020
Maxium gpfn for dom 9 is 0x40000
We get the mfn 0x14191a for this injection
( XEN) MCE_ACTION: PANIC
2. Mentre, l’altro contiene le stampe di DEBUG inserite nell’hypervisor. I log sono
nominati come segue:
Test_dmesg_{numero iniezione}.txt
Nel seguito ne è riportato un esempio:
(XEN) DEBUG_MCE: intel machine check
(XEN) DEBUG_MCE: intel machine check
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
82
(XEN) DEBUG_MCE: intel machine check
(XEN) DEBUG_MCE: intel machine check
(XEN) DEBUG_MCE: intel machine check
(XEN) DEBUG_MCE: intel machine check
(XEN) DEBUG_MCE: intel machine check
(XEN) DEBUG_MCE: intel machine check
(XEN) DEBUG_MCE: CPU6 - mce_urgent_action
(XEN) DEBUG_MCE: CPU6 - mce_action
(XEN) DEBUG_MCE: CPU6 - intel_default_mce_uhandler
(XEN) DEBUG_MCE: CPU6 - mce_action - return value: 2
(XEN) DEBUG_MCE: CPU4 - enter softirq
(XEN) DEBUG_MCE: CPU2 - enter softirq
(XEN) DEBUG_MCE: CPU0 - enter softirq
(XEN) DEBUG_MCE: CPU3 - enter softirq
(XEN) DEBUG_MCE: CPU7 - enter softirq
(XEN) DEBUG_MCE: CPU6 - enter softirq
(XEN) DEBUG_MCE: CPU1 - enter softirq
(XEN) DEBUG_MCE: CPU5 - enter softirq
(XEN) DEBUG_MCE: CPU7 - handling errors
(XEN) DEBUG_MCE: CPU7 - mce_action
(XEN) DEBUG_MCE: CPU7 - intel_default_mce_dhandler
(XEN) DEBUG_MCE: CPU7 - mce_action - return value: 2
(XEN) DEBUG_MCE: CPU7 - mce_delayed_action
(XEN) DEBUG_MCE: CPU7 - mce_delayed_action - Error can't be recovered,
system is tainted - continue!!!
Al termine dello script è generato un file di report, ad ogni errore corrisponde una riga
contenente:
Id_errore – argomenti dell’errore - esito
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
83
Nel seguito è riportato un frammento del file di report (result.txt) generato:
….
…..
test_11 -s 0x0 -S 0x0500000000000134 -M 0x80 -p 0x180020 -c 6 -B 8 -d 9 panic
test_12 -s 0x0 -S 0x0580000000000134 -M 0x80 -p 0x180020 -c 6 -B 8 -d 9 panic
test_13 -s 0x0 -S 0x0600000000000134 -M 0x80 -p 0x180020 -c 6 -B 8 -d 9 panic
test_14 -s 0x0 -S 0x0680000000000134 -M 0x80 -p 0x180020 -c 6 -B 8 -d 9 panic
test_15 -s 0x0 -S 0x0700000000000134 -M 0x80 -p 0x180020 -c 6 -B 8 -d 9 panic
test_16 -s 0x0 -S 0x0780000000000134 -M 0x80 -p 0x180020 -c 6 -B 8 -d 9 panic
test_17 -s 0x0 -S 0x0800000000000134 -M 0x80 -p 0x180020 -c 6 -B 8 -d 9 panic
test_18 -s 0x0 -S 0x0880000000000134 -M 0x80 -p 0x180020 -c 6 -B 8 -d 9 panic
test_19 -s 0x0 -S 0x0900000000000134 -M 0x80 -p 0x180020 -c 6 -B 8 -d 9 panic
test_20 -s 0x0 -S 0x0980000000000134 -M 0x80 -p 0x180020 -c 6 -B 8 -d 9 panic
test_21 -s 0x0 -S 0x0a00000000000134 -M 0x80 -p 0x180020 -c 6 -B 8 -d 9 panic
test_22 -s 0x0 -S 0x0a80000000000134 -M 0x80 -p 0x180020 -c 6 -B 8 -d 9 panic
test_23 -s 0x0 -S 0x0b00000000000134 -M 0x80 -p 0x180020 -c 6 -B 8 -d 9 panic
….
…..
….
….
In aggiunta è creato un ulteriore file contenente un sommario dell’analisi (summary.txt),
come ad esempio:
lun 25 mar 2013, 17.24.03, CET
panic: 3696 /4096
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
84
recovered: 0 /4096
continue: 399 /4096
domain_crash: 1
no error: 0 /4096
4.2.1 Risultati
Nei processori intel il registro MCG_CAP fornisce informazioni sul funzionalità
implementate dalla MCA del processore. Nel particolare il flag SER_P indica se il
processore è supporta azioni di recupero degli errori, questo bit può essere forzato via
software. Quindi la campagna di iniezione è stata ripetuta due volte in base al valore di
SER_P.
Per SER_P non abilitato: ogni errore causa irrimediabilmente al panic della macchina
come mostrato in figura 22.
Figura 22 Ser_p non settato
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
85
Per SER_P abilitato, si distinguono due casi:
1. Errori in contesto guest: sulla cpu target è in esecuzione un domU, figura 24;
2. Errori in contesto hypervisor: nessun guest è in escuzione sulla cpu target, figura 23.
Errori in contesto hypervisor, in modo analogo al caso SER_P disabilitato, causano
sempre il panic della macchina; poiché un errore in tale contesto potrebbe influenzare più
guest e quindi si preferisce resettare la macchina. Il discorso cambia nel caso di errore in
contesto guest dove alcuni errori sono tollerati (“conitnue”), mentre per altri (errori
Figura 23 Ser_p settato - errori in dominio hypervisor
Figura 24 SER_P settato - errori in contesto guest
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
86
riguardanti la memoria: Data load, L3 explicit.., ecc.) si cerca di intraprendere delle azioni
di recupero, tramite operazioni di page offline supportate solo per domini HVM, e poiché
il guest target è PV Xen distrugge il dominio.
In sintesi per processori Intel l’hypervisor cerca di gestire completamente l’errore
nell’hypervisor stesso, riducendo al minimo l’interazione con i guest.
4.3 Handler: mcheck_cmn_check
In modo analogo al caso intel è stato esaminato anche l’handler shared. Come già descritto
nel capitolo 2, tale handler è progettato per essere eseguito non in broadcast, quindi si è
forzato l’hypervisor modificando il codice di init della MCA (mce_intel.c,).
static void intel_init_mca(struct cpuinfo_x86 *c)
{
….
....
broadcast = 0;
.....
….
4.3.1 Risultati
In modo analogo al test precedente sono state svolte due campagne di testing: uno
emulando errori in contesto hypervisor (figura 25) ed un altro in contesto guest (figura 26).
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
87
L’handler shared non essendo specifico per una particolare architettura non implementa di
per sé azioni di recupero che sono dipendenti dal tipo di processore, ma si limita a
delegare al guest la gestione dell’errore, qualora l’errore non pregiudichi lo stato
dell’intero sistema.
Dalla figura 25 inoltre, si può notare che in contesto hypervisor un percentuale più ampia
Figura 25 Errori in contesto hypervisor
Figura 26 Errori in contesto dominio
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
88
degli errori è tollerata rispetto al caso intel.
4.3.2 Errori inoltrati al guest
Dai risultati ottenuti dal test precedente, si è visto che nel caso di errori in contesto guest il
5% degli errori iniettati sono demandati al dominio. Pertanto, si è pensato di svolgere un
ulteriore studio focalizzato su questo sotto insieme di errori in modo da poter capire come
poi il guest li gestisce.
4.3.2.1 Filtraggio degli errori
Il tool di generazione realizzato non permette di creare una lista di MCE conformi a
particolari pattern dei registri. Per esempio, posso generare tutte le combinazioni aventi un
medesimo bit alto ma non posso generare combinazioni del tipo: se il flag UC è alto, allora
il flag AR può essere basso e così via.
Poiché gli errori demandati al guest seguono dei pattern di bit particolari, a valle del
processo di generazione degli MCE è necessario un operazione di filtraggio, come
mostrato in figura 27.
Figura 27 Filtraggio MCE
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
89
L’azione di inoltro verso il guest da parte dell’handler dipende esclusivamente dai primi
nove bit del registro MCi_STATUS e dal registro MCG_STATUS; per cui i pattern
utilizzati nel filtraggio presentano queste due componenti. I pattern sono estratti dal file di
report del test dell’handler shared, tramite lo script bash, extract_pattern.sh, a cui è
passato in ingresso il file “result.txt”.
#!/bin/bash
result_list=$1 #input file
valid_pattern=$2 #output file
result=”send_to_guest” #case to filter
more ${result_list} | grep $3 | awk '{print $2" "$3" "$4" "substr($5,1,5)}' | sort |
uniq > ${valid_pattern}
lines=`wc -l < valid_pattern`
count=1
old=`more $valid_pattern | cut -d " " -f 4 | head -n $count | tail -1`
while [ $count -le $lines ]
do
let count++
new=`more valid_pattern | cut -d " " -f 4 | head -n $count | tail -1`
echo $old" "$new
let "old = (old & new)"
echo $old
done
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
90
Nel riquadro sottostante è riportato uno spezzone del file contenente i pattern estratti.
….
-s 0x5 -S 0x870
-s 0x5 -S 0x878
-s 0x5 -S 0x8a0
-s 0x5 -S 0x8a8
-s 0x5 -S 0x8b0
-s 0x5 -S 0x8b8
-s 0x5 -S 0x8e0
-s 0x5 -S 0x8e8
-s 0x5 -S 0x8f0
-s 0x5 -S 0x8f8
…….
Il filtro è implementato nello script bash filter.sh . Per ogni elemento contenuto nella lista
di MCEs verifica che le opzioni di iniezione rispettino uno dei pattern ammessi.
Lines=`wc -l < $test_cases_list`
count=0
rm ${tmp}
while [ $count -lt $Lines ]
do
arg=`head -n $count $test_cases_list | tail -1`
MCG_STATUS=`echo $arg | cut -d " " -f 2`
MCI_STATUS=`echo $arg | cut -d " " -f 4`
MCI_STATUS=`echo ${MCI_STATUS:0:5}`
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
91
more $valid_pattern | grep "s $MCG_STATUS -S $MCI_STATUS"
if [ $? -eq 0 ]
then
echo $arg
echo $arg >> ${tmp}
fi
echo $count
let count++
done
cp ${tmp} ${test_cases_list}
rm ${tmp}
4.3.2.2 Scelta degli errori
La scelta della tipologia di errore da iniettare è stata orientata principalmente verso errori
della memoria, nel particolare sono state svolte tre campagne di testing:
1. Errori TLB: 1536 errori
2. Errori della gerarchia cache: 1536 errori
Per maggiore dettagli sui codici di errore si rimanda al riferimento in bibliografia [intel].
4.3.2.3 Configurazione guest
Il sistema operativo guest sotto esame è il sistema linux con kernel versione 3.6.11. Il
kernel è stato modificato aggiungendo delle printk all’interno del codice dell’handler MCE
in modo da poter capire il comportamento intrapreso dal guest leggendo i log di sistema,
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
92
in aggiunta, nel modulo MCE è stato impostato il più alto livello di tolleranza agli errori in
modo da evitare il riavvio automatico del sistema operativo.
4.3.2.4 Script di iniezione
In figura è mostrato lo script bash test_dom.sh, utilizzato per la campagna di error-
injection.
#!/bin/bash
test_logs="test_logs"
summary_file="summary.txt"
results_file="results.txt"
test_prefix="test_"
result_prefix="_log"
dom_name="guest2"
dom_cfg="guest2.cfg"
dom_pass="napoli"
par_exec="partial"
if [ $# -ne 1 ]
then
echo "ERROR: no test_cases file specified"
echo "Usage>> ./test_dom.sh test_cases_file"
exit
else
test_cases_list=$1
fi
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
93
if [ -a $par_exec ]
then
echo "Restoring old test"
xl list | grep $dom_name
if [ $? -eq 0 ]
then
xl destroy $dom_name
fi
count=`more $par_exec | awk '{print $1}'`
else
count=1
if [ -a $results_file ]
then
rm $results_file
fi
rm -r $test_logs
rm $test_case_list
mkdir $test_logs
fi
if [ -a $summary_file ]
then
rm $summary_file
fi
./vcpu-pin.sh > /dev/null
Lines=`wc -l < $test_cases_list`
n=$count
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
94
xl dmesg -c > /dev/null
dmesg -c > /dev/null
while [ $count -le $Lines ]
do
echo "$n of $Lines"
echo $count > $par_exec
xl create $dom_cfg > /dev/null 2>/dev/null
echo "domain created"
sleep 20
sshpass -p $dom_pass ssh 192.168.122.90 rm /var/log/mcelog
sshpass -p $dom_pass ssh 192.168.122.90 "mcelog --daemon"
sshpass -p $dom_pass ssh 192.168.122.90 "nohup stress -c 1 > foo.out 2> foo.err
< /dev/null &"
sshpass -p $dom_pass ssh 192.168.122.90 "dmesg -c" > /dev/null
echo "stress running"
sleep 1
domid=`xl domid ${dom_name}`
arg=`head -n $count $test_cases_list | tail -1`
dom_arg=" -d $domid "
./inject-mce-error $arg $dom_arg > "./"${test_logs}"/"${test_prefix}${n}".txt"
echo "error injected"
sleep 3
sshpass -p $dom_pass ssh 192.168.122.90 dmesg >
"./"${test_logs}"/"${test_prefix}dmesg_${n}".txt"
action=`more "./"${test_logs}"/"${test_prefix}dmesg_${n}".txt" | grep
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
95
DO_MACHINE_CHECK | cut -d ">" -f 2`
echo "test_$n $arg $dom_arg $action" >> ${results_file}
more "./"${test_logs}"/"${test_prefix}dmesg_${n}".txt" | grep "mce:"
if [ $? -eq 0 ] #controllo che l’handler sia stato attivato
then
sshpass -p $dom_pass ssh 192.168.122.90 "cat /var/log/mcelog" >
"./"${test_logs}"/"${test_prefix}mcelog_${n}".txt"
else
echo "no event logged" > "./"${test_logs}"/"${test_prefix}mcelog_${n}".txt"
fi
xl destroy $domid
echo "domain destroyed"
sleep 3
let count++
n=$((n+1))
done
tot=`more ${results_file} | grep -c " "`
panic=`more ${results_file} | grep -c -w panic`
no_panic=`more ${results_file} | grep -c -w no_panic`
kill=`more ${results_file} | grep -c kill`
echo ""
echo "summary" >> ${summary_file}
echo "panic: $panic/$tot" >> ${summary_file}
echo "no_panic: $no_panic/$tot" >> ${summary_file}
echo "kill: $kill/$tot" >> ${summary_file}
more ${summary_file}
rm $par_exec
Per ogni errore lo script esegue le seguenti operazioni:
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
96
1. Creo il dominio;
2. Avvio il demone mcelog per il logging degli errori MCE
3. Eseguo un carico di lavoro sul guest
4. Inietto l’errore
5. Leggo i log MCE e di sistema dal guest
6. Salvo i log
7. Distruggo il dominio
Il framework comunica con il dominio target tramite ssh.
4.3.2.5 Risultati
Nelle figure 28 e 29 sono riportati i grafici a torta relativi a risultati ottenuti dagli
esperimenti svolti.
Figura 28 Cache hiearchy Error
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
97
Il kernel del sistema operativo guest tratta entrambe classi di errori della memoria nello
stesso modo. Infatti, in entrambi i casi il 50% degli errori provoca il riavvio del guest. I
casi di no Panic sono relativi agli MCE aventi flag EN (enable notification) basso.
4.4 Campagna 2: Linux Kernel 3.6.11
Un ultimo test è incentrato su un’analisi più dettagliata del kernel guest.
4.4.1 Scelta degli errori
La distruzione e la creazione del dominio ad ogni ciclo di iniezione comporta una
considerevole consumo di tempo. Per tale motivo si è cercato di ridurre al minimo il
numero di MCE. In figura son mostrati i criteri di generazione utilizzati.
MCIP
Figura 29 TLB error
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
98
VALID
EN
MISCR 0X80
ADDRV 0X18020
NR_RIP 1
CPU 6
BANK 8
TLB_ERROR
Anche in questo caso la scelta della tipologia di errori è ricaduta su errori della TLB.
4.4.2 Script iniezione
Lo script di iniezione è il medesimo utilizzato nella campagna di testing deiegli errori
inoltrati da Xen al guest (paragrafo 4.3.2.4). L’unica differenza è l’aggiunta dell’opzione
di bypass nell’iniezione:
….
./inject-mce-error $arg $dom_arg -g > "./"${test_logs}"/"${test_prefix}${n}".txt"
…..
4.4.3 Risultati
In figura 30 si può notare che il kernel guest adotta un approccio conservativo, infatti, la
maggior parte degli errori è gestita riavviando semplicemnte il sistema, mentre solo in
minima parte si cerca di continuare l’esecuzione uccidendo il processo in esecuzione.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
99
Il kernel linux classifica gli errori in sette livelli di severity:
NO
KEEP
SOME
AO
UC
AR
PANIC
In figura 31 sono presentati i livelli di severity riscontrati nella campagna. Gli errori
appartengono solo a 3 livelli: NO,SOME (errori a basso livello di severità) e PANIC
Figura 30 Grafico azioni intraprese dal Kernel guest
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
100
In figura 32, invece, è mostrato per ogni classe di errore le azioni intraprese dal kernel.
Per errori a basso livello di criticità (NO e SOME) l’handler uccide il processo in
esecuzione se il flasg RIPV (MCG_STATUS) è basso, poiché significa che non si può
riprendere l’esecuzione del processore in maniera sicura dall’indirizzo specificato
dall’istruction pointer inserito nello stack.
4.5 Problema HVM
Figura 31 Error severity levels
Figura 32 Istogramma Azioni intraprese per livello di severity
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
101
In un secondo momento si è pensato di testare anche domini fully virtualized. Però non è
stato possibile poiché per tali domini l’inoltro di un MCE causa la distruzione del dominio
a priori, senza che esso sia gestito dal kernel guest. La causa di questa anomalia è da
imputare ad una scorretta comunicazione tra hypervisor e demone qemu in dom0.
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
102
Conclusioni e Sviluppi futuri
Nel seguente lavoro di tesi è stato sviluppato un tool di emulazione di fallimenti hardware
in ambienti virtualizzati sfruttando i meccanismi di notifica degli errori hardware
implementati nei moderni processori. Tale approccio permette di emulare
malfunzionamenti reali senza impattare con l’hardware fisico.
Il tool realizzato è correlato di una patch da applicare all’hypervisor Xen (versione 4.2.1).
Esso permette di emulare l’occorrenza di un errore hardware nel contesto dell’hypervisor,
oppure di poter inoltrare l’errore direttamente ad una singola macchina virtuale,
trascurando lo strato di virtualizzazione sottostante.
Successivamente, è stato realizzato un framework per l’esecuzione di campagne
sperimentali. Una prima campagna è stata incentrata sull’analisi dei meccanismi di
gestione dell’hypervisor. Gli esperimenti effettuati hanno riscontrato che attualmente non
è implementata una gestione vera e propria dell’errore, ma bensì, il sistema adotta un
approccio conservativo nel quale ci si limita semplicemente a resettare la macchina.
Infatti, nel caso di errori uncorrected la macchina è riavviata perché si assume che tale
errore può aver impattato su più domini. Questa ipotesi è abbastanza limitativa, infatti, per
alcuni tipi di errori potrebbe essere possibile continuare l’esecuzione del sistema, in
maniera degradata, per esempio: si potrebbero isolare pagine di memoria e cpu corrotte
attraverso operazioni di page_offline o cpu_offline.
Una seconda campagna di test, invece, è mirata allo studio dei meccanismi di gestione del
Uno strumento per l’emulazione di fallimenti hardware in sistemi virtualizzati Inserire il titolo della tesi di laurea come intestazione
103
sistema operativo linux (versione 3.6.11). In maniera analoga al caso precedente non son
intraprese delle vere e proprie azioni di recupero ma si cerca di preservare lo stato del
sistema nel caso di errori non critici terminando il processo in esecuzione.
Un limite del tool è che esso è utilizzabile solo per domani paravirtualizzati (PV) e ciò
impedisce poter utilizzare l’infrastruttura di virtualizzazione per effettuare test di tipo
black-box per sistemi operativi proprietari, come windows. Per cui c si demanda a lavori
l’estensione dall’applicabilità del tool anche per domini fully-virtualized (HVM).
Inoltre, come sviluppi futuri si demanda l’utilizzo del tool per lo svolgimento di
sperimentazioni su sistemi critici reali.
104
Bibliografia
[1] Aussaguès, Chabrol, David, 2010, “a multicore OS ready for safety-relatedd
automotive systems: results and future prospects. In software and systems, pp 1-10”
[2] Navet, Monot, Bavoux 2010, “[Multi-source and multicore automotive ECUs-OS
protection mechanisms and scheduling”
[3] Agrou, Sainrat, Gatti, 2011, “A design approch for predicatable and efficient multi-
core processor for avionics.”
[4] Kinnan, 2009 “Use of multicore processors in avionics systems and its potential
impact in implementation and certification. In: Avionics Systems Conference, DASC
2009”
[5] Zhu, 2010 “Medical image viewing on multi-core platforms using parallel
computing patterns”
[6] Radisys 2011 “Leveraging virtualization in Aerospace and Defence applications”
[7] David Chisnall 2007 “The definitive guide to Xen Hypervisor”, Prentice Hall
[8] Andi kleen 2004 “Machine check handling on Linux”
[9] Agosto 2012 “Intel® 64 and IA-32 Architectures Software Developer’s Manual,
VOL 3”, www.intel.com