Awkernel is a safe and realtime operating system. It can execute async/await applications in kernel space safely.
$ sudo apt install clang qemu-system-arm qemu-system-x86 qemu-system-misc python3-pyelftools
$ rustup toolchain install nightly-2026-07-20
$ rustup default nightly-2026-07-20
$ rustup component add rust-src llvm-tools-preview
$ rustup target add x86_64-unknown-none aarch64-unknown-none riscv64gc-unknown-none-elf riscv32imac-unknown-none-elf
$ cargo install cargo-binutils
$ curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
$ cargo binstall mdbook
$ cargo binstall mdbook-mermaid
- kernel
- boot code
- initialization
- virtual memory
- heap memory
- stack memory
- devices (UART, etc)
- awkernel_lib
- library used by both kernel and awkernel_async_lib
- awkernel_async_lib
- asynchronous library for no_std
- awkernel_async_lib_verified
- verified library for awkernel_async_lib
- pure Rust (no dependencies on external functions and no inline assembly)
- awkernel_futures_macro
- awkernel_macros
#[awkernel::main]entry-point macro
- awkernel_drivers
- awkernel_aarch64
- userland
- applications
graph TD;
awkernel_async_lib-->awkernel_async_lib_verified;
awkernel_async_lib-->awkernel_futures_macro;
awkernel_lib-->awkernel_aarch64;
awkernel_async_lib-->awkernel_lib;
awkernel_lib-->awkernel_sync;
userland-->awkernel_async_lib;
kernel-->awkernel_lib;
kernel-->awkernel_async_lib;
kernel-->awkernel_aarch64;
kernel-->awkernel_drivers;
awkernel_drivers-->awkernel_lib;
userland-->kernel;
kernel-->awkernel_macros;
Applications can use awkernel_async_lib, awkernel_lib, and awkernel_drivers.
$ make docs
$ ls docs/index.html
$ cargo doc_raspi
$ ls target/aarch64-kernel/doc/awkernel/index.html
$ ls target/aarch64-kernel/doc/awkernel_lib/index.html
etc
$ cargo doc_aarch64_virt
$ ls target/aarch64-kernel/doc/awkernel/index.html
$ ls target/aarch64-kernel/doc/awkernel_lib/index.html
etc
$ cargo doc_x86
$ ls target/x86_64-kernel/doc/awkernel/index.html
$ ls target/aarch64-kernel/doc/awkernel_lib/index.html
etc
Release build (recommended).
$ make x86_64 RELEASE=1
Debug build.
$ make x86_64
The x86_64 build includes kernel/asm/x86/mpboot.S, an assembly file that mixes 16-, 32-, and 64-bit code. The build script assembles and links it with GNU tools, then uses objcopy to create a binary image. A Rust target alone does not provide these tools.
On Apple Silicon, install an x86_64 ELF GNU toolchain:
$ brew install x86_64-elf-gcc x86_64-elf-binutils
The build script automatically uses the x86_64-elf- tool prefix if x86_64-elf-gcc is available. Otherwise, it tries the host tools (gcc, ld, and objcopy), which may not support this build on a non-x86_64 host.
To select a toolchain with a different prefix, pass that prefix as CROSS_COMPILE. For example, if its tools are named my-x86_64-elf-gcc, my-x86_64-elf-ld, and my-x86_64-elf-objcopy, run:
$ make x86_64 RELEASE=1 CROSS_COMPILE=my-x86_64-elf-
Important
CROSS_COMPILE is a prefix, not a path to the compiler. Keep the trailing - so the build can append gcc, ld, and objcopy to it.
For example, CROSS_COMPILE=x86_64-elf- selects x86_64-elf-gcc, x86_64-elf-ld, and x86_64-elf-objcopy.
Qemu 8.x or later is required. Qemu 6.x is not supported.
$ make qemu-x86_64
$ make debug-x86_64
$ make gdb-x86_64
Release build (recommended).
$ make aarch64 BSP=aarch64_virt RELEASE=1
Debug build.
$ make aarch64 BSP=aarch64_virt
$ make qemu-aarch64-virt
$ make debug-aarch64_virt
$ make gdb-aarch64_virt
Release build (recommended).
RELEASE=1 must be used for actual devices.
$ make aarch64 BSP=raspi3 RELEASE=1
Debug build.
$ make aarch64 BSP=raspi3
$ make qemu-raspi3
$ make debug-raspi3
$ make gdb-raspi3
Specify Release=1.
$ make aarch64 BSP=raspi4 RELEASE=1
- Serial
- port: GPIO 14 (Tx) and 15 (Rx)
- 8N1: eight data bits, no parity, one stop bit
- Speed: 115200
Specify Release=1.
$ make aarch64 BSP=raspi5 RELEASE=1
- Serial
- port: GPIO 14 (Tx) and 15 (Rx)
- 8N1: eight data bits, no parity, one stop bit
- Speed: 115200
Release build (recommended).
$ make riscv64 RELEASE=1
Debug build.
$ make riscv64
$ make qemu-riscv64
Release build (recommended).
$ make riscv32 RELEASE=1
Debug build.
$ make riscv32
$ make qemu-riscv32
Debug build.
$ make std
Release build.
$ make std RELEASE=1
Debug build.
$ make run-std
Release build.
$ make run-std RELEASE=1
$ make qemu-raspi3
$ telnet localhost 5556
Unit tests by using Rust's mechanism can be executed as follows.
$ make test
Some mechanisms which use atomic instructions are verified by using loom, and these verifications are executed as follows. It will takes several minutes.
$ make loom
scripts/ci.sh runs the same checks as the CI.
It requires cargo-udeps in addition to the compiler tools.
$ cargo binstall cargo-udeps
$ scripts/ci.sh
Cargo.lock is not tracked, so the CI uses the latest compatible dependencies.
If a check fails only on your machine, run cargo update and try again.
To run the checks with pre-commit, install the hooks.
The pre-commit hook runs cargo fmt --check, and the pre-push hook runs scripts/ci.sh.
$ pre-commit install
scripts/ci.sh invokes x86_64 builds via make check_x86_64 and make udeps.
As cargo-udeps checks the x86 feature against the x86_64-unknown-linux-gnu target,
that target must also be installed for the pinned nightly toolchain:
$ rustup target add x86_64-unknown-linux-gnu
Therefore, as done for compiling x86 projects, you mut define the CROSS_COMPILE variable:
$ CROSS_COMPILE=x86_64-elf- scripts/ci.sh
Important
Do not remove the trailing - of x86_64-elf-