Skip to content

feat(kernel,hal): preemptive kernel-thread scheduling on riscv64 - #147

Merged
kernalix7 merged 1 commit into
mainfrom
feat/riscv64-preemptive-scheduling
Jul 15, 2026
Merged

feat(kernel,hal): preemptive kernel-thread scheduling on riscv64#147
kernalix7 merged 1 commit into
mainfrom
feat/riscv64-preemptive-scheduling

Conversation

@kernalix7

Copy link
Copy Markdown
Owner

Brings riscv64 to parity with aarch64 (#143+#144): S-mode timer interrupts + preemption of busy kernel threads.

  • boot.rs: real S-mode trap vector (was a spin stub) — saves caller-saved GPRs + sepc + sstatus (144-byte frame; sepc/sstatus stacked so a preemptive switch can't clobber them), calls riscv_handle_trap, restores, sret.
  • irq.rs (new): riscv_handle_trap reads scause; on S-mode timer (0x8000…0005) re-arms the SBI one-shot (clears pending STIP, keeps sie.STIE), charge_tick, guarded sched_yield_once. No GIC/EOI — the re-arm is the ack.
  • kthread.rs (new): pool + spawn_kthread seeding the 112-byte switch frame with entry at offset 0 (riscv switch_context does ld ra,0(sp) first, unlike aarch64's +8).
  • sched_glue.rs: real sched_yield_once; read_cr3 reads satp.
  • main.rs: riscv cooperative + preemptive demos (busy C/D never yield; the SBI timer rotates them). Threads set sstatus.SIE on entry (interrupt-mask-inheritance lesson).
  • timer.rs: drop unused CLINT_MTIME (read_mtime moved to rdtime in fix(hal): read riscv64 time via rdtime, not CLINT MMIO #145).

Verified (qemu-system-riscv64 -M virt -bios default):

cooperative: A ran / B ran / back on boot
timer IRQ received (preemptive) ×3
preemptive: thread C/D scheduled (interleaved — no yields)
preemptive: C and D both ran — timer preemption verified.

No S-mode faults (remaining traps are OpenSBI HPM probing). Rust side via an opus agent mirroring aarch64; trap-vector asm hand-written + QEMU-verified. x86_64/aarch64 unaffected.

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.
@kernalix7
kernalix7 merged commit cbfc57b into main Jul 15, 2026
2 checks passed
@kernalix7
kernalix7 deleted the feat/riscv64-preemptive-scheduling branch July 15, 2026 06:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant