From c03059319c8db60f7266a73892465367a5ec9b5d Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Sun, 6 Oct 2024 23:38:24 -0700 Subject: [PATCH] Improve rustdoc Signed-off-by: Nick Spinale --- crates/sel4-microkit/base/src/defer.rs | 1 + crates/sel4-microkit/base/src/handler.rs | 3 ++ crates/sel4-microkit/base/src/message.rs | 15 +++++++ crates/sel4-microkit/base/src/symbols.rs | 57 +++++++++++++++++++++--- crates/sel4-microkit/macros/src/lib.rs | 40 ----------------- crates/sel4-microkit/src/lib.rs | 41 +++++++++++++++-- crates/sel4-root-task/src/lib.rs | 10 +++-- crates/sel4/src/lib.rs | 7 ++- 8 files changed, 117 insertions(+), 57 deletions(-) diff --git a/crates/sel4-microkit/base/src/defer.rs b/crates/sel4-microkit/base/src/defer.rs index facda19a3..d04ddc934 100644 --- a/crates/sel4-microkit/base/src/defer.rs +++ b/crates/sel4-microkit/base/src/defer.rs @@ -91,6 +91,7 @@ impl PreparedDeferredAction { } } +/// Utility type for implementing [`Handler::take_deferred_action`]. // TODO maybe excessive. remove? pub struct DeferredActionSlot { inner: Option, diff --git a/crates/sel4-microkit/base/src/handler.rs b/crates/sel4-microkit/base/src/handler.rs index c60f649bd..992319610 100644 --- a/crates/sel4-microkit/base/src/handler.rs +++ b/crates/sel4-microkit/base/src/handler.rs @@ -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, diff --git a/crates/sel4-microkit/base/src/message.rs b/crates/sel4-microkit/base/src/message.rs index 182b8f525..4a606643e 100644 --- a/crates/sel4-microkit/base/src/message.rs +++ b/crates/sel4-microkit/base/src/message.rs @@ -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, @@ -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())) } @@ -55,26 +63,33 @@ impl Default for MessageInfo { } } +/// Provides access to the protection domain's message registers. pub fn with_msg_regs(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(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(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(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]) } diff --git a/crates/sel4-microkit/base/src/symbols.rs b/crates/sel4-microkit/base/src/symbols.rs index 538f4bd06..554230c7d 100644 --- a/crates/sel4-microkit/base/src/symbols.rs +++ b/crates/sel4-microkit/base/src/symbols.rs @@ -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) => {{ @@ -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 /// @@ -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; diff --git a/crates/sel4-microkit/macros/src/lib.rs b/crates/sel4-microkit/macros/src/lib.rs index 68acae4e5..53373f886 100644 --- a/crates/sel4-microkit/macros/src/lib.rs +++ b/crates/sel4-microkit/macros/src/lib.rs @@ -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); diff --git a/crates/sel4-microkit/src/lib.rs b/crates/sel4-microkit/src/lib.rs index 9e0831030..8a693a219 100644 --- a/crates/sel4-microkit/src/lib.rs +++ b/crates/sel4-microkit/src/lib.rs @@ -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; @@ -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 +/// ``` +/// +/// (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 = , +/// heap_size = , +/// )] +/// ``` +/// +/// - `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 { { @@ -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 diff --git a/crates/sel4-root-task/src/lib.rs b/crates/sel4-root-task/src/lib.rs index 0d16b1e19..e57526e9c 100644 --- a/crates/sel4-root-task/src/lib.rs +++ b/crates/sel4-root-task/src/lib.rs @@ -60,19 +60,21 @@ pub use sel4_panicking_env::{debug_print, debug_println}; /// } /// ``` /// -/// /// The main function have a signature of the form: /// /// ```rust -/// fn(&sel4::BootInfoPtr) -> T +/// fn(&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 = , heap_size = )] +/// #[root_task( +/// stack_size = , +/// heap_size = , +/// )] /// ``` /// /// - `stack_size`: Declares the size of the initial thread's stack, in bytes. Note that this diff --git a/crates/sel4/src/lib.rs b/crates/sel4/src/lib.rs index 1b2f83121..3cae0b229 100644 --- a/crates/sel4/src/lib.rs +++ b/crates/sel4/src/lib.rs @@ -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.