curiOS/AGENTS.md
2026-08-03 14:58:27 +02:00

3.2 KiB

AGENTS.md

Project

curiOS is an x86-64 OS kernel written (mostly) from scratch in Rust. It boots via Limine and runs in QEMU. A companion blog in org-mode format lives in blog/.

Workspace layout

Cargo workspace with members crates/* and kernel:

  • kernel/ — the kernel: no_std library crate (src/lib.rs) plus a no_std/no_main binary (src/main.rs). Custom target spec x86_64-unknown-kernel.json; .cargo/config.toml wires up the target, build-std, and the QEMU runner.
  • crates/rbtree/ — a no_std red-black tree crate used by the kernel's physical memory manager. Unit-tests on the host (it opts into std under cfg(test)).

Toolchain

  • Rust nightly (edition 2024) with many unstable features — see the #![feature(...)] lists at the top of kernel/src/lib.rs and crates/rbtree/src/lib.rs.
  • Development environment is a Nix flake devshell (direnv via .envrc). It provides the toolchain plus qemu, limine-full, OVMF, mtools, clang, gdb, mold, etc.
  • The kernel is built with build-std and the custom target; do not build it for the host target. kernel/.cargo/config.toml sets the target and a json-target-spec-enabled nightly; rust-analyzer needs CARGO_UNSTABLE_JSON_TARGET_SPEC=true (see kernel/.dir-locals.el).

Build & test

Run these from inside kernel/ (the workspace root uses the host target and won't build the kernel binary):

cargo build            # build the kernel (runs build.rs which links kernel/kernel.lds)
cargo clippy           # lint
cargo fmt --check      # format check

cargo run / cargo test invoke kernel/run.sh via the runner in .cargo/config.toml, which boots the kernel in QEMU. Tests are special [[test]] binaries (e.g. kernel/tests/simple.rs, stack_overflow.rs) that run inside the kernel in QEMU with a custom test harness (harness = false) and exit via the QEMU isa-debug-exit port:

cargo test             # run all integration tests in QEMU
cargo test --test simple

crates/rbtree runs its unit tests normally on the host (cargo test from crates/rbtree/).

The test framework (#![cfg_attr(test, custom_test_frameworks)] with test_runner from kernel/src/tests.rs), QEMU exit handling, and the Testable trait live in kernel/src/testing.rs and kernel/src/tests.rs. A #[panic_handler] is defined in the test binaries — don't add another.

Conventions

  • no_std everywhere in kernel code; extern crate alloc where allocation is needed.
  • Unsafe blocks require a // SAFETY: comment justifying the invariant.
  • Use the serial_println! / serial_print! macros for logging (defined in kernel/src/serial.rs) — there is no std output.
  • Kernel-wide statics prefer the sync::LazyLock wrapper in kernel/src/sync/mod.rs over bare static mut.
  • Follow existing patterns in kernel/src/x86_64/ (GDT, IDT, paging, cpuid) for new arch code.
  • #[cfg(test)] gate test-only modules and items.
  • No comments unless they convey something non-obvious (e.g. safety justifications).

Commit style

Short lowercase messages, crate: prefixed, e.g. kernel: fix unsafenode impl, rbtree: fix compile warnings.