mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
feat: refactor cap
This commit is contained in:
parent
c371fd543f
commit
5c1e73a4ee
28
api/src/failure.rs
Normal file
28
api/src/failure.rs
Normal file
@ -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,
|
||||
},
|
||||
}
|
@ -4,3 +4,4 @@
|
||||
extern crate num_derive;
|
||||
|
||||
pub mod cap;
|
||||
pub mod failure;
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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<RawCap>,
|
||||
pub struct Cap<'a, T: KernelObject + ?Sized> {
|
||||
cap: &'a Cell<RawCap>, // use Cell to avoid lifetime issues
|
||||
cap_type: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'a, T: KernelObject + ?Sized> TryFrom<&'a Cell<RawCap>> for Cap<'a, T> {
|
||||
type Error = CapFault;
|
||||
|
||||
fn try_from(new: &'a Cell<RawCap>) -> Result<Self, Self::Error> {
|
||||
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?
|
||||
|
@ -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<T: KernelObject>(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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user