diff options
| author | Vaze <vaze@vaze.dev> | 2026-05-19 16:47:52 +0200 |
|---|---|---|
| committer | Vaze <vaze@vaze.dev> | 2026-05-19 16:47:52 +0200 |
| commit | 10924a7138a288f5f717404b49e01f840dcfbcf2 (patch) | |
| tree | ecd35e2758eb830ea1fe820c688a67a6beb0b6e7 /README | |
Started kernel and bootloader project. Created a README
Diffstat (limited to 'README')
| -rw-r--r-- | README | 105 |
1 files changed, 105 insertions, 0 deletions
@@ -0,0 +1,105 @@ +ZenOS - A purposefully small project. +This page is to remind you of the goals you had in mind when starting this project. + +#This is *not* supposed to replace everything for everyone. +Keep in mind that what you do is only for you. You're the dev and the end user. +There is no pressure to do things in any order or at any speed. +No need to comply with any standarts or anything of that kind. +Just excercise. This isn't too unlike mental yoga. + +What needs to be done? +Whatever you want to do, really. +On a high level: +Edit files, manipulate filesystems, compute (calculator, compiler, etc.), at a later stage internet (gossipChat, gopher/gemini) + +What needs to be done on a lower level? (Feel free to add more stuff here, once clear) +Bootloader +- +- +- +Microkernel +- Services +Filesystem +- +- +- +Interface, whether graphical or text-based. +- + +Write in Rust. + +Nice — thanks for the clear priorities. Below is a concise, concrete design checklist and recommended trade-offs tuned to your goals: safety (practical, not formally guaranteed), high performance, extreme minimality/simplicity, extensibility, x86_64+UEFI only, resource efficiency, and maintainability. + +Top-level choices (decision summary) +- Kernel style: small microkernel-ish monolithic-minimal hybrid — keep the kernel tiny but include a few carefully chosen fast-path services in-kernel for performance (see list below). +- Language: Rust for most kernel code, with tiny assembly for entry/context-switch. Use Rust to get strong memory-safety benefits while keeping code minimal. Allow small, audited unsafe blocks where needed. +- Boot target: UEFI (x86_64, OVMF/QEMU for dev). ExitBootServices early and run in your own long mode environment. +- Build/testing: QEMU + GDB for iterative development; keep host-side unit tests for freestanding modules where possible. + +Kernel responsibilities (what stays in kernel) +1. IPC primitives and synchronous/asynchronous message passing with a very small, fast ABI (zero-copy/shared-buffer support). +2. Preemptive scheduler / context switch and per-CPU runqueues (strictly minimal API: create/kill/yield/block/unblock). +3. Minimal memory protection: basic page table manipulation, frame allocator, and mappings necessary to enforce isolation. Keep the allocator simple (buddy or slab-free with small footprint). +4. Interrupt/trap entry and demultiplexer to deliver events to in-kernel handlers or user services. +5. Low-level timer and high-resolution tick source for scheduling. +6. Capability / handle table (tiny capability mechanism) to grant resources to services. +7. Minimal device arbitration stubs only where absolutely needed for performance (e.g., IRQ dispatch to a driver service); otherwise forward to user services. + +User-space services (what runs as services) +- Block device server and simple filesystem server (user-space FS reduces kernel size). +- Network stack as a user service (unless you need ultra-low-latency—then keep NIC RX/TX fast-paths in kernel). +- Device drivers in user space, except for tiny interrupt-forwarding stubs in kernel. +- Pager service / user-level virtual memory manager handling page-faults signalled by kernel. +- Session/process manager, shell, and other high-level daemons. + +Performance vs safety trade-offs (concrete guidance) +- Fast IPC: implement a minimal syscall-like fast-path (direct call into kernel with shared ring buffer or mapped message pages) to reduce overhead. Make the fast-path small and verifiable; move complex logic to safe Rust user services. +- Shared memory: use explicit grant/mapping semantics (kernel mediates mappings) to avoid accidental aliasing/unsynchronized access. Prefer immutable shared pages or require explicit synchronization primitives in services. +- Critical fast-paths in kernel: keep them tiny (<200 LOC each) and audit them carefully; isolate unsafe code into small modules with heavy unit tests. +- Avoid heavy kernel inlining of high-level policies — move policy to services to reduce kernel complexity and make verification/auditing feasible. + +Simplicity & minimality tactics +- Minimal syscall/API surface: design 10–20 kernel calls only (IPC send/recv, map/unmap, create/process, nanosleep/timer, sysinfo, grant capabilities). +- Small trusted computing base: aim for <50K LOC total initially (kernel <5–10K LOC). +- Single-threaded service model to simplify state machine reasoning; use async in services if needed. +- Prefer clear, small data structures (no complex trees unless required). Use simple allocators and avoid full-featured memory managers early. + +Memory-safety practical rules +- Write most code in safe Rust; mark unsafe blocks explicitly and keep them tiny. +- Peer-review unsafe modules and provide tests and fuzz harnesses for them. +- Use strong assertions and debug builds when developing; enable fewer assertions in optimized builds if you need raw speed. +- Keep invariants explicit in types (e.g., newtypes for physical vs virtual addresses). + +Maintainability & extensibility +- Well-defined IPC interface versioning: attach a tiny version number to each service protocol to allow evolution without kernel changes. +- Module-per-concern layout + small crates (if using Rust) so components can be rebuilt/tested independently. +- Document the minimal kernel API in one page and maintain simple diagrams of control flow for interrupts and IPC. + +Resource efficiency +- Use static linking and strip debug info for release images. +- Keep default heap and stacks small; tune sizes per-service. +- Use on-demand allocation and avoid caches unless they measurably improve perf. + +Debugging / observability (minimal, optional) +- Lightweight serial console + panic logging; avoid heavy telemetry. +- Optional in-memory ring buffer for recent kernel events (readable from a privileged service). +- Use QEMU's built-in tracing/GDB for low-level debugging instead of instrumenting the OS too much. + +A minimal initial roadmap (stepwise) +1. UEFI boot stub in Rust/assembly that prints to serial/GOP and obtains memory map. +2. Small physical frame allocator + page-table setup. Create an initial address space and kernel stack. +3. Context switch + single-core scheduler and a thread abstraction; implement yield/block. +4. Simple IPC (sync call/response) and a trivial echo service in user-space. +5. Interrupt entry and timer; preemptive scheduling. +6. Implement user-space pager and a basic file/block server. +7. Measure hotspots; move vetted, tiny fast-paths into kernel only if necessary. + +Concrete tech choices +- Rust stable (use only minimal nightly features if unavoidable). +- x86_64 crate for low-level bindings, or write tiny inline assembly for CPUID/CR3/irq. +- Use OVMF + QEMU for dev, cargo-xbuild or custom cross-toolchain for freestanding targets. +- Logging over serial; use VGA framebuffer only for debugging initially. + +Final notes +- This plan gives strong practical safety via Rust while favoring speed and small trusted code. It keeps the kernel minimal but pragmatic: enough low-level primitives for isolation and fast IPC while pushing policy and complexity into user-space services you control. +- If you want, I can generate a 1-page kernel API (list of syscalls/IPC messages and their signatures) and a 200–300 line Rust starter template implementing the boot stub, frame allocator, and a trivial scheduler. Which would you prefer? |
