Skip to content

Commit

Permalink
crates/sel4-microkit: Add support for PD hierarchy
Browse files Browse the repository at this point in the history
Signed-off-by: Nick Spinale <[email protected]>
  • Loading branch information
nspin committed Jun 24, 2024
1 parent ca3ba40 commit ea9a50c
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 19 deletions.
18 changes: 18 additions & 0 deletions crates/sel4-microkit/base/src/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::MessageInfo;
const BASE_OUTPUT_NOTIFICATION_SLOT: usize = 10;
const BASE_ENDPOINT_SLOT: usize = BASE_OUTPUT_NOTIFICATION_SLOT + 64;
const BASE_IRQ_SLOT: usize = BASE_ENDPOINT_SLOT + 64;
const BASE_TCB_SLOT: usize = BASE_IRQ_SLOT + 64;

const MAX_CHANNELS: usize = 63;

Expand Down Expand Up @@ -79,3 +80,20 @@ impl fmt::Display for IrqAckError {
write!(f, "irq ack error: {:?}", self.inner())
}
}

/// A handle to a child protection domain, identified by a child protection domain index.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ProtectionDomain {
index: usize,
}

impl ProtectionDomain {
pub const fn new(index: usize) -> Self {
Self { index }
}

#[doc(hidden)]
pub fn tcb(&self) -> sel4::cap::Tcb {
sel4::Cap::from_bits((BASE_TCB_SLOT + self.index) as sel4::CPtrBits)
}
}
2 changes: 1 addition & 1 deletion crates/sel4-microkit/base/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ mod channel;
mod message;
mod symbols;

pub use channel::{Channel, IrqAckError};
pub use channel::{Channel, IrqAckError, ProtectionDomain};
pub use message::{
get_mr, set_mr, with_msg_bytes, with_msg_bytes_mut, with_msg_regs, with_msg_regs_mut,
MessageInfo, MessageLabel, MessageRegisterValue,
Expand Down
9 changes: 9 additions & 0 deletions crates/sel4-microkit/base/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ impl MessageInfo {
Self { inner }
}

#[doc(hidden)]
pub fn inner(&self) -> &sel4::MessageInfo {
&self.inner
}

#[doc(hidden)]
pub fn into_inner(self) -> sel4::MessageInfo {
self.inner
Expand All @@ -38,6 +43,10 @@ impl MessageInfo {
pub fn count(&self) -> usize {
self.inner.length()
}

pub fn fault(&self) -> sel4::Fault {
sel4::with_ipc_buffer(|ipc_buffer| sel4::Fault::new(ipc_buffer, self.inner()))
}
}

impl Default for MessageInfo {
Expand Down
2 changes: 1 addition & 1 deletion crates/sel4-microkit/base/src/symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ macro_rules! maybe_extern_var {

/// Returns whether this projection domain is a passive server.
pub fn pd_is_passive() -> bool {
*maybe_extern_var!(passive: bool = false)
*maybe_extern_var!(microkit_passive: bool = false)
}

/// Returns the name of this projection domain without converting to unicode.
Expand Down
21 changes: 15 additions & 6 deletions crates/sel4-microkit/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@

use core::fmt;

use sel4_microkit_base::MessageInfo;

use crate::{
defer::{DeferredAction, PreparedDeferredAction},
ipc::{self, Event},
pd_is_passive, Channel,
pd_is_passive, Channel, MessageInfo, ProtectionDomain,
};

pub use core::convert::Infallible;
Expand Down Expand Up @@ -39,6 +37,14 @@ pub trait Handler {
panic!("unexpected protected procedure call from channel {channel:?} with msg_info={msg_info:?}")
}

fn fault(
&mut self,
pd: ProtectionDomain,
msg_info: MessageInfo,
) -> Result<MessageInfo, Self::Error> {
panic!("unexpected fault from protection domain {pd:?} with msg_info={msg_info:?}")
}

/// An advanced feature for use by protection domains which seek to coalesce syscalls when
/// possible.
///
Expand Down Expand Up @@ -67,14 +73,17 @@ pub trait Handler {
};

match event {
Event::Protected(channel, msg_info) => {
reply_tag = Some(self.protected(channel, msg_info)?);
}
Event::Notified(notified_event) => {
for channel in notified_event.iter() {
self.notified(channel)?;
}
}
Event::Protected(channel, msg_info) => {
reply_tag = Some(self.protected(channel, msg_info)?);
}
Event::Fault(pd, msg_info) => {
reply_tag = Some(self.fault(pd, msg_info)?);
}
};

prepared_deferred_action = self
Expand Down
37 changes: 26 additions & 11 deletions crates/sel4-microkit/src/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,46 @@

use sel4_microkit_base::MessageInfo;

use crate::{defer::PreparedDeferredAction, Channel};
use crate::{defer::PreparedDeferredAction, Channel, ProtectionDomain};

const INPUT_CAP: sel4::cap::Endpoint = sel4::Cap::from_bits(1);
const REPLY_CAP: sel4::cap::Reply = sel4::Cap::from_bits(4);
const MONITOR_EP_CAP: sel4::cap::Endpoint = sel4::Cap::from_bits(5);

const EVENT_TYPE_MASK: sel4::Word = 1 << (sel4::WORD_SIZE - 1);
const CHANNEL_BADGE_BIT: usize = 63;
const PD_BADGE_BIT: usize = 62;

fn strip_flag(badge: sel4::Badge, bit: usize) -> Option<sel4::Word> {
let mask = 1 << bit;
if badge & mask != 0 {
Some(badge & !mask)
} else {
None
}
}

#[doc(hidden)]
#[derive(Debug, Clone)]
pub enum Event {
Protected(Channel, MessageInfo),
Notified(NotifiedEvent),
Protected(Channel, MessageInfo),
Fault(ProtectionDomain, MessageInfo),
}

impl Event {
fn new(tag: sel4::MessageInfo, badge: sel4::Badge) -> Self {
match badge & EVENT_TYPE_MASK {
0 => Self::Notified(NotifiedEvent(badge)),
_ => {
let channel_index = badge & (sel4::Word::try_from(sel4::WORD_SIZE).unwrap() - 1);
let channel = Channel::new(channel_index.try_into().unwrap());
let tag = MessageInfo::from_inner(tag);
Self::Protected(channel, tag)
}
if let Some(channel_index) = strip_flag(badge, CHANNEL_BADGE_BIT) {
Self::Protected(
Channel::new(channel_index.try_into().unwrap()),
MessageInfo::from_inner(tag),
)
} else if let Some(pd_index) = strip_flag(badge, PD_BADGE_BIT) {
Self::Fault(
ProtectionDomain::new(pd_index.try_into().unwrap()),
MessageInfo::from_inner(tag),
)
} else {
Self::Notified(NotifiedEvent(badge))
}
}

Expand Down

0 comments on commit ea9a50c

Please sign in to comment.