- caps record parent (mint/delegate/ipc), CapRef w/ pid+slot gens
- Revoke = delete subtree, keep self; drop/death re-parents children
- CreateRegion/MapRegion; mapping lives only as long as its cap
- drop Permission::Revoke + object-wide revoke
- mint any cap (badge only ep/ntfn), process caps delegable
- kani: descendants == subtree; model-based fuzz vs spec
- RunList -> intrusive FIFO, no starvation, no silent drop
- cap table sized to CapSlot range (kani caught OOB panic)
- snake food color test uses const
- kani cfg lint, RUST_MIN_STACK for big kernel struct in tests
- Driver now drains SYN/repeat/unknown events in a loop instead of
returning None on the first non-key event
- Snake drains all pending input events per tick, applies only the
latest direction change (prevents stale event accumulation)
- Add VirtIO input device driver (device ID 18) reading from eventq
- Translate Linux keycodes (WASD, arrows) to InputEvent
- Kernel probes for VirtIO input device, falls back to UART
- Add -device virtio-keyboard-device to run-gui Makefile target
- input-qemu tries VirtIO first, falls back to UART
- Fix swapped command IDs: attach_backing was 0x0104 (FLUSH),
resource_flush was 0x0106 (ATTACH_BACKING). Now correct.
- Increase process stack from 4 pages (16 KB) to 16 pages (64 KB)
to prevent stack overflow in display process.
- Restructure display-qemu to avoid MockFramebuffer's 32 KB array
inflating the VirtIO path's stack frame.
- Wire snake app to render through display server via IPC instead
of UART escape codes. Uses existing renderer.rs pixel renderer.
- Init now delegates display endpoint to snake process.
VirtIO GPU:
- Removed QEMU 11.x command type swap hack (0x0104↔0x0106).
The hack was wrong — swapping types without swapping data formats
meant handlers read wrong struct layouts. Commands returned OK
but did nothing.
- Restored correct VirtIO spec command types.
- Removed broken test pattern (fill + flush that never displayed).
- GPU setup now reports success/failure without crashing.
Display server resilience:
- VirtioFramebuffer::new() → try_new() -> Option<Self>.
Returns None if phys-info page is unmapped or has zero dimensions.
- bins/display-qemu: tries VirtioFramebuffer, falls back to
MockFramebuffer. Display server runs headless instead of crashing.
- No more page faults when GPU is absent.
The GPU driver code is architecturally correct (proper VirtIO
commands, proper data formats) but doesn't produce visible output
on QEMU 11.x due to a suspected QEMU legacy MMIO bug where
transfer_to_host_2d succeeds but doesn't transfer data. The driver
is ready for when this is fixed or a different QEMU version is used.
TimeSlice::DEFAULT and Priority::DEFAULT already exist with the
same values. Using them makes the intent clear and centralizes
the default values.
TimeSlice::new(2) in tick test is intentional — tests preemption
after 2 ticks specifically.
CRITICAL — MapPage privilege escalation:
handle_map_page allowed mapping kernel memory (VA >= 0x80000000)
into userspace. Any process with a Process capability could read/
write kernel data structures. Fixed: reject src_va >= USER_VA_LIMIT.
HIGH — resource leaks:
handle_kill: leaked pages (used cleanup_threads directly instead
of destroy_process). Now uses destroy_process for full cleanup.
handle_create_process: orphaned process on cap grant failure.
Now destroys process on rollback.
handle_create_endpoint: orphaned endpoint on cap grant failure.
Now destroys endpoint on rollback.
Thread ID array: hardcoded [None; 4] replaced with
[None; MAX_THREADS_PER_PROCESS] slice. cleanup_threads now
takes &[Option<ThreadId>] slice.
MEDIUM — quality fixes:
handle_request_pages: replaced unreachable!() with proper error
return + page pool rollback.
Page lifecycle:
- ProcessMemory now tracks (PhysicalAddress, count) pairs for each
allocation (up to 16). destroy_process iterates and frees all
pages back to the pool. No more permanent page leaks on exit/fault.
- RequestPages re-adds MemoryRegion entries so ReleasePages works.
Release test un-ignored, passes.
- RequestPages: VA allocation moved after pool allocation succeeds,
preventing VA leak on OOM.
IPC hardening:
- WaitQueue overflow (>16 waiters): returns WouldBlock error instead
of silently dropping the thread. Thread is not blocked if enqueue
fails.
- debug_assert on pending_messages[sender].take() — invariant that
a sender in wait queue must have a pending message.
Scheduler:
- remove() now clears current thread if the removed thread was
current on its core.
- add() asserts push succeeded; bitmap bit only set if thread was
actually added to RunList.
Cleanup:
- Priority::DEFAULT replaces Priority::new(16).unwrap() in
spawn_thread and spawn_thread_in.
36 kernel tests pass, 0 ignored.
Critical: kernel_ref() UB eliminated
- kernel_ref() returned &'static mut, creating aliasing mutable
references across trap handler + boot code (13+ call sites)
- Replaced with kernel_ptr() -> *mut Kernel, each use site does
explicit unsafe { &mut *kernel_ptr() }
- KernelCell: removed get_mut(), added as_ptr() -> *mut T
- UB is gone: raw pointer access makes the single-core invariant
explicit at every use site
Important: process cleanup on exit/fault
- New destroy_process() method consolidates cleanup:
- Removes all threads from scheduler and endpoints
- Clears pending messages and results
- Destroys process and frees ProcessMemory
- handle_exit and handle_fault both use destroy_process()
- handle_exit_thread uses destroy_process when last thread exits
IPC hardening:
- Added invariant comment on pending_messages[sender].take()
(sender in wait queue must have a pending message)
handle_release_pages:
- Now uses translate_va to convert VA→PA (was treating VA as PA)