- C 83.1%
- Assembly 11.3%
- Makefile 5.6%
| include | ||
| src | ||
| targets | ||
| .clang-format | ||
| .gitignore | ||
| current_plan.md | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
SquidgeOS
A small bare-metal 64-bit kernel for RISC-V and ARM, focused on booting, debugging, and eventually a useful built-in command shell.
Project overview
SquidgeOS is a hobby kernel for exploring low-level systems programming. It boots on two architectures from one codebase: the CPU-specific code lives behind a small interface (include/arch.h), and everything above it is shared. QEMU is the immediate target for both; real hardware (Raspberry Pi 3 and StarFive VisionFive 2) comes later.
Targets
| Target | Architecture | Machine | Status |
|---|---|---|---|
qemu-riscv64 (default) |
RISC-V 64 (M-mode) |
QEMU virt |
Boots to an interactive prompt: UART input, timer, PLIC interrupts |
raspi3b |
AArch64 (EL1) |
QEMU raspi3b (Pi 3 Model B) |
Boots to the prompt; interrupts, timer and UART input not implemented yet |
qemu-riscv64 |
raspi3b |
|
|---|---|---|
| Load address | 0x80000000 (ELF) |
0x80000 (raw kernel8.img) |
| Console | NS16550A | PL011 |
| Interrupt controller | PLIC | not implemented (BCM2836 local + BCM2835 ARM controller) |
| Timer | CLINT, 10 MHz | not implemented (ARM generic timer) |
| Power off | SiFive test device | halts (wfi) |
Requirements
clang,ld.lldandllvm-objcopy(one toolchain for both architectures)makeqemu-system-riscv64andqemu-system-aarch64
Building and running
make run # RISC-V on QEMU virt (default target)
make TARGET=raspi3b run # AArch64 on QEMU raspi3b
make # build only -> output/qemu-riscv64/kernel.elf
make TARGET=raspi3b # build only -> output/raspi3b/kernel8.img
make clean # remove build/ and output/ for every target
Quit QEMU with Ctrl-A then X.
Each target builds into its own build/<target>/ and output/<target>/, so both can exist side by side. Header dependencies are not tracked yet: run make clean after changing a header.
make also writes compile_commands.json (via clang -MJ) covering every target built so far, for clangd.
Source layout
include/arch.h CPU interface used by generic code
src/
arch/riscv64/ boot, trap entry, CSR helpers, CLINT timer
arch/aarch64/ boot (EL2 -> EL1), vector table, system register helpers
drivers/ ns16550, pl011, plic, syscon, and stubs (irq_none, power_halt)
uart.h / irq.h / power.h are the driver interfaces
kernel/ kmain, console (kprintf, line input), panic, memory, timer ticks
lib/ string functions, ring buffer
targets/<target>/
target.mk architecture flags, drivers, image format, QEMU command
linker.ld load address and memory layout
platform.h device addresses and RAM size (until device tree support)
Generic code (kernel/, lib/, drivers/) contains no inline assembly and never includes anything from arch/.
Current state
Implemented
- Boot on both targets; AArch64 parks the secondary cores, RISC-V assumes a single hart
- Trap handling: RISC-V machine-mode traps, AArch64 exception vectors (unhandled exceptions panic with ESR/ELR/FAR)
- Console output and
kprintfon both targets - Interrupt-driven, line-buffered UART input on RISC-V
- 1 ms timer tick on RISC-V
- Page allocator and heap (
kmalloc/kfree) with self-tests at boot - Panic handling (
kpanic,KASSERT)
Not implemented yet
- AArch64 interrupts, generic timer and UART input
- Shell command parsing and built-in commands
- Supervisor mode, virtual memory, scheduler, user mode
Roadmap
- Rewrite the RISC-V trap entry (macro-generated save/restore) and fix the trap frame layout
- Make the console ring buffer safe between the interrupt handler and the main loop
- RISC-V
S-modeunder OpenSBI (SBI timer, console and reset), as required by real RISC-V boards - Shell milestone: parser, command table, and
help,echo,clear,time,mem,panic,reboot - Device tree support: memory size, timer frequency and device addresses from the DTB instead of
platform.h - AArch64 interrupts (BCM2836/BCM2835 controllers), generic timer and PL011 input on
raspi3b - Real hardware: Raspberry Pi 3, then StarFive VisionFive 2
- Later: virtual memory, scheduler, user mode and syscalls