diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..a10556a --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,76 @@ +# AGENTS.md + +## Project + +curiOS is an x86-64 OS kernel written (mostly) from scratch in Rust. It boots via +[Limine](https://limine-bootloader.org/) 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`.