Skip to content

Commit

Permalink
crates/sel4: Fill in documentation for remaining items
Browse files Browse the repository at this point in the history
Signed-off-by: Nick Spinale <nick@nickspinale.com>
  • Loading branch information
nspin committed Feb 14, 2024
1 parent f1566f8 commit 0dfb5bc
Show file tree
Hide file tree
Showing 11 changed files with 192 additions and 3 deletions.
149 changes: 149 additions & 0 deletions crates/sel4/config/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,62 +15,211 @@ fn get_impls() -> MacroImpls<'static> {
MacroImpls::new(get_kernel_config(), "sel4_cfg")
}

/// Make the attached code conditional on a seL4 kernel configuration expression.
///
/// Supports the same syntax as `#[cfg]`, except primitive expressions are based on seL4 kernel
/// configuration rather than `rustc` configuration.
///
/// Suppose `$SEL4_PREFIX/libsel4/include/kernel/gen_config.json` contains:
///
/// ```ignore
/// {
/// "KERNEL_MCS": false,
/// "HAVE_FPU": true
/// "ARM_PLAT": "bcm2711",
/// "MAX_NUM_NODES": "4",
/// ...
/// }
/// ```
///
/// Note that values are either booleans or strings. Configuration keys corresponding to boolean
/// values are used as in `#[sel4_cfg(KERNEL_MCS)]`, whereas those corresponding to strings are used
/// in equalities as in `#[sel4_cfg(MAX_NUM_NODES = 4)]`. Expressions can be combined using `not()`,
/// `any()`, and `all()`, just like expressions in `#[cfg]`.
///
/// Unlike in `#[cfg]`, using a configuration key that is not present in the seL4 kernel
/// configuration will result in an error rather than just evaluating to false. That is, a key that
/// is not part of an equality expression evaluates to itsqqqqqqqqqq boolean value, whereas in `#[cfg]` a key
/// that is not part of an equality expression evaluates to whether it is present in the
/// configuration.
#[proc_macro_attribute]
pub fn sel4_cfg(input: TokenStream, item: TokenStream) -> TokenStream {
get_impls().cfg_impl(input.into(), item.into()).into()
}

/// Make the associated attribute expression conditional on a seL4 kernel configuration expression.
///
/// Supports the same syntax as `#[cfg_attr]`, except primitive expressions are based on seL4 kernel
/// configuration rather than `rustc` configuration.
///
/// See [`macro@sel4_cfg`].
#[proc_macro_attribute]
pub fn sel4_cfg_attr(input: TokenStream, item: TokenStream) -> TokenStream {
get_impls().cfg_attr_impl(input.into(), item.into()).into()
}

/// Allows a `struct`'s fields to use the [`macro@sel4_cfg`] attribute.
///
/// # Example
///
/// ```ignore
/// #[sel4_cfg_struct]
/// struct Foo {
/// #[sel4_cfg(KERNEL_MCS)]
/// bar: bool,
/// }
/// ```
#[proc_macro_attribute]
pub fn sel4_cfg_struct(input: TokenStream, item: TokenStream) -> TokenStream {
get_impls()
.cfg_struct_impl(input.into(), item.into())
.into()
}

/// Allows an `enum`'s variants to use the [`macro@sel4_cfg`] attribute.
///
/// # Example
///
/// ```ignore
/// #[sel4_cfg_enum]
/// enum Foo {
/// #[sel4_cfg(KERNEL_MCS)]
/// Bar,
/// }
/// ```
#[proc_macro_attribute]
pub fn sel4_cfg_enum(input: TokenStream, item: TokenStream) -> TokenStream {
get_impls().cfg_enum_impl(input.into(), item.into()).into()
}

