diff --git a/kernel/src/swap.rs b/kernel/src/swap.rs index 05f22d874..8cd4993a4 100644 --- a/kernel/src/swap.rs +++ b/kernel/src/swap.rs @@ -1,4 +1,4 @@ -use xous_kernel::SID; +use xous_kernel::{PID, SID}; #[cfg(baremetal)] #[no_mangle] @@ -44,21 +44,44 @@ impl Swap { SWAP.with(|ss| f(&mut ss.borrow_mut())) } - pub fn init_from_args(&mut self, args: &crate::args::KernelArguments) -> Result<(), xous_kernel::Error> { + pub fn init_from_args( + &mut self, + args: &crate::args::KernelArguments, + ) -> Result { for tag in args.iter() { if tag.name == u32::from_le_bytes(*b"Swap") { self.spt_ptr = tag.data[0] as usize; self.smt_base = tag.data[1] as usize; self.smt_bounds = tag.data[2] as usize; self.rpt_ptr = tag.data[3] as usize; - return Ok(()); + return Ok(xous_kernel::Result::Ok); } } Err(xous_kernel::Error::UseBeforeInit) } - pub fn register_handler(&mut self, s0: u32, s1: u32, s2: u32, s3: u32) { - assert!(self.sid == SID::from_u32(0, 0, 0, 0), "Swap handler already registered, fatal error!"); - self.sid = SID::from_u32(s0, s1, s2, s3); + pub fn register_handler( + &mut self, + s0: u32, + s1: u32, + s2: u32, + s3: u32, + ) -> Result { + if self.sid == SID::from_u32(0, 0, 0, 0) { + self.sid = SID::from_u32(s0, s1, s2, s3); + Ok(xous_kernel::Result::Ok) + } else { + // someone is trying to steal the swapper's privileges! + Err(xous_kernel::Error::AccessDenied) + } + } + + pub fn evict_page( + &mut self, + target_pid: PID, + vaddr: usize, + paddr: usize, + ) -> Result { + todo!() } } diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index c5a1a8fbe..136200430 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -1012,6 +1012,19 @@ pub fn handle_inner(pid: PID, tid: TID, in_irq: bool, call: SysCall) -> SysCallR SysCall::RegisterSwapper(s0, s1, s2, s3) => { Swap::with_mut(|swap| swap.register_handler(s0, s1, s2, s3)) } + #[cfg(feature = "swap")] + SysCall::EvictPage(target_pid, vaddr) => { + if pid.get() != 2 { + klog!("Illegal caller"); // only PID 2 can call this + return Err(xous_kernel::Error::AccessDenied); + } + let phys_addr = crate::arch::mem::virt_to_phys_pid(target_pid, vaddr as usize); + match phys_addr { + Ok(pa) => Swap::with_mut(|swap| swap.evict_page(target_pid, vaddr, pa)), + Err(_) => Err(xous_kernel::Error::BadAddress), + } + } + /* https://github.com/betrusted-io/xous-core/issues/90 SysCall::SetExceptionHandler(pc, sp) => SystemServices::with_mut(|ss| { ss.set_exception_handler(pid, pc, sp)