diff options
Diffstat (limited to '')
| -rw-r--r-- | CONTEXT.md | 45 |
1 files changed, 45 insertions, 0 deletions
| @@ -359,6 +359,51 @@ Workspace of four crates, all built for the `x86_64-unknown-uefi` target: | |||
| 359 | also untestable in QEMU. The disk arrival/removal path (PxSSTS | 359 | also untestable in QEMU. The disk arrival/removal path (PxSSTS |
| 360 | based) is verified on real hardware instead. | 360 | based) is verified on real hardware instead. |
| 361 | 361 | ||
| 362 | ✅ **Preemptive kernel tasks (ADR 0003)** — round-robin multitasking | ||
| 363 | on the 100 Hz PIT tick, one shared identity-mapped address space: | ||
| 364 | |||
| 365 | - `sched`: 16-slot static task table (no ISR-time allocation); task 0 | ||
| 366 | = shell (boot stack), task 1 = idle `hlt` loop, tasks 2+ spawned | ||
| 367 | via `sched::spawn(entry, name)` with 3 pages each (1 unmapped | ||
| 368 | guard + 8 KiB stack); preemptive RR with `int $0x60` software | ||
| 369 | yield; `sleep_ms`/`yield_now`; lazy reaping of Done slots. | ||
| 370 | - `gdt`: kernel-owned GDT mirroring UEFI's selector layout (no | ||
| 371 | far-jump; CS/DS/SS keep working) plus a TSS with IST1 (page | ||
| 372 | fault) and IST2 (double fault) stacks — a stack overflow faults | ||
| 373 | inside the guard page, the CPU pushes the fault frame onto the | ||
| 374 | IST stack, and the task dies gracefully instead of triple- | ||
| 375 | faulting the machine (the ADR's guard-page promise, honored). | ||
| 376 | - `interrupts`: `isr_dispatch` returns the next frame pointer in | ||
| 377 | rax; asm does `mov rsp, rax` → pop → iretq. **QEMU quirk that | ||
| 378 | bit us**: QEMU's 64-bit interrupt entry always pushes | ||
| 379 | SS/RSP/RFLAGS/CS/RIP (40 bytes) and iretq always pops all five | ||
| 380 | (its same-privilege branch is never taken for 64-bit iretq), so | ||
| 381 | interrupt frames are 176 bytes and the synthetic task frames | ||
| 382 | must carry rsp=stack-top + ss — a 160-byte frame made the first | ||
| 383 | iretq pop rsp/ss from the unmapped page beyond the frame (task | ||
| 384 | started with rsp=0, or the iretq itself page-faulted). Real | ||
| 385 | hardware pushes only 24 bytes at same privilege, so the extra | ||
| 386 | fields are inert there; the synthetic frames set them | ||
| 387 | explicitly either way. | ||
| 388 | - Panic handling: a task panic (or guard-page overflow) is caught, | ||
| 389 | logged as `sched: task N "name" panicked: …`, the task is marked | ||
| 390 | Done, and the scheduler switches away — the shell keeps running. | ||
| 391 | Shell/idle/ISR/pre-scheduler panics still halt the kernel. | ||
| 392 | - Shell: `bg <builtin>` (spinner/ticker/counter demo + deliberate | ||
| 393 | `boom` panic + `overflow` recursion), `jobs` (state/ticks/ | ||
| 394 | panic message), `sleep <ms>` (blocks only the shell), `kill | ||
| 395 | <id>`. Only the shell touches disk/fs/tty/vt; background tasks | ||
| 396 | are headless (sleep + serial/klog only). | ||
| 397 | - Boot order note: `sched::init` must run after the page allocator | ||
| 398 | and adopted page tables (the idle's stack + guard need both) — | ||
| 399 | it was originally before them, silently dropping the idle task. | ||
| 400 | |||
| 401 | Verified in QEMU (9-step script): demo interleaving at expected | ||
| 402 | cadences, sleep keeps background tasks logging, jobs states, | ||
| 403 | graceful `boom` panic with corpse in jobs, kill stops a task, and | ||
| 404 | `bg overflow` dies on the guard page with the machine intact; full | ||
| 405 | regression (rescan/til/klog/grammar/pager) re-passes. | ||
| 406 | |||
| 362 | ## Known issues / perf notes | 407 | ## Known issues / perf notes |
| 363 | 408 | ||
| 364 | - **Scroll cost** — scrolling still shifts the whole framebuffer (a | 409 | - **Scroll cost** — scrolling still shifts the whole framebuffer (a |
