feat(kernel): SystemControl cap for halt, board device table + boot caps to init, RegionAddress syscall, idle loop services irqs

This commit is contained in:
2026-10-26 23:59:57 +01:00
parent 130a82f50d
commit bafc18a5f8
21 changed files with 626 additions and 53 deletions

View File

@@ -218,32 +218,66 @@ fn switch_to_next(frame: &mut TrapFrame, current_tid: types::id::ThreadId) {
save_frame_to_context(frame, ctx);
}
if let Some(next_tid) = kern.pick_next_thread() {
let next_pid = kern.thread_process(next_tid);
let current_pid = kern.thread_process(current_tid);
let next_tid = next_runnable();
let kern = unsafe { &mut *crate::kernel_ptr() };
let next_pid = kern.thread_process(next_tid);
let current_pid = kern.thread_process(current_tid);
let core = types::id::CoreId::from_raw(0);
let _ = kern.set_thread_running(next_tid, core);
let core = types::id::CoreId::from_raw(0);
let _ = kern.set_thread_running(next_tid, core);
if let Some(ctx) = kern.thread_context(next_tid) {
load_context_to_frame(ctx, frame);
if let Some(ctx) = kern.thread_context(next_tid) {
load_context_to_frame(ctx, frame);
}
apply_pending_result(frame, next_tid);
if next_pid != current_pid
&& let Some(pid) = next_pid
{
let pt_addr = kern.platform_mut().page_table_for(pid);
if pt_addr != 0 {
let pt = unsafe { &*(pt_addr as *const crate::mmu::PageTable) };
crate::mmu::activate(pt);
}
}
}
apply_pending_result(frame, next_tid);
/// The next thread to run, idling until an interrupt makes one ready.
///
/// We are inside a trap, so SIE is clear and interrupts are not taken.
/// `wfi` still wakes once one is pending, and it is then serviced here by
/// polling `sip`, which is how a driver blocked on its IRQ notification
/// gets woken when nothing else can run.
fn next_runnable() -> types::id::ThreadId {
loop {
let kern = unsafe { &mut *crate::kernel_ptr() };
if let Some(tid) = kern.pick_next_thread() {
return tid;
}
unsafe { core::arch::asm!("wfi") };
let sip: usize;
unsafe { core::arch::asm!("csrr {0}, sip", out(reg) sip) };
if sip & (1 << CAUSE_S_TIMER) != 0 {
// No thread is running, so there is no time slice to charge.
crate::hw::timer::handle_interrupt();
}
if sip & (1 << CAUSE_S_EXTERNAL) != 0 {
dispatch_external();
}
}
}
if next_pid != current_pid
&& let Some(pid) = next_pid
{
let pt_addr = kern.platform_mut().page_table_for(pid);
if pt_addr != 0 {
let pt = unsafe { &*(pt_addr as *const crate::mmu::PageTable) };
crate::mmu::activate(pt);
}
}
} else {
loop {
unsafe { core::arch::asm!("wfi") };
/// Claims every pending PLIC interrupt and hands each to the kernel.
fn dispatch_external() {
loop {
let irq_num = crate::hw::plic::Plic::claim();
if irq_num == 0 {
return;
}
let kern = unsafe { &mut *crate::kernel_ptr() };
kern.handle_interrupt(types::id::IrqId::from_raw(irq_num as u16));
crate::hw::plic::Plic::complete(irq_num);
}
}
@@ -272,15 +306,7 @@ fn handle_interrupt(frame: &mut TrapFrame, cause: usize) {
}
}
}
CAUSE_S_EXTERNAL => {
let irq_num = crate::hw::plic::Plic::claim();
if irq_num != 0 {
let kern = unsafe { &mut *crate::kernel_ptr() };
let irq = types::id::IrqId::from_raw(irq_num as u16);
kern.handle_interrupt(irq);
crate::hw::plic::Plic::complete(irq_num);
}
}
CAUSE_S_EXTERNAL => dispatch_external(),
_ => {}
}
}