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
7d34dfc2cd
commit
cadfafca12
@ -3,6 +3,7 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
// Features
|
// Features
|
||||||
#![feature(asm_const)]
|
#![feature(asm_const)]
|
||||||
|
#![feature(cell_update)]
|
||||||
#![feature(concat_idents)]
|
#![feature(concat_idents)]
|
||||||
#![feature(const_mut_refs)]
|
#![feature(const_mut_refs)]
|
||||||
#![feature(extern_types)]
|
#![feature(extern_types)]
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use api::cap::ObjectType;
|
use api::cap::ObjectType;
|
||||||
|
use core::{cell::Cell, ptr::NonNull};
|
||||||
use vspace::addr::PhysAddr;
|
use vspace::addr::PhysAddr;
|
||||||
|
|
||||||
/// RawCap is the specific implementation of capability which stores in CNode
|
/// RawCap is the specific implementation of capability which stores in CNode
|
||||||
#[derive(Clone, Copy, Default)]
|
#[derive(Copy, Clone, Default)]
|
||||||
pub struct RawCap {
|
pub struct RawCap {
|
||||||
// TODO: this could be an enum, figure out a way to do this
|
// TODO: this could be an enum, figure out a way to do this
|
||||||
/// args: in vanilla seL4 implementation, a cap use two 64-bit words to store all information,
|
/// args: in vanilla seL4 implementation, a cap use two 64-bit words to store all information,
|
||||||
@ -25,3 +26,47 @@ impl RawCap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default)]
|
||||||
|
pub struct Link {
|
||||||
|
pub prev: Option<NonNull<Cell<CapEntry>>>,
|
||||||
|
pub next: Option<NonNull<Cell<CapEntry>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Default)]
|
||||||
|
pub struct CapEntry {
|
||||||
|
pub cap: RawCap,
|
||||||
|
pub link: Link,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type CapTableEntry = Cell<CapEntry>;
|
||||||
|
|
||||||
|
impl CapEntry {
|
||||||
|
pub fn new(cap: RawCap) -> Self {
|
||||||
|
Self {
|
||||||
|
cap: cap,
|
||||||
|
link: Link::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(&mut self) {
|
||||||
|
self.cap = RawCap::default();
|
||||||
|
self.link = Link::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prev(&self) -> Option<NonNull<Cell<CapEntry>>> {
|
||||||
|
self.link.prev
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(&self) -> Option<NonNull<Cell<CapEntry>>> {
|
||||||
|
self.link.next
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_prev(&mut self, prev: Option<NonNull<Cell<CapEntry>>>) {
|
||||||
|
self.link.prev = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_next(&mut self, next: Option<NonNull<Cell<CapEntry>>>) {
|
||||||
|
self.link.next = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
|
|
||||||
use super::{cap::RawCap, Cap, KernelObject};
|
use super::{
|
||||||
|
cap::{CapTableEntry, RawCap},
|
||||||
|
Cap, KernelObject,
|
||||||
|
};
|
||||||
use crate::arch::layout::mmap_phys_to_virt;
|
use crate::arch::layout::mmap_phys_to_virt;
|
||||||
use api::{cap::ObjectType, error::CapFault};
|
use api::{cap::ObjectType, error::CapFault};
|
||||||
use utils::MASK;
|
use utils::MASK;
|
||||||
@ -8,7 +11,7 @@ use vspace::addr::{AddressOps, PhysAddr};
|
|||||||
|
|
||||||
/// CNodeObject is a array of Capabilities (`RawCap`)
|
/// CNodeObject is a array of Capabilities (`RawCap`)
|
||||||
/// The size of the array is stored in CNodeCap
|
/// The size of the array is stored in CNodeCap
|
||||||
pub type CNodeObject = [Cell<RawCap>];
|
pub type CNodeObject = [CapTableEntry];
|
||||||
|
|
||||||
impl KernelObject for CNodeObject {
|
impl KernelObject for CNodeObject {
|
||||||
const OBJ_TYPE: ObjectType = ObjectType::CNode;
|
const OBJ_TYPE: ObjectType = ObjectType::CNode;
|
||||||
@ -41,29 +44,29 @@ impl<'a> CNodeCap<'a> {
|
|||||||
let arg0 = ((radix & Self::RADIX_MASK) << Self::RADIX_OFFSET)
|
let arg0 = ((radix & Self::RADIX_MASK) << Self::RADIX_OFFSET)
|
||||||
| ((guard_size & Self::GUARD_SIZE_MASK) << Self::GUARD_SIZE_OFFSET);
|
| ((guard_size & Self::GUARD_SIZE_MASK) << Self::GUARD_SIZE_OFFSET);
|
||||||
let arg1 = guard;
|
let arg1 = guard;
|
||||||
|
let cap: RawCap = RawCap::new(arg0, arg1, ptr, ObjectType::CNode);
|
||||||
|
|
||||||
let cap = RawCap::new(arg0, arg1, ptr, ObjectType::CNode);
|
// init memory
|
||||||
CNodeCap::try_from(&Cell::new(cap))
|
let cte = super::cap::CapEntry::new(cap);
|
||||||
|
CNodeCap::try_from(&Cell::new(cte))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_object()
|
.as_object_mut()
|
||||||
.iter()
|
.iter_mut()
|
||||||
.for_each(|cell| {
|
.for_each(|cap| cap.get_mut().init());
|
||||||
cell.set(RawCap::default());
|
|
||||||
});
|
|
||||||
|
|
||||||
cap
|
cap
|
||||||
}
|
}
|
||||||
|
|
||||||
fn radix(&self) -> usize {
|
fn radix(&self) -> usize {
|
||||||
(self.cap.get().args[0] >> Self::RADIX_OFFSET) & Self::RADIX_MASK
|
(self.cte.get().cap.args[0] >> Self::RADIX_OFFSET) & Self::RADIX_MASK
|
||||||
}
|
}
|
||||||
|
|
||||||
fn guard_size(&self) -> usize {
|
fn guard_size(&self) -> usize {
|
||||||
(self.cap.get().args[0] >> Self::GUARD_SIZE_OFFSET) & Self::GUARD_SIZE_MASK
|
(self.cte.get().cap.args[0] >> Self::GUARD_SIZE_OFFSET) & Self::GUARD_SIZE_MASK
|
||||||
}
|
}
|
||||||
|
|
||||||
fn guard(&self) -> usize {
|
fn guard(&self) -> usize {
|
||||||
self.cap.get().args[1]
|
self.cte.get().cap.args[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CNodeObject length
|
/// CNodeObject length
|
||||||
@ -76,14 +79,21 @@ impl<'a> CNodeCap<'a> {
|
|||||||
|
|
||||||
fn as_object(&self) -> &CNodeObject {
|
fn as_object(&self) -> &CNodeObject {
|
||||||
unsafe {
|
unsafe {
|
||||||
let virt = mmap_phys_to_virt(self.cap.get().ptr);
|
let virt = mmap_phys_to_virt(self.cte.get().cap.ptr);
|
||||||
core::slice::from_raw_parts(virt.as_const_ptr(), self.length())
|
core::slice::from_raw_parts(virt.as_const_ptr(), self.length())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_address_bits(&self, cap_ptr: usize, n_bits: usize) -> Result<&Cell<RawCap>, CapFault> {
|
fn as_object_mut(&mut self) -> &mut CNodeObject {
|
||||||
|
unsafe {
|
||||||
|
let virt = mmap_phys_to_virt(self.cte.get().cap.ptr);
|
||||||
|
core::slice::from_raw_parts_mut(virt.as_mut_ptr(), self.length())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_address_bits(&self, cap_ptr: usize, n_bits: usize) -> Result<&CapTableEntry, CapFault> {
|
||||||
let mut bits_remaining = n_bits;
|
let mut bits_remaining = n_bits;
|
||||||
let mut slot = self.cap;
|
let mut slot = self.cte;
|
||||||
|
|
||||||
while let Ok(cnode) = CNodeCap::try_from(slot) {
|
while let Ok(cnode) = CNodeCap::try_from(slot) {
|
||||||
let radix_bits = cnode.radix();
|
let radix_bits = cnode.radix();
|
||||||
|
@ -18,8 +18,8 @@ use api::{
|
|||||||
cap::ObjectType,
|
cap::ObjectType,
|
||||||
error::{SysError, SysResult},
|
error::{SysError, SysResult},
|
||||||
};
|
};
|
||||||
use cap::RawCap;
|
use cap::CapTableEntry;
|
||||||
use core::{cell::Cell, marker::PhantomData};
|
use core::{marker::PhantomData, ptr::NonNull};
|
||||||
|
|
||||||
pub mod cap;
|
pub mod cap;
|
||||||
pub mod cnode;
|
pub mod cnode;
|
||||||
@ -30,25 +30,45 @@ pub mod untyped;
|
|||||||
/// For the typed objects, we should bound it with an empty traits `KernelObject`
|
/// 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)
|
/// And for those objects, at least implement `mint` method and `decodeInvocation` (not enforcing in `KernelObject` for complexity)
|
||||||
pub struct Cap<'a, T: KernelObject + ?Sized> {
|
pub struct Cap<'a, T: KernelObject + ?Sized> {
|
||||||
cap: &'a Cell<RawCap>, // use Cell to avoid lifetime issues
|
cte: &'a CapTableEntry,
|
||||||
cap_type: PhantomData<T>,
|
cap_type: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: KernelObject + ?Sized> TryFrom<&'a Cell<RawCap>> for Cap<'a, T> {
|
impl<'a, T: KernelObject + ?Sized> TryFrom<&'a CapTableEntry> for Cap<'a, T> {
|
||||||
type Error = SysError;
|
type Error = SysError;
|
||||||
|
|
||||||
fn try_from(new: &'a Cell<RawCap>) -> SysResult<Self> {
|
fn try_from(new: &'a CapTableEntry) -> SysResult<Self> {
|
||||||
if new.get().cap_type != T::OBJ_TYPE {
|
if new.get().cap.cap_type != T::OBJ_TYPE {
|
||||||
Err(SysError::CapTypeMismatch)
|
Err(SysError::CapTypeMismatch)
|
||||||
} else {
|
} else {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
cap: new,
|
cte: new,
|
||||||
cap_type: PhantomData,
|
cap_type: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, T: KernelObject + ?Sized> Cap<'a, T> {
|
||||||
|
pub fn append(&mut self, new: &mut CapTableEntry) {
|
||||||
|
let next = self.cte.get().next();
|
||||||
|
|
||||||
|
// update new cap's link
|
||||||
|
new.get_mut().set_prev(Some(NonNull::from(self.cte)));
|
||||||
|
new.get_mut().set_next(next);
|
||||||
|
|
||||||
|
// record new cap's addr
|
||||||
|
let new_addr = Some(NonNull::from(new));
|
||||||
|
|
||||||
|
// update next cap's link.prev
|
||||||
|
next.map(|mut next| unsafe { next.as_mut().get().set_prev(new_addr) });
|
||||||
|
|
||||||
|
// update self's link.next
|
||||||
|
let mut raw = self.cte.get();
|
||||||
|
raw.set_next(new_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// KernelObject is the base trait for all kernel objects
|
/// KernelObject is the base trait for all kernel objects
|
||||||
pub trait KernelObject {
|
pub trait KernelObject {
|
||||||
// this should be optimized by compiler?
|
// this should be optimized by compiler?
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use super::cap::RawCap;
|
use super::cap::{CapEntry, RawCap};
|
||||||
use super::cnode::{CNodeCap, CNodeObject};
|
use super::cnode::{CNodeCap, CNodeObject};
|
||||||
use super::null::NullCap;
|
use super::null::NullCap;
|
||||||
use super::{Cap, KernelObject};
|
use super::{Cap, KernelObject};
|
||||||
@ -43,26 +43,29 @@ impl UntypedCap<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn free_offset(&self) -> usize {
|
fn free_offset(&self) -> usize {
|
||||||
self.cap.get().args[0]
|
self.cte.get().cap.args[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_free_offset(&self, free_offset: usize) {
|
fn set_free_offset(&mut self, free_offset: usize) {
|
||||||
self.cap.get().args[0] = free_offset;
|
self.cte.update(|mut c| {
|
||||||
|
c.cap.args[0] = free_offset;
|
||||||
|
c
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_device(&self) -> bool {
|
fn is_device(&self) -> bool {
|
||||||
(self.cap.get().args[1] >> 6) & 1 == 1
|
(self.cte.get().cap.args[1] >> 6) & 1 == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_bits(&self) -> usize {
|
fn block_bits(&self) -> usize {
|
||||||
self.cap.get().args[1] & MASK!(6)
|
self.cte.get().cap.args[1] & MASK!(6)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_size(&self) -> usize {
|
fn block_size(&self) -> usize {
|
||||||
1 << self.block_bits()
|
1 << self.block_bits()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn retype(&self, obj_type: ObjectType, user_obj_bits: usize, slots: &CNodeObject) -> SysResult<()> {
|
pub fn retype(&mut self, obj_type: ObjectType, user_obj_bits: usize, slots: &mut CNodeObject) -> SysResult<()> {
|
||||||
/*
|
/*
|
||||||
* vallina seL4: `decode_untiped_invocation`
|
* vallina seL4: `decode_untiped_invocation`
|
||||||
* - _service CPTR to an untyped object.
|
* - _service CPTR to an untyped object.
|
||||||
@ -85,7 +88,7 @@ impl UntypedCap<'_> {
|
|||||||
// Make sure all slots are empty
|
// Make sure all slots are empty
|
||||||
slots
|
slots
|
||||||
.iter()
|
.iter()
|
||||||
.any(|cap: &core::cell::Cell<RawCap>| NullCap::try_from(cap).is_err())
|
.any(|cte| NullCap::try_from(cte).is_err())
|
||||||
.then_ok((), SysError::CapTypeMismatch)?;
|
.then_ok((), SysError::CapTypeMismatch)?;
|
||||||
|
|
||||||
// Start allocating from free_offset
|
// Start allocating from free_offset
|
||||||
@ -108,8 +111,8 @@ impl UntypedCap<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create new capabilities in slot
|
// Create new capabilities in slot
|
||||||
for (i, slot) in slots.iter().enumerate() {
|
for (i, slot) in slots.iter_mut().enumerate() {
|
||||||
let addr = self.cap.get().ptr + start_offset + i * obj_size;
|
let addr = self.cte.get().cap.ptr + start_offset + i * obj_size;
|
||||||
let new_cap = match obj_type {
|
let new_cap = match obj_type {
|
||||||
ObjectType::Untyped => UntypedCap::mint(0, obj_type.bits(user_obj_bits), self.is_device(), addr),
|
ObjectType::Untyped => UntypedCap::mint(0, obj_type.bits(user_obj_bits), self.is_device(), addr),
|
||||||
ObjectType::CNode => CNodeCap::mint(user_obj_bits, 0, 0, addr),
|
ObjectType::CNode => CNodeCap::mint(user_obj_bits, 0, 0, addr),
|
||||||
@ -117,8 +120,8 @@ impl UntypedCap<'_> {
|
|||||||
_ => return Err(SysError::InvalidArgument),
|
_ => return Err(SysError::InvalidArgument),
|
||||||
};
|
};
|
||||||
|
|
||||||
slot.set(new_cap);
|
slot.get_mut().cap = new_cap;
|
||||||
// TODO: insert into linked list
|
self.append(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update free_offset
|
// Update free_offset
|
||||||
|
Loading…
Reference in New Issue
Block a user