Jak wspomniano wcześniej, musimy być w stanie wykonać dowolny kod Ring-0 z gościnnej maszyny wirtualnej. Jednym ze sposobów, aby to zrobić, jest zaimplementowanie sterownika jądra w celu wykonania dowolnego kodu w uniwersalnym systemie operacyjnym wdrożonym na maszynie wirtualnej. To podejście ma jednak kilka problemów. Po pierwsze, pełny system operacyjny jest powolny i rozdęty. Po drugie, niedeterminizm jest wprowadzany do naszego środowiska testowego przez wiele zadań, które są wykonywane jednocześnie. Aby uniknąć tych problemów, zaimplementujemy nasz własny unikernel3 z następującymi wymaganiami:
- Prostota Powinien mieć mały rozmiar i być wydajny.
- Szybkie (ponowne) uruchamianie Często dochodzi do stanu nieodwracalnego, więc musimy ponownie uruchomić.
- Odporność Jądro musi próbować odzyskać się z nieprawidłowego stanu i działać tak długo, jak to możliwe. Jeśli nie jest to możliwe, musimy ponownie uruchomić.
- Determinizm Osiągnięcie całkowitego determinizmu nie jest możliwe, ale musimy się do niego jak najbardziej zbliżyć. Jest to ważne dla celów reprodukcji błędów i minimalizacji przypadków rozmycia.
- Przenośność Powinien działać na większości implementacji hypervisora bez większych modyfikacji.
Nasz unikernel będzie komunikował się z narzędziami zewnętrznymi, umożliwiając im wstrzykiwanie i wykonywanie dowolnego kodu w maszynie wirtualnej w Ring-0. Musimy być w stanie zbierać wyniki wykonania i odsyłać je do narzędzi. W tych sekcjach omawiamy proces rozwoju tego kernela.