fix(hal): read riscv64 time via rdtime, not CLINT MMIO - #145
Merged
Conversation
RiscvTimer::read_mtime read the CLINT mtime register directly at 0x0200_BFF8. That MMIO is M-mode only — OpenSBI configures PMP so an S-mode load faults, and with the early trap vector still a stub the fault storms and hangs the kernel right after 'PLIC initialized' (the timer one-shot never arms). Read the architectural 'time' CSR via rdtime instead (Zicntr; the S-mode-accessible mirror of mtime that firmware maintains). Verified: 'qemu-system-riscv64 -M virt -bios default' now boots all the way through — Kernel booting -> NS16550 -> Heap -> PLIC -> Timer armed (10 ms via SBI) -> All early initialization complete -> halt loop, no traps. First runtime boot of the riscv64 kernel (qemu-extra now installed locally). x86_64/aarch64 unaffected.
kernalix7
added a commit
that referenced
this pull request
Jul 15, 2026
Brings riscv64 to parity with aarch64: it now takes S-mode timer interrupts and preempts busy kernel threads. - boot.rs: replace the spin-stub trap vector with a real S-mode handler. It saves the caller-saved GPRs + sepc + sstatus into a 144-byte frame (sepc/sstatus stacked so a preemptive switch can't clobber them), calls riscv_handle_trap, restores, and srets. - irq.rs (new): riscv_handle_trap reads scause; on the S-mode timer interrupt (0x8000_0000_0000_0005) it re-arms the SBI one-shot (which also clears the pending STIP and keeps sie.STIE), charges a tick, and runs a guarded sched_yield_once. No GIC/EOI on riscv — the re-arm is the acknowledgement. - kthread.rs (new): mirrors the aarch64 pool; spawn_kthread seeds the 112-byte switch frame with entry at offset 0 (riscv switch_context does first, unlike aarch64's +8). - sched_glue.rs: real sched_yield_once (prepare_switch -> switch_context); read_cr3 reads satp. - main.rs: riscv cooperative + preemptive demos (busy C/D that never yield; the SBI timer alone rotates them). Threads set sstatus.SIE on entry (the interrupt-mask-inheritance lesson from aarch64). - timer.rs: drop the now-unused CLINT_MTIME const (read_mtime moved to rdtime in #145). Verified: 'qemu-system-riscv64 -M virt -bios default' runs the cooperative demo, then C and D interleave under the timer and print 'timer preemption verified', with no S-mode faults (remaining traps are OpenSBI HPM probing). x86_64/aarch64 unaffected.
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.
RiscvTimer::read_mtimeread the CLINT mtime register directly (0x0200_BFF8). That MMIO is M-mode only — OpenSBI's PMP faults an S-mode load, and with the early trap vector still a stub the fault storms and hangs the kernel right afterPLIC initialized(the timer one-shot never arms).Fix: read the architectural
timeCSR viardtime(Zicntr — the S-mode-accessible mirror of mtime the firmware maintains).Verified (
qemu-system-riscv64 -M virt -bios default, first local riscv runtime with qemu-extra installed):No traps. x86_64/aarch64 unaffected.