/// Allows a `match` expression's variants to use the [`macro@sel4_cfg`] attribute.
///
/// Using this attribute macro currently requires nightly (`#![feature(proc_macro_hygiene)]` and
/// `#![feature(stmt_expr_attributes)]`). The less elegant [`macro@sel4_cfg_wrap_match`] serves the
/// same purpose and works on stable.
///
/// # Example
///
/// ```ignore
/// #[sel4_cfg_match]
/// match foo {
/// #[sel4_cfg(KERNEL_MCS)]
/// 1337 => bar,
/// }
/// ```
#[proc_macro_attribute]
pub fn sel4_cfg_match(input: TokenStream, item: TokenStream) -> TokenStream {
get_impls().cfg_match_impl(input.into(), item.into()).into()
}

/// Like [`macro@sel4_cfg_match`], except it works on stable, at the expense of not being an
/// attribute macro.
///
/// # Example
///
/// ```ignore
/// sel4_cfg_wrap_match! {
/// match foo {
/// #[sel4_cfg(KERNEL_MCS)]
/// 1337 => bar,
/// }
/// }
/// ```
#[proc_macro]
pub fn sel4_cfg_wrap_match(item: TokenStream) -> TokenStream {
get_impls().cfg_wrap_match_impl(item.into()).into()
}

/// Like `cfg_if::cfg_if!`, except with [`macro@sel4_cfg`] instead of `#[cfg]`.
///
/// # Example
///
/// ```ignore
/// sel4_cfg_if! {
/// if #[sel4_cfg(KERNEL_MCS)] {
/// ...
/// } else if #[sel4_cfg(MAX_NUM_NODES = "1")] {
/// ...
/// } else {
/// ...
/// }
/// }
/// ```
#[proc_macro]
pub fn sel4_cfg_if(toks: TokenStream) -> TokenStream {
get_impls().cfg_if_impl(toks.into()).into()
}

/// Like `core::cfg!()`, except using the seL4 kernel configuration.
///
/// Unlike `core::cfg!()`, this macro requires the configuration key to correspond to a boolean
/// value.
///
/// See [`macro@sel4_cfg`] for documentation on the configuration expression syntax.
///
/// # Example
///
/// ```ignore
/// if sel4_cfg_bool!(KERNEL_MCS) {
/// ...
/// }
/// ```
#[proc_macro]
pub fn sel4_cfg_bool(key_toks: TokenStream) -> TokenStream {
get_impls().cfg_bool_impl(key_toks.into()).into()
}

/// Like `core::cfg!()`, except using the seL4 kernel configuration.
///
/// This macro requires the configuration key to correspond to a string value. It parses that value
/// into an integer at compile-time, and assignes to it the type `usize`.
///
/// See [`macro@sel4_cfg`] for documentation on the configuration expression syntax.
///
/// # Example
///
/// ```ignore
/// assert_eq!(1usize, sel4_cfg_usize!(MAX_NUM_NODES));
/// ```
#[proc_macro]
pub fn sel4_cfg_str(key_toks: TokenStream) -> TokenStream {
get_impls()
.cfg_from_str_impl::<String>(PhantomData, key_toks.into())
.into()
}

/// Like `core::cfg!()`, except using the seL4 kernel configuration.
///
/// This macro requires the configuration key to correspond to a string value. It parses that value
/// into an integer at compile-time, and assigns it type `usize`.
///
/// See [`macro@sel4_cfg`] for documentation on the configuration expression syntax.
///
/// # Example
///
/// ```ignore
/// assert_eq!(1usize, sel4_cfg_usize!(MAX_NUM_NODES));
/// ```
#[proc_macro]
pub fn sel4_cfg_usize(key_toks: TokenStream) -> TokenStream {
get_impls()
.cfg_from_str_impl::<usize>(PhantomData, key_toks.into())
.into()
}

