feat(adapter-riscv): replace static mut with KernelCell, complete all 17 syscall decoders, wire timer and PLIC interrupts to kernel

This commit is contained in:
2026-10-18 02:29:46 +02:00
parent ededdb2ed9
commit 5a45c14cf5
4 changed files with 156 additions and 80 deletions

View File

@@ -3,19 +3,19 @@
mod board;
mod hw;
mod kernel_cell;
mod mmu;
mod platform;
mod trap;
use core::arch::global_asm;
use hw::uart::Uart;
use kernel_cell::KernelCell;
use core::ptr::addr_of_mut;
static KERNEL: KernelCell<kernel::Kernel<platform::RiscVPlatform>> = KernelCell::uninit();
static mut KERNEL: Option<kernel::Kernel<platform::RiscVPlatform>> = None;
pub fn kernel_mut() -> &'static mut kernel::Kernel<platform::RiscVPlatform> {
unsafe { (*addr_of_mut!(KERNEL)).as_mut() }.unwrap_or_else(|| unreachable!())
pub fn kernel_ref() -> &'static mut kernel::Kernel<platform::RiscVPlatform> {
KERNEL.get_mut()
}
global_asm!(
@@ -69,16 +69,15 @@ extern "C" fn kmain() -> ! {
types::address::PhysicalAddress::from_raw(board::USER_POOL_BASE),
board::USER_POOL_PAGES,
);
let kern = kernel::Kernel::new(riscv_platform, pool);
unsafe { *addr_of_mut!(KERNEL) = Some(kern); }
let kern = kernel_mut();
KERNEL.init(kernel::Kernel::new(riscv_platform, pool));
let kern = kernel_ref();
let (_pid, _tid) = kern
.boot(types::bounded::Priority::DEFAULT, types::time::TimeSlice::DEFAULT)
.unwrap_or_else(|_| loop { unsafe { core::arch::asm!("wfi") }; });
uart.write_str("k-os: kernel started\n");
userspace_demo(kern, &uart, kernel_pt);
userspace_demo(&uart, kernel_pt);
uart.write_str("k-os: demo complete\n");
loop {
@@ -86,28 +85,17 @@ extern "C" fn kmain() -> ! {
}
}
// Tiny userspace program: li a7, SYS_EXIT; ecall; j -4
// SYS_EXIT = 16 = 0x10
// RISC-V instructions (little-endian):
// li a7, 16 → addi a7, zero, 16 → 0x01000893
// ecall → 0x00000073
// j -4 → 0xffdff06f
static USER_EXIT_PROGRAM: [u8; 12] = [
0x93, 0x08, 0x00, 0x01, // addi a7, zero, 16
0x93, 0x08, 0x00, 0x01, // addi a7, zero, 16 (SYS_EXIT)
0x73, 0x00, 0x00, 0x00, // ecall
0x6f, 0xf0, 0xdf, 0xff, // j -4
];
const USER_VA: usize = 0x10000;
fn userspace_demo(
_kern: &mut kernel::Kernel<platform::RiscVPlatform>,
uart: &Uart,
kernel_pt: &mmu::PageTable,
) {
fn userspace_demo(uart: &Uart, kernel_pt: &mmu::PageTable) {
uart.write_str("k-os: --- userspace demo ---\n");
// Allocate a page for the user program and copy code into it
let program_page = mmu::allocator::alloc_zeroed_page();
unsafe {
core::ptr::copy_nonoverlapping(
@@ -117,32 +105,23 @@ fn userspace_demo(
);
}
// Create user page table with program mapped at USER_VA
let user_pt = mmu::create_user_page_table(
kernel_pt,
program_page,
1,
USER_VA,
);
let user_pt = mmu::create_user_page_table(kernel_pt, program_page, 1, USER_VA);
uart.write_str("k-os: user page table created, entering U-mode\n");
// Activate user page table
mmu::activate(user_pt);
// Set sscratch to kernel stack so trap vector can switch stacks
let kernel_sp: usize;
unsafe { core::arch::asm!("mv {0}, sp", out(reg) kernel_sp) };
trap::set_kernel_stack(kernel_sp);
// Enter user mode: set sstatus.SPP=0 (U-mode), sepc=USER_VA, sret
let user_stack = USER_VA - 8; // stack below program
let user_stack = USER_VA - 8;
unsafe {
core::arch::asm!(
"csrc sstatus, {spp}", // clear SPP → return to U-mode
"csrs sstatus, {spie}", // set SPIE → enable interrupts after sret
"csrw sepc, {entry}", // return address = user entry
"mv sp, {stack}", // user stack pointer (will be saved to sscratch on swap)
"csrc sstatus, {spp}",
"csrs sstatus, {spie}",
"csrw sepc, {entry}",
"mv sp, {stack}",
"sret",
spp = in(reg) 1usize << 8,
spie = in(reg) 1usize << 5,