wip derivation node

This commit is contained in:
Berkus Decker 2020-12-13 19:40:55 +02:00
parent 6de2ef38a7
commit d129db345f
1 changed files with 62 additions and 13 deletions

View File

@ -297,22 +297,25 @@ register_bitfields! {
register_bitfields! {
u128,
CapDerivationNode [
FirstBadged OFFSET(0) NUMBITS(1) [
Disable = 0,
Enable = 1
],
Revocable OFFSET(1) NUMBITS(1) [
Disable = 0,
Enable = 1
],
// -- 2 bits still free here --
// Next CTE node address -- per cteInsert this is address of the entire CTE slot
// cap derivation slots are supposedly aligned in u128 boundary (16 bytes) this means we can
// drop bottom 4 bits from it in these fields.
Next OFFSET(0) NUMBITS(44) [], // 16-bytes-aligned, size of canonical phys address is 48 bits
// -- 18 bits still free here --
Revocable OFFSET(62) NUMBITS(1) [
Disable = 0,
Enable = 1
],
FirstBadged OFFSET(63) NUMBITS(1) [
Disable = 0,
Enable = 1
],
Next OFFSET(4) NUMBITS(44) [], // 16-bytes-aligned, size of canonical phys address is 48 bits
// -- 16 bits still free here --
// -- New word doundary --
// -- 4 bits still free here --
// Prev CTE node address -- per cteInsert this is address of the entire CTE slot
Prev OFFSET(64) NUMBITS(44) []
// -- 20 bits still free here --
Prev OFFSET(68) NUMBITS(44) []
// -- 16 bits still free here --
]
}
@ -513,6 +516,8 @@ pub struct DerivationTreeNode(LocalRegisterCopy<u128, CapDerivationNode::Registe
pub enum DerivationTreeError {
/// Previous link is invalid.
InvalidPrev,
/// Next link is invalid.
InvalidNext,
}
// In seL4, the MDB is stored as a doubly-linked list, representing the **preorder-DFS** through
@ -525,17 +530,26 @@ pub enum DerivationTreeError {
// To reduce the complexity of operations described above, we replace the MDBs linked list with
// a more suitable search data structure.
// -- nevill-master-thesis Using Capabilities for OS Resource Management
// sel4: mdb_node_t
impl DerivationTreeNode {
const ADDR_BIT_SHIFT: usize = 4;
fn empty() -> Self {
Self(LocalRegisterCopy::new(0))
}
// Unlike mdb_node_new we do not pass revocable and firstBadged flags here, they are enabled
// using builder interface set_first_badged() and set_revocable().
fn new(prevPtr: PhysAddr, nextPtr: PhysAddr) -> Self {
Self::empty().set_prev(prevPtr).set_next(nextPtr)
}
/// Get previous link in derivation tree.
/// Previous link exists if this is a derived capability.
///
/// SAFETY: it is UB to get prev reference from a null Prev pointer.
pub unsafe fn get_prev(&self) -> CapTableEntry {
let ptr = self.0.read(CapDerivationNode::Prev) as *const CapTableEntry;
let ptr = (self.0.read(CapDerivationNode::Prev) << ADDR_BIT_SHIFT) as *const CapTableEntry;
(*ptr).clone()
}
@ -549,6 +563,39 @@ impl DerivationTreeNode {
}
}
pub fn set_prev(&mut self, prevPtr: PhysAddr) -> Self {
self.0
.write(CapDerivationNode::Prev(prevPtr >> ADDR_BIT_SHIFT));
self
}
/// Get next link in derivation tree.
/// Next link exists if this capability has derived capabilities or siblings.
///
/// SAFETY: it is UB to get next reference from a null Next pointer.
pub unsafe fn get_next(&self) -> CapTableEntry {
let ptr = (self.0.read(CapDerivationNode::Next) << ADDR_BIT_SHIFT) as *const CapTableEntry;
(*ptr).clone()
}
/// Try to get next link in derivation tree.
/// Next link exists if this capability has derived capabilities or siblings.
pub fn try_get_next(&self) -> Result<CapTableEntry, DerivationTreeError> {
if self.0.read(CapDerivationNode::Next) == 0 {
Err(DerivationTreeError::InvalidNext)
} else {
Ok(unsafe { self.get_next() })
}
}
pub fn set_next(&mut self, nextPtr: PhysAddr) -> Self {
self.0
.write(CapDerivationNode::Next(nextPtr >> ADDR_BIT_SHIFT));
self
}
/// Builder interface to modify firstBadged flag
/// @todo Describe the firstBadged flag and what it does.
fn set_first_badged(mut self, enable: bool) -> Self {
self.0.modify(if enable {
CapDerivationNode::FirstBadged::Enable
@ -558,6 +605,8 @@ impl DerivationTreeNode {
self
}
/// Builder interface to modify revocable flag
/// @todo Describe the revocable flag and what it does.
fn set_revocable(mut self, enable: bool) -> Self {
self.0.modify(if enable {
CapDerivationNode::Revocable::Enable