From d4256d01f58586821edd32c933a28db434aad9dd Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Sat, 10 Feb 2024 11:49:01 +0000 Subject: [PATCH] crates/sel4/sys: Add wrappers for sel4test --- Cargo.lock | 7 + Cargo.toml | 1 + crates/sel4/sys/Cargo.nix | 3 + crates/sel4/sys/Cargo.toml | 3 + crates/sel4/sys/build/bf/mod.rs | 106 ++++- crates/sel4/sys/build/main.rs | 21 +- crates/sel4/sys/build/xml/invocations/mod.rs | 73 ++- crates/sel4/sys/src/lib.rs | 3 + crates/sel4/sys/src/wrappers/fault.rs | 55 +++ crates/sel4/sys/src/wrappers/ipc_buffer.rs | 85 ++++ crates/sel4/sys/src/wrappers/misc.rs | 43 ++ crates/sel4/sys/src/wrappers/mod.rs | 23 + crates/sel4/sys/src/wrappers/syscalls.rs | 432 ++++++++++++++++++ crates/sel4/sys/src/wrappers/tls.rs | 37 ++ crates/sel4/sys/wrappers/Cargo.nix | 15 + crates/sel4/sys/wrappers/Cargo.toml | 23 + crates/sel4/sys/wrappers/src/lib.rs | 12 + crates/sel4/sys/wrappers/src/panic_handler.rs | 27 ++ 18 files changed, 944 insertions(+), 25 deletions(-) create mode 100644 crates/sel4/sys/src/wrappers/fault.rs create mode 100644 crates/sel4/sys/src/wrappers/ipc_buffer.rs create mode 100644 crates/sel4/sys/src/wrappers/misc.rs create mode 100644 crates/sel4/sys/src/wrappers/mod.rs create mode 100644 crates/sel4/sys/src/wrappers/syscalls.rs create mode 100644 crates/sel4/sys/src/wrappers/tls.rs create mode 100644 crates/sel4/sys/wrappers/Cargo.nix create mode 100644 crates/sel4/sys/wrappers/Cargo.toml create mode 100644 crates/sel4/sys/wrappers/src/lib.rs create mode 100644 crates/sel4/sys/wrappers/src/panic_handler.rs diff --git a/Cargo.lock b/Cargo.lock index 6241a246a..56ed50a14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2631,6 +2631,13 @@ dependencies = [ "xmltree", ] +[[package]] +name = "sel4-sys-wrappers" +version = "0.1.0" +dependencies = [ + "sel4-sys", +] + [[package]] name = "sel4-test-harness" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index f712e388e..814d567b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -135,6 +135,7 @@ members = [ "crates/sel4/config/generic/types", "crates/sel4/config/macros", "crates/sel4/sys", + "crates/sel4/sys/wrappers", ] [patch.crates-io.ring] diff --git a/crates/sel4/sys/Cargo.nix b/crates/sel4/sys/Cargo.nix index c56e9f132..393b4469d 100644 --- a/crates/sel4/sys/Cargo.nix +++ b/crates/sel4/sys/Cargo.nix @@ -29,4 +29,7 @@ mk { sel4-config-data ; }; + features = { + wrappers = []; + }; } diff --git a/crates/sel4/sys/Cargo.toml b/crates/sel4/sys/Cargo.toml index 46b9347c6..eb7d6f574 100644 --- a/crates/sel4/sys/Cargo.toml +++ b/crates/sel4/sys/Cargo.toml @@ -17,6 +17,9 @@ build = "build/main.rs" edition = "2021" license = "BSD-2-Clause" +[features] +wrappers = [] + [dependencies] log = "0.4.17" sel4-bitfield-ops = { path = "../bitfield-ops" } diff --git a/crates/sel4/sys/build/bf/mod.rs b/crates/sel4/sys/build/bf/mod.rs index 4eec55726..ceb12273c 100644 --- a/crates/sel4/sys/build/bf/mod.rs +++ b/crates/sel4/sys/build/bf/mod.rs @@ -8,7 +8,7 @@ use std::fs; use std::path::Path; use proc_macro2::{Literal, TokenStream}; -use quote::{format_ident, quote}; +use quote::{format_ident, quote, IdentFragment}; use syn::Ident; mod simplified; @@ -17,7 +17,7 @@ use simplified::*; pub fn generate_rust( blocklist_for_bindgen: &mut Vec, bf_path: impl AsRef, -) -> TokenStream { +) -> (TokenStream, TokenStream) { let text = fs::read_to_string(bf_path).unwrap(); let file = sel4_bitfield_parser::parse(&text); let file = simplify(&file); @@ -28,19 +28,21 @@ pub fn generate_rust( for tagged_union in file.tagged_unions.iter() { generator.generate_tagged_union(tagged_union); } - generator.toks + (generator.native_toks, generator.wrapper_toks) } struct BitfieldGenerator<'a> { blocklist_for_bindgen: &'a mut Vec, - toks: TokenStream, + native_toks: TokenStream, + wrapper_toks: TokenStream, } impl<'a> BitfieldGenerator<'a> { fn new(blocklist_for_bindgen: &'a mut Vec) -> Self { Self { blocklist_for_bindgen, - toks: quote!(), + native_toks: quote!(), + wrapper_toks: quote!(), } } @@ -60,6 +62,7 @@ impl<'a> BitfieldGenerator<'a> { self.blocklist_for_bindgen.push(name_ident.to_string()); + let qualified_name = quote!(crate::#name_ident); let unpacked_ident = format_ident!("{}_Unpacked", name_ident); let primitive_type = backing_type.primitive(); @@ -70,6 +73,7 @@ impl<'a> BitfieldGenerator<'a> { let mut unpack_field_assignments = vec![]; let mut new_body = quote!(); let mut methods = quote!(); + let mut wrapper_functions = quote!(); for field in fields.iter() { let field_name_ident = format_ident!("{}", field.name); @@ -124,6 +128,37 @@ impl<'a> BitfieldGenerator<'a> { #field_range_end - #field_range_start } }); + + let wrapper_get_prefix = + mk_wrapper_prefix(format!("{}_get_{}", name_ident, field.name)); + let wrapper_set_prefix = + mk_wrapper_prefix(format!("{}_set_{}", name_ident, field.name)); + let wrapper_ptr_get_prefix = + mk_wrapper_prefix(format!("{}_ptr_get_{}", name_ident, field.name)); + let wrapper_ptr_set_prefix = + mk_wrapper_prefix(format!("{}_ptr_set_{}", name_ident, field.name)); + + if !is_tag { + wrapper_functions.extend(quote! { + #wrapper_get_prefix(this: #qualified_name) -> #primitive_type { + this.#get_method_ident() + } + #wrapper_set_prefix(mut this: #qualified_name, #field_name_ident: #primitive_type) -> #qualified_name { + this.#set_method_ident(#field_name_ident); + this + } + #wrapper_ptr_get_prefix(this: *mut #qualified_name) -> #primitive_type { + unsafe { + (&*this).#get_method_ident() + } + } + #wrapper_ptr_set_prefix(this: *mut #qualified_name, #field_name_ident: #primitive_type) { + unsafe { + (&mut *this).#set_method_ident(#field_name_ident); + } + } + }) + } } let alias_stmt = if tag_info.is_none() { @@ -136,7 +171,7 @@ impl<'a> BitfieldGenerator<'a> { quote!() }; - self.toks.extend(quote! { + self.native_toks.extend(quote! { #[repr(transparent)] #[derive(Clone, Eq, PartialEq)] pub struct #name_ident(pub #bitfield_type); @@ -180,10 +215,28 @@ impl<'a> BitfieldGenerator<'a> { } } }); + + let wrapper_new_prefix = mk_wrapper_prefix(format!("{name_ident}_new")); + let wrapper_ptr_new_prefix = mk_wrapper_prefix(format!("{name_ident}_ptr_new")); + + self.wrapper_toks.extend(quote! { + #wrapper_new_prefix(#(#non_tag_fields_with_types,)*) -> #qualified_name { + #qualified_name::new(#(#non_tag_fields,)*) + } + + #wrapper_ptr_new_prefix(this: *mut #qualified_name, #(#non_tag_fields_with_types,)*) { + unsafe { + *this = #qualified_name::new(#(#non_tag_fields,)*); + } + } + + #wrapper_functions + }); } fn generate_tagged_union(&mut self, tagged_union: &TaggedUnion) { let name_ident = format_ident!("{}", tagged_union.name); + let qualified_name = quote!(crate::#name_ident); let splayed_ident = format_ident!("{}_Splayed", tagged_union.name); let primitive_type = tagged_union.backing_type.primitive(); let bitfield_type = tagged_union.backing_type.bitfield(); @@ -250,7 +303,7 @@ impl<'a> BitfieldGenerator<'a> { let tag_range_start = tagged_union.tag_range.start; let tag_range_end = tagged_union.tag_range.end; - self.toks.extend(quote! { + self.native_toks.extend(quote! { pub mod #tag_values_module_ident { #(#tag_value_consts;)* } @@ -295,6 +348,37 @@ impl<'a> BitfieldGenerator<'a> { #block_unsplay_toks }); + + let wrapper_get_tag_prefix = mk_wrapper_prefix(format!( + "{}_get_{}", + tagged_union.name, tagged_union.tag_name + )); + let wrapper_ptr_get_tag_prefix = mk_wrapper_prefix(format!( + "{}_ptr_get_{}", + tagged_union.name, tagged_union.tag_name + )); + let wrapper_tag_equals_prefix = mk_wrapper_prefix(format!( + "{}_{}_equals", + tagged_union.name, tagged_union.tag_name + )); + + let c_int = quote!(::core::ffi::c_int); + + self.wrapper_toks.extend(quote! { + #wrapper_get_tag_prefix(this: #qualified_name) -> #primitive_type { + this.get_tag() + } + + #wrapper_ptr_get_tag_prefix(this: *mut #qualified_name) -> #primitive_type { + unsafe { + (&*this).get_tag() + } + } + + #wrapper_tag_equals_prefix(this: #qualified_name, tag: #primitive_type) -> #c_int { + (this.get_tag() == tag) as #c_int + } + }); } } @@ -322,3 +406,11 @@ fn mk_tagged_union_variant_block_type_ident(tagged_union_name: &str, tag_name: & fn mk_tag_values_module_ident(tagged_union_name: &str) -> Ident { format_ident!("{}_tag", tagged_union_name) } + +fn mk_wrapper_prefix(fn_name: impl IdentFragment) -> TokenStream { + let fn_ident = format_ident!("{}", fn_name); + quote! { + #[no_mangle] + pub extern "C" fn #fn_ident + } +} diff --git a/crates/sel4/sys/build/main.rs b/crates/sel4/sys/build/main.rs index e078b749d..aa5bb07af 100644 --- a/crates/sel4/sys/build/main.rs +++ b/crates/sel4/sys/build/main.rs @@ -34,8 +34,13 @@ fn main() { .unwrap() .map(Result::unwrap) { - let fragment = bf::generate_rust(&mut blocklist_for_bindgen, &f); - out_dir.write_file(fragment, f.with_extension("rs").file_name().unwrap()); + let (native_fragment, wrappers_fragment) = + bf::generate_rust(&mut blocklist_for_bindgen, &f); + out_dir.write_file(native_fragment, f.with_extension("rs").file_name().unwrap()); + out_dir.write_file( + wrappers_fragment, + f.with_extension("wrappers.rs").file_name().unwrap(), + ); } } @@ -59,13 +64,15 @@ fn main() { ), ]; - let (invocation_labels_fragment, invocations_fragment) = xml::invocations::generate_rust( - &mut blocklist_for_bindgen, - &interface_definition_files, - ); + let (invocation_labels_fragment, native_fragment, wrappers_fragment) = + xml::invocations::generate_rust( + &mut blocklist_for_bindgen, + &interface_definition_files, + ); out_dir.write_file(invocation_labels_fragment, "invocation_labels.rs"); - out_dir.write_file(invocations_fragment, "invocations.rs"); + out_dir.write_file(native_fragment, "invocations.rs"); + out_dir.write_file(wrappers_fragment, "invocations.wrappers.rs"); } { diff --git a/crates/sel4/sys/build/xml/invocations/mod.rs b/crates/sel4/sys/build/xml/invocations/mod.rs index f10d54335..9bec88c94 100644 --- a/crates/sel4/sys/build/xml/invocations/mod.rs +++ b/crates/sel4/sys/build/xml/invocations/mod.rs @@ -33,7 +33,7 @@ type Word = u64; pub fn generate_rust( blocklist_for_bindgen: &mut Vec, interface_xml_paths: &[impl AsRef], -) -> (TokenStream, TokenStream) { +) -> (TokenStream, TokenStream, TokenStream) { let mut structs = vec![]; let mut interfaces = vec![]; for f in interface_xml_paths { @@ -82,9 +82,9 @@ pub fn generate_rust( } } } - let toks = invocation_generator.generate_module(); + let (native_toks, wrapper_toks) = invocation_generator.generate_module(); - (invocation_label_toks, toks) + (invocation_label_toks, native_toks, wrapper_toks) } pub struct InvocationGenerator<'a> { @@ -92,6 +92,7 @@ pub struct InvocationGenerator<'a> { blocklist_for_bindgen: &'a mut Vec, ret_struct_toks: TokenStream, ipc_buffer_method_toks: TokenStream, + wrapper_toks: TokenStream, } impl<'a> InvocationGenerator<'a> { @@ -101,14 +102,16 @@ impl<'a> InvocationGenerator<'a> { blocklist_for_bindgen, ret_struct_toks: quote!(), ipc_buffer_method_toks: quote!(), + wrapper_toks: quote!(), } } - pub fn generate_module(self) -> TokenStream { + pub fn generate_module(self) -> (TokenStream, TokenStream) { let ret_struct_toks = self.ret_struct_toks; let ipc_buffer_method_toks = self.ipc_buffer_method_toks; + let wrapper_toks = self.wrapper_toks; - let toks = quote! { + let native_toks = quote! { #ret_struct_toks impl seL4_IPCBuffer { @@ -116,7 +119,7 @@ impl<'a> InvocationGenerator<'a> { } }; - toks + (native_toks, wrapper_toks) } pub fn generate_invocation( @@ -134,7 +137,12 @@ impl<'a> InvocationGenerator<'a> { let param_list_generator = ParameterListGenerator::new(&self.parameter_types, in_params, out_params); - let param_list_for_type_sig = param_list_generator.generate(); + let param_list_for_type_sig = + param_list_generator.generate(ParameterListRole::NativeFunctionTypeSignature); + let param_list_for_wrapper_type_sig = + param_list_generator.generate(ParameterListRole::WrapperFunctionTypeSignature); + let param_list_for_wrapper_expr = + param_list_generator.generate(ParameterListRole::WrapperFunctionArguments); let out_params_passed_by_value = out_params .iter() @@ -216,6 +224,13 @@ impl<'a> InvocationGenerator<'a> { #ret_expr } }); + + self.wrapper_toks.extend(quote! { + #[no_mangle] + pub extern "C" fn #fn_ident(service: crate::#interface_ident, #(#param_list_for_wrapper_type_sig,)*) -> crate::#ret_type_path { + get_ipc_buffer_mut().#fn_ident(service, #(#param_list_for_wrapper_expr,)*) + } + }); } fn generate_ret_struct_definition( @@ -231,6 +246,7 @@ impl<'a> InvocationGenerator<'a> { } }); quote! { + #[cfg_attr(feature = "wrappers", repr(C))] // TODO better to just be unconditionally repr(C) for the sake of consistency? #[derive(Default)] pub struct #ret_struct_ident { pub error: seL4_Error::Type, @@ -336,6 +352,23 @@ struct ParameterListGenerator<'a> { out_params: &'a [Parameter], } +#[derive(Clone, PartialEq, Eq)] +enum ParameterListRole { + NativeFunctionTypeSignature, + WrapperFunctionTypeSignature, + WrapperFunctionArguments, +} + +impl ParameterListRole { + fn is_type_signature(&self) -> bool { + *self != Self::WrapperFunctionArguments + } + + fn is_native(&self) -> bool { + *self == Self::NativeFunctionTypeSignature + } +} + impl<'a> ParameterListGenerator<'a> { fn new( parameter_types: &'a ParameterTypes, @@ -349,7 +382,13 @@ impl<'a> ParameterListGenerator<'a> { } } - fn generate(&self) -> Vec { + // TODO use * instead of & for wrappers + fn generate(&self, role: ParameterListRole) -> Vec { + let ty_path_prefix = if role.is_native() { + quote!() + } else { + quote!(crate::) + }; let mut param_list = vec![]; for param in self.in_params.iter().chain(self.out_params.iter()) { let var_ident = raw_ident(¶m.name); @@ -367,18 +406,30 @@ impl<'a> ParameterListGenerator<'a> { } else { quote!() }; - param_list.push((quote!(#var_ident), quote!(#ty_modifier #ty #ty_suffix))); + param_list.push(( + quote!(#var_ident), + quote!(#ty_modifier #ty_path_prefix #ty #ty_suffix), + )); } ParameterDirection::Out => { if self.parameter_types.get(¶m.ty).pass_by_reference() { - param_list.push((quote!(#var_ident), quote!(&mut #ty #ty_suffix))); + param_list.push(( + quote!(#var_ident), + quote!(&mut #ty_path_prefix #ty #ty_suffix), + )); } } } } param_list .into_iter() - .map(move |(var, ty)| quote!(#var: #ty)) + .map(move |(var, ty)| { + if role.is_type_signature() { + quote!(#var: #ty) + } else { + quote!(#var) + } + }) .collect() } } diff --git a/crates/sel4/sys/src/lib.rs b/crates/sel4/sys/src/lib.rs index 1a2aabb76..5c82b124a 100644 --- a/crates/sel4/sys/src/lib.rs +++ b/crates/sel4/sys/src/lib.rs @@ -24,6 +24,9 @@ pub use c::*; pub use invocations::*; pub use syscalls::*; +#[cfg(feature = "wrappers")] +pub mod wrappers; + pub type ReplyAuthority = sel4_config::sel4_cfg_if! { if #[cfg(KERNEL_MCS)] { seL4_CPtr diff --git a/crates/sel4/sys/src/wrappers/fault.rs b/crates/sel4/sys/src/wrappers/fault.rs new file mode 100644 index 000000000..4e7f6f38c --- /dev/null +++ b/crates/sel4/sys/src/wrappers/fault.rs @@ -0,0 +1,55 @@ +// +// Copyright 2023, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +use sel4_config::sel4_cfg; + +use super::get_ipc_buffer; +use crate::{seL4_Fault, seL4_Fault_tag, seL4_MessageInfo, wrappers::seL4_MessageInfo_get_label}; + +#[sel4_cfg(KERNEL_MCS)] +use core::mem; + +#[sel4_cfg(KERNEL_MCS)] +use crate::{ + seL4_UserContext, seL4_Word, + wrappers::{seL4_MessageInfo_new, seL4_SetMR}, +}; + +#[no_mangle] +pub extern "C" fn seL4_getFault(tag: seL4_MessageInfo) -> seL4_Fault { + seL4_Fault::get_from_ipc_buffer(&tag, get_ipc_buffer()) +} + +#[no_mangle] +pub extern "C" fn seL4_isVMFault_tag(tag: seL4_MessageInfo) -> bool { + seL4_MessageInfo_get_label(tag) == seL4_Fault_tag::seL4_Fault_VMFault +} + +#[sel4_cfg(KERNEL_MCS)] +#[no_mangle] +pub extern "C" fn seL4_isTimeoutFault_tag(tag: seL4_MessageInfo) -> bool { + seL4_MessageInfo_get_label(tag) == seL4_Fault_tag::seL4_Fault_Timeout +} + +#[sel4_cfg(KERNEL_MCS)] +#[no_mangle] +pub extern "C" fn seL4_TimeoutReply_new( + resume: bool, + regs: seL4_UserContext, + length: seL4_Word, +) -> seL4_MessageInfo { + let info = seL4_MessageInfo_new((!resume).into(), 0, 0, length); + let regs_arr = unsafe { + mem::transmute::< + _, + [seL4_Word; mem::size_of::() / mem::size_of::()], + >(regs) + }; + for i in 0usize..length.try_into().unwrap() { + seL4_SetMR(i.try_into().unwrap(), regs_arr[i]); + } + info +} diff --git a/crates/sel4/sys/src/wrappers/ipc_buffer.rs b/crates/sel4/sys/src/wrappers/ipc_buffer.rs new file mode 100644 index 000000000..e2e30afc8 --- /dev/null +++ b/crates/sel4/sys/src/wrappers/ipc_buffer.rs @@ -0,0 +1,85 @@ +// +// Copyright 2023, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +use core::ffi::c_int; + +use super::{get_ipc_buffer, get_ipc_buffer_mut, get_ipc_buffer_ptr, set_ipc_buffer_ptr}; +use crate::{seL4_CPtr, seL4_IPCBuffer, seL4_Word}; + +#[no_mangle] +pub unsafe extern "C" fn seL4_SetIPCBuffer(ipc_buffer_ptr: *mut seL4_IPCBuffer) { + set_ipc_buffer_ptr(ipc_buffer_ptr) +} + +#[no_mangle] +pub unsafe extern "C" fn seL4_GetIPCBuffer() -> *mut seL4_IPCBuffer { + get_ipc_buffer_ptr() +} + +#[no_mangle] +pub extern "C" fn seL4_GetMR(i: c_int) -> seL4_Word { + get_ipc_buffer().get_mr(i.try_into().unwrap()) +} + +#[no_mangle] +pub extern "C" fn seL4_SetMR(i: c_int, value: seL4_Word) { + get_ipc_buffer_mut().set_mr(i.try_into().unwrap(), value) +} + +#[no_mangle] +pub extern "C" fn seL4_GetUserData() -> seL4_Word { + get_ipc_buffer().userData +} + +#[no_mangle] +pub extern "C" fn seL4_SetUserData(data: seL4_Word) { + get_ipc_buffer_mut().userData = data; +} + +#[no_mangle] +pub extern "C" fn seL4_GetBadge(i: c_int) -> seL4_Word { + get_ipc_buffer().caps_or_badges[usize::try_from(i).unwrap()] +} + +#[no_mangle] +pub extern "C" fn seL4_GetCap(i: c_int) -> seL4_CPtr { + get_ipc_buffer().get_cap(i.try_into().unwrap()) +} + +#[no_mangle] +pub extern "C" fn seL4_SetCap(i: c_int, cap: seL4_CPtr) { + get_ipc_buffer_mut().set_cap(i.try_into().unwrap(), cap) +} + +#[no_mangle] +pub unsafe extern "C" fn seL4_GetCapReceivePath( + receiveCNode: *mut seL4_CPtr, + receiveIndex: *mut seL4_CPtr, + receiveDepth: *mut seL4_Word, +) { + let ipc_buffer = get_ipc_buffer(); + if !receiveCNode.is_null() { + *receiveCNode = ipc_buffer.receiveCNode; + } + if !receiveIndex.is_null() { + *receiveIndex = ipc_buffer.receiveIndex; + } + if !receiveDepth.is_null() { + *receiveDepth = ipc_buffer.receiveDepth; + } +} + +#[no_mangle] +pub extern "C" fn seL4_SetCapReceivePath( + receiveCNode: seL4_CPtr, + receiveIndex: seL4_CPtr, + receiveDepth: seL4_Word, +) { + let ipc_buffer = get_ipc_buffer_mut(); + ipc_buffer.receiveCNode = receiveCNode; + ipc_buffer.receiveIndex = receiveIndex; + ipc_buffer.receiveDepth = receiveDepth; +} diff --git a/crates/sel4/sys/src/wrappers/misc.rs b/crates/sel4/sys/src/wrappers/misc.rs new file mode 100644 index 000000000..57499d114 --- /dev/null +++ b/crates/sel4/sys/src/wrappers/misc.rs @@ -0,0 +1,43 @@ +// +// Copyright 2023, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +use sel4_config::sel4_cfg; + +use super::get_ipc_buffer; +use crate::{seL4_Word, SEL4_MAPPING_LOOKUP_LEVEL}; + +#[sel4_cfg(KERNEL_MCS)] +use crate::{ + seL4_Error, seL4_SchedContext, seL4_SchedContextFlag, seL4_SchedControl, seL4_Time, + wrappers::get_ipc_buffer_mut, +}; + +#[no_mangle] +pub extern "C" fn seL4_MappingFailedLookupLevel() -> seL4_Word { + get_ipc_buffer().get_mr(SEL4_MAPPING_LOOKUP_LEVEL.try_into().unwrap()) +} + +// alias +#[no_mangle] +#[sel4_cfg(KERNEL_MCS)] +pub extern "C" fn seL4_SchedControl_Configure( + service: seL4_SchedControl, + schedcontext: seL4_SchedContext, + budget: seL4_Time, + period: seL4_Time, + extra_refills: seL4_Word, + badge: seL4_Word, +) -> seL4_Error::Type { + get_ipc_buffer_mut().seL4_SchedControl_ConfigureFlags( + service, + schedcontext, + budget, + period, + extra_refills, + badge, + seL4_SchedContextFlag::seL4_SchedContext_NoFlag, + ) +} diff --git a/crates/sel4/sys/src/wrappers/mod.rs b/crates/sel4/sys/src/wrappers/mod.rs new file mode 100644 index 000000000..e90a674e9 --- /dev/null +++ b/crates/sel4/sys/src/wrappers/mod.rs @@ -0,0 +1,23 @@ +// +// Copyright 2023, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +mod fault; +mod ipc_buffer; +mod misc; +mod syscalls; +mod tls; + +use tls::{get_ipc_buffer, get_ipc_buffer_mut}; + +pub use fault::*; +pub use ipc_buffer::*; +pub use misc::*; +pub use syscalls::*; +pub use tls::{get_ipc_buffer_ptr, set_ipc_buffer_ptr}; + +include!(concat!(env!("OUT_DIR"), "/invocations.wrappers.rs")); +include!(concat!(env!("OUT_DIR"), "/shared_types.wrappers.rs")); +include!(concat!(env!("OUT_DIR"), "/types.wrappers.rs")); diff --git a/crates/sel4/sys/src/wrappers/syscalls.rs b/crates/sel4/sys/src/wrappers/syscalls.rs new file mode 100644 index 000000000..cf450463f --- /dev/null +++ b/crates/sel4/sys/src/wrappers/syscalls.rs @@ -0,0 +1,432 @@ +// +// Copyright 2023, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +use core::ffi::{c_char, CStr}; + +use sel4_config::{sel4_cfg, sel4_cfg_if}; + +use super::tls::get_ipc_buffer_mut; +use crate::{seL4_CPtr, seL4_MessageInfo, seL4_Uint32, seL4_Word, ReplyAuthority}; + +#[sel4_cfg(not(KERNEL_MCS))] +const DUMMY_REPLY_ARG: ReplyAuthority = (); + +macro_rules! ptr_to_opt { + ( + $msg0:ident, $msg1:ident, $msg2:ident, $msg3:ident, + $m0:ident, $m1:ident, $m2:ident, $m3:ident, + ) => { + $m0 = $msg0.as_ref().copied(); + $m1 = $msg1.as_ref().copied(); + $m2 = $msg2.as_ref().copied(); + $m3 = $msg3.as_ref().copied(); + }; +} + +macro_rules! ptr_to_opt_ref { + ( + $msg0:ident, $msg1:ident, $msg2:ident, $msg3:ident, + $m0:ident, $m1:ident, $m2:ident, $m3:ident, + ) => { + $m0 = $msg0.as_mut(); + $m1 = $msg1.as_mut(); + $m2 = $msg2.as_mut(); + $m3 = $msg3.as_mut(); + }; +} + +#[no_mangle] +pub unsafe extern "C" fn seL4_Send(dest: seL4_CPtr, msg_info: seL4_MessageInfo) { + get_ipc_buffer_mut().seL4_Send(dest, msg_info) +} + +#[no_mangle] +pub unsafe extern "C" fn seL4_SendWithMRs( + dest: seL4_CPtr, + msg_info: seL4_MessageInfo, + msg0: *mut seL4_Word, + msg1: *mut seL4_Word, + msg2: *mut seL4_Word, + msg3: *mut seL4_Word, +) { + let m0; + let m1; + let m2; + let m3; + + ptr_to_opt!(msg0, msg1, msg2, msg3, m0, m1, m2, m3,); + + crate::seL4_SendWithMRsWithoutIPCBuffer(dest, msg_info, m0, m1, m2, m3) +} + +#[no_mangle] +pub unsafe extern "C" fn seL4_NBSend(dest: seL4_CPtr, msg_info: seL4_MessageInfo) { + get_ipc_buffer_mut().seL4_NBSend(dest, msg_info) +} + +#[no_mangle] +pub unsafe extern "C" fn seL4_NBSendWithMRs( + dest: seL4_CPtr, + msg_info: seL4_MessageInfo, + msg0: *mut seL4_Word, + msg1: *mut seL4_Word, + msg2: *mut seL4_Word, + msg3: *mut seL4_Word, +) { + let m0; + let m1; + let m2; + let m3; + + ptr_to_opt!(msg0, msg1, msg2, msg3, m0, m1, m2, m3,); + + crate::seL4_NBSendWithMRsWithoutIPCBuffer(dest, msg_info, m0, m1, m2, m3) +} + +#[no_mangle] +#[sel4_cfg(not(KERNEL_MCS))] +pub unsafe extern "C" fn seL4_Reply(msg_info: seL4_MessageInfo) { + get_ipc_buffer_mut().seL4_Reply(msg_info) +} + +#[no_mangle] +#[sel4_cfg(not(KERNEL_MCS))] +pub unsafe extern "C" fn seL4_ReplyWithMRs( + msg_info: seL4_MessageInfo, + msg0: *mut seL4_Word, + msg1: *mut seL4_Word, + msg2: *mut seL4_Word, + msg3: *mut seL4_Word, +) { + let m0; + let m1; + let m2; + let m3; + + ptr_to_opt!(msg0, msg1, msg2, msg3, m0, m1, m2, m3,); + + crate::seL4_ReplyWithMRsWithoutIPCBuffer(msg_info, m0, m1, m2, m3) +} + +#[no_mangle] +pub unsafe extern "C" fn seL4_Signal(dest: seL4_CPtr) { + get_ipc_buffer_mut().seL4_Signal(dest) +} + +unsafe fn recv_common( + src: seL4_CPtr, + sender: *mut seL4_Word, + reply_authority: ReplyAuthority, +) -> seL4_MessageInfo { + let (msg_info, badge) = get_ipc_buffer_mut().seL4_Recv(src, reply_authority); + + if !sender.is_null() { + *sender = badge; + } + + msg_info +} + +sel4_cfg_if! { + if #[cfg(KERNEL_MCS)] { + #[no_mangle] + pub unsafe extern "C" fn seL4_Recv(src: seL4_CPtr, sender: *mut seL4_Word, reply: seL4_CPtr) -> seL4_MessageInfo { + recv_common(src, sender, reply) + } + } else { + #[no_mangle] + pub unsafe extern "C" fn seL4_Recv(src: seL4_CPtr, sender: *mut seL4_Word) -> seL4_MessageInfo { + recv_common(src, sender, DUMMY_REPLY_ARG) + } + } +} + +unsafe fn recv_with_mrs_common( + src: seL4_CPtr, + sender: *mut seL4_Word, + msg0: *mut seL4_Word, + msg1: *mut seL4_Word, + msg2: *mut seL4_Word, + msg3: *mut seL4_Word, + reply_authority: ReplyAuthority, +) -> seL4_MessageInfo { + let m0; + let m1; + let m2; + let m3; + + ptr_to_opt_ref!(msg0, msg1, msg2, msg3, m0, m1, m2, m3,); + + let (msg_info, badge) = + crate::seL4_RecvWithMRsWithoutIPCBuffer(src, m0, m1, m2, m3, reply_authority); + + if !sender.is_null() { + *sender = badge; + } + + msg_info +} + +sel4_cfg_if! { + if #[cfg(KERNEL_MCS)] { + #[no_mangle] + pub unsafe extern "C" fn seL4_RecvWithMRs( + src: seL4_CPtr, + sender: *mut seL4_Word, + msg0: *mut seL4_Word, + msg1: *mut seL4_Word, + msg2: *mut seL4_Word, + msg3: *mut seL4_Word, + reply: seL4_CPtr, + ) -> seL4_MessageInfo { + recv_with_mrs_common(src, sender, msg0, msg1, msg2, msg3, reply) + } + } else { + #[no_mangle] + pub unsafe extern "C" fn seL4_RecvWithMRs( + src: seL4_CPtr, + sender: *mut seL4_Word, + msg0: *mut seL4_Word, + msg1: *mut seL4_Word, + msg2: *mut seL4_Word, + msg3: *mut seL4_Word, + ) -> seL4_MessageInfo { + recv_with_mrs_common(src, sender, msg0, msg1, msg2, msg3, DUMMY_REPLY_ARG) + } + } +} + +unsafe fn nb_recv_common( + src: seL4_CPtr, + sender: *mut seL4_Word, + reply_authority: ReplyAuthority, +) -> seL4_MessageInfo { + let (msg_info, badge) = get_ipc_buffer_mut().seL4_NBRecv(src, reply_authority); + + if !sender.is_null() { + *sender = badge; + } + + msg_info +} + +sel4_cfg_if! { + if #[cfg(KERNEL_MCS)] { + #[no_mangle] + pub unsafe extern "C" fn seL4_NBRecv(src: seL4_CPtr, sender: *mut seL4_Word, reply: seL4_CPtr) -> seL4_MessageInfo { + nb_recv_common(src, sender, reply) + } + } else { + #[no_mangle] + pub unsafe extern "C" fn seL4_NBRecv(src: seL4_CPtr, sender: *mut seL4_Word) -> seL4_MessageInfo { + nb_recv_common(src, sender, DUMMY_REPLY_ARG) + } + } +} + +#[no_mangle] +pub unsafe extern "C" fn seL4_Call( + dest: seL4_CPtr, + msg_info: seL4_MessageInfo, +) -> seL4_MessageInfo { + get_ipc_buffer_mut().seL4_Call(dest, msg_info) +} + +#[no_mangle] +pub unsafe extern "C" fn seL4_CallWithMRs( + dest: seL4_CPtr, + msg_info: seL4_MessageInfo, + msg0: *mut seL4_Word, + msg1: *mut seL4_Word, + msg2: *mut seL4_Word, + msg3: *mut seL4_Word, +) -> seL4_MessageInfo { + let m0; + let m1; + let m2; + let m3; + + ptr_to_opt_ref!(msg0, msg1, msg2, msg3, m0, m1, m2, m3,); + + let msg_info = crate::seL4_CallWithMRsWithoutIPCBuffer(dest, msg_info, m0, m1, m2, m3); + + msg_info +} + +unsafe fn reply_recv_common( + src: seL4_CPtr, + msg_info: seL4_MessageInfo, + sender: *mut seL4_Word, + reply_authority: ReplyAuthority, +) -> seL4_MessageInfo { + let (out_msg_info, badge) = get_ipc_buffer_mut().seL4_ReplyRecv(src, msg_info, reply_authority); + + if !sender.is_null() { + *sender = badge; + } + + out_msg_info +} + +sel4_cfg_if! { + if #[cfg(KERNEL_MCS)] { + #[no_mangle] + pub unsafe extern "C" fn seL4_ReplyRecv(src: seL4_CPtr, msg_info: seL4_MessageInfo, sender: *mut seL4_Word, reply: seL4_CPtr) -> seL4_MessageInfo { + reply_recv_common(src, msg_info, sender, reply) + } + } else { + #[no_mangle] + pub unsafe extern "C" fn seL4_ReplyRecv(src: seL4_CPtr, msg_info: seL4_MessageInfo, sender: *mut seL4_Word) -> seL4_MessageInfo { + reply_recv_common(src, msg_info, sender, DUMMY_REPLY_ARG) + } + } +} + +#[no_mangle] +pub unsafe extern "C" fn seL4_Yield() { + crate::seL4_Yield() +} + +sel4_cfg_if! { + if #[cfg(KERNEL_MCS)] { + #[no_mangle] + pub unsafe extern "C" fn seL4_NBSendRecv( + dest: seL4_CPtr, + msg_info: seL4_MessageInfo, + src: seL4_CPtr, + sender: *mut seL4_Word, + reply_authority: ReplyAuthority, + ) -> seL4_MessageInfo { + let (out_msg_info, badge) = get_ipc_buffer_mut().seL4_NBSendRecv(dest, msg_info, src, reply_authority); + + if !sender.is_null() { + *sender = badge; + } + + out_msg_info + } + + #[no_mangle] + pub unsafe extern "C" fn seL4_NBSendWait( + dest: seL4_CPtr, + msg_info: seL4_MessageInfo, + src: seL4_CPtr, + sender: *mut seL4_Word, + ) -> seL4_MessageInfo { + let (out_msg_info, badge) = get_ipc_buffer_mut().seL4_NBSendWait(dest, msg_info, src); + + if !sender.is_null() { + *sender = badge; + } + + out_msg_info + } + + #[no_mangle] + pub unsafe extern "C" fn seL4_Wait(src: seL4_CPtr, sender: *mut seL4_Word) -> seL4_MessageInfo { + let (out_msg_info, badge) = get_ipc_buffer_mut().seL4_Wait(src); + + if !sender.is_null() { + *sender = badge; + } + + out_msg_info + } + + #[no_mangle] + pub unsafe extern "C" fn seL4_WaitWithMRs( + src: seL4_CPtr, + sender: *mut seL4_Word, + msg0: *mut seL4_Word, + msg1: *mut seL4_Word, + msg2: *mut seL4_Word, + msg3: *mut seL4_Word, + ) -> seL4_MessageInfo { + let m0; + let m1; + let m2; + let m3; + + ptr_to_opt_ref!(msg0, msg1, msg2, msg3, m0, m1, m2, m3,); + + let (msg_info, badge) = crate::seL4_WaitWithMRsWithoutIPCBuffer(src, m0, m1, m2, m3); + + if !sender.is_null() { + *sender = badge; + } + + msg_info + } + } else { + #[no_mangle] + pub unsafe extern "C" fn seL4_Wait(src: seL4_CPtr, sender: *mut seL4_Word) { + let ((), badge) = get_ipc_buffer_mut().seL4_Wait(src); + + if !sender.is_null() { + *sender = badge; + } + } + } +} + +#[no_mangle] +pub unsafe extern "C" fn seL4_Poll(src: seL4_CPtr, sender: *mut seL4_Word) -> seL4_MessageInfo { + let (msg_info, badge) = get_ipc_buffer_mut().seL4_Poll(src); + + if !sender.is_null() { + *sender = badge; + } + + msg_info +} + +sel4_cfg_if! { + if #[cfg(DEBUG_BUILD)] { + // Doesn't actually matter, but libsel4 uses char, which may be signed. Use c_char here and + // cast to u8 for the sake of principles. + #[no_mangle] + pub unsafe extern "C" fn seL4_DebugPutChar(c: c_char) { + crate::seL4_DebugPutChar(c as u8) + } + + #[no_mangle] + pub unsafe extern "C" fn seL4_DebugHalt( + ) { + crate::seL4_DebugHalt() + } + + #[no_mangle] + pub unsafe extern "C" fn seL4_DebugSnapshot( + ) { + crate::seL4_DebugSnapshot() + } + + #[no_mangle] + pub unsafe extern "C" fn seL4_DebugCapIdentify(cap: seL4_CPtr) -> seL4_Uint32 { + crate::seL4_DebugCapIdentify(cap) + } + + #[no_mangle] + pub unsafe extern "C" fn seL4_DebugNameThread(tcb: seL4_CPtr, name: *const c_char) { + crate::seL4_DebugNameThread(tcb, CStr::from_ptr(name).to_bytes(), &mut get_ipc_buffer_mut()) + } + } +} + +sel4_cfg_if! { + if #[cfg(ENABLE_BENCHMARKS)] { + // TODO + } +} + +sel4_cfg_if! { + if #[cfg(SET_TLS_BASE_SELF)] { + #[no_mangle] + pub unsafe extern "C" fn seL4_SetTLSBase(tls_base: seL4_Word) { + crate::seL4_SetTLSBase(tls_base) + } + } +} diff --git a/crates/sel4/sys/src/wrappers/tls.rs b/crates/sel4/sys/src/wrappers/tls.rs new file mode 100644 index 000000000..f6e57b4ee --- /dev/null +++ b/crates/sel4/sys/src/wrappers/tls.rs @@ -0,0 +1,37 @@ +// +// Copyright 2023, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +use core::ptr; + +use crate::seL4_IPCBuffer; + +#[no_mangle] +#[thread_local] +static mut __sel4_ipc_buffer: *mut seL4_IPCBuffer = ptr::null_mut(); + +pub unsafe fn set_ipc_buffer_ptr(ptr: *mut seL4_IPCBuffer) { + __sel4_ipc_buffer = ptr; +} + +pub unsafe fn get_ipc_buffer_ptr() -> *mut seL4_IPCBuffer { + __sel4_ipc_buffer +} + +pub(crate) fn get_ipc_buffer() -> &'static seL4_IPCBuffer { + unsafe { + let ptr = get_ipc_buffer_ptr(); + assert!(!ptr.is_null()); + &*ptr + } +} + +pub(crate) fn get_ipc_buffer_mut() -> &'static mut seL4_IPCBuffer { + unsafe { + let ptr = get_ipc_buffer_ptr(); + assert!(!ptr.is_null()); + &mut *ptr + } +} diff --git a/crates/sel4/sys/wrappers/Cargo.nix b/crates/sel4/sys/wrappers/Cargo.nix new file mode 100644 index 000000000..ffd87d383 --- /dev/null +++ b/crates/sel4/sys/wrappers/Cargo.nix @@ -0,0 +1,15 @@ +# +# Copyright 2023, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# + +{ mk, localCrates }: + +mk { + package.name = "sel4-sys-wrappers"; + lib.crate-type = [ "staticlib" ]; + dependencies = { + sel4-sys = localCrates.sel4-sys // { features = [ "wrappers" ]; }; + }; +} diff --git a/crates/sel4/sys/wrappers/Cargo.toml b/crates/sel4/sys/wrappers/Cargo.toml new file mode 100644 index 000000000..8e93f3f39 --- /dev/null +++ b/crates/sel4/sys/wrappers/Cargo.toml @@ -0,0 +1,23 @@ +# +# Copyright 2023, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# +# +# This file is generated from './Cargo.nix'. You can edit this file directly +# if you are not using this project's Cargo manifest management tools. +# See 'hacking/cargo-manifest-management/README.md' for more information. +# + +[package] +name = "sel4-sys-wrappers" +version = "0.1.0" +authors = ["Nick Spinale "] +edition = "2021" +license = "BSD-2-Clause" + +[lib] +crate-type = ["staticlib"] + +[dependencies] +sel4-sys = { path = "..", features = ["wrappers"] } diff --git a/crates/sel4/sys/wrappers/src/lib.rs b/crates/sel4/sys/wrappers/src/lib.rs new file mode 100644 index 000000000..1ba873d65 --- /dev/null +++ b/crates/sel4/sys/wrappers/src/lib.rs @@ -0,0 +1,12 @@ +// +// Copyright 2023, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +#![no_std] +#![feature(core_intrinsics)] + +pub use sel4_sys::wrappers::*; + +mod panic_handler; diff --git a/crates/sel4/sys/wrappers/src/panic_handler.rs b/crates/sel4/sys/wrappers/src/panic_handler.rs new file mode 100644 index 000000000..ec9a04d70 --- /dev/null +++ b/crates/sel4/sys/wrappers/src/panic_handler.rs @@ -0,0 +1,27 @@ +// +// Copyright 2023, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +use core::fmt::{self, Write}; +use core::panic::PanicInfo; + +use sel4_sys::seL4_DebugPutChar; + +#[panic_handler] +fn panic(info: &PanicInfo<'_>) -> ! { + let _ = writeln!(Debug, "{}", info); + core::intrinsics::abort() +} + +struct Debug; + +impl Write for Debug { + fn write_str(&mut self, s: &str) -> fmt::Result { + for &c in s.as_bytes() { + seL4_DebugPutChar(c) + } + Ok(()) + } +}