65
EMBEDDED
MAGGIO
HYPERVISOR |
SOFTWARE
À
eseguito all’interno del de-
bugger. Accedendo ai sim-
boli di tutte le macchine, è
anche possibile impostare
breakpoint su qualunque
funzione di qualsiasi mac-
china in ogni momento.
Naturalmente la vista del debugger può essere
anche girata verso il set di registri di una certa
macchina o di un certo processo. Se in quel mo-
mento i registri non sono caricati in un core reale,
il debugger ne legge i valori dall’hypervisor o dal-
la memoria del sistema guest. Con questi valori il
debugger determina lo stack frame corrente per
mostrare, ad esempio, l’attuale gerarchia di chia-
mate delle funzioni di un task. Così il progettista
può vedere direttamente a che punto è arrivato il
task e perché potrebbe essere fermo in attesa.
Come si possono usare tutte queste funzionali-
tà per il debug dell’applicazione citata all’inizio?
Non dimentichiamo che il processo guest non
aveva ricevuto un interrupt hardware. Di fat-
to ora è facile analizzare questo problema: per
mezzo del debugger hardware basta impostare
un breakpoint direttamente sul vettore di inter-
rupt. Il sistema si fermerà non appena l’inter-
rupt scatta. Dato che il debugger conosce tutti
i componenti, lo sviluppatore ora può seguire la
catena degli eventi, cioè l’avanzamento dal pun-
to dell’interrupt nell’hypervisor, attraverso il si-
À
per step successivi o mediante breakpoint sulle
diverse fasi. In questo modo è facile trovare qua-
lunque malfunzionamento che potrebbe essere
subentrato. Occorre anche dire, però, che le con-
% À
À
se, per esempio, due processi che comunicano fra
loro si bloccano reciprocamente. In questo caso
può aiutare la vista di sistema poiché gli stati di
tutti i componenti d’interesse possono essere rap-
presentati vicini fra loro. Pertanto è facile vedere
quale task di quale guest - o anche dell’hypervisor
- si trovi in uno stato errato o sia potenzialmente
in attesa di mutue risorse. Non va sottostimata
l’opzione di un’analisi post-mortem se l’intero si-
stema si porta in uno stato in cui non risponde
più. Dal momento che un debugger hardware non
richiede alcun software attivo sul sistema target,
ci sono le condizioni per analizzare lo stato di
tutti i componenti. Grazie al fatto che TRACE32
di Lauterbach contiene anche un simulatore del
set di istruzioni, lo sviluppatore può ottenere un
dump completo di memoria dal sistema sotto test
e analizzarlo comodamente in seguito nel simula-
tore senza più bisogno del target hardware vero
e proprio, come si analizza un core dump. Questa
volta però su tutto il sistema, compresi l’hypervi-
sor, tutti i guest e i processi.
Costi più bassi, maggior complessità
Nel mondo embedded si stanno usando sempre
di più gli hypervisor. Vantaggi come la riduzione
dei costi e il controllo in tempo reale costituiscono
chiare argomentazioni a loro favore. Ma questo
si paga con il prezzo di una maggiore comples-
sità del sistema. L’hardware deve fornire una
virtualizzazione tramite una gerarchia MMU a
due livelli che deve essere gestita dall’hypervisor.
Un debugger con supporto hardware (ad esempio
via JTAG) richiede una conoscenza dell’hypervi-
sor e del sistema guest per poter offrire allo svi-
luppatore delle viste sul software. Per questo un
“awareness” adattata al rispettivo hypervisor e
al rispettivo sistema operativo guest deve essere
caricata nel debugger, che legge dal sistema tar-
get le informazioni necessarie.
Per dimostrarne le funzionalità, Lauterbach ha
creato un’implementazione di riferimento con
l’hypervisor Xen e i guest Linux e FreeRTOS su
una scheda Hikey. Il supporto MMU implemen-
tato nel debugger TRACE32 e un’espansione del-
la modalità di gestione degli indirizzi per i siste-
mi virtualizzati permettono di accedere in ogni
momento a qualsiasi componente, così da rende-
re possibile il debug dell’hypervisor, dei sistemi
operativi guest e di tutti i processi guest. Allo
stesso modo è anche possibile l’analisi retrospet-
tiva di un’immagine di memoria senza qualsivo-
glia tipo di problema. Soprattutto lo sviluppatore
si ritrova un tool che può usare per debuggare
senza sforzo questi sistemi così complessi.
Fig. 7 – Gerarchia di chiamate di un task inattivo in un guest inattivo