Feature/bootloader hardening#162
Open
senseix21 wants to merge 124 commits into
Open
Conversation
…static-checks.sh [1.4]
…ed) — capsule_integration_matrix.md [1.4]
…->submit) — lib.rs [3.1]
…unter) — main.rs [3.2]
…ect of progressive/arith/entropy) — jpeg.rs [4c]
…er >4 GiB; fixes ExitBootServices #PF) — constants.rs
allocate_user_stack mapped frames straight from frame_alloc (phys::alloc(EMPTY) -- never zeroed) into the capsule's address space, so a capsule's initial user stack inherited whatever the frame last held. When a frame had previously backed a kernel stack, that's live kernel-VA content (e.g. 0xffffff50.. VMAP kstack addresses); a capsule that returns from _start pops the stale slot and jumps into the kernel half -> CPL=3 fault. Zero each frame via its directmap alias before mapping. Fixes the info-leak and the kstack-VA-in-control-flow faults (verified: no more 0xffffff50.. rips on the full desktop; residual faults are app capsules' own null-derefs/#GPs, unrelated).
Adds a free-quarantine ring (heap/types/quarantine.rs): freed user regions are filled with a canonical-but-unmapped poison word (0x0000_5EED_5EED_5EED) and held in a 1024-slot ring so reuse is delayed. A use-after-free *read* of a poisoned pointer then faults as a #PF with cr2=...5EED.. (visible in the trap dump); a stray *write* to freed memory is caught when the block is evicted and re-scanned ([UAF-WRITE] logs the offset + the written word). Gated by nonos-heap-debug; the production dealloc path is unchanged. Empirical signal: with quarantine active, the intermittent teardown #GP (~80% of runs without it) did not reproduce across the first runs, implying the inbox-registry corruption is reuse/layout-related (a freed block reused too eagerly), not a wild write to live memory.
The inbox registry (BTreeMap<String, Arc<Inbox>>) was guarded by a spin::RwLock that does not mask interrupts. A timer tick during a register/unregister could preempt the thread mid-BTreeMap-mutation; the preemption path itself allocates (saving context into the INTERRUPT_SAVED_CONTEXTS map), so the global allocator handed back a node the in-progress mutation had just freed, and the resuming op then walked a recycled/overwritten link -> non-canonical pointer -> #GP in remove_leaf_kv on the next capsule teardown, wedging the kernel. Disable interrupts across each registry tree mutation (acquire the write lock first, then the interrupt guard, so a writer never disables interrupts while spinning on a reader-held lock). The mutation now runs atomically and no preemption can recycle its transient frees. Diagnosis: a poison+quarantine allocator (nonos-heap-debug) showed the corruption is reuse-sensitive -- a 1-slot reuse delay suppressed it across all runs, and HEAP_ZERO_ON_FREE=true ruled out stale content -- isolating it to immediate re-entrant reuse. Verified: 6/6 full-desktop boots clean (teardown #GP gone) vs ~80% wedge before.
…d resume is the fix
…itch, FPU+rsp in PCB)
…phase 1) Eager FXSAVE/FXRSTOR state moves from the pid-keyed global side-table INTERRUPT_SAVED_FPU_STATES (RwLock<BTreeMap<Pid, FpuState>>) into per-PCB fields fpu: Mutex<FpuState> + fpu_valid: AtomicBool, parallel to the existing aarch64/riscv64 arch_fpu. save/restore/has/clear_fpu_state now resolve the PCB via PROCESS_TABLE.find_by_pid instead of the map; the map and its re-export are deleted. First step of the context-switch rewrite (docs/superpowers/plans/2026-05-23-ctx-switch-rewrite-implementation-plan.md): drops one of the two global context maps. Verified: minimal repro boots zero TRAP (FPU correct across switches).
…h rewrite phase 2) Introduce the standard ret-based kernel context switch (cpu_switch: push callee-saved + return addr, swap rsp, pop, ret) and build_initial_switch_frame that seeds a fresh kernel stack with a fake switch frame. Add pcb.kernel_rsp to hold a parked task's switch rsp. None of this is routed yet; it is exercised only by a feature-gated (nonos-cpuswitch-selftest) kernel<->kernel round-trip self-test run at INIT. This is the inert groundwork for the phase-4 cutover that replaces the setjmp/longjmp + INTERRUPT_SAVED_CONTEXTS mechanism. Verified: target build clean with and without the feature; with the feature the virtio-rng repro boots and prints "[CPUSWITCH] selftest PASS" with zero faults; without it the new code is dead.
…switch rewrite phase 3) Add the two cpu_switch resume targets (first_entry_trampoline, resume_user_trampoline) that drive the existing first-entry / preempt-resume tails, and seed pcb.kernel_rsp with a fake switch frame pointing at them: first-entry in setup_initial_user_pcb_x86_64, preempt-resume in try_resume. The old dispatch path still drives every resume; kernel_rsp is populated in parallel and is not yet consumed. Deviation from the plan: the preempt-case frame is built on the resume side (try_resume), not in the timer ISR. Writing a switch frame at kstack_top-56 during the timer trampoline would clobber the in-flight interrupt frame on the same stack; the resume side runs while the target is parked and its kernel stack top is idle, so it is the safe choke point. restore_user_context_iretq pushes its iretq tuple on the dispatcher stack via rdi, so the seeded frame never collides. Frame population is always-on (phase 4 consumes it); only the [CPUSWITCH] trace is behind nonos-cpuswitch-selftest. Verified: target build clean with and without the feature; with the feature the virtio-rng repro prints "first-entry kernel_rsp set" for every spawned task and "preempt kernel_rsp set" on every resume, zero faults, and the boot is unchanged (same proof_io starvation loop the phase-4 cutover fixes).
…witch rewrite phase 4a) Cut the cooperative scheduler over to the ret-based cpu_switch. yield and preempt no longer setjmp via Context::save_to + park in INTERRUPT_SAVED_CONTEXTS; they call switch_to_process, which now returns when the task is scheduled again. Resume is a single unified path (dispatch.rs): prepare_resume installs the next task's TSS.RSP0/CR3/state/FPU/user-rsp on the outgoing (global) kernel stack, then cpu_switch swaps stacks. A never-run task lands on its first_entry_ trampoline frame; an already-run task resumes exactly where it parked inside its own preempt/yield call, and the iretq/SYSRET frame still on its kernel stack carries it back to userspace. resume_user_trampoline is dropped: a preempted task needs no trampoline in this model. Deleted the old per-mode arch paths (first_entry/resume/kernel_thread) folded into resume_env + the trampoline; the setjmp/longjmp machinery (Context::save_to/ restore, CONTEXT_JUST_RESTORED, INTERRUPT_SAVED_CONTEXTS) stays for now, used only by signal delivery + suspend/resume, and is removed in 4b. build_initial_switch_frame now lands the trampoline at rsp = 8 (mod 16), the SysV state right after a call, so the target's SSE spills stay 16-aligned. The prior frame left rsp 16-aligned, which #GP'd the first switch into a never-run task (movaps on a misaligned spill) once real code ran on it. prepare_resume tolerates kernel_stack_top == 0 (skips TSS.RSP0) so the boot/init task, which runs on the boot stack, can be parked and resumed. Verified: target build clean with and without nonos-cpuswitch-selftest; the virtio-rng repro boots zero-TRAP for the full 130 s window, the voluntary yield now resumes (bidirectional init<->capsule switching), and init completes yield_after_spawns and proceeds to launch_final_payload (forward progress that was impossible while the yield never returned).
…x-switch rewrite phase 4b) The restored-flag bounce guard (CONTEXT_JUST_RESTORED + set_restored_flag/ was_just_restored/clear_restored_flag) existed only to stop the old setjmp/ longjmp yield+preempt from double-saving when a restored task immediately took a timer interrupt. Phase 4a deleted those callers, so the flag has no readers. Drop the static, the three flag fns, and Context::restore's now-pointless set_restored_flag() call. Context::save_to/save and Context::restore stay: signal delivery (syscall_return, signal/delivery/install) and suspend/resume (suspend.rs) still legitimately use the Context type + INTERRUPT_SAVED_CONTEXTS, which are no longer scheduler state and are left intact. Verified: target build clean; virtio-rng repro boots zero-TRAP for 125 s, behavior identical to 4a (dead-code removal only).
Capsule INTx MkIrqBind always failed with GsiNotFound: the broker's IO-APIC backend (arch::x86_64::interrupt::ioapic) was never initialized, so its IOAPICS registry was empty and program_route_external's locate() found no chip. The boot path only ran the legacy sys::apic::ioapic programmer, which drives kernel IRQs but does not populate the broker registry. Wire nonos_ioapic::init() into sys::apic::init() with the MADT IOAPIC/ISO descriptors (falling back to the 0xFEC00000 default the legacy path uses when the MADT IOAPIC table parses empty, as it does under this OVMF). Fix the broker's ioapic map_mmio: it referenced an undefined __nonos_alloc_mmio_va (dead since the subsystem was never called) and, once live, a raw-physical 0xFEC00000 access faulted because the identity map is torn down by capsule-spawn time. Resolve the register window through the persistent directmap (phys_to_virt) instead, matching how the kernel reaches physical memory post-handoff. With this the gpu capsule's IRQ binds: zero bind/route/IOAPIC faults across the boot, and it now advances past bind into device init. (A separate downstream virtio-gpu "device timeout"/"claim failed" remains; not an IRQ issue.) A proper UC MMIO mapping for the APIC region (vs the WB directmap, fine under QEMU) is the broader APIC-MMIO-addressing cleanup tracked with the LAPIC #PF.
The virtio-gpu driver mapped the wrong BAR (VGA framebuffer, BAR0) because it guessed registers via "first MMIO BAR" and keyed modern/legacy on the device id alone. On a modern virtio device the register structures live in whatever BAR the vendor caps name (BAR2 @ 0x1000/0x2000/0x3000 for QEMU virtio-vga), so every bring-up read/wrote garbage and the device never initialized (timeout / bogus queue size). Capsules cannot read PCI config space, so the kernel now parses the virtio vendor caps (cfg_type common/notify/device/isr) into a VirtioPciCfg (get_virtio_info, mirroring the MSI-X parser), stores it on PciDevice, and publishes the BAR+offsets through DeviceRecord (wire size 176 -> 200; libc mirror + size asserts updated; the other driver capsules' empty_record gain the zeroed fields). The gpu driver maps the common-cfg BAR at its cap offset and bases its modern registers there, with notify at notify_off - common_off. With this the virtio-gpu fully initializes under a modern device (no disable-modern): IRQ binds, control queue round-trips, and get_display_info / create_resource_2d / attach_backing / set_scanout all succeed. (Surface registration is the next blocker: the surface registry translates the capsule DMA VA through the kernel page table instead of the capsule's — separate bug.) Requires booting the GPU without disable-modern=on so the modern caps exist.
…table do_register walked the kernel's PAGING_MANAGER (translate_address) to resolve the surface descriptor's base_va to physical frames, but base_va is a capsule user VA. The kernel is upper-half with PML4[0] cleared, so the kernel table has no capsule user mappings and every page resolved to None -> EFAULT, rejecting the surface. Add usercopy::user_page_phys, which walks the active (capsule) table the same way usercopy reads user buffers, and use it per page. Surface registration still requires the capsule to hold GraphicsSurfaceCreate; the virtio-gpu driver capsule does not yet (its signed manifest must grant it), so this fix is not yet exercised end-to-end — but it removes a wrong-address- space bug any surface producer would hit.
Set the virtio-gpu capsule's required caps to 0x1FB118 (adds GraphicsSurface Create|Map) so it may register/share its primary scanout surface, and advance the nonos-data trust-keystore pointer to the re-signed scratch chain (915a3cf). With this the lean desktop boots without disable-modern and the compositor presents a live wallpaper through the virtio-gpu framebuffer.
disable-modern=on hides the modern virtio PCI capabilities the kernel parses to locate the gpu register BARs. Without them the gpu driver cannot claim or DMA-map and the compositor falls back to GOP. The hand-rolled bring-up command already omitted the flag; align the run target with it so make nonos-mk-run-* exercises the working path.
allocate_frame scatters single-frame allocations across the whole bitmap at a randomized index. By the time the desktop profile spawns the gpu, that pseudo-random placement leaves no multi-MB contiguous free run, so alloc_contiguous for the primary surface (768 frames / 3 MiB) returns NoMemory and the gpu cannot map its framebuffer. Carve a top reserve (contig_split) that the randomized single-frame path never touches, so first-fit find_contiguous_free always has an unfragmented window for framebuffer-sized DMA grants.
run() returned run_gop_once() before ever attempting the virtio path, so the compositor always drew into the GOP framebuffer even when the gpu surface was available. Once the gpu owns the scanout the GOP framebuffer is no longer presented, so this left the screen blank. Try run_virtio_once() first (the existing retry loop waits for the gpu to come up) and fall back to GOP only when virtio never appears, matching the "fallback" the marker already advertises.
attach_surface mapped the shared surface pages READ|WRITE without USER, so the CPL=3 compositor took a U/S protection fault the instant it touched its attached framebuffer (read of a present supervisor page). Add PagePermissions::USER so the receiver capsule can read and write the surface it attached, matching every other user-page mapping.
The .superpowers/ tree holds local brainstorm/session scratch state, not source. Untrack it and add it to .gitignore so it stays local.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds multiple debug/dev hardening capabilities across the kernel and userland, expands the device-broker ABI to surface modern virtio PCI capability-derived register locations, and adjusts the QEMU run target to include a GPU by default—together aimed at improving bring-up reliability and debugging for the desktop/graphics stack.
Changes:
- Introduces new debug/dev feature flags (heap corruption quarantine/logging, cpu_switch selftest, kernel-stack writer trap) and a “lean desktop” boot mode.
- Extends
DeviceRecordABI and PCI probing to expose virtio modern register window metadata; updates virtio-gpu capsule discovery/MMIO setup to consume it. - Improves framebuffer/graphics present paths and QEMU run configuration (GPU enabled by default).
Reviewed changes
Copilot reviewed 128 out of 154 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| userland/libc/src/broker/types.rs | Extends broker ABI DeviceRecord with virtio modern register metadata and updates size assert. |
| userland/compositor/src/setup/prime.rs | Adds GOP fallback compositor mode using display dimensions + mmap-backed buffer. |
| userland/compositor/src/frame_pacer/tick.rs | Presents via nonos_surface_present_full when using GOP fallback context. |
| userland/capsule_net_sockets/src/server/handlers/setsockopt.rs | Refactors early returns to explicit respond(...); return;. |
| userland/capsule_net_sockets/src/server/handlers/getsockopt.rs | Refactors early returns and match block termination. |
| userland/capsule_net_nym/src/server/handlers/surb.rs | Refactors error handling to explicit respond(...); return; and expands credential error mapping. |
| userland/capsule_net_nym/src/server/handlers/set_topology.rs | Refactors error handling to explicit respond + return. |
| userland/capsule_net_nym/src/server/handlers/set_timing.rs | Refactors error handling to explicit respond + return. |
| userland/capsule_net_nym/src/server/handlers/set_authority.rs | Refactors error handling to explicit respond + return. |
| userland/capsule_net_nym/src/server/handlers/send.rs | Refactors error handling to explicit respond + return. |
| userland/capsule_net_nym/src/server/handlers/send_reply.rs | Refactors error handling to explicit respond + return. |
| userland/capsule_net_nym/src/server/handlers/recv.rs | Refactors error handling to explicit respond + return. |
| userland/capsule_net_nym/src/server/handlers/open.rs | Refactors error handling to explicit respond + return. |
| userland/capsule_net_nym/src/server/handlers/gateway.rs | Refactors error handling to explicit respond + return. |
| userland/capsule_net_nym/src/server/handlers/cover.rs | Refactors error handling to explicit respond + return. |
| userland/capsule_net_nym/src/server/handlers/close.rs | Refactors error handling to explicit respond + return. |
| userland/capsule_net_dns/src/server/handlers/resolve_common.rs | Wraps mk_yield() in a block for consistency. |
| userland/capsule_driver_xhci/src/discover.rs | Updates empty_record() for expanded DeviceRecord. |
| userland/capsule_driver_virtio_rng/src/discover.rs | Updates empty_record() for expanded DeviceRecord. |
| userland/capsule_driver_virtio_net/src/discover.rs | Updates empty_record() for expanded DeviceRecord. |
| userland/capsule_driver_virtio_gpu/src/setup/sequence.rs | Adjusts register accessor call to use Found (modern virtio support). |
| userland/capsule_driver_virtio_gpu/src/setup/mmio.rs | Changes regs setup to use virtio cap-derived common/notify offsets. |
| userland/capsule_driver_virtio_gpu/src/discover.rs | Adds virtio-cap-aware discovery path for modern virtio register window. |
| userland/capsule_driver_virtio_gpu/Capsule.mk | Updates required capability mask/comment for virtio-gpu capsule. |
| userland/capsule_driver_virtio_blk/src/discover.rs | Updates empty_record() for expanded DeviceRecord. |
| userland/capsule_driver_rtl8169/src/discover.rs | Updates empty_record() for expanded DeviceRecord. |
| userland/capsule_driver_rtl8139/src/discover.rs | Updates empty_record() for expanded DeviceRecord. |
| userland/capsule_driver_ps2_input/src/discover.rs | Updates empty_record() for expanded DeviceRecord. |
| userland/capsule_driver_nvme/src/discover.rs | Updates empty_record() for expanded DeviceRecord. |
| userland/capsule_driver_iwlwifi/src/discover.rs | Updates empty_record() for expanded DeviceRecord. |
| userland/capsule_driver_i2c_pci/src/discover.rs | Updates empty_record() for expanded DeviceRecord. |
| userland/capsule_driver_hda/src/discover.rs | Updates empty_record() for expanded DeviceRecord. |
| userland/capsule_driver_e1000/src/discover.rs | Updates empty_record() for expanded DeviceRecord. |
| userland/capsule_driver_ahci/src/discover.rs | Updates empty_record() for expanded DeviceRecord. |
| userland/capsule_crypto/src/server/handlers/hkdf_sha256.rs | Fixes hmac_sha256 call to avoid taking &prk of an already-referenced array. |
| userland/capsule_crypto/Cargo.lock | Adds x25519-dalek (+ deps) to lockfile. |
| src/userspace/init/entry.rs | Adds cpu_switch selftest hook + lean desktop spawn gating. |
| src/usercopy/mod.rs | Adds helper to translate user VA to phys via capsule page tables. |
| src/syscall/dispatch/router/surface_handlers.rs | Uses capsule-address-space translation for surface registration frames. |
| src/syscall/dispatch/router/graphics_present.rs | Adds cache flush after framebuffer blit (intended for directmap fallback). |
| src/sys/apic/api.rs | Adds broker IOAPIC init path based on MADT descriptors. |
| src/smp/percpu/operations.rs | Adds GS-base revalidation, and per-CPU saved user stack helpers. |
| src/smp/percpu/mod.rs | Re-exports new per-CPU helpers. |
| src/process/userspace/asm.rs | Removes verbose debug prints; keeps user-entry proof under feature. |
| src/process/scheduler/preemption/yield_body.rs | Saves per-process user RSP snapshot and updates state transitions. |
| src/process/scheduler/preemption/switch.rs | Saves per-process user RSP snapshot and simplifies resume state handling. |
| src/process/mod.rs | Updates reexports after removing global saved FPU map. |
| src/process/core/table/create.rs | Adds PCB fields for saved user stack, kernel_rsp, and per-PCB FPU storage. |
| src/process/core/suspend.rs | Moves x86_64 FPU save/restore from global map into PCB. |
| src/process/core/pcb.rs | Extends PCB with saved user stack, kernel_rsp, and x86_64 FPU slot. |
| src/process/context/full/save.rs | Removes per-CPU “just restored” bookkeeping from Context save path. |
| src/process/context/full/restore.rs | Removes restored-flag set in Context restore path. |
| src/memory/phys/types/allocator_state.rs | Adds contig_split() to reserve frames for contiguous allocations. |
| src/memory/phys/allocator/alloc.rs | Uses contig_split() to limit regular frame allocation range. |
| src/memory/paging/manager/faults/handler.rs | Rejects user-mode faults on kernel-half addresses early. |
| src/memory/heap/types/quarantine.rs | Adds debug-only free quarantine ring + poison checking. |
| src/memory/heap/types/mod.rs | Wires quarantine module behind nonos-heap-debug. |
| src/memory/heap/types/dealloc_impl.rs | Adds debug-only corruption logging and quarantine path for frees. |
| src/memory/heap/manager/init.rs | Prevents re-init based on bootstrap usage flag. |
| src/kernel_core/surface_registry/share.rs | Maps attached surfaces with USER permission. |
| src/kernel_core/process_spawn/user_stack.rs | Zeroes user stack frames and adds debug watch plumbing behind feature. |
| src/kernel_core/process_spawn/pending_stack_free.rs | Prevents freeing the currently-in-use kernel stack in deferred drain. |
| src/kernel_core/init/framebuffer.rs | Adds directmap fallback for framebuffer mapping + draws a boot desktop. |
| src/kernel_core/init/entry.rs | Calls draw_desktop() during arch framebuffer init. |
| src/ipc/nonos_inbox/registry.rs | Adds interrupt disable guard around inbox registry mutations. |
| src/interrupts/safety/context.rs | Makes interrupt-context cpu_id GS-independent via crate::smp::cpu_id(). |
| src/interrupts/isr/timer_trampoline.rs | Ensures GS base is valid on timer trap entry. |
| src/interrupts/handlers/exceptions/page_fault.rs | Adds debug-only user RSP vicinity dump for a specific investigation. |
| src/hardware/virtio_gpu_capsule/spawn.rs | Adds Debug capability for virtio-gpu capsule spawn. |
| src/hardware/broker/table.rs | Populates virtio cap-derived fields in broker DeviceRecord. |
| src/hardware/broker/platform.rs | Uses struct update syntax to fill new DeviceRecord fields. |
| src/hardware/broker/device.rs | Extends broker DeviceRecord with virtio modern register metadata and size assert. |
| src/drivers/pci/types/virtio.rs | Introduces VirtioPciCfg type for parsed modern virtio PCI caps. |
| src/drivers/pci/types/mod.rs | Exposes new virtio PCI cfg type. |
| src/drivers/pci/types/device.rs | Adds optional virtio cap info to PciDevice. |
| src/drivers/pci/manager/probe.rs | Collects virtio vendor capability info during PCI probe. |
| src/drivers/pci/capabilities/mod.rs | Re-exports virtio cap helper. |
| src/drivers/pci/capabilities/helpers.rs | Parses virtio vendor capabilities into VirtioPciCfg. |
| src/crypto/hash/sha512/hasher.rs | Removes debug serial prints from Sha512 constructor. |
| src/boot/handoff/types/tests.rs | Adds golden offset/size ABI pin tests for BootHandoffV1. |
| src/boot/handoff/types/handoff.rs | Adds const-eval ABI pin asserts for BootHandoffV1. |
| src/arch/x86_64/interrupt/ioapic/mmio.rs | Switches IOAPIC MMIO mapping to directmap translation with bounds checking. |
| src/arch/x86_64/diag/mod.rs | Exposes user-stack dump helper behind debug feature. |
| src/arch/x86_64/diag/dump_trap.rs | Adds debug-only dump of user memory around RSP. |
| src/arch/x86_64/context/switch/trampolines.rs | Adds first-entry trampoline for cpu_switch-based scheduling. |
| src/arch/x86_64/context/switch/resume_env.rs | Refactors resume environment staging (TSS/CR3/FPU/user RSP restore). |
| src/arch/x86_64/context/switch/mod.rs | Replaces old switch modules with cpu_switch/resume_env/trampolines. |
| src/arch/x86_64/context/switch/kernel_thread.rs | Removes old kernel-thread resume path. |
| src/arch/x86_64/context/switch/first_entry.rs | Removes old first-entry path. |
| src/arch/x86_64/context/switch/dispatch.rs | Switches scheduler dispatch to cpu_switch-based kernel stack swap. |
| src/arch/x86_64/context/switch/cpu_switch.rs | Adds ret-based cpu_switch + initial switch-frame builder. |
| src/arch/x86_64/context/switch/cpu_switch_selftest.rs | Adds boot-time cpu_switch selftest behind feature. |
| src/arch/x86_64/context/setup.rs | Seeds initial kernel_rsp switch frame for first-entry trampoline. |
| src/arch/x86_64/context/mod.rs | Re-exports switch helpers (and selftest) at arch context layer. |
| rustc-ice-2026-05-15T10_55_04-43970.txt | Adds recorded rustc ICE log artifact. |
| nonos-bootloader/src/handoff/types/handoff.rs | Adds const-eval ABI pin asserts for bootloader BootHandoffV1. |
| Makefile | Enables QEMU GPU by default for serial run; removes disable-modern=on. |
| eK_notes/graphics_audit_prompt.md | Adds a graphics capsule maturity audit prompt doc. |
| docs/superpowers/specs/2026-05-22-kstack-writer-trap-design.md | Adds design spec for kernel-side watchpoint trap. |
| docs/superpowers/specs/2026-05-20-trust-verifier-nondeterminism-design.md | Adds design spec for diagnosing trust verifier nondeterminism. |
| docs/superpowers/plans/wp-phys-compare.py | Adds LLDB/QEMU monitor helper script for VA→PA comparisons. |
| docs/superpowers/plans/wp-directmap-catch.py | Adds LLDB/QEMU monitor helper script to arm directmap watchpoints. |
| docs/superpowers/plans/NOTE-FOR-EK-gui-blocker.md | Adds note summarizing GUI blocker status and plan. |
| docs/superpowers/plans/2026-05-24-virtio-pci-cap-discovery.md | Adds implementation plan for virtio PCI cap discovery. |
| docs/superpowers/plans/2026-05-23-ROOT-CAUSE-pcpu-user-stack-clobber.md | Adds root-cause writeup for per-CPU user stack clobber across preemption. |
| docs/superpowers/plans/2026-05-23-ctx-switch-rewrite-implementation-plan.md | Adds detailed implementation plan for context switch rewrite. |
| docs/superpowers/plans/2026-05-22-ROOT-CAUSE-frame-collision.md | Adds (superseded) root-cause note on frame collision theory. |
| docs/superpowers/plans/2026-05-22-ctx-switch-rewrite-PROMPT.md | Adds investigation prompt for context-switch rewrite. |
| docs/superpowers/plans/2026-05-22-CONTEXT-gui-blocker.md | Adds comprehensive context doc for GUI blocker investigation. |
| docs/superpowers/plans/2026-05-21-userland-crash-blocker.md | Adds crash blocker tracking doc for userland. |
| docs/superpowers/plans/2026-05-21-gui-rca-progress.md | Adds GUI bring-up RCA progress doc. |
| docs/plans/user_surface_pan(rusty).md | Adds Plan A user-surface roadmap doc. |
| docs/bootloader-investigation-prompt.md | Adds bootloader hardening investigation prompt doc. |
| docs/audits/bootloader-hardening/04-boot-ui-direction.md | Adds boot UI direction document for hardening audit. |
| Cargo.toml | Adds new debug/dev feature flags and “lean desktop” feature. |
| .gitignore | Ignores .superpowers/ scratch artifacts. |
Comment on lines
105
to
107
| let mut reg = REGISTRY.write(); | ||
| let _irq = crate::interrupts::disable_interrupts_guard(); | ||
| if reg.map.contains_key(module) { |
Comment on lines
+99
to
102
| // The GOP framebuffer is reached through the write-back directmap when | ||
| // map_framebuffer is unavailable; flush so the stores hit the scanout. | ||
| unsafe { core::arch::asm!("wbinvd", options(nostack, preserves_flags)) }; | ||
| SyscallResult::success_audited(0) |
Comment on lines
123
to
128
| ArchSpecificHandoff::X86_64 { v1 } => { | ||
| #[cfg(target_arch = "x86_64")] | ||
| init_memory(v1); | ||
| init_framebuffer(v1); | ||
| super::framebuffer::draw_desktop(); | ||
| } |
Comment on lines
+94
to
+99
| let base_va = match crate::memory::mmio::map_framebuffer(PhysAddr::new(base), map_len) { | ||
| Ok(v) => v, | ||
| Err(_) => { | ||
| crate::sys::serial::println(b"[FBINIT] map_framebuffer failed; using directmap"); | ||
| VirtAddr::new(crate::memory::layout::DIRECTMAP_BASE + base) | ||
| } |
Comment on lines
+62
to
+69
| fill_rect(fb, 0, 0, fb.width, fb.height, 0xFF1A2738); | ||
| fill_rect(fb, 0, 0, fb.width, 28, 0xFF0C141E); | ||
| fill_rect(fb, 0, fb.height.saturating_sub(56), fb.width, 56, 0xFF0C141E); | ||
| let dock_x = fb.width / 2; | ||
| fill_rect(fb, dock_x.saturating_sub(120), fb.height.saturating_sub(48), 240, 40, 0xFF1E66A8); | ||
| // Push write-back directmap stores out to the scanout device. | ||
| unsafe { core::arch::asm!("wbinvd", options(nostack, preserves_flags)) }; | ||
| crate::sys::serial::println(b"[DESKTOP] drawn"); |
Comment on lines
+14
to
+15
| # IPC|Memory|Debug|Driver|DeviceEnum|Mmio|Irq|Dma|Pio = 0x1F8118 | ||
| CAPSULE_REQUIRED_CAPS := 0x1FB118 |
Comment on lines
+17
to
+21
| //! Standard `ret`-based kernel context switch. Saves callee-saved regs + the | ||
| //! return address on the outgoing kernel stack, stores rsp in `*prev_rsp_slot`, | ||
| //! loads `next_rsp`, pops, and `ret`s into the next task's resume point. This | ||
| //! replaces the setjmp/longjmp + `INTERRUPT_SAVED_CONTEXTS` mechanism. Not yet | ||
| //! routed (phase 2): exercised only by the self-test until the phase-4 cutover. |
Comment on lines
+49
to
+54
| match prev { | ||
| Some(p) => unsafe { cpu_switch(p.kernel_rsp.as_ptr(), next_rsp) }, | ||
| None => { | ||
| let mut discard = 0u64; | ||
| unsafe { cpu_switch(&mut discard as *mut u64, next_rsp) } | ||
| } |
Comment on lines
+49
to
+62
| if r.virtio_present != 0 { | ||
| let cb = r.virtio_common_bar as usize; | ||
| let size = if cb < r.bars.len() { r.bars[cb].size } else { 0 }; | ||
| return Some(Found { | ||
| device_id: r.device_id, | ||
| irq_line: r.irq_line, | ||
| register_bar: r.virtio_common_bar, | ||
| register_kind: BAR_KIND_MMIO, | ||
| register_size: size, | ||
| pci_device: r.device, | ||
| has_virtio: true, | ||
| common_off: r.virtio_common_off, | ||
| notify_rel: r.virtio_notify_off.saturating_sub(r.virtio_common_off), | ||
| }); |
Comment on lines
+35
to
41
| pub fn regs(self, dev: Found) -> Regs { | ||
| match self { | ||
| Self::Mmio(g) if pci_device == VIRTIO_GPU_MODERN => { | ||
| Regs::mmio_with_notify(g.user_va, MOD_NOTIFY_BASE) | ||
| } | ||
| Self::Mmio(g) if dev.has_virtio => Regs::mmio_with_notify( | ||
| g.user_va + dev.common_off as u64, | ||
| dev.notify_rel as usize, | ||
| ), | ||
| Self::Mmio(g) => Regs::mmio(g.user_va), |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request introduces several new debug-only features to the project, primarily by adding new feature flags in
Cargo.toml. Additionally, it makes minor improvements to the QEMU configuration in theMakefileto enhance the emulation environment. The changes are mostly focused on aiding kernel and heap debugging, as well as improving the development workflow for the desktop environment.Debug and development features:
Cargo.toml:nonos-trap-kstack-writer: Traps kernel writers that overwrite kernel memory in user-stack return slots, with additional diagnostics.nonos-heap-debug: Logs heap canary/header mismatches at free to surface heap corruption.nonos-cpuswitch-selftest: Runs a kernel context-switch self-test at boot.nonos-desktop-lean: Spawns only the GUI core for a lean desktop environment, skipping network, apps, and market.QEMU emulation improvements:
QEMU_GPU) by default in the QEMU invocation fornonos-mk-run-serialand removed thedisable-modern=onoption, improving graphical emulation. [1] [2]