Unikraft Boot Sequence
The Unikraft boot sequence is dependent on the selected platform (linuxu, kvm, xen), but is very similar to how any other operating system would behave.
In the case of the
KVM platform, the booting process involves more steps.
First, the image is loaded from the disk into memory and the program sections are defined (see
plat/kvm/x86/link64.lds.S, as example for the x86 architecture).
Those sections include the
INITTAB sections, which are used later in the booting process.
The next step is done by the bootloader,
Multiboot in our case, which sets up some of the sections (zero-ing the
.bss, writing the
.text with the effective code) and passes information about the memory layout and available devices to the entry function,
The CPU is left in the
Protected Mode, and a small piece of code is needed to enable the
Long Mode, paging and extended instruction sets, like
All those are done in
After that, interrupts, traps, the heap, the ACPI tables, and others, are initialized, in the
_libkvmplat_entry function, in
This is the last step of the booting sequence that depends on the platform or the architecture.
Booting continues in the bootstraper library,
ukboot, where constructors and initializers are called.
In the case of
ARM, there is no bootloader to load information about the system and set up the sections. Those steps are done manually, in
plat/kvm/arm/entry64.S, along with other component initialization.
After that, the booting sequence is similar to the one from
CTORTAB and INITTAB
Unikraft calls various “constructor” (
ctor) and “initialiser” (
init) methods during the booting step done in the boostrapping library.
These constructors and initialisers are located in a static section of the final binary image,
There are 7 entry points during the boot sequence:
New constructors and initialisers can be registered using the methods defined above at various levels (meaning they are called in that order) and at various priorities (between
9); allowing the registration of numerous constructors or initialisers at the same level.
This allows application developers or library developers to correctly set up the unikernel by registering a constructor or initialiser at the right time or before or after others.
Initialisers have 6 different levels, allowing code to be injected before certain operations occur during the boot sequence.
This includes, in order: before and after the
platform drivers are initialised; before and after all
libraries are initialised; before and after all filesystems (
rootfs) are initialised; and, before and after various “
system” methods are called.
The source code for this sequence is defined in