summaryrefslogtreecommitdiff
path: root/README
diff options
context:
space:
mode:
authorVaze <vaze@vaze.dev>2026-05-19 16:47:52 +0200
committerVaze <vaze@vaze.dev>2026-05-19 16:47:52 +0200
commit10924a7138a288f5f717404b49e01f840dcfbcf2 (patch)
treeecd35e2758eb830ea1fe820c688a67a6beb0b6e7 /README
Started kernel and bootloader project. Created a README
Diffstat (limited to 'README')
-rw-r--r--README105
1 files changed, 105 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..1b2c17b
--- /dev/null
+++ b/README
@@ -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?