diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index a8196c6..4e1a367 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -4,17 +4,10 @@ use uapi::{error::*, syscall::*}; pub fn handle_syscall(tcb: &mut TcbObject) -> SysResult { let info = MessageInfo::try_from(tcb.trapframe.get_reg(0))?; - let cspace = CNodeCap::try_from(tcb.cspace())?; - - let cap_ptr = tcb.trapframe.get_reg(1); - let cap = cspace - .resolve_address_bits(cap_ptr, usize::BITS as usize) - .map_err(SysError::from)?; - - trace!("handle_syscall: info={:?} cap={:?}", info, cap); + // Invalid, Debug*, Yield will bypass the capability check match info.label() { - Syscall::Invalid => Ok(()), + Syscall::Invalid => return Ok(()), Syscall::DebugPutChar => { if info.length() != 3 { return Err(SysError::InvalidArgument); @@ -22,13 +15,23 @@ pub fn handle_syscall(tcb: &mut TcbObject) -> SysResult { let c = tcb.trapframe.get_reg(2) as u8 as char; crate::print!("{}", c); - - Ok(()) + return Ok(()); }, Syscall::Yield => { tcb.clear_timetick(); - Ok(()) + return Ok(()); }, + _ => (), + }; + + let cspace = CNodeCap::try_from(tcb.cspace())?; + let cap_ptr = tcb.trapframe.get_reg(1); + let cap = cspace.resolve_address_bits(cap_ptr, info.bits()).map_err(SysError::from)?; + + trace!("handle_syscall: info={:?} cap={:?}", info, cap); + + match info.label() { + Syscall::Send => Ok(()), _ => unimplemented!("handle_syscall: {:?}, {:?}", info.label(), cap), } } diff --git a/root/root.S b/root/root.S index 9f61c8a..6e8e4eb 100644 --- a/root/root.S +++ b/root/root.S @@ -11,15 +11,15 @@ _start: .loop: lb a2, 0(t0) beqz a2, .yield - # msg: label = DebugPutChar(1), length = 3 - # ptr: self-referential to cspace, just to create a valid cptr - syscall (1<<12 | 3), 0x0202020202020202 + # msg: label = DebugPutChar(1), bits = 1, length = 3 + # ptr: (any) + syscall (1<<13 | 0<<7 | 3), 0 addi t0, t0, 1 j .loop .yield: - # msg: label = Yield(2), length = 2 - # ptr: self-referential to cspace, just to create a valid cptr - syscall (2<<12 | 2), 0x0202020202020202 + # msg: label = Yield(2), bits = 1, length = 2 + # ptr: (any) + syscall (2<<13 | 0<<7 | 2), 0 j _start .data diff --git a/uapi/src/syscall.rs b/uapi/src/syscall.rs index 3d267f5..b1a8bee 100644 --- a/uapi/src/syscall.rs +++ b/uapi/src/syscall.rs @@ -1,9 +1,7 @@ -use core::fmt::Debug; - -use num_traits::{FromPrimitive, ToPrimitive}; -use utils::MASK; - use crate::error::SysError; +use core::fmt::Debug; +use num_traits::{FromPrimitive, ToPrimitive}; +use utils::{then::Then, MASK}; #[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)] pub enum Syscall { @@ -17,40 +15,62 @@ pub enum Syscall { Reply = 7, } -/* in vanilla seL4, MessageInfo layout: - * > | label | caps | extra_caps | length | - * > | [63:12] | [11:9] | [8:7] | [6:0] | - * - * in out implementation, MessageInfo layout: - * > label: Syscall - * > length: args.len() - * - * Syscall convention: +/* Syscall convention: * > Call: * > > [a0]: MessageInfo * > > [a1]: Capability Pointer * > > [a2..a7]: extra arguments * > > length = (a0..a?).len() + * > * > Reply: * > TODO: figure out how vanilla seL4 handle reply */ +/* MessageInfo layout: + * > | label | bits | length | + * > | [63:13] | [12:7] | [6:0] | + * > label: Syscall + * > bits: cap_ptr n_bits + * > length: args.len() + * + */ #[derive(Clone, Copy)] pub struct MessageInfo(usize); impl MessageInfo { - const LABEL_MASK: usize = MASK!(63 - 12 + 1); + const LABEL_MASK: usize = MASK!(63 - 13 + 1); + const LABEL_OFFSET: usize = 13; - pub fn new(label: Syscall, length: usize) -> Self { - Self((label.to_usize().unwrap_or(0)) << 12 | (length & 0x7f)) + const BITS_MASK: usize = MASK!(6); + const BITS_OFFSET: usize = 7; + + const LENGTH_MASK: usize = MASK!(7); + const LENGTH_OFFSET: usize = 0; + + pub fn new(label: Syscall, bits: usize, length: usize) -> Self { + let label = label.to_usize().unwrap_or(0); + let bits = bits - 1; // stored as n_bits - 1 + + assert!(label <= Self::LABEL_MASK); + assert!(bits <= Self::BITS_MASK); + assert!(length <= Self::LENGTH_MASK); + + let info = ((label & Self::LABEL_MASK) << Self::LABEL_OFFSET) + | ((bits & Self::BITS_MASK) << Self::BITS_OFFSET) + | ((length & Self::LENGTH_MASK) << Self::LENGTH_OFFSET); + Self(info) } pub fn label(&self) -> Syscall { - Syscall::from_usize((self.0 >> 12) & Self::LABEL_MASK).unwrap_or(Syscall::Invalid) + Syscall::from_usize((self.0 >> Self::LABEL_OFFSET) & Self::LABEL_MASK).unwrap_or(Syscall::Invalid) + } + + pub fn bits(&self) -> usize { + ((self.0 >> Self::BITS_OFFSET) & Self::BITS_MASK) + 1 } pub fn length(&self) -> usize { - self.0 & 0x7F + (self.0 >> Self::LENGTH_OFFSET) & Self::LENGTH_MASK } pub fn as_usize(&self) -> usize { @@ -62,6 +82,7 @@ impl Debug for MessageInfo { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("MessageInfo") .field("label", &self.label()) + .field("bits", &self.bits()) .field("length", &self.length()) .finish() } @@ -71,8 +92,7 @@ impl TryFrom for MessageInfo { type Error = SysError; fn try_from(value: usize) -> Result { - let syscall = Syscall::from_usize((value >> 12) & MessageInfo::LABEL_MASK).ok_or(SysError::InvalidArgument)?; - let length = value & 0x7F; - Ok(Self::new(syscall, length)) + let info = Self(value); + (info.label() != Syscall::Invalid).then_ok(info, SysError::InvalidArgument) } }