Skip to content

devzbysiu/zos

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

zOS

A minimal Zig kernel for RISC-V, built from scratch

Built with Zig ⚡

🚀 Overview

zOS is a small educational kernel written in Zig, targeting RISC-V (RV32). It is designed to be simple, readable, and hackable, showing how to bring up a system from bare metal all the way to handling traps and making SBI calls.

🎯 Goals

  • Show how to write a tiny kernel\
  • Be easy to read, learn from, and experiment with\
  • Provide a minimal but real trap pipeline and allocator\
  • Demonstrate using Zig in a bare-metal environment\

🧩 Built With

  • Zig --- low-level programming without fear
  • RISC-V / RV32 --- clean and open architecture
  • OpenSBI --- standard interface for firmware/syscalls
  • QEMU --- fast virtual RISC-V environment

✨ Features

🧵 Boot Process

  • Custom linker script sets the entry symbol (boot)
  • First code executed is _start() function
  • Stack pointer is initialized manually
  • Control is transferred cleanly to kernelMain()

💬 Console Output

  • Minimal putchar() implemented through OpenSBI ecall
  • A tiny, compile-time-formatted printf() + log() implementation
  • Prints hex/decimal/string without relying on the standard library

⚠️ Trap Handling

  • A fully custom trap vector:
    • trap_vector.S aligns the handler correctly
    • Jumps into a Zig kernelEntry function
  • kernelEntry:
    • Saves all registers manually
    • Calls handleTrap with a well-defined TrapFrame
    • Restores registers and executes sret
  • Trap debugging includes:
    • scause
    • stval
    • sepc

📦 Memory Management

  • Extremely simple linear allocator:
    • Allocates whole pages
    • Zeros allocations with memset
    • Pointer range validated using linker-defined symbols:
      • __free_ram
      • __free_ram_end
  • Helpful for early boot and experimentation

🧠 How It Works

🔹 1. Boot Entry

The linker script defines ENTRY(boot), and the .text.boot section contains:

pub export fn _start() linksection(".text.boot") callconv(.naked) noreturn {...}

This function:

  1. Initializes next_addr for the allocator
  2. Sets up the stack pointer
  3. Jumps to kernelMain

🔹 2. Kernel Main Logic

Inside kernelMain:

  • Install trap vector (stvec)
  • Test allocator (allocPages)
  • Print system state
  • Enter low-power wfi loop

🔹 3. Trap Handling Pipeline

Exception → stvec register → trap_vector.S → kernelEntry → handleTrap()
  • Fully manual context save & restore
  • Clean C-ABI trap handler in Zig
  • Prints a panic with CSR information

🔹 4. Memory Layout

The linker defines:

[text | rodata | data | bss] → stack → RAM (64 MB)

Key exported symbols:

__stack_top       # initial stack pointer
__free_ram        # start of free RAM allocator
__free_ram_end    # allocator limit

▶️ Running It

You can run the kernel under QEMU: ./run.sh

Ensure OpenSBI firmware is present (default QEMU uses one automatically).

🧪 Example Output

[*] starting kernel...
[*] trap vector address: 0x80203000
[*] allocPages test: paddr0=0x80220000
[*] allocPages test: paddr1=0x80222000
[*] continuing execution...

And if something traps:

[*] trap scause=0x00000002, stval=0x00000000, sepc=0x80200420
[*]     in: kernel.zig:123

⭐ License

This project is licensed under either of

at your option.

About

Toy OS in Zig

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published