/// Like `core::cfg!()`, except using the seL4 kernel configuration.
///
/// This macro requires the configuration key to correspond to a string value. It parses that value
/// into an integer at compile-time, and assigns to it the one of the types `u32` or `u64`,
/// depending on the value of `WORD_SIZE` configuration key.
///
/// See [`macro@sel4_cfg`] for documentation on the configuration expression syntax.
///
/// # Example
///
/// ```ignore
/// assert_eq!(1u64, sel4_cfg_word!(MAX_NUM_NODES));
/// ```
#[proc_macro]
pub fn sel4_cfg_word(key_toks: TokenStream) -> TokenStream {
let impls = get_impls();
Expand Down
6 changes: 6 additions & 0 deletions crates/sel4/config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
pub use sel4_config_macros::*;

pub mod consts {
//! The kernel configuration as `const` items.
//!
//! While this module can be used as an alternative to the `sel4_cfg_*!` macros for accessing
//! the kernel configuration at the value level, its primary purpose is to provide a reference
//! within Rustdoc for the active configuration. Towards that end, the generated source of this
//! module is also provided in this module's Rustdoc to make browsing easier.
#![doc = concat!("```rust\n", include_str!(concat!(env!("OUT_DIR"), "/consts_gen.rs")), "```\n")]

include!(concat!(env!("OUT_DIR"), "/consts_gen.rs"));
Expand Down
4 changes: 4 additions & 0 deletions crates/sel4/src/bootinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ use sel4_config::sel4_cfg;

use crate::{cap_type, init_thread::SlotRegion, newtype_methods, sys, IpcBuffer, GRANULE_SIZE};

/// A wrapped pointer to a [`BootInfo`] block.
///
/// Access [`BootInfo`] via `Deref`, and [`BootInfoExtraIter`] via [`extra`](BootInfoPtr::extra).
#[repr(transparent)]
#[derive(Debug)]
pub struct BootInfoPtr {
Expand Down Expand Up @@ -173,6 +176,7 @@ impl BootInfoExtraId {
}
}

/// An iterator for accessing the [`BootInfoExtra`] entires associated with a [`BootInfoPtr`].
pub struct BootInfoExtraIter<'a> {
bootinfo: &'a BootInfoPtr,
cursor: usize,
Expand Down
3 changes: 3 additions & 0 deletions crates/sel4/src/cptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ impl<T: CapType, C> fmt::Debug for Cap<T, C> {
}
}

/// Trait for marker types corresponding to capability types in the seL4 API.
///
/// Implementors are used to mark instantiations of [`Cap`].
// NOTE require 'Copy' for convenience to make up for limitations of automatic trait derivation
pub trait CapType: Copy {
const NAME: &'static str;
Expand Down
2 changes: 2 additions & 0 deletions crates/sel4/src/init_thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
// SPDX-License-Identifier: MIT
//

//! Items that are applicable within the context of the root task's initial thread.
use core::marker::PhantomData;
use core::ops::Range;

Expand Down
1 change: 1 addition & 0 deletions crates/sel4/src/invocations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::Badge;
#[sel4_cfg(not(KERNEL_MCS))]
use crate::CPtr;

/// Corresponds to `seL4_Time`.
#[sel4_cfg(KERNEL_MCS)]
pub type Time = u64;

Expand Down
4 changes: 3 additions & 1 deletion crates/sel4/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ mod vspace;
pub mod fault;
pub mod init_thread;

pub use bootinfo::{BootInfo, BootInfoExtra, BootInfoExtraId, BootInfoPtr, UntypedDesc};
pub use bootinfo::{
BootInfo, BootInfoExtra, BootInfoExtraId, BootInfoExtraIter, BootInfoPtr, UntypedDesc,
};
pub use cap_rights::{CapRights, CapRightsBuilder};
pub use cnode_cap_data::CNodeCapData;
pub use cptr::{
Expand Down
9 changes: 7 additions & 2 deletions crates/sel4/src/reply_authority.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,27 @@ use crate::sys;
#[sel4_cfg(KERNEL_MCS)]
use crate::Reply;

/// Configuration-dependant alias for conveying reply authority to syscalls.
pub type ReplyAuthority = ReplyAuthorityImpl;

sel4_cfg_if! {
if #[sel4_cfg(KERNEL_MCS)] {
pub type ReplyAuthority = Reply;
pub type ReplyAuthorityImpl = Reply;

impl ReplyAuthority {
pub(crate) fn into_sys_reply_authority(self) -> sys::ReplyAuthority {
self.bits()
}
}
} else {
pub type ReplyAuthority = ImplicitReplyAuthority;
pub type ReplyAuthorityImpl = ImplicitReplyAuthority;

impl ReplyAuthority {
pub(crate) fn into_sys_reply_authority(self) -> sys::ReplyAuthority {
}
}

/// Under this configuration, no reply authority is required.
pub struct ImplicitReplyAuthority;

impl ConveysReplyAuthority for () {
Expand All @@ -38,6 +42,7 @@ sel4_cfg_if! {
}
}

/// Trait for types from which [`ReplyAuthority`] can be derived.
pub trait ConveysReplyAuthority {
fn into_reply_authority(self) -> ReplyAuthority;
}
Expand Down
13 changes: 13 additions & 0 deletions crates/sel4/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ where
try_with_ipc_buffer_slot_mut(|buf| f(buf.unwrap().as_mut().unwrap()))
}

/// Provides low-level access to this thread's IPC buffer.
///
/// This function does not modify kernel state. It only affects this crate's thread-local state.
///
/// Requires the `"state"` feature to be enabled.
pub fn try_with_ipc_buffer_slot<F, T>(f: F) -> T
where
F: FnOnce(Result<&Option<&'static mut IpcBuffer>, BorrowError>) -> T,
Expand All @@ -72,6 +77,11 @@ where
f(r.map(|_| unsafe { __sel4_ipc_buffer.0.get().as_ref().unwrap() }))
}

/// Provides low-level mutable access to this thread's IPC buffer.
///
/// This function does not modify kernel state. It only affects this crate's thread-local state.
///
/// Requires the `"state"` feature to be enabled.
pub fn try_with_ipc_buffer_slot_mut<F, T>(f: F) -> T
where
F: FnOnce(Result<&mut Option<&'static mut IpcBuffer>, BorrowMutError>) -> T,
Expand All @@ -87,6 +97,9 @@ fn take_ok<T, E>(r: Result<T, E>) -> (Option<T>, Result<(), E>) {
}
}

/// Returns whether this crate's IPC buffer slot is thread-local.
///
/// Requires the `"state"` feature to be enabled.
pub const fn ipc_buffer_is_thread_local() -> bool {
IPC_BUFFER_IS_THREAD_LOCAL
}
Expand Down
2 changes: 2 additions & 0 deletions crates/sel4/src/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub const NUM_MESSAGE_REGISTERS: usize = u32_into_usize(sys::seL4_MsgLimits::seL
/// A capability badge.
pub type Badge = Word;

/// Trait for [`CapType`]s which are used as targets of IPC syscalls.
pub trait IpcCapType: CapType {}

impl IpcCapType for cap_type::Notification {}
Expand Down Expand Up @@ -250,6 +251,7 @@ type ConcreteFastMessagesForIn = [Option<Word>; NUM_FAST_MESSAGE_REGISTERS];

type ConcreteFastMessagesForInOut = [Word; NUM_FAST_MESSAGE_REGISTERS];

/// Trait for types which can hold the contents of a set of inline message registers.
pub trait FastMessages: fast_messages_sealing::FastMessagesSealed {
fn prepare_in(self) -> ConcreteFastMessagesForIn;

Expand Down
2 changes: 2 additions & 0 deletions crates/sel4/src/vspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ impl FrameSize {
}
}

/// Trait for [`CapType`]s which correspond to frame objects.
pub trait FrameType: CapType {}

impl FrameType for cap_type::UnspecifiedFrame {}

/// Trait for [`FrameType`]s which correspond to frame objects of fixed size.
pub trait SizedFrameType: FrameType {
const FRAME_SIZE: FrameSize;
}

0 comments on commit 0dfb5bc

Please sign in to comment.