From 8f05ea44f69cb796e7b1f581ba1b8045c98d615b Mon Sep 17 00:00:00 2001 From: salmonik Date: Sat, 1 Aug 2026 17:38:57 +0200 Subject: rsnix: preemptive kernel tasks (ADR 0003) — sched, IST fault stacks, 176-byte frames MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - sched: 16-slot static table, shell=task 0, idle=task 1, spawn with guard page + 8 KiB stack, RR on the 100 Hz tick, int 0x60 yield, sleep_ms, lazy reap, jobs/bg/sleep/kill shell commands - gdt: own GDT mirroring UEFI selectors + TSS with IST1/IST2 (guard-page overflows die gracefully instead of triple-faulting) - interrupts: isr_dispatch returns next frame in rax; IntFrame grows rsp/ss fields — QEMU's 64-bit iretq always pops all five slots from a 176-byte frame, so synthetic task frames must carry rsp=top+ss (a 160-byte frame made the first iretq pop rsp/ss from the unmapped page beyond the frame) - panic handler: task panics abort the task, shell keeps running - main: sched::init moved after page allocator + adopted tables (the idle's stack+guard need both; it was silently not spawning) --- CONTEXT.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'CONTEXT.md') diff --git a/CONTEXT.md b/CONTEXT.md index 924854c..112b8de 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -359,6 +359,51 @@ Workspace of four crates, all built for the `x86_64-unknown-uefi` target: also untestable in QEMU. The disk arrival/removal path (PxSSTS based) is verified on real hardware instead. +✅ **Preemptive kernel tasks (ADR 0003)** — round-robin multitasking + on the 100 Hz PIT tick, one shared identity-mapped address space: + +- `sched`: 16-slot static task table (no ISR-time allocation); task 0 + = shell (boot stack), task 1 = idle `hlt` loop, tasks 2+ spawned + via `sched::spawn(entry, name)` with 3 pages each (1 unmapped + guard + 8 KiB stack); preemptive RR with `int $0x60` software + yield; `sleep_ms`/`yield_now`; lazy reaping of Done slots. +- `gdt`: kernel-owned GDT mirroring UEFI's selector layout (no + far-jump; CS/DS/SS keep working) plus a TSS with IST1 (page + fault) and IST2 (double fault) stacks — a stack overflow faults + inside the guard page, the CPU pushes the fault frame onto the + IST stack, and the task dies gracefully instead of triple- + faulting the machine (the ADR's guard-page promise, honored). +- `interrupts`: `isr_dispatch` returns the next frame pointer in + rax; asm does `mov rsp, rax` → pop → iretq. **QEMU quirk that + bit us**: QEMU's 64-bit interrupt entry always pushes + SS/RSP/RFLAGS/CS/RIP (40 bytes) and iretq always pops all five + (its same-privilege branch is never taken for 64-bit iretq), so + interrupt frames are 176 bytes and the synthetic task frames + must carry rsp=stack-top + ss — a 160-byte frame made the first + iretq pop rsp/ss from the unmapped page beyond the frame (task + started with rsp=0, or the iretq itself page-faulted). Real + hardware pushes only 24 bytes at same privilege, so the extra + fields are inert there; the synthetic frames set them + explicitly either way. +- Panic handling: a task panic (or guard-page overflow) is caught, + logged as `sched: task N "name" panicked: …`, the task is marked + Done, and the scheduler switches away — the shell keeps running. + Shell/idle/ISR/pre-scheduler panics still halt the kernel. +- Shell: `bg ` (spinner/ticker/counter demo + deliberate + `boom` panic + `overflow` recursion), `jobs` (state/ticks/ + panic message), `sleep ` (blocks only the shell), `kill + `. Only the shell touches disk/fs/tty/vt; background tasks + are headless (sleep + serial/klog only). +- Boot order note: `sched::init` must run after the page allocator + and adopted page tables (the idle's stack + guard need both) — + it was originally before them, silently dropping the idle task. + + Verified in QEMU (9-step script): demo interleaving at expected + cadences, sleep keeps background tasks logging, jobs states, + graceful `boom` panic with corpse in jobs, kill stops a task, and + `bg overflow` dies on the guard page with the machine intact; full + regression (rescan/til/klog/grammar/pager) re-passes. + ## Known issues / perf notes - **Scroll cost** — scrolling still shifts the whole framebuffer (a -- cgit v1.2.3