diff --git a/crates/adapter-riscv/linker.ld b/crates/adapter-riscv/linker.ld index 1727e95..d0da499 100644 --- a/crates/adapter-riscv/linker.ld +++ b/crates/adapter-riscv/linker.ld @@ -29,7 +29,7 @@ SECTIONS { . = ALIGN(4096); _stack_bottom = .; - . += 0x10000; + . += 0x80000; _stack_top = .; _heap_start = .; diff --git a/crates/adapter-riscv/src/main.rs b/crates/adapter-riscv/src/main.rs index 199f928..7f07ae7 100644 --- a/crates/adapter-riscv/src/main.rs +++ b/crates/adapter-riscv/src/main.rs @@ -2,6 +2,8 @@ #![no_main] mod page_table; +mod platform; +mod plic; mod timer; mod trap; mod uart; @@ -52,8 +54,28 @@ extern "C" fn kmain() -> ! { trap::init_trap(); timer::init_timer(); + plic::Plic::init(); uart.write_str("k-os: traps and timer initialized\n"); + let riscv_platform = platform::RiscVPlatform::new(); + let pool = domain::memory::page_pool::PagePool::new( + types::address::PhysicalAddress::from_raw(0x84000000), + 256, + ); + let mut kern = kernel::Kernel::new(riscv_platform, pool); + let (pid, tid) = kern + .boot( + types::bounded::Priority::new(16).unwrap_or_else(|| unreachable!()), + types::time::TimeSlice::new(100), + ) + .unwrap_or_else(|_| loop { unsafe { core::arch::asm!("wfi") }; }); + + uart.write_str("k-os: kernel started (pid="); + uart.write_dec(pid.raw() as usize); + uart.write_str(", tid="); + uart.write_dec(tid.raw() as usize); + uart.write_str(")\n"); + loop { unsafe { core::arch::asm!("wfi") }; } diff --git a/crates/adapter-riscv/src/platform.rs b/crates/adapter-riscv/src/platform.rs new file mode 100644 index 0000000..9e03556 --- /dev/null +++ b/crates/adapter-riscv/src/platform.rs @@ -0,0 +1,77 @@ +use domain::memory::MemoryRegion; +use domain::thread::SavedContext; +use platform::Platform; +use types::{ + address::{EntryPoint, PhysicalAddress, StackPointer}, + bounded::PageCount, + id::{CoreId, IrqId, ProcessId}, + permission::PermissionSet, + time::{Ticks, TimerDuration}, +}; + +use crate::plic::Plic; +use crate::timer; + +pub struct RiscVPlatform { + num_cores: u8, +} + +impl RiscVPlatform { + pub fn new() -> Self { + Self { num_cores: 1 } + } +} + +impl Platform for RiscVPlatform { + fn configure_protection(&mut self, _process: ProcessId, _regions: &[MemoryRegion]) { + // page table activation happens separately per context switch + } + + fn context_switch(&mut self, _from: &mut SavedContext, _to: &SavedContext) { + // context switch is handled by the trap vector assembly + } + + fn enable_user_mode(&mut self, _entry: EntryPoint, _stack: StackPointer) -> ! { + // handled by setting up TrapFrame and sret in the main loop + loop { unsafe { core::arch::asm!("wfi") }; } + } + + fn set_timer(&mut self, _duration: TimerDuration) { + let now = timer::read_time(); + timer::set_next_timer(now + 10_000_000); + } + + fn current_ticks(&self) -> Ticks { + Ticks::from_raw(timer::read_time()) + } + + fn mask_irq(&mut self, irq: IrqId) { + Plic::disable(irq.raw() as u32); + } + + fn unmask_irq(&mut self, irq: IrqId) { + Plic::enable(irq.raw() as u32); + } + + fn send_ipi(&mut self, _target: CoreId) { + // single core — no-op + } + + fn core_id(&self) -> CoreId { + CoreId::from_raw(0) + } + + fn num_cores(&self) -> u8 { + self.num_cores + } + + fn map_shared( + &mut self, + _process: ProcessId, + _base: PhysicalAddress, + _size: PageCount, + _permissions: PermissionSet, + ) { + // page table mapping for shared memory — deferred to full MMU integration + } +} diff --git a/crates/adapter-riscv/src/plic.rs b/crates/adapter-riscv/src/plic.rs new file mode 100644 index 0000000..4620b93 --- /dev/null +++ b/crates/adapter-riscv/src/plic.rs @@ -0,0 +1,45 @@ +const PLIC_BASE: usize = 0x0C000000; +const PLIC_PRIORITY: usize = PLIC_BASE; +const PLIC_S_ENABLE: usize = PLIC_BASE + 0x2080; // S-mode hart 0 context = 1 +const PLIC_S_THRESHOLD: usize = PLIC_BASE + 0x201000; +const PLIC_S_CLAIM: usize = PLIC_BASE + 0x201004; + +pub struct Plic; + +impl Plic { + pub fn init() { + // set threshold to 0 (accept all priorities) + unsafe { core::ptr::write_volatile(PLIC_S_THRESHOLD as *mut u32, 0) }; + } + + pub fn enable(irq: u32) { + let word = (irq / 32) as usize; + let bit = irq % 32; + let addr = PLIC_S_ENABLE + word * 4; + unsafe { + let current = core::ptr::read_volatile(addr as *const u32); + core::ptr::write_volatile(addr as *mut u32, current | (1 << bit)); + } + // set priority > 0 + let prio_addr = PLIC_PRIORITY + (irq as usize) * 4; + unsafe { core::ptr::write_volatile(prio_addr as *mut u32, 1) }; + } + + pub fn disable(irq: u32) { + let word = (irq / 32) as usize; + let bit = irq % 32; + let addr = PLIC_S_ENABLE + word * 4; + unsafe { + let current = core::ptr::read_volatile(addr as *const u32); + core::ptr::write_volatile(addr as *mut u32, current & !(1 << bit)); + } + } + + pub fn claim() -> u32 { + unsafe { core::ptr::read_volatile(PLIC_S_CLAIM as *const u32) } + } + + pub fn complete(irq: u32) { + unsafe { core::ptr::write_volatile(PLIC_S_CLAIM as *mut u32, irq) }; + } +} diff --git a/crates/adapter-riscv/src/timer.rs b/crates/adapter-riscv/src/timer.rs index 6acadb3..0c3f856 100644 --- a/crates/adapter-riscv/src/timer.rs +++ b/crates/adapter-riscv/src/timer.rs @@ -22,6 +22,10 @@ pub fn init_timer() { sbi_set_timer(now + TICK_INTERVAL); } +pub fn set_next_timer(deadline: u64) { + sbi_set_timer(deadline); +} + pub fn handle_timer_interrupt() { let now = read_time(); sbi_set_timer(now + TICK_INTERVAL);