Skip to content

Commit

Permalink
Improve rustdoc
Browse files Browse the repository at this point in the history
Signed-off-by: Nick Spinale <[email protected]>
  • Loading branch information
nspin committed Oct 7, 2024
1 parent 08b3bbf commit c030593
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 57 deletions.
1 change: 1 addition & 0 deletions crates/sel4-microkit/base/src/defer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ impl PreparedDeferredAction {
}
}

/// Utility type for implementing [`Handler::take_deferred_action`].
// TODO maybe excessive. remove?
pub struct DeferredActionSlot {
inner: Option<DeferredAction>,
Expand Down
3 changes: 3 additions & 0 deletions crates/sel4-microkit/base/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ pub trait Handler {
panic!("unexpected protected procedure call from channel {channel:?} with msg_info={msg_info:?}")
}

/// This method has the same meaning and type as its analog in `libmicrokit`.
///
/// The default implementation just panics.
fn fault(
&mut self,
child: Child,
Expand Down
15 changes: 15 additions & 0 deletions crates/sel4-microkit/base/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
// SPDX-License-Identifier: BSD-2-Clause
//

/// Type alias for [`MessageInfo`] labels.
pub type MessageLabel = sel4::Word;

/// Type alias for message register values.
pub type MessageRegisterValue = sel4::Word;

/// Corresponds to `microkit_msginfo`.
#[derive(Debug, Clone)]
pub struct MessageInfo {
inner: sel4::MessageInfo,
Expand All @@ -32,18 +36,22 @@ impl MessageInfo {
Self::from_inner(sel4::MessageInfo::new(label, 0, 0, count))
}

/// The label associated with this message.
pub fn label(&self) -> MessageLabel {
self.inner.label()
}

/// The number of meaningful bits in `MessageLabel`.
pub const fn label_width() -> usize {
sel4::MessageInfo::label_width()
}

/// The number of filled message registers associated with this message.
pub fn count(&self) -> usize {
self.inner.length()
}

/// Interpret this message as a [`sel4::Fault`].
pub fn fault(&self) -> sel4::Fault {
sel4::with_ipc_buffer(|ipc_buffer| sel4::Fault::new(ipc_buffer, self.inner()))
}
Expand All @@ -55,26 +63,33 @@ impl Default for MessageInfo {
}
}

/// Provides access to the protection domain's message registers.
pub fn with_msg_regs<T>(f: impl FnOnce(&[MessageRegisterValue]) -> T) -> T {
sel4::with_ipc_buffer(|ipc_buffer| f(ipc_buffer.msg_regs()))
}

/// Provides mutable access to the protection domain's message registers.
pub fn with_msg_regs_mut<T>(f: impl FnOnce(&mut [MessageRegisterValue]) -> T) -> T {
sel4::with_ipc_buffer_mut(|ipc_buffer| f(ipc_buffer.msg_regs_mut()))
}

/// Provides access to the protection domain's message registers, viewed as an array of bytes.
pub fn with_msg_bytes<T>(f: impl FnOnce(&[u8]) -> T) -> T {
sel4::with_ipc_buffer(|ipc_buffer| f(ipc_buffer.msg_bytes()))
}

/// Provides mutable access to the protection domain's message registers, viewed as an array of
/// bytes.
pub fn with_msg_bytes_mut<T>(f: impl FnOnce(&mut [u8]) -> T) -> T {
sel4::with_ipc_buffer_mut(|ipc_buffer| f(ipc_buffer.msg_bytes_mut()))
}

/// Corresponds to `microkit_mr_set`.
pub fn set_mr(i: usize, value: MessageRegisterValue) {
with_msg_regs_mut(|regs| regs[i] = value)
}

/// Corresponds to `microkit_mr_get`.
pub fn get_mr(i: usize) -> MessageRegisterValue {
with_msg_regs(|regs| regs[i])
}
57 changes: 51 additions & 6 deletions crates/sel4-microkit/base/src/symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,50 @@
use core::ptr;
use core::str::{self, Utf8Error};

/// Declares a symbol via which the `microkit` tool can inject a variable declared by e.g.
/// `setvar_vaddr`, and returns the variable's value at runtime.
///
/// This macro is represents a lower-level interface than
/// [`memory_region_symbol`](crate::memory_region_symbol).
///
/// The following fragment demonstrates its usage:
///
/// ```rust
/// let my_var: &'static T = var!(my_var_symbol_name: T = MY_DEFAULT_VALUE)
/// ```
///
/// where `MY_DEFAULT_VALUE` is the value that the variable will be given at compile-time, before
/// the protection domain image is passed to the `microkit` tool.
///
/// The patching mechanism used by the `microkit` tool requires that the symbol be allocated space
/// in the protection domain's ELF file, so we declare the symbol as part of the `.data` section.
///
/// For more detail, see this macro's definition.
///
/// # Examples
///
/// ```rust
/// let foo = bar + *var!(baz: usize = 0);
/// ```
///
/// # Note
///
/// The `microkit` tool requires memory region address symbols to be present in protection domain
/// binaries. To prevent Rust from optimizing them out in cases where it is not used, add the
/// unstable `#[used(linker)]` attribute. For example:
///
/// ```rust
/// #![feature(used_with_arg)]
///
/// // might be optimized away if not used
/// memory_region_symbol!(foo: usize = 0)
///
/// // won't be optimized away
/// memory_region_symbol! {
/// #[used(linker)]
/// foo: usize = 0
/// }
/// ```
#[macro_export]
macro_rules! var {
($(#[$attrs:meta])* $symbol:ident: $ty:ty = $default:expr) => {{
Expand All @@ -25,10 +69,10 @@ macro_rules! var {
/// Declares a symbol via which the `microkit` tool can inject a memory region's address, and
/// returns the memory region's address at runtime.
///
/// For more detail, see its definition.
///
/// The patching mechanism used by the `microkit` tool requires that the symbol be allocated space
/// in the protection domain's ELF file, so we delare the symbol as part of the `.data` section.
/// in the protection domain's ELF file, so we declare the symbol as part of the `.data` section.
///
/// For more detail, see this macro's definition.
///
/// # Examples
///
Expand Down Expand Up @@ -116,23 +160,24 @@ macro_rules! maybe_extern_var {
}};
}

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

/// Returns the name of this projection domain without converting to unicode.
/// Returns the name of this protection domain without converting to unicode.
pub fn pd_name_bytes() -> &'static [u8] {
let all_bytes = maybe_extern_var!(microkit_name: [u8; 16] = [0; 16]);
let n = all_bytes.iter().take_while(|b| **b != 0).count();
&all_bytes[..n]
}

/// Returns the name of this projection domain.
/// Returns the name of this protection domain.
pub fn pd_name() -> Result<&'static str, Utf8Error> {
str::from_utf8(pd_name_bytes())
}

/// Returns a pointer to the protection domain's [`sel4::IpcBuffer`].
pub fn ipc_buffer_ptr() -> *mut sel4::IpcBuffer {
extern "C" {
static mut __sel4_ipc_buffer_obj: sel4::IpcBuffer;
Expand Down
40 changes: 0 additions & 40 deletions crates/sel4-microkit/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,6 @@ use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::parse_macro_input;

/// Declares the initialization function, stack size, and, optionally, heap and heap size.
///
/// The syntax is:
///
/// ```rust
/// #[protection_domain($($key:ident = $value:expr),* $(,)?)]
/// fn init() -> impl Handler {
/// // ...
/// }
/// ```
///
/// Where the possible keys are:
/// - `stack_size`: Sets the stack size. Defaults to `0x4000`.
/// - `heap_size`: Declares a `#[global_allocator]` implemented using Dlmalloc and a
/// statically-allocated heap. Optional.
///
/// The function to which the attribute is applied will be used to initialize the protection domain.
/// It must satisfy `FnOnce() -> T where T: Handler`.
///
/// This macro is a thin wrapper around `sel4_microkit::declare_protection_domain`. The following
/// are equivalent:
///
/// ```rust
/// #[protection_domain(stack_size = 0x12000, heap_size = 0x34000)]
/// fn init() -> impl Handler {
/// // ...
/// }
/// ```
///
/// ```rust
/// declare_protection_domain! {
/// init = my_init,
/// stack_size = 0x12000,
/// heap_size = 0x34000,
/// }
///
/// fn init() -> impl Handler {
/// // ...
/// }
/// ```
#[proc_macro_attribute]
pub fn protection_domain(attr: TokenStream, item: TokenStream) -> TokenStream {
let item = parse_macro_input!(item as syn::ItemFn);
Expand Down
41 changes: 38 additions & 3 deletions crates/sel4-microkit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ extern crate alloc;
use sel4::sel4_cfg;

pub use sel4_microkit_base::*;
pub use sel4_microkit_macros::protection_domain;

mod entry;
mod heap;
Expand All @@ -49,9 +48,44 @@ pub mod panicking;
#[sel4_cfg(PRINTING)]
pub use printing::{debug_print, debug_println};

/// Declares the initialization function, stack size, and, optionally, heap and heap size.
/// Declares a function to be the the protection domain's initialization function.
///
/// For example:
///
/// ```rust
/// #[protection_domain]
/// fn init() -> impl Handler {
/// todo!()
/// }
/// ```
///
/// The initialization function have a signature of the form:
///
/// ```rust
/// fn<T: Handler>() -> T
/// ```
///
/// (See [`Handler`])
///
/// See the [`protection_domain`] attribute macro for more detail.
/// This macro takes two optional parameters, whose values can be any expression of type `usize`:
///
/// ```rust
/// #[protection_domain(
/// stack_size = <stack_size_expr: usize>,
/// heap_size = <heap_size_expr: usize>,
/// )]
/// ```
///
/// - `stack_size`: Declares the size of the protection domain's stack, in bytes. Note that this
/// includes space for thread-local storage. If absent, [`DEFAULT_STACK_SIZE`] will be used.
/// - `heap_size`: Creates a `#[global_allocator]`, backed by a static heap of the specified size.
/// If this parameter is not specified, no `#[global_allocator]` will be automatically declared,
/// and, unless one is manually declared, heap allocations will result in a link-time error.
///
/// Note that, if both parameters are provided, they must appear in the order above.
pub use sel4_microkit_macros::protection_domain;

#[doc(hidden)]
#[macro_export]
macro_rules! declare_protection_domain {
{
Expand Down Expand Up @@ -82,6 +116,7 @@ macro_rules! declare_protection_domain {
};
}

/// The default stack size used by [`#[protection_domain]`](crate::protection_domain).
pub const DEFAULT_STACK_SIZE: usize = 1024
* if cfg!(panic = "unwind") && cfg!(debug_assertions) {
128
Expand Down
10 changes: 6 additions & 4 deletions crates/sel4-root-task/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,21 @@ pub use sel4_panicking_env::{debug_print, debug_println};
/// }
/// ```
///
///
/// The main function have a signature of the form:
///
/// ```rust
/// fn<T: sel4_root_task::Termination>(&sel4::BootInfoPtr) -> T
/// fn<T: Termination>(&sel4::BootInfoPtr) -> T
/// ```
///
/// (See [`Termination`])
///
/// This macro takes two optional parameters:
/// This macro takes two optional parameters, whose values can be any expression of type `usize`:
///
/// ```rust
/// #[root_task(stack_size = <stack_size_expr: usize>, heap_size = <heap_size_expr: usize>)]
/// #[root_task(
/// stack_size = <stack_size_expr: usize>,
/// heap_size = <heap_size_expr: usize>,
/// )]
/// ```
///
/// - `stack_size`: Declares the size of the initial thread's stack, in bytes. Note that this
Expand Down
7 changes: 3 additions & 4 deletions crates/sel4/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@
//! This crate provides straightforward, pure-Rust bindings to the [seL4
//! API](https://sel4.systems/Info/Docs/seL4-manual-latest.pdf).
//!
//! Most items in this crate correspond to types, constants, and functions in
//! [libsel4](https://docs.sel4.systems/projects/sel4/api-doc.html). Notably, when applicable,
//! `seL4_CPtr` is agumented in [`Cap`] with a marker specifying the type of capability it points
//! to.
//! Most items in this crate correspond to types, constants, and functions in `libsel4`. See the
//! [seL4 manual](https://sel4.systems/Info/Docs/seL4-manual-latest.pdf) for more information about
//! the seL4 concepts and `libsel4` items references in this crate's documentation.
//!
//! This crate's implementation is based on the lower-level [`sel4-sys`](::sel4_sys) crate, which is
//! generated from the libsel4 headers and interface definition files.
Expand Down

0 comments on commit c030593

Please sign in to comment.