diff --git a/api/src/failure.rs b/api/src/failure.rs new file mode 100644 index 0000000..8cbaa2a --- /dev/null +++ b/api/src/failure.rs @@ -0,0 +1,28 @@ +use crate::cap::ObjectType; + +pub enum Fault { + Ok, + CapFault(CapFault), +} + +pub enum CapFault { + // vallina + InvalidRoot, + MissingCapability { + bits_left: usize, + }, + DepthMismatch { + bits_found: usize, + bits_left: usize, + }, + GuardMismatch { + guard_found: usize, + bits_left: usize, + guard_size: usize, + }, + // additional + TypeMismatch { + expected: ObjectType, + found: ObjectType, + }, +} diff --git a/api/src/lib.rs b/api/src/lib.rs index 3709a49..68319d3 100644 --- a/api/src/lib.rs +++ b/api/src/lib.rs @@ -4,3 +4,4 @@ extern crate num_derive; pub mod cap; +pub mod failure; diff --git a/kernel/src/objects/cap.rs b/kernel/src/objects/cap.rs index 19518e4..365c106 100644 --- a/kernel/src/objects/cap.rs +++ b/kernel/src/objects/cap.rs @@ -1,23 +1,26 @@ use api::cap::ObjectType; +use vspace::addr::PhysAddr; /// RawCap is the specific implementation of capability which stores in CNode +#[derive(Clone, Copy)] pub struct RawCap { /// args: in vanilla seL4 implementation, a cap use two 64-bit words to store all information, /// but we'll waste some space rather than using bitfield to simplify the implementation - args: [usize; 2], + pub args: [usize; 2], + /// ptr: vanilla seL4 stores the pointer with either higher bits or lower bits cut off, + /// which limits the address space. Use an independent field to store the pointer. + /// Kernel will not manage memory, userspace should pass PhysAddr to kernel + pub ptr: PhysAddr, /// cap_type: every capability links to one specific object - cap_type: ObjectType, + pub cap_type: ObjectType, } impl RawCap { - pub fn new(arg0: usize, arg1: usize, cap_type: ObjectType) -> Self { + pub fn new(arg0: usize, arg1: usize, ptr: PhysAddr, cap_type: ObjectType) -> Self { Self { args: [arg0, arg1], + ptr, cap_type, } } - - pub fn cap_type(&self) -> ObjectType { - self.cap_type - } } diff --git a/kernel/src/objects/mod.rs b/kernel/src/objects/mod.rs index 5ad9cc1..1b85765 100644 --- a/kernel/src/objects/mod.rs +++ b/kernel/src/objects/mod.rs @@ -14,10 +14,9 @@ */ -use api::cap::ObjectType; +use api::{cap::ObjectType, failure::CapFault}; use cap::RawCap; -use core::cell::Cell; -use core::marker::PhantomData; +use core::{cell::Cell, marker::PhantomData}; pub mod cap; pub mod null; @@ -25,11 +24,29 @@ pub mod null; /// Cap is the high-level wrapper of RawCap, it's a typed reference to RawCap (which is untyped in Rust) /// For the typed objects, we should bound it with an empty traits `KernelObject` /// And for those objects, at least implement `mint` method and `decodeInvocation` (not enforcing in `KernelObject` for complexity) -pub struct Cap<'a, T: KernelObject> { - cap: &'a Cell, +pub struct Cap<'a, T: KernelObject + ?Sized> { + cap: &'a Cell, // use Cell to avoid lifetime issues cap_type: PhantomData, } +impl<'a, T: KernelObject + ?Sized> TryFrom<&'a Cell> for Cap<'a, T> { + type Error = CapFault; + + fn try_from(new: &'a Cell) -> Result { + if new.get().cap_type != T::OBJ_TYPE { + Err(CapFault::TypeMismatch { + expected: T::OBJ_TYPE, + found: new.get().cap_type, + }) + } else { + Ok(Self { + cap: new, + cap_type: PhantomData, + }) + } + } +} + /// KernelObject is the base trait for all kernel objects pub trait KernelObject { // this should be optimized by compiler? diff --git a/kernel/src/objects/null.rs b/kernel/src/objects/null.rs index 645b166..858428a 100644 --- a/kernel/src/objects/null.rs +++ b/kernel/src/objects/null.rs @@ -1,27 +1,17 @@ use super::cap::RawCap; use super::{Cap, KernelObject}; use api::cap::ObjectType; -use core::marker::PhantomData; +use vspace::addr::PhysAddr; /// NullObject is used as empty (capability) slot pub struct NullObject {} -pub type NullCap<'a> = Cap<'a, NullObject>; impl KernelObject for NullObject { const OBJ_TYPE: ObjectType = ObjectType::Null; } +pub type NullCap<'a> = Cap<'a, NullObject>; impl<'a> NullCap<'a> { pub fn mint() -> RawCap { - let cap = RawCap::new(0, 0, ObjectType::Null); - cap - } - - pub fn retype(self, new: RawCap) -> Cap<'a, T> { - assert!(T::OBJ_TYPE == new.cap_type()); - self.cap.set(new); - Cap { - cap: self.cap, - cap_type: PhantomData, - } + RawCap::new(0, 0, PhysAddr(0), ObjectType::Null) } }