Selfie features bare-metal support in the form of a library operating system and a multitasking kernel. Both of them include the same rudiumentary filesystem that is constructed during compile-time and are able to execute programs written in C*. They are built upon an implementation of RISC-V's Supervisor Binary Interface in the form of OpenSBI v0.7. Supported platforms are QEMU v5.0, the SiFive HiFive Unleashed, and the Kendryte K210.
The library OS is a unikernel that is linked at compile-time with Selfie. Upon boot, the unikernel initializes the hardware and prepares an execution environment, before calling into Selfie's main function with compile-time arguments. After returning from main or calling exit, the kernel prints the exit code and stalls the system.
As the library OS is a simple layer between the hardware and Selfie, it does not utilize multitasking or memory virtualization. In a cooperative way, the kernel passes control to the linked application and regains control when Selfie performs a syscall. Selfie and the kernel are not spatially isolated and both use physical addressing. System calls are plain function calls and do not raise an environment call exception.
The library OS does not install a trap handler. If Selfie or the kernel raise an exception, it will be handled by OpenSBI.
| Privilege level | Software |
|---|---|
| Machine mode | OpenSBI |
| Supervisor mode | Library OS |
The multitasking kernel builds upon RISC-V's privileged specification v1.11 but is compatible with implementations of RISC-V's privileged specification v1.10. This means that at the moment it is not possible to execute it on the Kendryte K210.
Special features include:
- Preemptive multitasking
- Round-robin scheduling
- Memory virtualization through the use of RISC-V's Sv39 paging
- Rudimentary trap handling including support for the five system calls
exit,read,write,openat, andbrk - An ELF loader that is capable of loading ELF files emitted by Selfie
Details of this kernel's implementation are described in Martin Fischer's bachelor thesis "RISC-V S-Mode-Hosted Bare-Metal Selfie".
| Privilege level | Software |
|---|---|
| Machine mode | OpenSBI |
| Supervisor mode | Kernel |
| User mode | User processes |
Both the library OS and kernel OS variant share common code for:
- Kernel Bootstrapping
- Generalized init process bootstrapping
- Kernel C standard library
- Console
- SBI calls
- Static read-only File System
- Diagnostics
- Generalized system calls
Each kernel variant must provide implementations for concrete init process bootstrapping as well as glue code between the syscall interface and the generalized syscall implementation.
Selfie's bare-metal support comes with a separate Makefile.
gcc-riscv64-linux-gnubinutils-riscv64-linux-gnu
Running make within the machine directory will download OpenSBI's v0.7 release and build both the library operating system and the multitasking kernel for all supported platforms. The resulting payloads are in the respective directories in the build directory.
The Makefile refers to distinct hardware platforms as boards. Currently, three boards are supported:
qemu: The QEMU virtual machinefu540: SiFive Freedom U540 (HiFive Unleashed)k210: Kendryte K210
Also, the Makefile distinguishes between two build profiles:
library: Targets the library OSkernel: Targets the multitasking kernel
| Target name | Description |
|---|---|
| all (default) | Builds all board/build profile combinations |
| clean | Cleans all build artifacts, but retains opensbi |
| distclean | Cleans all build artifacts and opensbi (requires re-download) |
| debug | Sets the debugging macro (i.e. adds -DDEBUG to compiler flags) |
| list-targets | Lists targets names of all board/build profile combinations |
| selfie-$board.elf | Builds all build profiles for the specified board as ELF file (without OpenSBI) |
| selfie-$board.bin | Builds all build profiles for the specified board as flat binary (without OpenSBI) |
| selfie-opensbi-$board.elf | Builds all build profiles for the specified board as ELF file (with OpenSBI) |
| selfie-$board-$profile.elf | Builds the specified build profiles for the specified board as ELF file (without OpenSBI) |
| selfie-$board-$profile.bin | Builds the specified build profiles for the specified board as flat binary (without OpenSBI) |
| selfie-opensbi-$board-$profile.elf | Builds the specified build profiles for the specified board as ELF file (with OpenSBI) |
| test | Builds QEMU library and kernel variants and tries to run them |
| opensbi | Fetches and extracts OpenSBI |
The debug target may be used by prepending it to the target to build, e.g. make debug all to build all possible board/build profile combinations in debug mode. Switching between debug and non-debug builds requires to clean the build tree.
The build directory contains all intermediate object files and linker scripts as well as the resulting binaries:
build
├── fu540
│ ├── kernel
│ │ ├── [...]
│ │ ├── selfie.bin
│ │ ├── selfie.elf
│ │ ├── selfie-opensbi.elf
│ │ └── [...]
│ └── library
│ ├── [..]
│ ├── selfie.bin
│ ├── selfie.elf
│ ├── selfie-opensbi.elf
│ └── [...]
:
selfie.elf is the main artifact that contains the kernel and the static file system. selfie.bin is the flat binary version of selfie.elf that must be loaded to $SBI_START+$PAYLOAD_OFFSET, as specified in the Makefile.
selfie.elf and selfie.bin do not contain OpenSBI which is required as supervisor binary. Therefore, it is necessary that the board's bootloader loads OpenSBI and the kernel.
selfie-opensbi.elf packages selfie.bin to OpenSBI using the FW_PAYLOAD Makefile configuration. Thus, it is an OpenSBI binary that passes execution to the selfie.bin payload after initialization. This is necessary for binaries that must be self-contained, mostly on embedded platforms.
⚠️ Warning: QEMU 5.1 behavoral changesQEMU v5.1+ changed default behavior on
virtandsifive_uRISC-V emulation machines to load OpenSBI 0.7 per default. To prevent two OpenSBI binaries from clashing, one of two options must be considered:
- Use
selfie.elfbinary- Use
selfie-opensbi.elfbinary and prevent QEMU from loading the shipped OpenSBI using the-bios noneflagOlder QEMU versions do not load OpenSBI per default and require the
selfie-opensbi.elfbinary.