From 37d7f080c585928a497335efa9ca0e5949bc0bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20B=C3=B6ving?= Date: Tue, 14 Nov 2023 09:02:58 +0000 Subject: [PATCH] feat: import @hargonix hardware diff --- .../pkg/io/libvbus/include/vbus_interfaces.h | 4 +- src/l4/pkg/l4rust/l4-rust/Cargo.toml | 17 +- src/l4/pkg/l4rust/l4-rust/cap.rs | 20 +- src/l4/pkg/l4rust/l4-rust/error.rs | 21 +- src/l4/pkg/l4rust/l4-rust/ipc/iface.rs | 11 +- src/l4/pkg/l4rust/l4-rust/ipc/mod.rs | 83 ++- src/l4/pkg/l4rust/l4-rust/ipc/serialise.rs | 80 +-- src/l4/pkg/l4rust/l4-rust/ipc/server.rs | 11 +- src/l4/pkg/l4rust/l4-rust/ipc/types.rs | 68 +-- src/l4/pkg/l4rust/l4-rust/lib.rs | 14 +- src/l4/pkg/l4rust/l4-rust/utcb.rs | 146 ++---- src/l4/pkg/l4rust/l4-sys-rust/Cargo.toml | 5 +- src/l4/pkg/l4rust/l4-sys-rust/Control | 2 +- src/l4/pkg/l4rust/l4-sys-rust/Makefile | 2 +- src/l4/pkg/l4rust/l4-sys-rust/bindgen.h | 8 +- src/l4/pkg/l4rust/l4-sys-rust/build.rs | 11 +- src/l4/pkg/l4rust/l4-sys-rust/cap.rs | 15 +- src/l4/pkg/l4rust/l4-sys-rust/consts.rs | 14 +- src/l4/pkg/l4rust/l4-sys-rust/factory.rs | 193 +++---- src/l4/pkg/l4rust/l4-sys-rust/helpers.rs | 18 +- src/l4/pkg/l4rust/l4-sys-rust/ipc_basic.rs | 109 ++-- src/l4/pkg/l4rust/l4-sys-rust/ipc_ext.rs | 36 +- src/l4/pkg/l4rust/l4-sys-rust/lib.rs | 33 +- src/l4/pkg/l4rust/l4_derive-rust/lib.rs | 3 + src/l4/pkg/l4rust/l4re-rust/Cargo.toml | 16 +- src/l4/pkg/l4rust/l4re-rust/bindgen.h | 4 + src/l4/pkg/l4rust/l4re-rust/build.rs | 4 +- src/l4/pkg/l4rust/l4re-rust/cap.rs | 14 +- src/l4/pkg/l4rust/l4re-rust/factory.rs | 106 ++++ src/l4/pkg/l4rust/l4re-rust/io.rs | 478 ++++++++++++++++++ src/l4/pkg/l4rust/l4re-rust/lib.rs | 11 +- src/l4/pkg/l4rust/l4re-rust/mem.rs | 336 ++++++------ src/l4/pkg/l4rust/l4re-rust/sys.rs | 20 +- .../l4rust/libl4re-wrapper/include/fpage.h | 27 + .../pkg/l4rust/libl4re-wrapper/include/icu.h | 24 + .../pkg/l4rust/libl4re-wrapper/include/ipc.h | 2 + .../pkg/l4rust/libl4re-wrapper/include/irq.h | 22 + .../pkg/l4rust/libl4re-wrapper/include/vbus.h | 12 + .../pkg/l4rust/libl4re-wrapper/lib/Makefile | 2 +- src/l4/pkg/l4rust/libl4re-wrapper/lib/fpage.c | 51 ++ src/l4/pkg/l4rust/libl4re-wrapper/lib/icu.c | 57 +++ src/l4/pkg/l4rust/libl4re-wrapper/lib/ipc.c | 10 +- src/l4/pkg/l4rust/libl4re-wrapper/lib/irq.c | 39 ++ src/l4/pkg/l4rust/libl4re-wrapper/lib/vbus.c | 5 + 44 files changed, 1500 insertions(+), 664 deletions(-) create mode 100644 src/l4/pkg/l4rust/l4re-rust/factory.rs create mode 100644 src/l4/pkg/l4rust/l4re-rust/io.rs create mode 100644 src/l4/pkg/l4rust/libl4re-wrapper/include/fpage.h create mode 100644 src/l4/pkg/l4rust/libl4re-wrapper/include/icu.h create mode 100644 src/l4/pkg/l4rust/libl4re-wrapper/include/irq.h create mode 100644 src/l4/pkg/l4rust/libl4re-wrapper/include/vbus.h create mode 100644 src/l4/pkg/l4rust/libl4re-wrapper/lib/fpage.c create mode 100644 src/l4/pkg/l4rust/libl4re-wrapper/lib/icu.c create mode 100644 src/l4/pkg/l4rust/libl4re-wrapper/lib/irq.c create mode 100644 src/l4/pkg/l4rust/libl4re-wrapper/lib/vbus.c diff --git a/src/l4/pkg/io/libvbus/include/vbus_interfaces.h b/src/l4/pkg/io/libvbus/include/vbus_interfaces.h index ca7c9ddd8e..f1160678c6 100644 --- a/src/l4/pkg/io/libvbus/include/vbus_interfaces.h +++ b/src/l4/pkg/io/libvbus/include/vbus_interfaces.h @@ -28,7 +28,7 @@ * the type of the device, i.e. from the point of view of the client * a device is defined by the kinds of sub-interfaces it supports. */ -enum l4vbus_iface_type_t { +typedef enum { L4VBUS_INTERFACE_ICU = 0, L4VBUS_INTERFACE_GPIO, L4VBUS_INTERFACE_PCI, @@ -36,7 +36,7 @@ enum l4vbus_iface_type_t { L4VBUS_INTERFACE_PM, L4VBUS_INTERFACE_BUS, L4VBUS_INTERFACE_GENERIC = 0x20 -}; +} l4vbus_iface_type_t; enum { diff --git a/src/l4/pkg/l4rust/l4-rust/Cargo.toml b/src/l4/pkg/l4rust/l4-rust/Cargo.toml index fd485f44f3..bde38fb295 100644 --- a/src/l4/pkg/l4rust/l4-rust/Cargo.toml +++ b/src/l4/pkg/l4rust/l4-rust/Cargo.toml @@ -2,35 +2,26 @@ name = "l4" version = "0.1.0" authors = ["Sebastian Humenda "] -edition = "2021" +edition = "2018" [lib] path = "lib.rs" [dependencies] -libc = "0.2.147" +num = "0.2" +libc = "0.2.50" [dependencies.bitflags] version = "1.0" default-features = false -[dependencies.l4_sys] -path = "../l4-sys-rust" - -[dependencies.num] -version = "0.4" -default-features = false -features = [] - [dependencies.num-traits] version = "0.2" default-features = false -features = [] [dependencies.num-derive] -version = "0.4" +version = "0.2.3" default-features = false -features = [] [features] default = ["std"] diff --git a/src/l4/pkg/l4rust/l4-rust/cap.rs b/src/l4/pkg/l4rust/l4-rust/cap.rs index e1a0c46e02..e302c83d71 100644 --- a/src/l4/pkg/l4rust/l4-rust/cap.rs +++ b/src/l4/pkg/l4rust/l4-rust/cap.rs @@ -1,4 +1,4 @@ -use core::ops::{Deref, DerefMut}; +use _core::ops::{Deref, DerefMut}; use l4_sys::{ self, l4_cap_consts_t::{L4_CAP_SHIFT, L4_INVALID_CAP_BIT}, @@ -95,6 +95,12 @@ impl Cap { } impl Cap { + pub fn from_raw(val : T) -> Cap { + Cap { + interface: val + } + } + pub fn cast(self) -> Cap { Cap { interface: U::new(self.raw()), @@ -141,7 +147,7 @@ impl Cap { L4_BASE_TASK_CAP as u64, L4_BASE_TASK_CAP as u64, l4_sys::l4_obj_fpage(source.raw(), 0, L4_CAP_FPAGE_RWSD as u8), - self.send_base(L4_MAP_ITEM_GRANT as u32, None) as super::sys::l4_addr_t | 0xe0, + self.send_base(L4_MAP_ITEM_GRANT as u64, None) as super::sys::l4_addr_t | 0xe0, ); Ok(()) } @@ -152,13 +158,11 @@ impl Cap { /// itself). If the first parameter is set, the object will be **granted**. /// In other words, it is possible to specify the object space location of this capability for /// map operations. - fn send_base(&self, grant: u32, base_cap: Option) -> u64 { + fn send_base(&self, grant: u64, base_cap: Option) -> u64 { let base_cap = base_cap.unwrap_or_else(|| self.raw()); l4_sys::l4_map_obj_control(base_cap, grant) } } - -/// Short-hand to construct a Cap from an index. pub fn from(c: CapIdx) -> Cap { Cap { interface: Untyped { 0: c }, @@ -167,8 +171,10 @@ pub fn from(c: CapIdx) -> Cap { /// Construct an invalid cap #[inline] -pub const fn invalid_cap() -> Cap { +pub fn invalid_cap() -> Cap { Cap { - interface: Untyped(l4_sys::l4_cap_consts_t::L4_INVALID_CAP as u64), + interface: Untyped { + 0: L4_INVALID_CAP_BIT as u64, + }, } } diff --git a/src/l4/pkg/l4rust/l4-rust/error.rs b/src/l4/pkg/l4rust/l4-rust/error.rs index c424410b8c..e812eda095 100644 --- a/src/l4/pkg/l4rust/l4-rust/error.rs +++ b/src/l4/pkg/l4rust/l4-rust/error.rs @@ -115,10 +115,7 @@ impl TcrErr { /// Get error from given tag (for current thread) #[inline] pub fn from_tag(tag: l4_msgtag_t) -> Result { - // SAFETY: ToDo, this is unsafe and awaits a generic solution to track usage of the UTCB - unsafe { - Self::from_tag_u(tag, &Utcb::current()) - } + Self::from_tag_u(tag, &Utcb::current()) } /// Get error from given tag and corresponding UTCB. @@ -152,8 +149,8 @@ pub enum Error { InvalidEncoding(Option), } -impl core::fmt::Display for Error { - fn fmt(&self, f: &mut Formatter) -> core::fmt::Result { +impl _core::fmt::Display for Error { + fn fmt(&self, f: &mut Formatter) -> _core::fmt::Result { match self { Error::Generic(e) => write!(f, "Generic L4 error code: {}", e.to_i64().unwrap()), Error::Tcr(i) => write!(f, "IPC error: {}", i.to_i64().unwrap()), @@ -230,12 +227,6 @@ impl Error { } } -impl core::convert::From for Error { - fn from(o: GenericErr) -> Self { - Error::Generic(o) - } -} - #[cfg(feature = "std")] impl core::convert::From for Error { fn from(u: std::string::FromUtf8Error) -> Self { @@ -243,7 +234,7 @@ impl core::convert::From for Error { } } -pub type Result = core::result::Result; +pub type Result = ::_core::result::Result; /// Short-hand macro for several `l4::error::Error` cases /// @@ -255,7 +246,7 @@ pub type Result = core::result::Result; #[macro_export] macro_rules! l4_err { (Generic, $err:ident) => { - Err($crate::error::Error::Generic( + return Err($crate::error::Error::Generic( $crate::error::GenericErr::$err, )) }; @@ -274,7 +265,7 @@ macro_rules! l4_err { macro_rules! l4_err_if { ($condition:expr => $($token:tt)*) => { if $condition { - return l4_err!($($token)*); + l4_err!($($token)*); } } } diff --git a/src/l4/pkg/l4rust/l4-rust/ipc/iface.rs b/src/l4/pkg/l4rust/l4-rust/ipc/iface.rs index c5d677a6a2..f84ba86dc1 100644 --- a/src/l4/pkg/l4rust/l4-rust/ipc/iface.rs +++ b/src/l4/pkg/l4rust/l4-rust/ipc/iface.rs @@ -76,7 +76,13 @@ macro_rules! derive_functors { } } +/// Extract the opcode from a list of function names +/// +/// The basic assumption is that all functions share the same opcode type in an IPC interface. +/// Within a macro, it is impossible to separate the first element from a type list, hence this +/// helper macro gets the head and yields the opcode type. #[macro_export] + macro_rules! derive_ipc_calls { ($proto:expr; $($opcode:expr => fn $name:ident($($argname:ident: $type:ty),*) -> $return:ty;)* @@ -90,10 +96,7 @@ macro_rules! derive_ipc_calls { // ToDo: would re-allocate a capability each time; how to control number of // required slots let mut caps = $crate::ipc::types::Bufferless { }; - // SAFETY: We have to assume that the UTCB is unused, see #5. - let mut mr = unsafe { - $crate::utcb::Utcb::current().mr() - }; + let mut mr = $crate::utcb::Utcb::current().mr(); // write opcode unsafe { mr.write($opcode)?; diff --git a/src/l4/pkg/l4rust/l4-rust/ipc/mod.rs b/src/l4/pkg/l4rust/l4-rust/ipc/mod.rs index 7f14d0d0e8..9f85c8e0ae 100644 --- a/src/l4/pkg/l4rust/l4-rust/ipc/mod.rs +++ b/src/l4/pkg/l4rust/l4-rust/ipc/mod.rs @@ -1,9 +1,9 @@ /// L4 IPC framework /// -/// The interplay in a component-based microkernel system and the number of interfaces create -/// inherent complexity. This framework assists the application programmer to implement services -/// easily without the need to understand all low-level details. As a plus, clients can be -/// auto-derived from the IPC interface definition shared between client and server. +/// L4 IPC becomes due to its minimality a comlex affair, which is why this framework assists the +/// application programmer to implement services easily without the need to understand all +/// low-level details. As a plus, clients can be auto-derived from the IPC interface definition +/// shared between client and server. /// /// # Interface Compatibility /// @@ -16,20 +16,20 @@ mod iface; mod serialise; pub mod server; -pub mod syscall; pub mod types; pub use self::serialise::{Serialisable, Serialiser}; pub use self::server::{server_impl_callback, Callback, Loop, LoopBuilder}; pub use self::types::*; -pub use syscall::*; -use core::{convert::From, mem::transmute}; -use l4_sys::{l4_msgtag_flags::*, l4_msgtag_t, msgtag}; +use _core::{convert::From, mem::transmute}; +use l4_sys::{l4_msgtag_flags::*, l4_msgtag_t, l4_timeout_t, l4_ipc_error, msgtag}; use num_traits::FromPrimitive; +use crate::cap::{Cap, Interface}; use crate::error::{Error, Result}; use crate::types::{Mword, Protocol, UMword}; +use crate::utcb::Utcb; use l4_sys; @@ -83,7 +83,6 @@ const L4_MSGTAG_ERROR_I: isize = L4_MSGTAG_ERROR as isize; /// let _ = msgtag(0, 1, 1, 0); /// ``` #[derive(Clone)] -#[repr(transparent)] pub struct MsgTag { raw: Mword, } @@ -98,7 +97,7 @@ impl MsgTag { MsgTag { // the C type is a wrapper type and we reimplement its creation function in // l4_sys::ipc_basic anyway. We want to safe every cycle here. - raw: msgtag(label, words, items, flags).raw as _, + raw: unsafe { transmute::(msgtag(label, words, items, flags)) }, } } @@ -186,11 +185,17 @@ impl MsgTag { } #[inline] - pub fn raw(self) -> l4_msgtag_t { + pub fn raw(&self) -> l4_msgtag_t { ::l4_sys::l4_msgtag_t { raw: self.raw as i64, } } + + #[inline] + pub fn has_ipc_error(&self) -> bool { + let err = unsafe { l4_ipc_error(self.raw(), Utcb::current().raw) }; + err != 0 + } } impl From for MsgTag { @@ -202,6 +207,62 @@ impl From for MsgTag { } } +/// Simple IPC Call +/// +/// Call to given destination and block for answer. +#[inline(always)] +pub fn call( + dest: &Cap, + utcb: &mut Utcb, + tag: MsgTag, + timeout: l4_timeout_t, +) -> MsgTag { + unsafe { + MsgTag::from(l4_sys::l4_ipc_call( + dest.raw(), + utcb.raw, + tag.raw(), + timeout, + )) + } +} + +#[inline] +pub unsafe fn receive( + object: Cap, + utcb: &mut Utcb, + timeout: l4_timeout_t, +) -> l4_msgtag_t { + l4_sys::l4_ipc_receive(object.raw(), utcb.raw, timeout) +} + +/* +#[inline] +pub unsafe fn reply_and_wait(utcb: &mut Utcb, tag: l4_msgtag_t, + src: *mut UMword, timeout: l4_timeout_t) -> l4_msgtag_t { + l4_ipc_reply_and_wait_w(utcb.raw, tag, src, timeout) +} + + +#[inline] +pub unsafe fn l4_ipc_wait(utcb: &mut Utcb, label: *mut l4_umword_t, + timeout: l4_timeout_t) -> l4_msgtag_t { + l4_ipc_wait_w(utcb, label, timeout) +} + +#[inline] +pub unsafe fn l4_msgtag(label: ::libc::c_long, words: c_uint, + items: c_uint, flags: c_uint) -> l4_msgtag_t { + l4_msgtag_w(label, words, items, flags) +} + +#[inline] +pub unsafe fn l4_rcv_ep_bind_thread(gate: &Cap, thread: &Cap, + label: l4_umword_t) -> l4_msgtag_t { + l4_rcv_ep_bind_thread_w(gate.cap, thread.cap, label) +} +*/ + //////////////////////////////////////////////////////////////////////////////// // re-implemented inline functions from l4/sys/ipc.h: diff --git a/src/l4/pkg/l4rust/l4-rust/ipc/serialise.rs b/src/l4/pkg/l4rust/l4-rust/ipc/serialise.rs index 2ef0ee790f..b981742152 100644 --- a/src/l4/pkg/l4rust/l4-rust/ipc/serialise.rs +++ b/src/l4/pkg/l4rust/l4-rust/ipc/serialise.rs @@ -21,12 +21,15 @@ pub unsafe trait Serialisable: Clone {} /// as well, great care has been taken. This is usually safe for primitive /// types, a few types from this framework and for structs with a C ABI. /// -/// # Safety -/// -/// The implementor must make sure that the type does not contain references, pointers, and no -/// non-primitive types. -/// An exception is if the references can be resolved while writing. For instance, when writing a -/// vector. +/// The UTCB is accessed through the [`ArgAccesss`](struct.ArgAccess.T.html). +/// The implementor may choose to use the default implementation which +/// transmutes the message registers at the next free and already correctly +/// aligned location and copies the data of `Self` to it. The implementor may +/// choose to override this behaviour, i.e. by using the `write_items` function +/// of the message registers, by doing internal accounting or by using the +/// kernel buffer store (if capabilities are being transfered), etc. This +/// description applies both for reading and writing. For examples of +/// implementors, see the Flex Page and Cap(ability) types. pub unsafe trait Serialiser where Self: Sized, @@ -40,12 +43,12 @@ where /// though it is expected to hold a value when this type reads a value from it. In other words, /// before the framework passes the slice and the implementing type for this method is a /// `Cap`, a capability needs to be within the slice. - fn read(mr: &mut UtcbMr, _: &mut BufferAccess) -> Result; + unsafe fn read(mr: &mut UtcbMr, _: &mut BufferAccess) -> Result; /// Write a value of this type to the message registers /// /// Offset and alignment are automatically calculated by the `ArgAccess`. - fn write(self, mr: &mut UtcbMr) -> Result<()>; + unsafe fn write(self, mr: &mut UtcbMr) -> Result<()>; } macro_rules! impl_serialisable { @@ -54,11 +57,11 @@ macro_rules! impl_serialisable { unsafe impl Serialisable for $type { } unsafe impl Serialiser for $type { #[inline] - fn read(mr: &mut UtcbMr, _: &mut BufferAccess) -> Result { + unsafe fn read(mr: &mut UtcbMr, _: &mut BufferAccess) -> Result { mr.read::() // most types are read from here } #[inline] - fn write(self, mr: &mut UtcbMr) -> Result<()> { + unsafe fn write(self, mr: &mut UtcbMr) -> Result<()> { mr.write::(self) } } @@ -72,12 +75,11 @@ impl_serialisable!( unsafe impl Serialiser for () { #[inline] - fn read(_: &mut UtcbMr, _: &mut BufferAccess) -> Result<()> { + unsafe fn read(_: &mut UtcbMr, _: &mut BufferAccess) -> Result<()> { Ok(()) } - #[inline] - fn write(self, _: &mut UtcbMr) -> Result<()> { + unsafe fn write(self, _: &mut UtcbMr) -> Result<()> { Ok(()) } } @@ -85,25 +87,25 @@ unsafe impl Serialiser for () { unsafe impl Serialisable for SndFlexPage {} unsafe impl Serialiser for SndFlexPage { #[inline] - fn write(self, mr: &mut UtcbMr) -> Result<()> { + unsafe fn write(self, mr: &mut UtcbMr) -> Result<()> { mr.write_item::(self) } #[inline] - fn read(_: &mut UtcbMr, _: &mut BufferAccess) -> Result { + unsafe fn read(_: &mut UtcbMr, _: &mut BufferAccess) -> Result { unimplemented!("flex pages are read by the concrete type, e.g. Cap"); } } unsafe impl Serialiser for Option { #[inline] - fn read(mr: &mut UtcbMr, _: &mut BufferAccess) -> Result> { + unsafe fn read(mr: &mut UtcbMr, _: &mut BufferAccess) -> Result> { let val = mr.read::()?; mr.read::().map(|_| Some(val)) } #[inline] - fn write(self, mr: &mut UtcbMr) -> Result<()> { + unsafe fn write(self, mr: &mut UtcbMr) -> Result<()> { match self { None => { mr.skip::()?; @@ -118,39 +120,46 @@ unsafe impl Serialiser for Option { } unsafe impl Serialiser for Cap { - /// Read a capability. + /// Read a capability from the given capability slice + /// + /// The slice must be constructed such that the first entry is the capability to be read, this + /// method relies on it. #[inline] - fn read(_: &mut UtcbMr, bufs: &mut BufferAccess) -> Result { - // SAFETY: ToDo, this awaits the resolution of #5 - unsafe { - Ok(bufs.rcv_cap_unchecked()) - } + unsafe fn read(_: &mut UtcbMr, bufs: &mut BufferAccess) -> Result { + Ok(bufs.rcv_cap_unchecked()) } #[inline] - fn write(self, mr: &mut UtcbMr) -> Result<()> { + unsafe fn write(self, mr: &mut UtcbMr) -> Result<()> { let fp = SndFlexPage::from_cap(&self, FpageRights::RWX, None); fp.write(mr) } } #[cfg(feature = "std")] +unsafe impl<'a> Serialiser for &'a str { + #[inline] + unsafe fn read(mr: &mut UtcbMr, _: &mut BufferAccess) -> Result { + mr.read_str() + } + + #[inline] + unsafe fn write(self, mr: &mut UtcbMr) -> Result<()> { + mr.write_str(self) + } +} + #[cfg(feature = "std")] #[cfg(feature = "std")] unsafe impl Serialiser for std::string::String { #[inline] - fn read(mr: &mut UtcbMr, _x: &mut BufferAccess) -> Result { + unsafe fn read(mr: &mut UtcbMr, _x: &mut BufferAccess) -> Result { use std::borrow::ToOwned; - // SAFETY: Reading a string slice is unsafe as the UTCB may be overridden at any point. - // Since we allocate a string straight after acquiring the slice, it is turned into a safe - // operation. - unsafe { - Ok(mr.read_str()?.to_owned()) - } + Ok(mr.read_str()?.to_owned()) } #[inline] - fn write(self, mr: &mut UtcbMr) -> Result<()> { + unsafe fn write(self, mr: &mut UtcbMr) -> Result<()> { mr.write_str(&self) } } @@ -158,12 +167,13 @@ unsafe impl Serialiser for std::string::String { #[cfg(feature = "std")] unsafe impl Serialiser for std::vec::Vec { #[inline] - fn read(mr: &mut UtcbMr, x: &mut BufferAccess) -> Result { - super::types::BufArray::read(mr, x).map(|v| v.into()) + unsafe fn read(mr: &mut UtcbMr, x: &mut BufferAccess) -> Result { + let slice: &[T] = super::types::BufArray::read(mr, x)?.into(); + Ok(std::vec::Vec::from(slice)) } #[inline] - fn write(self, mr: &mut UtcbMr) -> Result<()> { + unsafe fn write(self, mr: &mut UtcbMr) -> Result<()> { mr.write_slice::(self.as_slice()) } } diff --git a/src/l4/pkg/l4rust/l4-rust/ipc/server.rs b/src/l4/pkg/l4rust/l4-rust/ipc/server.rs index 1b56053f70..2f27b1dd9d 100644 --- a/src/l4/pkg/l4rust/l4-rust/ipc/server.rs +++ b/src/l4/pkg/l4rust/l4-rust/ipc/server.rs @@ -1,4 +1,4 @@ -use core::marker::PhantomData; +use _core::marker::PhantomData; use l4_sys::{self, l4_cap_idx_t as CapIdx, l4_timeout_t, l4_utcb_t}; use super::super::{ @@ -10,7 +10,7 @@ use super::{ types::{BufferAccess, BufferManager, Bufferless, Callable, CapProvider, Demand, Dispatch}, MsgTag, }; -use core::ffi::c_void; +use libc::c_void; /// Stack-based buffer for server objects /// @@ -76,7 +76,7 @@ pub trait LoopHook { /// [LoopAction](enum.LoopAction.html). fn ipc_error(&mut self, _: &mut Loop, tag: &MsgTag) -> LoopAction where - Self: core::marker::Sized, + Self: ::_core::marker::Sized, C: CapProvider, { match (*tag).clone().result() { @@ -98,7 +98,7 @@ pub trait LoopHook { // ToDo: docs + rethink Dispatch trait and LoopHook interface to take **any** error interace fn application_error(&mut self, _: &mut Loop, e: Error) -> LoopAction where - Self: core::marker::Sized, + Self: ::_core::marker::Sized, C: CapProvider, { // ^ by convention, error types are returned as negative integer @@ -143,8 +143,7 @@ where } // first c_void is the server struct, the second c_void is the ArgAccess instance -pub type Callback = - fn(*mut core::ffi::c_void, MsgTag, &mut UtcbMr, &mut BufferAccess) -> Result; +pub type Callback = fn(*mut libc::c_void, MsgTag, &mut UtcbMr, &mut BufferAccess) -> Result; pub struct Loop<'a, Hooks: LoopHook, BrMgr> { /// thread that this server runs in diff --git a/src/l4/pkg/l4rust/l4-rust/ipc/types.rs b/src/l4/pkg/l4rust/l4-rust/ipc/types.rs index 36789d74f2..eb34a3108d 100644 --- a/src/l4/pkg/l4rust/l4-rust/ipc/types.rs +++ b/src/l4/pkg/l4rust/l4-rust/ipc/types.rs @@ -1,12 +1,11 @@ //! IPC Interface Types -use core::ptr::NonNull; +use _core::{mem::transmute, ptr::NonNull}; use super::super::{ cap::{invalid_cap, Cap, CapIdx, IfaceInit, Interface}, error::{Error, GenericErr, Result}, ipc::serialise::{Serialisable, Serialiser}, ipc::MsgTag, - l4_err, types::UMword, utcb::UtcbMr, }; @@ -300,74 +299,57 @@ impl CapProvider for BufferManager { /// Note that this array can be constructed from a slice and also supports the /// conversion into a vector via the `Into` trait. pub struct Array<'a, Len, T> { - len: Len, - start: *const T, - _life: core::marker::PhantomData<&'a T>, + inner: &'a [T], + // (l4) c++ arrays use different slice length by default + _len_type: ::core::marker::PhantomData, } unsafe impl<'a, Len, T> Serialiser for Array<'a, Len, T> where - Len: num::NumCast + Serialisable + Copy, + Len: num::NumCast + Serialisable, T: Serialisable, - Self: 'a, { #[inline] - fn read(mr: &mut UtcbMr, _: &mut BufferAccess) -> Result { - // SAFETY: This can only be made safe when #9 is implemented. - let sl = unsafe { - mr.read_slice::()? - }; + unsafe fn read(mr: &mut UtcbMr, _: &mut BufferAccess) -> Result { Ok(Array { - start: sl.as_ptr(), - // SAFETY: the IPC buffer is bounded to 32 mwords and hence the len always fits - len: Len::from(sl.len()).ok_or(GenericErr::OutOfBounds)?, - _life: core::marker::PhantomData, + inner: transmute::<_, &'a [T]>(mr.read_slice::()?), + _len_type: ::core::marker::PhantomData, }) } - - fn write(self, mr: &mut UtcbMr) -> Result<()> { - // SAFETY: ToDo, this awaits resolution of #9. This is safe for anything valid *outside* - // the UTCB. - let sl = unsafe { core::slice::from_raw_parts(self.start, self.len().to_u64().unwrap() as usize) }; + unsafe fn write(self, mr: &mut UtcbMr) -> Result<()> { // default array in C++ is unsigned short - should be flexible - mr.write_slice::(sl) + mr.write_slice::(self.inner) } } impl<'a, Len, T> From<&'a [T]> for Array<'a, Len, T> where - Len: Serialisable + num::NumCast + num::FromPrimitive + Copy, + Len: Serialisable + num::NumCast, T: Serialisable, { fn from(sl: &'a [T]) -> Self { Array { - start: sl.as_ptr(), - len: Len::from_u64(sl.len() as u64).unwrap(), - _life: core::marker::PhantomData, + inner: sl, + _len_type: ::core::marker::PhantomData, } } } -#[cfg(feature = "std")] -impl<'a, T: Serialisable> core::convert::Into> for BufArray<'a, T> { - fn into(self) -> Vec { - // SAFETY: Safe only because the slice is immediately copied to a vector. - let sl: &[T] = unsafe { - core::slice::from_raw_parts(self.start, self.len() as usize) - }; - let mut v = Vec::new(); - v.extend_from_slice(sl); - v - } -} - -impl<'a, Len, T> Array<'a, Len, T> +impl<'a, Len, T> Into<&'a [T]> for Array<'a, Len, T> where - Len: Serialisable + num::NumCast + Copy, + Len: Serialisable + num::NumCast, T: Serialisable, { - pub fn len(&self) -> Len { - self.len + fn into(self) -> &'a [T] { + self.inner + } +} + +#[cfg(feature = "std")] +impl<'a, T: Serialisable> core::convert::Into> for BufArray<'a, T> { + fn into(self) -> Vec { + let slice: &[T] = self.into(); + Vec::from(slice) } } diff --git a/src/l4/pkg/l4rust/l4-rust/lib.rs b/src/l4/pkg/l4rust/l4-rust/lib.rs index 168b5ae73b..21a60b9c35 100644 --- a/src/l4/pkg/l4rust/l4-rust/lib.rs +++ b/src/l4/pkg/l4rust/l4-rust/lib.rs @@ -1,14 +1,20 @@ +// ToDo: things to be stabilised in Rust: +#![feature(associated_type_defaults)] #![no_std] #[cfg(feature = "std")] extern crate std; +#[cfg(not(without_std))] +pub extern crate core as _core; + +extern crate l4_sys; #[macro_use] extern crate bitflags; #[macro_use] extern crate num_derive; extern crate num_traits; -// apart from macro_use, keep this alphabetical +// apart from macro_use, eep this alphabetical #[macro_use] pub mod types; #[macro_use] @@ -17,9 +23,6 @@ pub mod error; pub mod utcb; pub mod cap; pub mod ipc; -#[cfg(not(feature = "std"))] -#[macro_use] -pub mod nostd_helper; pub mod task; pub use crate::error::{Error, Result}; @@ -28,3 +31,6 @@ pub use crate::utcb::*; pub mod sys { pub use l4_sys::*; } + +// a few re-exports +pub use sys::{round_page, trunc_page}; diff --git a/src/l4/pkg/l4rust/l4-rust/utcb.rs b/src/l4/pkg/l4rust/l4-rust/utcb.rs index 297bb55d56..3262c4957f 100644 --- a/src/l4/pkg/l4rust/l4-rust/utcb.rs +++ b/src/l4/pkg/l4rust/l4-rust/utcb.rs @@ -1,5 +1,4 @@ -use core::{ - convert::From, +use _core::{ marker::PhantomData, mem::{align_of, size_of}, ops::{Deref, DerefMut}, @@ -21,7 +20,7 @@ use crate::types::{Mword, UMword}; use num::{cast::ToPrimitive, NumCast}; /// UTCB constants (architecture-specific) -pub use crate::sys::consts::UtcbConsts as Consts; +pub use crate::l4_sys::consts::UtcbConsts as Consts; /// Number of words used by an item when written to the message registers pub const WORDS_PER_ITEM: usize = 2; @@ -57,13 +56,11 @@ pub struct Utcb { } impl Utcb { - /// Get a reference to the current UTCB. - /// - /// # Safety - /// - /// The caller must make sure that the UTCB exists exactly once, otherwise concurrent - /// modifications and invalidation of references to the UTCB can occur. - pub unsafe fn current() -> Utcb { + pub fn from_utcb(utcb: *mut l4_utcb_t) -> Utcb { + Utcb { raw: utcb } + } + + pub fn current() -> Utcb { unsafe { // this can't fail: no UTCB, no thread -> no execution Utcb { raw: l4_utcb() } @@ -112,19 +109,7 @@ impl Utcb { pub fn bdr(&self) -> usize { unsafe { (*l4_utcb_br()).bdr as usize } } - - pub fn raw(&mut self) -> *mut l4_utcb_t { - self.raw - } } - -impl From<*mut l4_utcb_t> for Utcb { - fn from(utcb: *mut l4_utcb_t) -> Utcb { - Utcb { raw: utcb } - } -} - - /// Flex page types #[repr(u8)] #[derive(FromPrimitive, ToPrimitive)] @@ -206,18 +191,22 @@ impl SndFlexPage { } } -/// Align the given pointer -/// -/// # Safety +/// Return an aligned pointer to the next free message register /// -/// The given pointer MUST stay within the allocated bounds and is UB otherwise. +/// The pointer is advanced by the end of the already written message registers, +/// aligned to the required type. Returned is a +/// pointer to the type-aligned memory region. +//#[inline] +//pub unsafe fn align_with_offset(ptr: *mut u8, offset: usize) +// -> (*mut u8, usize) { +// let ptr = ptr.offset(offset as isize); +// let new_offset = ptr.align_offset(align_of::()); +// (ptr.offset(new_offset as isize), offset + new_offset) +//} #[inline(always)] unsafe fn align(ptr: *mut u8) -> *mut u8 { let new_offset = ptr.align_offset(align_of::()); - // SAFETY: the given pointer MUST stay within the allocated object. - unsafe { - ptr.add(new_offset) - } + ptr.add(new_offset) } // make the dumb C types more smart: let them know their limits @@ -263,21 +252,12 @@ impl Registers { /// /// The value is aligned and written into the message registers. #[inline] - pub fn write(&mut self, val: T) -> Result<()> { - // SAFETY: The ponter must be checked for the bounds of the object beforehand. - let ptr = unsafe { - align::(self.buf) - }; - // SAFETY: The ponter must be checked for the bounds of the object beforehand. - let next = unsafe { - ptr.add(size_of::()) - }; + pub unsafe fn write(&mut self, val: T) -> Result<()> { + let ptr = align::(self.buf); + let next = ptr.add(size_of::()); l4_err_if!((next as usize - self.base as usize) > U::BUF_SIZE => Generic, MsgTooLong); - // SAFETY: Bounds and alignment have been checked. - unsafe { - *(ptr as *mut T) = val; - } + *(ptr as *mut T) = val; self.buf = next; Ok(()) } @@ -287,69 +267,51 @@ impl Registers { /// This function reads from the given pointer + the internal offset a value /// from the specified type. If a read beyond the message registers is /// attempted, an error is returned. + /// This is unsafe due to a missing guarantee that + /// the pointer to the UTCB, with which the object was constructed is valid + /// and that the memory region behind has the length of + /// `UTCB_DATA_SIZE_IN_BYTES`. #[inline] - pub fn read(&mut self) -> Result { - // SAFETY: ToDo, this is unsafe unless bounds are checked - let ptr = unsafe { - align::(self.buf) - }; - // SAFETY: ToDo, this is unsafe unless bounds are checked - let next = unsafe { - ptr.add(size_of::()) - }; + pub unsafe fn read(&mut self) -> Result { + let ptr = align::(self.buf); + let next = ptr.add(size_of::()); l4_err_if!((next as usize - self.base as usize) > U::BUF_SIZE => Generic, MsgTooLong); - // SAFETY: ToDo, this is unsafe unless bounds are checked - let val: T = unsafe { - (*(ptr as *mut T)).clone() - }; + let val: T = (*(ptr as *mut T)).clone(); self.buf = next; Ok(val) } /// Write a slice - pub fn write_slice(&mut self, val: &[T]) -> Result<()> + pub unsafe fn write_slice(&mut self, val: &[T]) -> Result<()> where Len: Serialisable + NumCast, T: Serialisable, { - // SAFETY: this is safe as the pointer calculations are not used for accessing an object, - // but only for its bounds calculation. - let (buf_start, buf_end) = unsafe { - let ptr = align::(self.buf); - let ptr = ptr.add(1); - // ToDo: does C align? - let buf_start = align::(ptr); - (buf_start, buf_start.add(size_of::() * val.len())) - }; - l4_err_if!(buf_end as usize - self.base as usize > U::BUF_SIZE + self.write::(NumCast::from(val.len()).ok_or(Error::Generic(GenericErr::InvalidArg))?)?; + let ptr = align::(self.buf); + let end = ptr.add(size_of::() * val.len()); + l4_err_if!(end as usize - self.base as usize > U::BUF_SIZE => Generic, MsgTooLong); - // SAFETY: The bounds and the alignment has been checked above. - unsafe { - self.write::(NumCast::from(val.len()).ok_or(Error::Generic(GenericErr::InvalidArg))?)?; - val.as_ptr() - .copy_to_nonoverlapping(buf_start as *mut T, val.len()); - } - self.buf = buf_end; // move pointer + val.as_ptr() + .copy_to_nonoverlapping(ptr as *mut T, val.len()); + self.buf = end; // move pointer Ok(()) } - /// Serialise a &str as a framework-compatible string. - pub fn write_str(&mut self, val: &str) -> Result<()> { - self.write_slice::(val.as_bytes()) + // Serialise a &str as a C-compatible, 0-terminated UTF-8 string. + pub unsafe fn write_str(&mut self, val: &str) -> Result<()> { + self.write::(val.len() + 1)?; + + let ptr = align::(self.buf); + let end = ptr.add(size_of::() * val.len()); + l4_err_if!(end as usize - self.base as usize > U::BUF_SIZE + => Generic, MsgTooLong); + val.as_ptr().copy_to_nonoverlapping(ptr, val.len()); + self.buf = end; // advance pointer behind last element + self.write::(0u8) } - /// Read a slice from the registers - /// - /// This function reads a slice from the registers, compatible to the C++ Array types. - /// - /// # Safety - /// - /// The slice is a direct view into the registers and hence highly unsafe. A system call may - /// directly overwrite the data that this slice points to. - /// - /// The caller must make sure that the data is not overwritten by a syscall, or by other parts - /// of the code in the current application. pub unsafe fn read_slice(&mut self) -> Result<&[T]> where Len: Serialisable + ToPrimitive, @@ -368,11 +330,7 @@ impl Registers { /// /// This is not a copy, but operates on the bytes of the message registers. /// Copy this string ASAP and at least before the next IPC takes place. - /// 0-bytes from C strings will be discarded. - /// - /// # Safety - /// - /// See [Self::read_slice]. + /// 0-bytes from C strings will be discarded pub unsafe fn read_str<'a>(&mut self) -> Result<&'a str> { let len = self.read::()?; let end = self.buf.add(len); @@ -454,7 +412,7 @@ impl UtcbMr { /// Write given item to the next free, type-aligned slot /// /// The item (e.g. a flex page) is aligned and written into the message registers. - pub fn write_item(&mut self, val: T) -> Result<()> { + pub unsafe fn write_item(&mut self, val: T) -> Result<()> { self.regs.write(val)?; self.items += 1; Ok(()) diff --git a/src/l4/pkg/l4rust/l4-sys-rust/Cargo.toml b/src/l4/pkg/l4rust/l4-sys-rust/Cargo.toml index fd8fc62a53..0bf1837e37 100644 --- a/src/l4/pkg/l4rust/l4-sys-rust/Cargo.toml +++ b/src/l4/pkg/l4rust/l4-sys-rust/Cargo.toml @@ -8,8 +8,7 @@ edition = "2018" path = "lib.rs" [build-dependencies] -bindgen = "0.68" +bindgen = "0.65.1" [dependencies] -core-ffi-helpers = { path = "../core-ffi-helpers" } -libc = "0.2.147" +libc = "0.2.50" diff --git a/src/l4/pkg/l4rust/l4-sys-rust/Control b/src/l4/pkg/l4rust/l4-sys-rust/Control index 4498d81f2e..509198696a 100644 --- a/src/l4/pkg/l4rust/l4-sys-rust/Control +++ b/src/l4/pkg/l4rust/l4-sys-rust/Control @@ -1,3 +1,3 @@ provides: l4-sys-rust -requires: l4sys libpthread libl4re-wrapper +requires: l4sys libpthread libl4re-wrapper libio libio-vbus Maintainer: sebastian.humenda@tu-dresden.de diff --git a/src/l4/pkg/l4rust/l4-sys-rust/Makefile b/src/l4/pkg/l4rust/l4-sys-rust/Makefile index 672cd29d95..0523690692 100644 --- a/src/l4/pkg/l4rust/l4-sys-rust/Makefile +++ b/src/l4/pkg/l4rust/l4-sys-rust/Makefile @@ -5,5 +5,5 @@ TARGET = libl4_sys-rust.rlib SRC_RS = lib.rs DEPENDS_PKGS = l4sys -REQUIRES_LIBS = l4sys libl4re-wrapper +REQUIRES_LIBS = l4sys libl4re-wrapper libio libio-vbus include $(L4DIR)/mk/lib.mk diff --git a/src/l4/pkg/l4rust/l4-sys-rust/bindgen.h b/src/l4/pkg/l4rust/l4-sys-rust/bindgen.h index dbf6bd112e..7d332e2400 100644 --- a/src/l4/pkg/l4rust/l4-sys-rust/bindgen.h +++ b/src/l4/pkg/l4rust/l4-sys-rust/bindgen.h @@ -8,9 +8,15 @@ #include #include #include +#include +#include +#include +#include // custom wrapper to make inlined C functions visible #include #include -#include +#include +#include +#include diff --git a/src/l4/pkg/l4rust/l4-sys-rust/build.rs b/src/l4/pkg/l4rust/l4-sys-rust/build.rs index eed7adbf3e..56967efacd 100644 --- a/src/l4/pkg/l4rust/l4-sys-rust/build.rs +++ b/src/l4/pkg/l4rust/l4-sys-rust/build.rs @@ -1,3 +1,5 @@ +extern crate bindgen; + use std::env; use std::path::PathBuf; @@ -6,13 +8,11 @@ fn main() { .header("bindgen.h") .use_core() .derive_default(true) - .rustified_enum(".*") // ToDo: this is dangerous, get rid + .rustified_enum(".*") .blocklist_type("l4_addr_t") - .blocklist_type("strtod") - .blocklist_type("max_align_t") - .blocklist_file(".*/stdlib.h") - .ctypes_prefix("core::ffi"); + .ctypes_prefix("::libc"); if let Ok(include_dirs) = ::std::env::var("L4_INCLUDE_DIRS") { + println!("hi: {}", include_dirs); for item in include_dirs.split(" ") { bindings = bindings.clang_arg(item); } @@ -23,3 +23,4 @@ fn main() { .write_to_file(out_path.join("bindings.rs")) .expect("Couldn't write bindings!"); } + diff --git a/src/l4/pkg/l4rust/l4-sys-rust/cap.rs b/src/l4/pkg/l4rust/l4-sys-rust/cap.rs index eddd599cb7..24a7a5926d 100644 --- a/src/l4/pkg/l4rust/l4-sys-rust/cap.rs +++ b/src/l4/pkg/l4rust/l4-sys-rust/cap.rs @@ -1,4 +1,4 @@ -use core::ffi::{c_uchar, c_uint}; +use libc::{c_uchar, c_uint}; use crate::c_api::*; @@ -6,6 +6,8 @@ use crate::c_api::*; //////////////////////////////////////////////////////////////////////////////// // inline functions from l4/sys/env.h: + + #[inline] pub fn l4_is_invalid_cap(cap: l4_cap_idx_t) -> bool { (cap & l4_cap_consts_t::L4_INVALID_CAP_BIT as u64) > 0 @@ -13,7 +15,8 @@ pub fn l4_is_invalid_cap(cap: l4_cap_idx_t) -> bool { // ToDo: leicht nachzuimplementieren #[inline] -pub unsafe fn l4_obj_fpage(obj: l4_cap_idx_t, order: c_uint, rights: c_uchar) -> l4_fpage_t { +pub unsafe fn l4_obj_fpage(obj: l4_cap_idx_t, order: c_uint, rights: c_uchar) + -> l4_fpage_t { l4_obj_fpage_w(obj, order, rights) } @@ -29,11 +32,12 @@ pub unsafe fn l4_obj_fpage(obj: l4_cap_idx_t, order: c_uint, rights: c_uchar) -> /// * `cache` Cacheability hints for memory flex pages. See `l4_fpage_cacheability_opt_t` /// * `grant` Indicates if it is a map or a grant item. #[inline] -pub fn l4_map_control(snd_base: l4_umword_t, cache: u8, grant: u32) -> l4_umword_t { +pub fn l4_map_control(snd_base: l4_umword_t, cache: u8, grant: u64) + -> l4_umword_t { (snd_base & L4_fpage_control::L4_FPAGE_CONTROL_MASK as u64) | ((cache as l4_umword_t) << 4) | (l4_msg_item_consts_t::L4_ITEM_MAP as u64) - | grant as l4_umword_t + | grant } /// Create the first word for a map item for the object space. @@ -43,6 +47,7 @@ pub fn l4_map_control(snd_base: l4_umword_t, cache: u8, grant: u32) -> l4_umword /// * `spot`: Hot spot address, used to determine what is actually mapped /// when send and receive flex pages have different size. /// * `grant`: Indicates if it is a map item or a grant item. -pub fn l4_map_obj_control(snd_base: l4_umword_t, grant: u32) -> l4_umword_t { +pub fn l4_map_obj_control(snd_base: l4_umword_t, grant: u64) -> l4_umword_t { l4_map_control(snd_base, 0, grant) } + diff --git a/src/l4/pkg/l4rust/l4-sys-rust/consts.rs b/src/l4/pkg/l4rust/l4-sys-rust/consts.rs index 79354100e8..3ce0b98224 100644 --- a/src/l4/pkg/l4rust/l4-sys-rust/consts.rs +++ b/src/l4/pkg/l4rust/l4-sys-rust/consts.rs @@ -4,14 +4,16 @@ use crate::c_api::*; /// An alias for the corresponding platform enum #[cfg(target_arch = "x86_64")] pub use crate::c_api::L4_utcb_consts_amd64 as UtcbConsts; -#[cfg(target_arch = "aarch64")] -pub use crate::c_api::L4_utcb_consts_arm64 as UtcbConsts; +/// An alias for the corresponding platform enum #[cfg(target_arch = "x86")] pub use L4_utcb_consts_x86 as UtcbConsts; + // redefined constants and enums with (wrongly) generated type -pub const UTCB_GENERIC_DATA_SIZE: usize = UtcbConsts::L4_UTCB_GENERIC_DATA_SIZE as usize; -pub const UTCB_BUF_REGS_OFFSET: isize = UtcbConsts::L4_UTCB_BUF_REGS_OFFSET as isize; +pub const UTCB_GENERIC_DATA_SIZE: usize = + L4_utcb_consts_amd64::L4_UTCB_GENERIC_DATA_SIZE as usize; +pub const UTCB_BUF_REGS_OFFSET: isize = UtcbConsts::L4_UTCB_BUF_REGS_OFFSET + as isize; // Constants for message items. // @@ -23,4 +25,6 @@ pub const UTCB_BUF_REGS_OFFSET: isize = UtcbConsts::L4_UTCB_BUF_REGS_OFFSET as i pub const MSGTAG_ERROR: i64 = l4_msgtag_flags::L4_MSGTAG_ERROR as i64; /// 0 send timeout -pub const L4_IPC_SEND_TIMEOUT_0: l4_timeout_t = l4_timeout_t { raw: 0x04000000 }; +pub const L4_IPC_SEND_TIMEOUT_0: l4_timeout_t = l4_timeout_t { + raw: 0x04000000 +}; diff --git a/src/l4/pkg/l4rust/l4-sys-rust/factory.rs b/src/l4/pkg/l4rust/l4-sys-rust/factory.rs index 23cb1e5f6b..ab9bb3805a 100644 --- a/src/l4/pkg/l4rust/l4-sys-rust/factory.rs +++ b/src/l4/pkg/l4rust/l4-sys-rust/factory.rs @@ -10,14 +10,15 @@ //! //! **Note:** The limit does not give any guarantee for the amount of available kernel memory. -use core::mem::size_of; use core::ptr; +use core::mem::size_of; -use crate::c_api::{l4_msgtag_protocol as MsgTagProto, *}; +use crate::c_api::{*, l4_msgtag_protocol as MsgTagProto}; use crate::cap; use crate::consts::UtcbConsts; -use crate::ipc_basic::{l4_ipc_call, l4_utcb, l4_utcb_br_u, l4_utcb_mr_u, timeout_never}; +use crate::ipc_basic::{l4_ipc_call, l4_utcb, l4_utcb_mr_u, l4_utcb_br_u, timeout_never}; use crate::ipc_ext::{msgtag, msgtag_flags, msgtag_label, msgtag_words}; +use crate::helpers; /// Create a new task. /// @@ -25,22 +26,18 @@ use crate::ipc_ext::{msgtag, msgtag_flags, msgtag_label, msgtag_words}; /// task. Refer to `l4_add_ku_mem`. /// The new capability is stored in `target_cap`. #[inline] -pub unsafe fn l4_factory_create_task( - factory: l4_cap_idx_t, - target_cap: &mut l4_cap_idx_t, - utcb_area: l4_fpage_t, -) -> l4_msgtag_t { +pub unsafe fn l4_factory_create_task(factory: l4_cap_idx_t, + target_cap: &mut l4_cap_idx_t, utcb_area: l4_fpage_t) -> l4_msgtag_t { l4_factory_create_task_u(factory, target_cap, utcb_area, l4_utcb()) } #[inline] -pub unsafe fn l4_factory_create_task_u( - factory: l4_cap_idx_t, - target_cap: &mut l4_cap_idx_t, - utcb_area: l4_fpage_t, - u: *mut l4_utcb_t, -) -> l4_msgtag_t { - let mut tag = l4_factory_create_start_u(MsgTagProto::L4_PROTO_TASK as i32, *target_cap, u); +pub unsafe fn l4_factory_create_task_u(factory: l4_cap_idx_t, + target_cap: &mut l4_cap_idx_t, utcb_area: l4_fpage_t, + u: *mut l4_utcb_t) -> l4_msgtag_t { + let mut tag = l4_factory_create_start_u( + MsgTagProto::L4_PROTO_TASK as i32, + *target_cap, u); l4_factory_create_add_fpage_u(utcb_area, &mut tag, u); l4_factory_create_commit_u(factory, tag, u) } @@ -49,42 +46,38 @@ pub unsafe fn l4_factory_create_task_u( /// /// Create a new thread with the given capability. The capability has to be allocated before. #[inline] -pub fn l4_factory_create_thread(factory: l4_cap_idx_t, target_cap: l4_cap_idx_t) -> l4_msgtag_t { +pub fn l4_factory_create_thread(factory: l4_cap_idx_t, + target_cap: l4_cap_idx_t) -> l4_msgtag_t { // This is safe because most of the functions called from that one below are safe and the only // one which could fail is the IPC call itself if the UTCB were a null pointer, but we give it // a valid pointer below - unsafe { l4_factory_create_thread_u(factory, target_cap, l4_utcb()) } + unsafe { + l4_factory_create_thread_u(factory, target_cap, l4_utcb()) + } } #[inline] -pub unsafe fn l4_factory_create_thread_u( - factory: l4_cap_idx_t, - target_cap: l4_cap_idx_t, - u: *mut l4_utcb_t, -) -> l4_msgtag_t { - l4_factory_create_u(factory, MsgTagProto::L4_PROTO_THREAD as i32, target_cap, u) +pub unsafe fn l4_factory_create_thread_u(factory: l4_cap_idx_t, + target_cap: l4_cap_idx_t, u: *mut l4_utcb_t) -> l4_msgtag_t { + l4_factory_create_u(factory, MsgTagProto::L4_PROTO_THREAD as i32, + target_cap, u) } /// Create a factory /// /// This creates a new factory with the given `target_cap`, which needs to be allocated before. #[inline] -pub unsafe fn l4_factory_create_factory( - factory: l4_cap_idx_t, - target_cap: l4_cap_idx_t, - limit: u64, -) -> l4_msgtag_t { +pub unsafe fn l4_factory_create_factory(factory: l4_cap_idx_t, + target_cap: l4_cap_idx_t, limit: u64) -> l4_msgtag_t { l4_factory_create_factory_u(factory, target_cap, limit, l4_utcb()) } #[inline] -pub unsafe fn l4_factory_create_factory_u( - factory: l4_cap_idx_t, - target_cap: l4_cap_idx_t, - limit: u64, - u: *mut l4_utcb_t, -) -> l4_msgtag_t { - let mut tag = l4_factory_create_start_u(MsgTagProto::L4_PROTO_FACTORY as i32, target_cap, u); +pub unsafe fn l4_factory_create_factory_u(factory: l4_cap_idx_t, + target_cap: l4_cap_idx_t, limit: u64, u: *mut l4_utcb_t) + -> l4_msgtag_t { + let mut tag = l4_factory_create_start_u( + MsgTagProto::L4_PROTO_FACTORY as i32, target_cap, u); l4_factory_create_add_uint_u(limit, &mut tag, u); l4_factory_create_commit_u(factory, tag, u) } @@ -103,38 +96,29 @@ pub unsafe fn l4_factory_create_factory_u( /// - `-L4_ENOENT`: `thread_cap` is void or points to something that is not a thread. /// - `-L4_EPERM`: No write rights on `thread_cap`. #[inline] -pub unsafe fn l4_factory_create_gate( - factory: l4_cap_idx_t, - target_cap: l4_cap_idx_t, - thread_cap: l4_cap_idx_t, - label: l4_umword_t, -) -> l4_msgtag_t { +pub unsafe fn l4_factory_create_gate(factory: l4_cap_idx_t, + target_cap: l4_cap_idx_t, thread_cap: l4_cap_idx_t, label: l4_umword_t) + -> l4_msgtag_t { l4_factory_create_gate_u(factory, target_cap, thread_cap, label, l4_utcb()) } #[inline] -pub unsafe fn l4_factory_create_gate_u( - factory: l4_cap_idx_t, - target_cap: l4_cap_idx_t, - thread_cap: l4_cap_idx_t, - label: l4_umword_t, - u: *mut l4_utcb_t, -) -> l4_msgtag_t { +pub unsafe fn l4_factory_create_gate_u(factory: l4_cap_idx_t, + target_cap: l4_cap_idx_t, thread_cap: l4_cap_idx_t, label: l4_umword_t, + u: *mut l4_utcb_t) -> l4_msgtag_t { let mut items = 0; let mut tag = l4_factory_create_start_u(0, target_cap, u); l4_factory_create_add_uint_u(label, &mut tag, u); let v = l4_utcb_mr_u(u); if (thread_cap & l4_cap_consts_t::L4_INVALID_CAP_BIT as u64) == 0 { items = 1; - mr!(v[3] = cap::l4_map_obj_control(0, 0)); - mr!(v[4] = cap::l4_obj_fpage(thread_cap, 0, L4_fpage_rights::L4_FPAGE_RWX as u8).raw); + mr!(v[3] = cap::l4_map_obj_control(0,0)); + mr!(v[4] = cap::l4_obj_fpage(thread_cap, 0, + L4_fpage_rights::L4_FPAGE_RWX as u8) + .raw); } - tag = msgtag( - msgtag_label(tag), - msgtag_words(tag), - items, - msgtag_flags(tag), - ); + tag = msgtag(msgtag_label(tag), msgtag_words(tag), items, + msgtag_flags(tag)); l4_factory_create_commit_u(factory, tag, u) } @@ -193,11 +177,8 @@ pub unsafe fn l4_factory_create_gate_u( //L4_INLINE l4_msgtag_t // ToDo: docs #[inline] -pub fn l4_factory_create_add_int_u( - d: l4_mword_t, - tag: &mut l4_msgtag_t, - u: *mut l4_utcb_t, -) -> bool { +pub fn l4_factory_create_add_int_u(d: l4_mword_t, tag: &mut l4_msgtag_t, + u: *mut l4_utcb_t) -> bool { // safe, because tag is a mutable reference and hence never null and l4_utcb_mr_u works // *always* let mut w = msgtag_words(*tag) as usize; @@ -206,7 +187,8 @@ pub fn l4_factory_create_add_int_u( } unsafe { let v = l4_utcb_mr_u(u); - mr!(v[w] = L4_varg_type::L4_VARG_TYPE_MWORD as u64 | (size_of::() << 16) as u64); + mr!(v[w] = L4_varg_type::L4_VARG_TYPE_MWORD as u64 + | (size_of::() << 16) as u64); mr!(v[w + 1] = d); } w += 2; @@ -215,19 +197,16 @@ pub fn l4_factory_create_add_int_u( } #[inline] -pub fn l4_factory_create_add_uint_u( - d: l4_umword_t, - tag: &mut l4_msgtag_t, - u: *mut l4_utcb_t, -) -> bool { +pub fn l4_factory_create_add_uint_u(d: l4_umword_t, tag: &mut l4_msgtag_t, + u: *mut l4_utcb_t) -> bool { let mut w = msgtag_words(*tag); if w + 2 > UtcbConsts::L4_UTCB_GENERIC_DATA_SIZE as u32 { return false; } unsafe { let v = l4_utcb_mr_u(u); - mr!(v[w] = - L4_varg_type::L4_VARG_TYPE_UMWORD as u64 | (size_of::() << 16) as u64); + mr!(v[w] = L4_varg_type::L4_VARG_TYPE_UMWORD as u64 + | (size_of::() << 16) as u64); mr!(v[w + 1] = d); } w += 2; @@ -235,17 +214,14 @@ pub fn l4_factory_create_add_uint_u( true } + #[inline] -pub unsafe fn l4_factory_create_add_cstr_u( - s: *const u8, - tag: &mut l4_msgtag_t, - u: *mut l4_utcb_t, -) -> bool { +pub unsafe fn l4_factory_create_add_cstr_u(s: *const u8, + tag: &mut l4_msgtag_t, u: *mut l4_utcb_t) -> bool { let mut w = msgtag_words(*tag) as usize; - let len = core_ffi_helpers::strlen(s) as usize; + let len = helpers::strlen(s) as usize; if w + 1 + (len + size_of::() - 1) / size_of::() - > (UtcbConsts::L4_UTCB_GENERIC_DATA_SIZE as usize) - { + > (UtcbConsts::L4_UTCB_GENERIC_DATA_SIZE as usize) { return false; } let v = l4_utcb_mr_u(u); @@ -258,12 +234,12 @@ pub unsafe fn l4_factory_create_add_cstr_u( } #[inline] -pub fn l4_factory_create_add_str_u(s: &str, tag: &mut l4_msgtag_t, u: *mut l4_utcb_t) -> bool { +pub fn l4_factory_create_add_str_u(s: &str, tag: &mut l4_msgtag_t, + u: *mut l4_utcb_t) -> bool { let mut w = msgtag_words(*tag); let len = s.len(); if w as usize + 1 + (len + size_of::() - 1) / size_of::() - > UtcbConsts::L4_UTCB_GENERIC_DATA_SIZE as usize - { + > UtcbConsts::L4_UTCB_GENERIC_DATA_SIZE as usize { return false; } unsafe { @@ -274,37 +250,30 @@ pub fn l4_factory_create_add_str_u(s: &str, tag: &mut l4_msgtag_t, u: *mut l4_ut let c = ((c as usize) + len) as *mut u8; *c = 0; // add 0-byte } - w = w + 1 + ((len + size_of::() - 1) / size_of::()) as u32; - tag.raw = (tag.raw & !0x3f) | (w as i64 & 0x3f); + w = w + 1 + ((len + size_of::() - 1) / + size_of::()) as u32; + tag.raw = (tag.raw & !0x3f) | (w as i64 & 0x3f); true } #[inline] -pub unsafe fn l4_factory_create_commit_u( - factory: l4_cap_idx_t, - tag: l4_msgtag_t, - u: *mut l4_utcb_t, -) -> l4_msgtag_t { +pub unsafe fn l4_factory_create_commit_u(factory: l4_cap_idx_t, + tag: l4_msgtag_t, u: *mut l4_utcb_t) -> l4_msgtag_t { l4_ipc_call(factory, u, tag, timeout_never()) } #[inline] -pub unsafe fn l4_factory_create_u( - factory: l4_cap_idx_t, - protocol: i32, - target: l4_cap_idx_t, - utcb: *mut l4_utcb_t, -) -> l4_msgtag_t { +pub unsafe fn l4_factory_create_u(factory: l4_cap_idx_t, protocol: i32, + target: l4_cap_idx_t, utcb: *mut l4_utcb_t) -> l4_msgtag_t { let t = l4_factory_create_start_u(protocol, target, utcb); l4_factory_create_commit_u(factory, t, utcb) } + + #[inline] -pub unsafe fn l4_factory_create( - factory: l4_cap_idx_t, - protocol: i32, - target: l4_cap_idx_t, -) -> l4_msgtag_t { +pub unsafe fn l4_factory_create(factory: l4_cap_idx_t, protocol: i32, + target: l4_cap_idx_t) -> l4_msgtag_t { l4_factory_create_u(factory, protocol, target, l4_utcb()) } @@ -323,7 +292,7 @@ pub unsafe fn l4_factory_create( //{ // return l4_factory_create_u(factory, L4_PROTO_VM, target_cap, u); //} -// +// //L4_INLINE l4_msgtag_t //l4_factory_create_irq(l4_cap_idx_t factory, // l4_cap_idx_t target_cap) L4_NOTHROW @@ -343,11 +312,8 @@ pub unsafe fn l4_factory_create( /// This function instructs the factory to allocate a new object. The type is determined by the /// given protocol. See `MsgTagProto`. #[inline] -unsafe fn l4_factory_create_start_u( - protocol: i32, - target_cap: l4_cap_idx_t, - u: *mut l4_utcb_t, -) -> l4_msgtag_t { +unsafe fn l4_factory_create_start_u(protocol: i32, target_cap: l4_cap_idx_t, + u: *mut l4_utcb_t) -> l4_msgtag_t { let v = l4_utcb_mr_u(u); let b = l4_utcb_br_u(u); mr!(v[0] = protocol); @@ -358,14 +324,11 @@ unsafe fn l4_factory_create_start_u( #[inline] /// Add a flex page to the given UTCB -pub fn l4_factory_create_add_fpage_u( - d: l4_fpage_t, - tag: &mut l4_msgtag_t, - u: *mut l4_utcb_t, -) -> bool { +pub fn l4_factory_create_add_fpage_u(d: l4_fpage_t, tag: &mut l4_msgtag_t, + u: *mut l4_utcb_t) -> bool { let mut w = msgtag_words(*tag); if w + 2 > UtcbConsts::L4_UTCB_GENERIC_DATA_SIZE as u32 { - return false; + return false; } unsafe { let v = l4_utcb_mr_u(u); @@ -378,15 +341,17 @@ pub fn l4_factory_create_add_fpage_u( } #[inline] -pub unsafe fn l4_factory_create_add_nil_u(tag: &mut l4_msgtag_t, u: *mut l4_utcb_t) -> bool { - let mut w = msgtag_words(*tag); +pub unsafe fn l4_factory_create_add_nil_u(tag: &mut l4_msgtag_t, + u: *mut l4_utcb_t) -> bool { + let mut w = msgtag_words(*tag); if w + 1 > UtcbConsts::L4_UTCB_GENERIC_DATA_SIZE as u32 { - return false; + return false; } let v = l4_utcb_mr_u(u); mr!(v[w] = L4_varg_type::L4_VARG_TYPE_NIL); w += 1; - tag.raw = (tag.raw & !0x3fi64) | (w as i64 & 0x3f); + tag.raw = (tag.raw & !0x3fi64) | (w as i64 & 0x3f); true } + diff --git a/src/l4/pkg/l4rust/l4-sys-rust/helpers.rs b/src/l4/pkg/l4rust/l4-sys-rust/helpers.rs index 2a6e722f5d..06362a3646 100644 --- a/src/l4/pkg/l4rust/l4-sys-rust/helpers.rs +++ b/src/l4/pkg/l4rust/l4-sys-rust/helpers.rs @@ -1,5 +1,3 @@ -use core::ffi::c_uchar; - #[cfg(no_libc)] pub unsafe fn strlen(c_str: *const u8) -> usize { let mut length = 0usize; @@ -10,7 +8,19 @@ pub unsafe fn strlen(c_str: *const u8) -> usize { length } -pub unsafe fn eq_str_cstr(name: &str, other: *const c_uchar) -> bool { +#[cfg(not(no_libc))] +extern "C" { + pub(crate) fn strlen(c_str: *const u8) -> usize; +} + +/// Provide a convenient mechanism to access the message registers +macro_rules! mr { + ($v:ident[$w:expr] = $stuff:expr) => { + (*$v).mr.as_mut()[$w as usize] = $stuff as u64; + } +} + +pub unsafe fn eq_str_cstr(name: &str, other: *const u8) -> bool { let mut in_name = other; for byte in name.as_bytes() { match *in_name { @@ -20,5 +30,5 @@ pub unsafe fn eq_str_cstr(name: &str, other: *const c_uchar) -> bool { } in_name = in_name.offset(1); } - return *in_name == 0; // if 0 reached, strings matched + return *in_name == 0 // if 0 reached, strings matched } diff --git a/src/l4/pkg/l4rust/l4-sys-rust/ipc_basic.rs b/src/l4/pkg/l4rust/l4-sys-rust/ipc_basic.rs index 8d682070da..a07a456f72 100644 --- a/src/l4/pkg/l4rust/l4-sys-rust/ipc_basic.rs +++ b/src/l4/pkg/l4rust/l4-sys-rust/ipc_basic.rs @@ -1,6 +1,7 @@ -use core::ffi::{c_int, c_long, c_uint, c_ulong}; +use libc::{c_int, c_uint, c_long, c_ulong}; -use crate::c_api::{l4_error_code_t::*, l4_msg_item_consts_t::*, *}; +use crate::c_api::{*, l4_error_code_t::*, l4_msg_item_consts_t::*, + L4_fpage_control::*}; use crate::consts::*; //////////////////////////////////////////////////////////////////////////////// @@ -9,23 +10,15 @@ use crate::consts::*; #[must_use] #[inline] -pub unsafe fn l4_ipc_call( - dest: l4_cap_idx_t, - utcb: *mut l4_utcb_t, - tag: l4_msgtag_t, - timeout: l4_timeout_t, -) -> l4_msgtag_t { +pub unsafe fn l4_ipc_call(dest: l4_cap_idx_t, utcb: *mut l4_utcb_t, + tag: l4_msgtag_t, timeout: l4_timeout_t) -> l4_msgtag_t { l4_ipc_call_w(dest, utcb, tag, timeout) } #[must_use] #[inline(always)] -pub unsafe fn l4_ipc_send( - dest: l4_cap_idx_t, - utcb: *mut l4_utcb_t, - tag: l4_msgtag_t, - timeout: l4_timeout_t, -) -> l4_msgtag_t { +pub unsafe fn l4_ipc_send(dest: l4_cap_idx_t, utcb: *mut l4_utcb_t, + tag: l4_msgtag_t, timeout: l4_timeout_t) -> l4_msgtag_t { l4_ipc_send_w(dest, utcb, tag, timeout) } @@ -36,57 +29,47 @@ pub unsafe fn l4_ipc_error(tag: l4_msgtag_t, utcb: *mut l4_utcb_t) -> l4_umword_ #[must_use] #[inline] -pub unsafe fn l4_ipc_receive( - object: l4_cap_idx_t, - utcb: *mut l4_utcb_t, - timeout: l4_timeout_t, -) -> l4_msgtag_t { +pub unsafe fn l4_ipc_receive(object: l4_cap_idx_t, utcb: *mut l4_utcb_t, + timeout: l4_timeout_t) -> l4_msgtag_t { l4_ipc_receive_w(object, utcb, timeout) } + #[must_use] #[inline] -pub unsafe fn l4_ipc_reply_and_wait( - utcb: *mut l4_utcb_t, - tag: l4_msgtag_t, - src: *mut l4_umword_t, - timeout: l4_timeout_t, -) -> l4_msgtag_t { +pub unsafe fn l4_ipc_reply_and_wait(utcb: *mut l4_utcb_t, tag: l4_msgtag_t, + src: *mut l4_umword_t, timeout: l4_timeout_t) -> l4_msgtag_t { l4_ipc_reply_and_wait_w(utcb, tag, src, timeout) } + #[must_use] #[inline] -pub unsafe fn l4_ipc_wait( - utcb: *mut l4_utcb_t, - label: *mut l4_umword_t, - timeout: l4_timeout_t, -) -> l4_msgtag_t { +pub unsafe fn l4_ipc_wait(utcb: *mut l4_utcb_t, label: *mut l4_umword_t, + timeout: l4_timeout_t) -> l4_msgtag_t { l4_ipc_wait_w(utcb, label, timeout) } /// This function only serves compatibility. One can use the MsgTag struct from the l4 crate /// instead. #[inline] -pub fn l4_msgtag(label: c_long, words: c_uint, items: c_uint, flags: c_uint) -> l4_msgtag_t { +pub fn l4_msgtag(label: c_long, words: c_uint, items: c_uint, + flags: c_uint) -> l4_msgtag_t { l4_msgtag_t { - raw: (label << 16) - | (words & 0x3f) as l4_mword_t - | ((items & 0x3f) << 6) as l4_mword_t - | (flags & 0xf000) as l4_mword_t, + raw: (label << 16) | (words & 0x3f) as l4_mword_t + | ((items & 0x3f) << 6) as l4_mword_t + | (flags & 0xf000) as l4_mword_t } } #[must_use] #[inline] -pub unsafe fn l4_rcv_ep_bind_thread( - gate: l4_cap_idx_t, - thread: l4_cap_idx_t, - label: l4_umword_t, -) -> l4_msgtag_t { +pub unsafe fn l4_rcv_ep_bind_thread(gate: l4_cap_idx_t, thread: l4_cap_idx_t, + label: l4_umword_t) -> l4_msgtag_t { l4_rcv_ep_bind_thread_w(gate, thread, label) } + //////////////////////////////////////////////////////////////////////////////// // re-implemented inline functions from l4/sys/ipc.h: @@ -120,12 +103,8 @@ pub fn l4_msgtag_words(t: l4_msgtag_t) -> u32 { /// See sndfpage_add_u and sndfpage_add #[inline] -pub unsafe fn l4_sndfpage_add_u( - snd_fpage: l4_fpage_t, - snd_base: c_ulong, - tag: *mut l4_msgtag_t, - utcb: *mut l4_utcb_t, -) -> c_int { +pub unsafe fn l4_sndfpage_add_u(snd_fpage: l4_fpage_t, snd_base: c_ulong, + tag: *mut l4_msgtag_t, utcb: *mut l4_utcb_t) -> c_int { let i = l4_msgtag_words(*tag) as usize + 2 * l4_msgtag_items(*tag); if i >= (UTCB_GENERIC_DATA_SIZE - 1) { return L4_ENOMEM as i32 * -1; @@ -135,12 +114,8 @@ pub unsafe fn l4_sndfpage_add_u( mr!(v[i] = snd_base | L4_ITEM_MAP as u64 | L4_ITEM_CONT as u64); mr!(v[i + 1] = snd_fpage.raw); - *tag = l4_msgtag( - l4_msgtag_label(*tag), - l4_msgtag_words(*tag), - l4_msgtag_items(*tag) as u32 + 1, - l4_msgtag_flags(*tag) as u32, - ); + *tag = l4_msgtag(l4_msgtag_label(*tag), l4_msgtag_words(*tag), + l4_msgtag_items(*tag) as u32 + 1, l4_msgtag_flags(*tag) as u32); 0 } @@ -149,21 +124,37 @@ pub unsafe fn l4_utcb_mr() -> *mut l4_msg_regs_t { l4_utcb_mr_u(l4_utcb()) } + /// re-implementation of the inline function from l4sys/include/ipc.h #[inline] -pub unsafe fn l4_sndfpage_add( - snd_fpage: l4_fpage_t, - snd_base: c_ulong, - tag: *mut l4_msgtag_t, -) -> c_int { +pub unsafe fn l4_sndfpage_add(snd_fpage: l4_fpage_t, snd_base: c_ulong, + tag: *mut l4_msgtag_t) -> c_int { l4_sndfpage_add_u(snd_fpage, snd_base, tag, l4_utcb()) } + #[inline(always)] pub unsafe fn l4_utcb() -> *mut l4_utcb_t { l4_utcb_w() } +// ToDo: potentially broken (or one of the functions called +//#[inline] +//pub unsafe fn l4_rcv_ep_bind_thread(gate: l4_cap_idx_t, thread: l4_cap_idx_t, +// label: l4_umword_t) -> l4_msgtag_t { +// return l4_rcv_ep_bind_thread_u(gate, thread, label, l4_utcb()) +//} + + +#[inline] +pub fn l4_map_control(snd_base: l4_umword_t, cache: u8, + grant: u32) -> l4_umword_t { + (snd_base & L4_FPAGE_CONTROL_MASK as l4_umword_t) + | ((cache as l4_umword_t) << 4) + | L4_ITEM_MAP as u64 + | (grant as l4_umword_t) +} + /// Retrieve pointer to buffer registers from current UTCB #[inline(always)] pub unsafe fn l4_utcb_br() -> *mut l4_buf_regs_t { @@ -178,7 +169,9 @@ pub unsafe fn l4_utcb_br_u(u: *mut l4_utcb_t) -> *mut l4_buf_regs_t { #[inline] pub unsafe fn l4_utcb_mr_u(u: *mut l4_utcb_t) -> *mut l4_msg_regs_t { - (u as *mut u8).offset(UtcbConsts::L4_UTCB_MSG_REGS_OFFSET as isize) as *mut l4_msg_regs_t + (u as *mut u8).offset(UtcbConsts::L4_UTCB_MSG_REGS_OFFSET + as isize) + as *mut l4_msg_regs_t } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/l4/pkg/l4rust/l4-sys-rust/ipc_ext.rs b/src/l4/pkg/l4rust/l4-sys-rust/ipc_ext.rs index 7f2299e5fc..e467c2c233 100644 --- a/src/l4/pkg/l4rust/l4-sys-rust/ipc_ext.rs +++ b/src/l4/pkg/l4rust/l4-sys-rust/ipc_ext.rs @@ -1,16 +1,9 @@ -use crate::c_api::{l4_msgtag_flags::*, *}; -use crate::cap; +use crate::c_api::{*, l4_msgtag_flags::*}; use crate::ipc_basic::{self, l4_utcb}; -/// Provide a convenient mechanism to access the message registers -macro_rules! mr { - ($v:ident[$w:expr] = $stuff:expr) => { - (*$v).mr.as_mut()[$w as usize] = $stuff as u64; - }; -} - -#[inline(always)] -pub fn msgtag(label: i64, words: u32, items: u32, flags: u32) -> l4_msgtag_t { +#[inline] +pub fn msgtag(label: i64, words: u32, + items: u32, flags: u32) -> l4_msgtag_t { ipc_basic::l4_msgtag(label, words, items, flags) } @@ -45,26 +38,25 @@ pub fn msgtag_words(t: l4_msgtag_t) -> u32 { /// Additionally, the given message tag is modified by increasing the word count. /// A return code of 0 denotes success, errors are negative. #[inline] -pub unsafe fn sndfpage_add_u( - snd_fpage: l4_fpage_t, - snd_base: u64, - tag: &mut l4_msgtag_t, - utcb: *mut l4_utcb_t, -) -> i32 { +pub unsafe fn sndfpage_add_u(snd_fpage: l4_fpage_t, snd_base: u64, + tag: &mut l4_msgtag_t, utcb: *mut l4_utcb_t) -> i32 { ipc_basic::l4_sndfpage_add_u(snd_fpage, snd_base, tag, utcb) } // See `sndfpage_add_u` #[inline] -pub fn sndfpage_add(snd_fpage: l4_fpage_t, snd_base: u64, tag: &mut l4_msgtag_t) -> i32 { - unsafe { - // the only unsafe bit here is passing the UTCB pointer, but l4_utcb() is gauranteed +pub fn sndfpage_add(snd_fpage: l4_fpage_t, snd_base: u64, + tag: &mut l4_msgtag_t) -> i32 { + unsafe { // the only unsafe bit here is passing the UTCB pointer, but l4_utcb() is gauranteed // to work, so the whole operation is safe sndfpage_add_u(snd_fpage, snd_base, tag, l4_utcb()) } } + #[inline] -pub fn map_control(snd_base: l4_umword_t, cache: u8, grant: u32) -> l4_umword_t { - cap::l4_map_control(snd_base, cache, grant.into()) +pub fn map_control(snd_base: l4_umword_t, cache: u8, + grant: u32) -> l4_umword_t { + ipc_basic::l4_map_control(snd_base, cache, grant) } + diff --git a/src/l4/pkg/l4rust/l4-sys-rust/lib.rs b/src/l4/pkg/l4rust/l4-sys-rust/lib.rs index c4063a9324..c6847cb920 100644 --- a/src/l4/pkg/l4rust/l4-sys-rust/lib.rs +++ b/src/l4/pkg/l4rust/l4-sys-rust/lib.rs @@ -1,25 +1,25 @@ #![no_std] +extern crate libc; + #[macro_use] -mod ipc_ext; +pub mod helpers; mod c_api; mod cap; pub mod consts; mod factory; -pub mod helpers; mod ipc_basic; +mod ipc_ext; mod platform; -mod scheduler; mod task; -pub use crate::c_api::*; /// expose public C API pub use crate::cap::*; +pub use crate::c_api::*; pub use crate::factory::*; -pub use crate::ipc_basic::*; pub use crate::ipc_ext::*; +pub use crate::ipc_basic::*; pub use crate::platform::*; -pub use crate::scheduler::*; pub use crate::task::*; const L4_PAGEMASKU: l4_addr_t = L4_PAGEMASK as l4_addr_t; @@ -37,24 +37,3 @@ pub fn trunc_page(address: l4_addr_t) -> l4_addr_t { pub fn round_page(address: usize) -> l4_addr_t { ((address + L4_PAGESIZE as usize - 1usize) & (L4_PAGEMASK as usize)) as l4_addr_t } - -pub mod util { - #[cfg(target_arch = "x86_64")] - pub fn rdtscp() -> u64 { - unsafe { - let mut _val = 0; - core::arch::x86_64::__rdtscp(&mut _val) - } - } -} - -#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] -pub type L4Umword = u64; -#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] -pub type L4Mword = i64; - -#[cfg(any(target_arch = "x86", target_arch = "aarch32"))] -pub type L4Umword = u32; -#[cfg(any(target_arch = "x86", target_arch = "aarch32"))] -pub type L4Mword = i32; - diff --git a/src/l4/pkg/l4rust/l4_derive-rust/lib.rs b/src/l4/pkg/l4rust/l4_derive-rust/lib.rs index 362fb88eb1..544632bd92 100644 --- a/src/l4/pkg/l4rust/l4_derive-rust/lib.rs +++ b/src/l4/pkg/l4rust/l4_derive-rust/lib.rs @@ -1,4 +1,7 @@ #![recursion_limit = "128"] +extern crate lazy_static; +extern crate proc_macro; +extern crate proc_macro2; #[macro_use] mod macros; diff --git a/src/l4/pkg/l4rust/l4re-rust/Cargo.toml b/src/l4/pkg/l4rust/l4re-rust/Cargo.toml index 6d540ede7d..7007cf4ec1 100644 --- a/src/l4/pkg/l4rust/l4re-rust/Cargo.toml +++ b/src/l4/pkg/l4rust/l4re-rust/Cargo.toml @@ -2,18 +2,20 @@ name = "l4re" version = "0.1.0" authors = ["Sebastian Humenda "] -edition = "2021" +edition = "2018" [lib] path = "lib.rs" [build-dependencies] -bindgen = "0.68" +bindgen = "0.65.1" -[dependencies.l4] -path = "../l4-rust" -# ToDo: make this conditional +[dependencies] +libc = "0.2.43" + +[dependencies.bitflags] +version = "1.0" default-features = false -[dependencies.l4_derive] -path = "../l4_derive-rust" +[features] +default = [] diff --git a/src/l4/pkg/l4rust/l4re-rust/bindgen.h b/src/l4/pkg/l4rust/l4re-rust/bindgen.h index 77adebbaa7..3b09869811 100644 --- a/src/l4/pkg/l4rust/l4re-rust/bindgen.h +++ b/src/l4/pkg/l4rust/l4re-rust/bindgen.h @@ -3,6 +3,10 @@ #include #include #include +#include #include +#include +#include #include #include +#include diff --git a/src/l4/pkg/l4rust/l4re-rust/build.rs b/src/l4/pkg/l4rust/l4re-rust/build.rs index f2266385a5..46d6f19cb2 100644 --- a/src/l4/pkg/l4rust/l4re-rust/build.rs +++ b/src/l4/pkg/l4rust/l4re-rust/build.rs @@ -1,10 +1,12 @@ +extern crate bindgen; + use std::env; use std::path::PathBuf; fn main() { let mut bindings = bindgen::Builder::default() .use_core() - .ctypes_prefix("core::ffi") + .ctypes_prefix("::libc") .rustified_enum(".*") .header("bindgen.h"); if let Ok(include_dirs) = ::std::env::var("L4_INCLUDE_DIRS") { diff --git a/src/l4/pkg/l4rust/l4re-rust/cap.rs b/src/l4/pkg/l4rust/l4re-rust/cap.rs index 66d3a73cbb..4ec9b4f32c 100644 --- a/src/l4/pkg/l4rust/l4re-rust/cap.rs +++ b/src/l4/pkg/l4rust/l4re-rust/cap.rs @@ -1,18 +1,16 @@ use core::ops::{Deref, DerefMut}; use l4::{ - cap::{Cap, IfaceInit}, + cap::{Cap, IfaceInit, Interface}, error::{Error, Result}, }; -use crate::sys; - -pub struct OwnedCap(Cap); +pub struct OwnedCap(pub(crate) Cap); impl OwnedCap { /// Allocate new capability slot pub fn alloc() -> OwnedCap { - OwnedCap(Cap::::new(unsafe { sys::l4re_util_cap_alloc() })) + OwnedCap(Cap::::new(unsafe { l4_sys::l4re_util_cap_alloc() })) } pub fn from(src: Cap) -> Result { @@ -32,20 +30,20 @@ impl OwnedCap { } } -impl Deref for OwnedCap { +impl Deref for OwnedCap { type Target = Cap; fn deref(&self) -> &Self::Target { &self.0 } } -impl DerefMut for OwnedCap { +impl DerefMut for OwnedCap { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } -impl Drop for OwnedCap { +impl Drop for OwnedCap { fn drop(&mut self) { unsafe { // free allocated capability index diff --git a/src/l4/pkg/l4rust/l4re-rust/factory.rs b/src/l4/pkg/l4rust/l4re-rust/factory.rs new file mode 100644 index 0000000000..2669e22050 --- /dev/null +++ b/src/l4/pkg/l4rust/l4re-rust/factory.rs @@ -0,0 +1,106 @@ +use crate::sys::l4re_env; +use crate::OwnedCap; + +use l4::cap::{Cap, CapIdx, IfaceInit, Interface}; +use l4::ipc::MsgTag; +use l4::Result; +use l4_sys::{l4_factory_create}; +use l4_sys::l4_msgtag_protocol::{L4_PROTO_IRQ_SENDER, L4_PROTO_DMA_SPACE}; + +use core::marker::PhantomData; + +pub struct Factory { + cap: CapIdx, + _typ: PhantomData, +} + +impl Interface for Factory { + #[inline] + fn raw(&self) -> CapIdx { + self.cap + } +} + +impl IfaceInit for Factory { + #[inline] + fn new(cap: CapIdx) -> Self { + Self { + cap, + _typ: PhantomData, + } + } +} + +pub struct DefaultFactory; +pub struct IrqSender { + cap: CapIdx, +} +pub struct DmaSpace { + cap: CapIdx +} + +impl Interface for IrqSender { + #[inline] + fn raw(&self) -> CapIdx { + self.cap + } +} + +impl IfaceInit for IrqSender { + #[inline] + fn new(cap: CapIdx) -> Self { + Self { cap } + } +} + +impl Interface for DmaSpace { + #[inline] + fn raw(&self) -> CapIdx { + self.cap + } +} + +impl IfaceInit for DmaSpace { + #[inline] + fn new(cap: CapIdx) -> Self { + Self { cap } + } +} + + +impl Factory { + pub fn default_factory_from_env() -> Cap> { + let env = unsafe { l4re_env().as_ref() }.unwrap(); + Cap::new(env.factory) + } +} + +pub trait FactoryCreate { + type Args; + + fn create(&self, arg: Self::Args) -> Result; +} + +impl FactoryCreate> for Factory { + type Args = (); + + fn create(&self, _arg: ()) -> Result> { + let cap: OwnedCap = OwnedCap::alloc(); + let tag: MsgTag = + unsafe { l4_factory_create(self.cap, L4_PROTO_IRQ_SENDER as i32, cap.raw()) }.into(); + tag.result()?; + Ok(cap) + } +} + +impl FactoryCreate> for Factory { + type Args = (); + + fn create(&self, _arg: ()) -> Result> { + let cap: OwnedCap = OwnedCap::alloc(); + let tag: MsgTag = + unsafe { l4_factory_create(self.cap, L4_PROTO_DMA_SPACE as i32, cap.raw()) }.into(); + tag.result()?; + Ok(cap) + } +} diff --git a/src/l4/pkg/l4rust/l4re-rust/io.rs b/src/l4/pkg/l4rust/l4re-rust/io.rs new file mode 100644 index 0000000000..b11f6a63a0 --- /dev/null +++ b/src/l4/pkg/l4rust/l4re-rust/io.rs @@ -0,0 +1,478 @@ +use l4::cap::{IfaceInit, CapIdx, Interface}; +use l4::ipc::MsgTag; +use l4::{Error, Result}; +use l4::error::TcrErr; +use l4_sys::l4_error_code_t::L4_EOK; +use l4_sys::{l4_icu_bind_w, l4_icu_info_t, l4_icu_info_w, l4_icu_msi_info_t, l4_icu_msi_info_w, l4_icu_unmask_w, l4_timeout_t, l4_uint32_t,l4vbus_get_next_device ,l4vbus_get_resource ,l4vbus_pcidev_cfg_read ,l4vbus_pcidev_cfg_write ,l4vbus_resource_t ,l4vbus_vicu_get_cap ,L4VBUS_NULL ,L4VBUS_ROOT_BUS , l4vbus_device_handle_t, l4vbus_assign_dma_domain, l4vbus_device_t, l4_irq_unmask_w, l4_rcv_ep_bind_thread_w, l4_irq_receive_w, timeout_never, l4_irq_detach_w}; + +use l4::sys::L4vbus_dma_domain_assign_flags::{L4VBUS_DMAD_KERNEL_DMA_SPACE, L4VBUS_DMAD_BIND}; +use l4_sys::l4vbus_consts_t::L4VBUS_MAX_DEPTH; +use l4_sys::l4vbus_resource_type_t::*; +use l4_sys::l4vbus_icu_src_types::L4VBUS_ICU_SRC_DEV_HANDLE; +use l4_sys::L4_icu_flags::L4_ICU_FLAG_MSI; +use bitflags::bitflags; + +use crate::factory::IrqSender; +use crate::sys::l4io_iomem_flags_t::*; +use crate::sys::{l4io_release_iomem, l4io_request_iomem, l4vbus_iface_type_t, l4vbus_subinterface_supported_w, l4re_env}; +use crate::OwnedCap; +use crate::factory::DmaSpace; +use crate::mem::VolatileMemoryInterface; + +use core::iter::Iterator; + +// TODO: unclear whether it is okay to clone vbus, it does make the API nicer +#[derive(Clone)] +pub struct Vbus { + cap: CapIdx +} + +impl Interface for Vbus { + #[inline] + fn raw(&self) -> CapIdx { + self.cap + } +} + +impl IfaceInit for Vbus { + #[inline] + fn new(cap: CapIdx) -> Self { + Self { cap } + } +} + +pub struct Device { + handle: l4vbus_device_handle_t, + info: l4vbus_device_t, + vbus: Vbus, +} + +pub struct Resource { + res: l4vbus_resource_t, +} + +#[derive(PartialEq, Eq, Debug, Copy, Clone)] +pub enum ResourceType { + Invalid, + Irq, + Mem, + Port, + Bus, + Gpio, + DmaDomain, + Max +} + +pub struct DeviceIter { + curr: Device, +} + +pub struct ResourceIter<'a> { + dev: &'a Device, + idx: i32, // TODO: correct width +} + +impl Iterator for DeviceIter { + type Item = Device; + + fn next(&mut self) -> Option { + let mut next_dev = self.curr.handle; + let mut next_info = self.curr.info; + let err = unsafe { + l4vbus_get_next_device( + self.curr.vbus.raw(), + L4VBUS_ROOT_BUS as l4vbus_device_handle_t, + &mut next_dev as *mut l4vbus_device_handle_t, + L4VBUS_MAX_DEPTH as i32, + &mut next_info as *mut l4vbus_device_t, + ) + }; + if err != L4_EOK as i32 { + return None; + } + + self.curr.handle = next_dev; + + Some(Device { + handle: next_dev, + info: next_info, + vbus: self.curr.vbus.clone() + }) + } +} + +impl Iterator for ResourceIter<'_> { + type Item = Resource; + + fn next(&mut self) -> Option { + self.idx += 1; + let mut res: l4vbus_resource_t = unsafe { core::mem::zeroed() }; + let err = unsafe { + l4vbus_get_resource( + self.dev.vbus.raw(), + self.dev.handle, + self.idx, + &mut res as *mut l4vbus_resource_t, + ) + }; + + if err != L4_EOK as i32 { + return None; + } + + Some(Resource { res }) + } +} + +impl Vbus { + pub fn new(cap: CapIdx) -> Vbus { + Vbus { cap } + } + + pub fn device_iter(&self) -> DeviceIter{ + DeviceIter { + curr: Device { + handle: L4VBUS_NULL as i64, + vbus: self.clone(), + info: l4vbus_device_t { + flags: 0, + // TODO: check if this is fine + name: [0; 64], + num_resources: 0, + type_: 0 + } + }, + } + } + + fn pcidev_cfg_read(&self, dev: &Device, reg: l4_uint32_t, bits: l4_uint32_t) -> Result { + let mut res: l4_uint32_t = 0; + let err = unsafe { + l4vbus_pcidev_cfg_read( + self.raw(), + dev.handle, + reg, + &mut res as *mut l4_uint32_t, + bits, + ) + }; + if err != L4_EOK as i32 { + Err(Error::from_ipc(err.into())) + } else { + Ok(res) + } + } + + fn pcidev_cfg_write( + &self, + dev: &Device, + reg: l4_uint32_t, + val: l4_uint32_t, + bits: l4_uint32_t, + ) -> Result<()> { + let err = unsafe { l4vbus_pcidev_cfg_write(self.raw(), dev.handle, reg, val, bits) }; + if err != L4_EOK as i32 { + Err(Error::from_ipc(err.into())) + } else { + Ok(()) + } + } + + pub fn pcidev_cfg_read8(&self, dev: &Device, reg: l4_uint32_t) -> Result { + Ok(self.pcidev_cfg_read(dev, reg, 8)? as u8) + } + + pub fn pcidev_cfg_read16(&self, dev: &Device, reg: l4_uint32_t) -> Result { + Ok(self.pcidev_cfg_read(dev, reg, 16)? as u16) + } + + pub fn pcidev_cfg_read32(&self, dev: &Device, reg: l4_uint32_t) -> Result { + self.pcidev_cfg_read(dev, reg, 32) + } + + pub fn pcidev_cfg_write8(&self, dev: &Device, reg: l4_uint32_t, val: u8) -> Result<()> { + self.pcidev_cfg_write(dev, reg, val as u32, 8) + } + + pub fn pcidev_cfg_write16(&self, dev: &Device, reg: l4_uint32_t, val: u16) -> Result<()> { + self.pcidev_cfg_write(dev, reg, val as u32, 16) + } + + pub fn pcidev_cfg_write32(&self, dev: &Device, reg: l4_uint32_t, val: u32) -> Result<()> { + self.pcidev_cfg_write(dev, reg, val as u32, 32) + } + + pub fn assign_dma_domain(&self, dma_domain: &mut Resource, dma_space: &mut DmaSpace) -> Result<()> { + assert!(dma_domain.typ() == ResourceType::DmaDomain); + let err = unsafe { l4vbus_assign_dma_domain( + self.cap, + dma_domain.start() as u32, + L4VBUS_DMAD_BIND as u32 | L4VBUS_DMAD_KERNEL_DMA_SPACE as u32, + dma_space.raw() + )}; + + if err != L4_EOK as i32 { + Err(Error::from_ipc(err.into())) + } else { + Ok(()) + } + } +} + +impl Device { + pub fn vbus(&self) -> &Vbus { + &self.vbus + } + + pub fn resource_iter<'a>(&'a self) -> ResourceIter<'a> { + ResourceIter { + dev: self, + idx: -1, + } + } + + pub fn supports_interface(&self, iface: l4vbus_iface_type_t) -> bool { + if unsafe { l4vbus_subinterface_supported_w(self.info.type_, iface) } == 0 { + false + } else { + true + } + } +} + +impl Resource { + pub fn start(&self) -> usize { + self.res.start + } + + pub fn end(&self) -> usize { + self.res.end + } + + pub fn typ(&self) -> ResourceType { + // match with as is not supported :( + if self.res.type_ == L4VBUS_RESOURCE_INVALID as u16 { + ResourceType::Invalid + } else if self.res.type_ == L4VBUS_RESOURCE_IRQ as u16 { + ResourceType::Irq + } else if self.res.type_ == L4VBUS_RESOURCE_MEM as u16 { + ResourceType::Mem + } else if self.res.type_ == L4VBUS_RESOURCE_PORT as u16 { + ResourceType::Port + } else if self.res.type_ == L4VBUS_RESOURCE_BUS as u16 { + ResourceType::Bus + } else if self.res.type_ == L4VBUS_RESOURCE_GPIO as u16 { + ResourceType::Gpio + } else if self.res.type_ == L4VBUS_RESOURCE_DMA_DOMAIN as u16 { + ResourceType::DmaDomain + } else if self.res.type_ == L4VBUS_RESOURCE_MAX as u16 { + ResourceType::Max + } else { + unreachable!() + } + } +} + +pub struct IoMem { + addr: *mut u8, + size: u64, +} + +bitflags! { + pub struct IoMemFlags : i32 { + const NONCACHED = L4IO_MEM_NONCACHED as i32; + const CACHED = L4IO_MEM_CACHED as i32; + const USE_MTRR = L4IO_MEM_USE_MTRR as i32; + const EAGER_MAP = L4IO_MEM_EAGER_MAP as i32; + } +} + +impl IoMem { + pub fn request(phys: u64, size: u64, flags: IoMemFlags) -> Result { + let mut virt: u64 = 0; + let err = + unsafe { l4io_request_iomem(phys, size, flags.bits() as i32, &mut virt as *mut u64) }; + if err != 0 { + Err(Error::from_ipc(err.into())) + } else { + Ok(IoMem { + addr: virt as *mut u8, + size, + }) + } + } + + fn release(&mut self) -> Result<()> { + let err = unsafe { l4io_release_iomem(self.addr as u64, self.size) }; + if err != 0 { + Err(Error::from_ipc(err.into())) + } else { + Ok(()) + } + } +} + +impl VolatileMemoryInterface for IoMem { + fn ptr(&self) -> *mut u8 { + self.addr + } +} + +impl Drop for IoMem { + fn drop(&mut self) { + self.release().unwrap(); + } +} + +pub struct Icu { + cap: CapIdx, +} + +#[derive(Copy, Clone, Debug)] +pub struct IcuInfo { + pub has_msi: bool, + pub nr_irqs: u32, + pub nr_msis: u32, +} + +pub struct MsiInfo { + pub addr: u64, + pub data: u32, +} + +impl Interface for Icu { + #[inline] + fn raw(&self) -> CapIdx { + self.cap + } +} + +impl IfaceInit for Icu { + #[inline] + fn new(cap: CapIdx) -> Self { + Self { cap } + } +} + +impl Icu { + pub fn from_device(vbus: &Vbus, dev: Device) -> Result> { + let cap: OwnedCap = OwnedCap::alloc(); + let err = unsafe { l4vbus_vicu_get_cap(vbus.raw(), dev.handle, cap.raw()) }; + if err != L4_EOK as i32 { + Err(Error::from_ipc(err.into())) + } else { + Ok(cap) + } + } + + pub fn info(&self) -> Result { + let mut info: l4_icu_info_t = unsafe { core::mem::zeroed() }; + let tag: MsgTag = + unsafe { l4_icu_info_w(self.cap, &mut info as *mut l4_icu_info_t) }.into(); + tag.result()?; + Ok(IcuInfo { + has_msi: info.features != 0, + nr_irqs: info.nr_irqs, + nr_msis: info.nr_msis, + }) + } + + /// Returns the MSI info and whether to unmask via the ICU or not + pub fn bind_msi( + &self, + irq_cap: &IrqSender, + irq_num: u32, + dev: &Device, + ) -> Result<(MsiInfo, bool)> { + let final_irq = irq_num | L4_ICU_FLAG_MSI as u32; + let tag: MsgTag = unsafe { l4_icu_bind_w(self.cap, final_irq, irq_cap.raw()) }.into(); + let label = tag.label(); + tag.result()?; + let mut msi_info_c: l4_icu_msi_info_t = unsafe { core::mem::zeroed() }; + let tag: MsgTag = unsafe { + l4_icu_msi_info_w( + self.cap, + final_irq, + (dev.handle | L4VBUS_ICU_SRC_DEV_HANDLE as i64) as u64, + &mut msi_info_c as *mut l4_icu_msi_info_t, + ) + } + .into(); + tag.result()?; + let msi_info = MsiInfo { + addr: msi_info_c.msi_addr, + data: msi_info_c.msi_data, + }; + + if label == 0 { + Ok((msi_info, false)) + } else if label == 1 { + Ok((msi_info, true)) + } else { + panic!("Invalid return label from l4_icu_bind: {}", label) + } + } + + pub fn unmask(&self, irq_num: u32) -> Result<()> { + let tag: MsgTag = unsafe { + l4_icu_unmask_w( + self.cap, + irq_num, + core::ptr::null_mut(), + l4_timeout_t { raw: 0 }, + ) + } + .into(); + if tag.has_ipc_error() { + Err(Error::Tcr(TcrErr::from_tag(tag.raw()).unwrap())) + } else { + Ok(()) + } + } +} + +impl IrqSender { + pub fn receive(&mut self) -> Result<()> { + let tag: MsgTag = unsafe { l4_irq_receive_w(self.raw(), timeout_never()) }.into(); + if tag.has_ipc_error() { + Err(Error::Tcr(TcrErr::from_tag(tag.raw()).unwrap())) + } else { + Ok(()) + } + } + + pub fn bind_curr_thread(&mut self, label: u64) -> Result<()> { + let env = unsafe { l4re_env().as_ref() }.unwrap(); + // TODO! This makes us effectively single threaded for now + let tag: MsgTag = unsafe { l4_rcv_ep_bind_thread_w(self.raw(), env.main_thread, label) }.into(); + if tag.has_ipc_error() { + Err(Error::Tcr(TcrErr::from_tag(tag.raw()).unwrap())) + } else { + Ok(()) + } + } + + pub fn unmask(&mut self) -> Result<()> { + let tag: MsgTag = unsafe { l4_irq_unmask_w(self.raw()) }.into(); + if tag.has_ipc_error() { + Err(Error::Tcr(TcrErr::from_tag(tag.raw()).unwrap())) + } else { + Ok(()) + } + } + + pub fn detach(&self) -> Result<()> { + let tag: MsgTag = unsafe { l4_irq_detach_w(self.raw()) }.into(); + if tag.has_ipc_error() { + Err(Error::Tcr(TcrErr::from_tag(tag.raw()).unwrap())) + } else { + Ok(()) + } + } +} + +impl Drop for IrqSender { + fn drop(&mut self) { + self.detach().unwrap(); + } +} diff --git a/src/l4/pkg/l4rust/l4re-rust/lib.rs b/src/l4/pkg/l4rust/l4re-rust/lib.rs index e533ea75e6..a4e47cf3d1 100644 --- a/src/l4/pkg/l4rust/l4re-rust/lib.rs +++ b/src/l4/pkg/l4rust/l4re-rust/lib.rs @@ -1,10 +1,19 @@ //! L4Re interface crate //! //! Reimplemented methods -#![no_std] +//#![no_std] +#![feature(associated_type_defaults)] + +extern crate core as _core; +extern crate l4; +extern crate l4_derive; +extern crate l4_sys; +extern crate libc; mod cap; pub mod env; +pub mod factory; +pub mod io; pub mod mem; pub mod sys; diff --git a/src/l4/pkg/l4rust/l4re-rust/mem.rs b/src/l4/pkg/l4rust/l4re-rust/mem.rs index cce7eea54e..3c0593662d 100644 --- a/src/l4/pkg/l4rust/l4re-rust/mem.rs +++ b/src/l4/pkg/l4rust/l4re-rust/mem.rs @@ -1,174 +1,210 @@ -// ToDo: proc macros didn't support doc comments at some point, make them support doc strings and -// reformat the two interfaces -use l4::{ - cap::Cap, - utcb::SndFlexPage as FlexPage, - sys::{l4_addr_t, l4_size_t}, -}; -use l4_derive::{iface, l4_client}; -use super::sys::L4ReProtocols::L4RE_PROTO_DATASPACE; - -const PROTO_DATASPACE: i64 = L4RE_PROTO_DATASPACE as i64; - -/// Information about the dataspace -#[repr(C)] -#[derive(Clone)] -pub struct DsStats { - /// size of dataspace - pub size: u64, - /// dataspace flags - pub flags: u64, +use l4::Error; +use l4::Result; +use l4::cap::CapIdx; +use l4::cap::Interface; +use l4::cap::Cap; +use l4::task::THIS_TASK; +use l4::ipc::MsgTag; +use bitflags::bitflags; +use crate::factory::DmaSpace; +use crate::sys::l4re_ma_alloc; +use crate::sys::l4re_ds_map_flags::*; +use crate::sys::l4re_ma_flags::*; +use crate::sys::l4re_rm_flags_values::*; +use crate::sys::l4re_rm_attach; +use crate::sys::l4re_rm_detach; +use l4_sys::l4re_util_cap_alloc; +use l4_sys::l4_error_code_t::L4_EOK; +use l4_sys::{L4_PAGESHIFT, L4_SUPERPAGESHIFT}; +use l4_sys::l4_task_map; +use l4_sys::l4_msg_item_consts_t::*; +use l4_sys::l4_map_obj_control; +use l4_sys::L4_fpage_rights::*; +use l4_sys::l4_fpage_w; + +use core::ffi::c_void; +use core::marker::PhantomData; + +use crate::OwnedCap; + +// TODO: This file shows that the OwnedCap abstraction doesn't compose well, fix it +#[derive(Debug)] +pub struct Dataspace { + cap : CapIdx, + size: usize, + pageshift: usize } -// the struct is #[repr(C)] and hence the default implementation can be used -unsafe impl l4::ipc::Serialisable for DsStats { } -unsafe impl l4::ipc::Serialiser for DsStats { - #[inline] - fn read(mr: &mut l4::utcb::UtcbMr, _: &mut l4::ipc::BufferAccess) -> l4::error::Result { - mr.read::() // most types are read from here +pub struct AttachedDataspace { + cap: OwnedCap, + ptr: *mut u8, +} + +pub trait VolatileMemoryInterface { + fn ptr(&self) -> *mut u8; + + fn write8(&mut self, offset: usize, val: u8) { + unsafe { core::ptr::write_volatile(self.ptr().add(offset), val) } } - #[inline] - fn write(self, mr: &mut l4::utcb::UtcbMr) -> l4::error::Result<()> { - mr.write::(self) + fn write16(&mut self, offset: usize, val: u16) { + unsafe { core::ptr::write_volatile(self.ptr().add(offset) as *mut u16, val) } + } + + fn write32(&mut self, offset: usize, val: u32) { + unsafe { core::ptr::write_volatile(self.ptr().add(offset) as *mut u32, val) } + } + + fn write64(&mut self, offset: usize, val: u64) { + unsafe { core::ptr::write_volatile(self.ptr().add(offset) as *mut u64, val) } + } + + fn read8(&self, offset: usize) -> u8 { + unsafe { core::ptr::read_volatile(self.ptr().add(offset)) } + } + + fn read16(&self, offset: usize) -> u16 { + unsafe { core::ptr::read_volatile(self.ptr().add(offset) as *mut u16) } + } + + fn read32(&self, offset: usize) -> u32 { + unsafe { core::ptr::read_volatile(self.ptr().add(offset) as *mut u32) } + } + + fn read64(&self, offset: usize) -> u64 { + unsafe { core::ptr::read_volatile(self.ptr().add(offset) as *mut u64) } } } -#[l4_client(DataspaceProvider)] -pub struct Dataspace; +bitflags! { + pub struct MaFlags : u64 { + const CONTINUOUS = L4RE_MA_CONTINUOUS as u64; + const PINNED = L4RE_MA_PINNED as u64; + const SUPER_PAGES = L4RE_MA_SUPER_PAGES as u64; + } +} -/// used as return type for the **deprecated** phys() method of the DataspaceProvider trait -#[derive(Clone)] -#[repr(C)] -pub struct DeprecatedPhys { - phys_addr: l4_addr_t, - phys_size: l4_size_t +bitflags! { + pub struct DsMapFlags : u64 { + const R = L4RE_DS_F_R as u64; + const W = L4RE_DS_F_W as u64; + const X = L4RE_DS_F_X as u64; + const RW = L4RE_DS_F_RW as u64; + const RX = L4RE_DS_F_RX as u64; + const RWX = L4RE_DS_F_RWX as u64; + const RIGHTS_MASK = L4RE_DS_F_RIGHTS_MASK as u64; + const NORMAL = L4RE_DS_F_NORMAL as u64; + const BUFFERABLE = L4RE_DS_F_BUFFERABLE as u64; + const UNCACHEABLE = L4RE_DS_F_UNCACHEABLE as u64; + const CACHING_MASK = L4RE_DS_F_CACHING_MASK as u64; + } } -unsafe impl l4::ipc::Serialisable for DeprecatedPhys { } -unsafe impl l4::ipc::Serialiser for DeprecatedPhys { - #[inline] - fn read(mr: &mut l4::utcb::UtcbMr, _: &mut l4::ipc::BufferAccess) -> l4::error::Result { - mr.read::() + +bitflags! { + pub struct DsAttachFlags : u64 { + const SEARCH_ADDR = L4RE_RM_F_SEARCH_ADDR as u64; + const IN_AREA = L4RE_RM_F_IN_AREA as u64; + const EAGER_MAP = L4RE_RM_F_EAGER_MAP as u64; } +} +impl Interface for Dataspace { #[inline] - fn write(self, mr: &mut l4::utcb::UtcbMr) -> l4::error::Result<()> { - mr.write::(self) + fn raw(&self) -> CapIdx { + self.cap } } -// ToDo: this interface is not functional, the map operation is **broken**; it serves mostly as a -// marker trait and needs to be fixed; only the info() operation is tested -iface! { - trait DataspaceProvider { - const PROTOCOL_ID: i64 = PROTO_DATASPACE; - // ToDo: docs - fn map(&mut self, offset: l4_addr_t, spot: l4_addr_t, flags: u64, - r: FlexPage) -> Cap; - - /// Clear parts of a dataspace. - /// - /// Clear region within dataspace. `offset` gives the offset within the - /// dataspace to mark the beginning and `offset + size` the end of the region. - /// The memory is either zeroed out or unmapped and replaced through a null - /// page mapping. - fn clear(&mut self, offset: usize, size: usize) -> (); - - /// Get information on the dataspace. - fn info(&mut self) -> DsStats; - - /// Copy contents from another dataspace. - /// - /// The copy operation may use copy-on-write mechanisms. The operation may also fail if both - /// dataspaces are not from the same dataspace manager or the dataspace managers do not - /// cooperate. - fn copy_in(&mut self, dst_offset: l4_addr_t, src: Cap, - src_offset: l4_addr_t, size: l4_addr_t) -> (); - - /// Take operation. - /// **Deprecated**: Dataspaces exists as long as a capability on the dataspace exists. - fn take(&mut self, todo_delme: i32) -> (); - - /// Release operation. - /// **Deprecated:** Dataspaces exist as long as a capability on the dataspace exists. - fn release(&mut self, todo_delme: i32) -> (); - - /// Get the physical addresses of a dataspace. - /// - /// This call will only succeed on pinned memory dataspaces. - /// Returns phys_size - /// **Deprecated:** Use L4Re::Dma_space instead. This function will be removed - fn phys(&mut self, offset: l4_addr_t) -> DeprecatedPhys; - - /// Allocate a range in the dataspace. - /// - /// On success, at least the given range is guaranteed to be allocated. The - /// dataspace manager may also allocate more memory due to page granularity. - /// - /// The memory is allocated with the same rights as the dataspace - /// capability. - /// - /// A dataspace provider may also silently ignore areas - /// outside the dataspace. - fn allocate(&mut self, offset: l4_addr_t, size: l4_size_t) -> (); +impl Drop for AttachedDataspace { + fn drop(&mut self) { + let err = unsafe { l4re_rm_detach(self.ptr as *mut c_void) }; + if err < 0 { + Err(Error::from_ipc(err.into())).unwrap() + } } } +impl Dataspace { + pub fn alloc(size: usize, flags: MaFlags) -> Result> { + let cap = unsafe { l4re_util_cap_alloc() }; + let err = unsafe { l4re_ma_alloc(size, cap, flags.bits() as u64) }; + if err != 0 { + Err(Error::from_ipc(err.into())) + } else { + let has_super = flags.contains(MaFlags::SUPER_PAGES); + let pageshift = if has_super { L4_SUPERPAGESHIFT } else { L4_PAGESHIFT }; + Ok(OwnedCap(Cap::from_raw(Dataspace { + cap, + size, + pageshift: pageshift as usize + }))) + } + } -/// Flags for memory allocation -#[repr(u8)] -pub enum MemAllocFlags { - /// Allocate physically contiguous memory - Continuous = 0x01, - /// Allocate super pages - SuperPages = 0x04, + pub fn attach(space: OwnedCap, map_flags: DsMapFlags, attach_flags: DsAttachFlags) -> Result { + let mut vaddr = core::ptr::null_mut(); + let err = unsafe { l4re_rm_attach( + &mut vaddr as *mut *mut c_void, + space.size as u64, + map_flags.bits() as u64 | attach_flags.bits() as u64, + space.cap, + 0, + space.pageshift as u8 + ) }; + + if err != L4_EOK as i32 { + Err(Error::from_ipc(err.into())) + } else { + Ok(AttachedDataspace { + cap: space, + ptr: vaddr as *mut u8, + }) + } + } } -// TODO: this interface is not functional -// The Mem_alloc (C++) interface just mimics the ipc_iface framework, but is actually a plain C++ -// task. To expose this interface, the factory interface (also mimicking the framework interface to -// some extend) needs to be ported and then this stub needs to be rewritten to expose Cap, Demand, -// etc. manually. -/* -/// Memory allocation interface. -/// -/// The memory-allocator API is the basic API to allocate memory from the L4Re -/// subsystem. The memory is allocated in terms of dataspaces (see -/// [l4re::mem::dataspace](trait.Dataspace.html). -/// The provided dataspaces have at least the property that data written to such -/// a dataspace is available as long as the dataspace is not freed or the data -/// is not overwritten. In particular, the memory backing a dataspace from an -/// allocator need not be allocated instantly, but may be allocated lazily on -/// demand. -/// -/// A memory allocator can provide dataspaces with additional properties, such -/// as physically contiguous memory, pre-allocated memory, or pinned memory. To -/// request memory with an additional property the `alloc()` method provides a -/// flags parameter. If the concrete implementation of a memory allocator does -/// not support or allow allocation of memory with a certain property, the -/// allocation may be refused. -/// -/// Memory is not freed using this interface; use -/// `l4_task_unmap(mem, L4_FP_DELETE_OBJ)` or other similar means to remove a -/// dataspace. -iface! { - trait MemoryAllocator { - const PROTOCOL_ID: i64 = PROTO_EMPTY; - /// Allocate anonymous memory. - /// - /// The size is given in bytes and has the granularity of a (super)page. - /// If `size` is a negative value and `flags` set the - /// [MemAllocFlags::Continuous](enum.MemAllocFlags.html) bit the - /// allocator tries to allocate as much memory as possible leaving an - /// amount of at least `-size` bytes within the associated quota. - /// The flags parameters controls the allocation, see [MemAllocFlags](enum.MemAllocFlags.html) - /// If `align` is given and the allocator supports it, the memory will - /// be aligned and will be at least L4_PAGESHIFT, with SuperPages flag - /// set at least L4_SUPERPAGESHIFT - fn alloc(&mut self, size: isize, flags: u64, align: Option) -> Cap; +fn maxorder(base: usize, size: usize, pageshift: usize) -> usize { + let mut o = pageshift; + loop { + let m = (1 << (o+1)) - 1; + if (base & m) != 0 { + return o; + } + if size <= m { + return o; + } + o += 1; } } -#[l4_client(MemoryAllocator, demand = 1)] -pub struct MemAlloc; -*/ +impl AttachedDataspace { + pub fn map_dma(&mut self, target: &DmaSpace) -> Result { + let mut len = self.cap.size; + let mut addr = self.ptr as usize; // source address; + let page_size = 1 << self.cap.pageshift; + assert!((addr | len) % page_size == 0); + println!("Starting to map dataspace from 0x{:x} to 0x{:x}, length: 0x{:x}, alignment: 0x{:x}", addr, addr, len, page_size); + + while len != 0 { + let o = maxorder(addr, len, self.cap.pageshift); + let sz = 1 << o; + + let fp = unsafe { l4_fpage_w(addr, o as u32, L4_FPAGE_RWX as u8) }; + let ctl = l4_map_obj_control(addr as u64, L4_MAP_ITEM_MAP as u64); + let tag : MsgTag = unsafe { l4_task_map(target.raw(), THIS_TASK.raw(), fp, ctl as usize) }.into(); + tag.result()?; + + len -= sz; + println!("Mapped from 0x{:x} to 0x{:x}, length: 0x{:x}, remaining: 0x{:x}", addr, addr, sz, len); + addr += sz; + } + + Ok(self.ptr as usize) + } +} + +impl VolatileMemoryInterface for AttachedDataspace { + fn ptr(&self) -> *mut u8 { + self.ptr + } +} diff --git a/src/l4/pkg/l4rust/l4re-rust/sys.rs b/src/l4/pkg/l4rust/l4re-rust/sys.rs index 89c1850179..8be2e435ce 100644 --- a/src/l4/pkg/l4rust/l4re-rust/sys.rs +++ b/src/l4/pkg/l4rust/l4re-rust/sys.rs @@ -2,12 +2,10 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] -use core::{ - convert::TryInto, - ffi::{c_int, c_long, c_ulong, c_void}, - ptr::NonNull, -}; -use l4::sys::helpers::eq_str_cstr; +use _core::convert::TryInto; +use _core::ptr::NonNull; +use l4_sys::helpers::eq_str_cstr; +use libc::{c_int, c_long, c_ulong, c_void}; include!(concat!(env!("OUT_DIR"), "/bindings.rs")); @@ -30,8 +28,6 @@ pub unsafe fn l4re_env() -> *const l4re_env_t { /// It is advised to use l4re::env::get_cap instead. #[inline] pub fn l4re_env_get_cap(name: &str) -> Option { - // SAFETY: the unsafety stems from using pointers that are by the function signature declared - // to be non-null unsafe { l4re_env_get_cap_l(name, NonNull::new(l4re_env() as *mut l4re_env_t)) .map(|record| record.as_ref().cap) @@ -41,11 +37,13 @@ pub fn l4re_env_get_cap(name: &str) -> Option { #[inline] unsafe fn l4re_env_get_cap_l( name: &str, - env: Option>, + e: Option>, ) -> Option> { - let mut c = unsafe { env?.as_ref() }.caps; + // unwrap here because this function is internal and doesn't get a null pointer, see calling + // functions + let mut c = e.unwrap().as_ref().caps; while !c.is_null() && (*c).flags != !0u64 { - if eq_str_cstr(name, ((&(*c).name) as *const _) as *const u8) { + if eq_str_cstr(name, &(*c).name as *const u8) { return NonNull::new(c); } c = c.offset(1); // advance one record diff --git a/src/l4/pkg/l4rust/libl4re-wrapper/include/fpage.h b/src/l4/pkg/l4rust/libl4re-wrapper/include/fpage.h new file mode 100644 index 0000000000..00c213b723 --- /dev/null +++ b/src/l4/pkg/l4rust/libl4re-wrapper/include/fpage.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +#ifdef __cplusplus +#define EXTERN extern "C" +#else +#define EXTERN +#endif + +// TODO: rest later +EXTERN l4_fpage_t l4_fpage_w (l4_addr_t address, unsigned int size, unsigned char rights) L4_NOTHROW; +EXTERN l4_fpage_t l4_fpage_all_w (void) L4_NOTHROW; +EXTERN l4_fpage_t l4_fpage_invalid_w (void) L4_NOTHROW; +EXTERN l4_fpage_t l4_iofpage_w (unsigned long port, unsigned int size) L4_NOTHROW; +EXTERN l4_fpage_t l4_obj_fpage_w (l4_cap_idx_t obj, unsigned int order, unsigned char rights) L4_NOTHROW; +EXTERN int l4_is_fpage_writable_w (l4_fpage_t fp) L4_NOTHROW; +EXTERN unsigned l4_fpage_rights_w (l4_fpage_t f) L4_NOTHROW; +EXTERN unsigned l4_fpage_type_w (l4_fpage_t f) L4_NOTHROW; +EXTERN unsigned l4_fpage_size_w (l4_fpage_t f) L4_NOTHROW; +EXTERN unsigned long l4_fpage_page_w (l4_fpage_t f) L4_NOTHROW; +EXTERN l4_addr_t l4_fpage_memaddr_w (l4_fpage_t f) L4_NOTHROW; +EXTERN l4_cap_idx_t l4_fpage_obj_w (l4_fpage_t f) L4_NOTHROW; +EXTERN unsigned long l4_fpage_ioport_w (l4_fpage_t f) L4_NOTHROW; +EXTERN l4_fpage_t l4_fpage_set_rights_w (l4_fpage_t src, unsigned char new_rights) L4_NOTHROW; +EXTERN int l4_fpage_contains_w (l4_fpage_t fpage, l4_addr_t addr, unsigned size) L4_NOTHROW; +EXTERN unsigned char l4_fpage_max_order_w (unsigned char order, l4_addr_t addr, l4_addr_t min_addr, l4_addr_t max_addr, l4_addr_t hotspot); diff --git a/src/l4/pkg/l4rust/libl4re-wrapper/include/icu.h b/src/l4/pkg/l4rust/libl4re-wrapper/include/icu.h new file mode 100644 index 0000000000..f95f174538 --- /dev/null +++ b/src/l4/pkg/l4rust/libl4re-wrapper/include/icu.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +#ifdef __cplusplus +#define EXTERN extern "C" +#else +#define EXTERN +#endif + +EXTERN l4_msgtag_t l4_icu_bind_w (l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq); +EXTERN l4_msgtag_t l4_icu_bind_u_w (l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq, l4_utcb_t *utcb); +EXTERN l4_msgtag_t l4_icu_unbind_w (l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq); +EXTERN l4_msgtag_t l4_icu_unbind_u_w (l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq, l4_utcb_t *utcb); +EXTERN l4_msgtag_t l4_icu_set_mode_w (l4_cap_idx_t icu, unsigned irqnum, l4_umword_t mode); +EXTERN l4_msgtag_t l4_icu_set_mode_u_w (l4_cap_idx_t icu, unsigned irqnum, l4_umword_t mode, l4_utcb_t *utcb); +EXTERN l4_msgtag_t l4_icu_info_w (l4_cap_idx_t icu, l4_icu_info_t *info); +EXTERN l4_msgtag_t l4_icu_info_u_w (l4_cap_idx_t icu, l4_icu_info_t *info, l4_utcb_t *utcb); +EXTERN l4_msgtag_t l4_icu_msi_info_w (l4_cap_idx_t icu, unsigned irqnum, l4_uint64_t source, l4_icu_msi_info_t *msi_info); +EXTERN l4_msgtag_t l4_icu_msi_info_u_w (l4_cap_idx_t icu, unsigned irqnum, l4_uint64_t source, l4_icu_msi_info_t *msi_info, l4_utcb_t *utcb); +EXTERN l4_msgtag_t l4_icu_unmask_w (l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, l4_timeout_t to); +EXTERN l4_msgtag_t l4_icu_unmask_u_w (l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, l4_timeout_t to, l4_utcb_t *utcb); +EXTERN l4_msgtag_t l4_icu_mask_w (l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, l4_timeout_t to); +EXTERN l4_msgtag_t l4_icu_mask_u_w (l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, l4_timeout_t to, l4_utcb_t *utcb); diff --git a/src/l4/pkg/l4rust/libl4re-wrapper/include/ipc.h b/src/l4/pkg/l4rust/libl4re-wrapper/include/ipc.h index 0a87ded6c3..8d634a0787 100644 --- a/src/l4/pkg/l4rust/libl4re-wrapper/include/ipc.h +++ b/src/l4/pkg/l4rust/libl4re-wrapper/include/ipc.h @@ -20,6 +20,8 @@ EXTERN l4_msgtag_t l4_ipc_call_w(l4_cap_idx_t object, EXTERN l4_msgtag_t l4_ipc_send_w(l4_cap_idx_t object, l4_utcb_t *utcb, l4_msgtag_t tag, l4_timeout_t timeout); +EXTERN long l4_error_w (l4_msgtag_t tag) L4_NOTHROW; + EXTERN l4_umword_t l4_ipc_error_w(l4_msgtag_t tag, l4_utcb_t *utcb); EXTERN l4_msgtag_t l4_ipc_wait_w(l4_utcb_t *utcb, l4_umword_t *label, diff --git a/src/l4/pkg/l4rust/libl4re-wrapper/include/irq.h b/src/l4/pkg/l4rust/libl4re-wrapper/include/irq.h new file mode 100644 index 0000000000..6bea50cfd8 --- /dev/null +++ b/src/l4/pkg/l4rust/libl4re-wrapper/include/irq.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#ifdef __cplusplus +#define EXTERN extern "C" +#else +#define EXTERN +#endif + +EXTERN l4_msgtag_t l4_irq_mux_chain_w (l4_cap_idx_t irq, l4_cap_idx_t slave) L4_NOTHROW; +EXTERN l4_msgtag_t l4_irq_mux_chain_u_w (l4_cap_idx_t irq, l4_cap_idx_t slave, l4_utcb_t *utcb) L4_NOTHROW; +EXTERN l4_msgtag_t l4_irq_detach_w (l4_cap_idx_t irq) L4_NOTHROW; +EXTERN l4_msgtag_t l4_irq_detach_u_w (l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW; +EXTERN l4_msgtag_t l4_irq_trigger_w (l4_cap_idx_t irq) L4_NOTHROW; +EXTERN l4_msgtag_t l4_irq_trigger_u_w (l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW; +EXTERN l4_msgtag_t l4_irq_receive_w (l4_cap_idx_t irq, l4_timeout_t to) L4_NOTHROW; +EXTERN l4_msgtag_t l4_irq_receive_u_w (l4_cap_idx_t irq, l4_timeout_t timeout, l4_utcb_t *utcb) L4_NOTHROW; +EXTERN l4_msgtag_t l4_irq_wait_w (l4_cap_idx_t irq, l4_umword_t *label, l4_timeout_t to) L4_NOTHROW; +EXTERN l4_msgtag_t l4_irq_wait_u_w (l4_cap_idx_t irq, l4_umword_t *label, l4_timeout_t timeout, l4_utcb_t *utcb) L4_NOTHROW; +EXTERN l4_msgtag_t l4_irq_unmask_w (l4_cap_idx_t irq) L4_NOTHROW; +EXTERN l4_msgtag_t l4_irq_unmask_u_w (l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW; diff --git a/src/l4/pkg/l4rust/libl4re-wrapper/include/vbus.h b/src/l4/pkg/l4rust/libl4re-wrapper/include/vbus.h new file mode 100644 index 0000000000..621f3ea7ef --- /dev/null +++ b/src/l4/pkg/l4rust/libl4re-wrapper/include/vbus.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +#define EXTERN extern "C" +#else +#define EXTERN +#endif + +EXTERN int l4vbus_subinterface_supported_w (l4_uint32_t dev_type, l4vbus_iface_type_t iface_type); diff --git a/src/l4/pkg/l4rust/libl4re-wrapper/lib/Makefile b/src/l4/pkg/l4rust/libl4re-wrapper/lib/Makefile index 987841486a..5d3b8b5a8d 100644 --- a/src/l4/pkg/l4rust/libl4re-wrapper/lib/Makefile +++ b/src/l4/pkg/l4rust/libl4re-wrapper/lib/Makefile @@ -3,7 +3,7 @@ L4DIR ?= $(PKGDIR)/../.. TARGET = libl4re-wrapper.a PC_FILENAME = libl4re-wrapper -SRC_C = debug.c env.c ipc.c mem.c scheduler.c +SRC_C = debug.c env.c ipc.c mem.c icu.c irq.c fpage.c vbus.c REQUIRES_LIBS += libpthread l4re_c l4re_c-util diff --git a/src/l4/pkg/l4rust/libl4re-wrapper/lib/fpage.c b/src/l4/pkg/l4rust/libl4re-wrapper/lib/fpage.c new file mode 100644 index 0000000000..e4344f1136 --- /dev/null +++ b/src/l4/pkg/l4rust/libl4re-wrapper/lib/fpage.c @@ -0,0 +1,51 @@ +#include +#include + +EXTERN l4_fpage_t l4_fpage_w (l4_addr_t address, unsigned int size, unsigned char rights) L4_NOTHROW { + return l4_fpage(address, size, rights); +} +EXTERN l4_fpage_t l4_fpage_all_w (void) L4_NOTHROW { + return l4_fpage_all(); +} +EXTERN l4_fpage_t l4_fpage_invalid_w (void) L4_NOTHROW { + return l4_fpage_invalid(); +} +EXTERN l4_fpage_t l4_iofpage_w (unsigned long port, unsigned int size) L4_NOTHROW { + return l4_iofpage(port, size); +} +EXTERN l4_fpage_t l4_obj_fpage_w (l4_cap_idx_t obj, unsigned int order, unsigned char rights) L4_NOTHROW { + return l4_obj_fpage(obj, order, rights); +} +EXTERN int l4_is_fpage_writable_w (l4_fpage_t fp) L4_NOTHROW { + return l4_is_fpage_writable(fp); +} +EXTERN unsigned l4_fpage_rights_w (l4_fpage_t f) L4_NOTHROW { + return l4_fpage_rights(f); +} +EXTERN unsigned l4_fpage_type_w (l4_fpage_t f) L4_NOTHROW { + return l4_fpage_type(f); +} +EXTERN unsigned l4_fpage_size_w (l4_fpage_t f) L4_NOTHROW { + return l4_fpage_size(f); +} +EXTERN unsigned long l4_fpage_page_w (l4_fpage_t f) L4_NOTHROW { + return l4_fpage_page(f); +} +EXTERN l4_addr_t l4_fpage_memaddr_w (l4_fpage_t f) L4_NOTHROW { + return l4_fpage_memaddr(f); +} +EXTERN l4_cap_idx_t l4_fpage_obj_w (l4_fpage_t f) L4_NOTHROW { + return l4_fpage_obj(f); +} +EXTERN unsigned long l4_fpage_ioport_w (l4_fpage_t f) L4_NOTHROW { + return l4_fpage_ioport(f); +} +EXTERN l4_fpage_t l4_fpage_set_rights_w (l4_fpage_t src, unsigned char new_rights) L4_NOTHROW { + return l4_fpage_set_rights(src, new_rights); +} +EXTERN int l4_fpage_contains_w (l4_fpage_t fpage, l4_addr_t addr, unsigned size) L4_NOTHROW { + return l4_fpage_contains(fpage, addr, size); +} +EXTERN unsigned char l4_fpage_max_order_w (unsigned char order, l4_addr_t addr, l4_addr_t min_addr, l4_addr_t max_addr, l4_addr_t hotspot) { + return l4_fpage_max_order(order, addr, min_addr, max_addr, hotspot); +} diff --git a/src/l4/pkg/l4rust/libl4re-wrapper/lib/icu.c b/src/l4/pkg/l4rust/libl4re-wrapper/lib/icu.c new file mode 100644 index 0000000000..a2699794a4 --- /dev/null +++ b/src/l4/pkg/l4rust/libl4re-wrapper/lib/icu.c @@ -0,0 +1,57 @@ +#include + +EXTERN l4_msgtag_t l4_icu_bind_w (l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq) { + return l4_icu_bind(icu, irqnum, irq); +} + +EXTERN l4_msgtag_t l4_icu_bind_u_w (l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq, l4_utcb_t *utcb) { + return l4_icu_bind_u(icu, irqnum, irq, utcb); +} + +EXTERN l4_msgtag_t l4_icu_unbind_w (l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq) { + return l4_icu_unbind(icu, irqnum, irq); +} + +EXTERN l4_msgtag_t l4_icu_unbind_u_w (l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq, l4_utcb_t *utcb) { + return l4_icu_unbind_u(icu, irqnum, irq, utcb); +} + +EXTERN l4_msgtag_t l4_icu_set_mode_w (l4_cap_idx_t icu, unsigned irqnum, l4_umword_t mode) { + return l4_icu_set_mode(icu, irqnum, mode); +} + +EXTERN l4_msgtag_t l4_icu_set_mode_u_w (l4_cap_idx_t icu, unsigned irqnum, l4_umword_t mode, l4_utcb_t *utcb) { + return l4_icu_set_mode_u(icu, irqnum, mode, utcb); +} + +EXTERN l4_msgtag_t l4_icu_info_w (l4_cap_idx_t icu, l4_icu_info_t *info) { + return l4_icu_info(icu, info); +} + +EXTERN l4_msgtag_t l4_icu_info_u_w (l4_cap_idx_t icu, l4_icu_info_t *info, l4_utcb_t *utcb) { + return l4_icu_info_u(icu, info, utcb); +} + +EXTERN l4_msgtag_t l4_icu_msi_info_w (l4_cap_idx_t icu, unsigned irqnum, l4_uint64_t source, l4_icu_msi_info_t *msi_info) { + return l4_icu_msi_info(icu, irqnum, source, msi_info); +} + +EXTERN l4_msgtag_t l4_icu_msi_info_u_w (l4_cap_idx_t icu, unsigned irqnum, l4_uint64_t source, l4_icu_msi_info_t *msi_info, l4_utcb_t *utcb) { + return l4_icu_msi_info_u(icu, irqnum, source, msi_info, utcb); +} + +EXTERN l4_msgtag_t l4_icu_unmask_w (l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, l4_timeout_t to) { + return l4_icu_unmask(icu, irqnum, label, to); +} + +EXTERN l4_msgtag_t l4_icu_unmask_u_w (l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, l4_timeout_t to, l4_utcb_t *utcb) { + return l4_icu_unmask_u(icu, irqnum, label, to, utcb); +} + +EXTERN l4_msgtag_t l4_icu_mask_w (l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, l4_timeout_t to) { + return l4_icu_mask(icu, irqnum, label, to); +} + +EXTERN l4_msgtag_t l4_icu_mask_u_w (l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, l4_timeout_t to, l4_utcb_t *utcb) { + return l4_icu_mask_u(icu, irqnum, label, to, utcb); +} diff --git a/src/l4/pkg/l4rust/libl4re-wrapper/lib/ipc.c b/src/l4/pkg/l4rust/libl4re-wrapper/lib/ipc.c index e9e490669e..61bcb33eb7 100644 --- a/src/l4/pkg/l4rust/libl4re-wrapper/lib/ipc.c +++ b/src/l4/pkg/l4rust/libl4re-wrapper/lib/ipc.c @@ -17,6 +17,11 @@ EXTERN l4_msgtag_t l4_ipc_send_w(l4_cap_idx_t object, return l4_ipc_send(object, utcb, tag, timeout); } + +EXTERN long l4_error_w (l4_msgtag_t tag) L4_NOTHROW { + return l4_error(tag); +} + EXTERN l4_umword_t l4_ipc_error_w(l4_msgtag_t tag, l4_utcb_t *utcb) { return l4_ipc_error(tag, utcb); } @@ -49,11 +54,6 @@ EXTERN unsigned l4_msgtag_words_w(l4_msgtag_t t) { return l4_msgtag_words(t); } -EXTERN l4_fpage_t l4_obj_fpage_w(l4_cap_idx_t obj, unsigned int order, - unsigned char rights) { - return l4_obj_fpage(obj, order, rights); -} - EXTERN l4_msgtag_t l4_rcv_ep_bind_thread_w(l4_cap_idx_t ep, l4_cap_idx_t thread, l4_umword_t label) { return l4_rcv_ep_bind_thread(ep, thread, label); diff --git a/src/l4/pkg/l4rust/libl4re-wrapper/lib/irq.c b/src/l4/pkg/l4rust/libl4re-wrapper/lib/irq.c new file mode 100644 index 0000000000..827b14395b --- /dev/null +++ b/src/l4/pkg/l4rust/libl4re-wrapper/lib/irq.c @@ -0,0 +1,39 @@ +#include +#include + +EXTERN l4_msgtag_t l4_irq_mux_chain_w (l4_cap_idx_t irq, l4_cap_idx_t slave) L4_NOTHROW { + return l4_irq_mux_chain(irq, slave); +} +EXTERN l4_msgtag_t l4_irq_mux_chain_u_w (l4_cap_idx_t irq, l4_cap_idx_t slave, l4_utcb_t *utcb) L4_NOTHROW { + return l4_irq_mux_chain_u(irq, slave, utcb); +} +EXTERN l4_msgtag_t l4_irq_detach_w (l4_cap_idx_t irq) L4_NOTHROW { + return l4_irq_detach(irq); +} +EXTERN l4_msgtag_t l4_irq_detach_u_w (l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW { + return l4_irq_detach_u(irq, utcb); +} +EXTERN l4_msgtag_t l4_irq_trigger_w (l4_cap_idx_t irq) L4_NOTHROW { + return l4_irq_trigger(irq); +} +EXTERN l4_msgtag_t l4_irq_trigger_u_w (l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW { + return l4_irq_trigger_u(irq, utcb); +} +EXTERN l4_msgtag_t l4_irq_receive_w (l4_cap_idx_t irq, l4_timeout_t to) L4_NOTHROW { + return l4_irq_receive(irq, to); +} +EXTERN l4_msgtag_t l4_irq_receive_u_w (l4_cap_idx_t irq, l4_timeout_t timeout, l4_utcb_t *utcb) L4_NOTHROW { + return l4_irq_receive_u(irq, timeout, utcb); +} +EXTERN l4_msgtag_t l4_irq_wait_w (l4_cap_idx_t irq, l4_umword_t *label, l4_timeout_t to) L4_NOTHROW { + return l4_irq_wait(irq, label, to); +} +EXTERN l4_msgtag_t l4_irq_wait_u_w (l4_cap_idx_t irq, l4_umword_t *label, l4_timeout_t timeout, l4_utcb_t *utcb) L4_NOTHROW { + return l4_irq_wait_u(irq, label, timeout, utcb); +} +EXTERN l4_msgtag_t l4_irq_unmask_w (l4_cap_idx_t irq) L4_NOTHROW { + return l4_irq_unmask(irq); +} +EXTERN l4_msgtag_t l4_irq_unmask_u_w (l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW { + return l4_irq_unmask_u(irq, utcb); +} diff --git a/src/l4/pkg/l4rust/libl4re-wrapper/lib/vbus.c b/src/l4/pkg/l4rust/libl4re-wrapper/lib/vbus.c new file mode 100644 index 0000000000..ddc75f72b6 --- /dev/null +++ b/src/l4/pkg/l4rust/libl4re-wrapper/lib/vbus.c @@ -0,0 +1,5 @@ +#include + +EXTERN int l4vbus_subinterface_supported_w (l4_uint32_t dev_type, l4vbus_iface_type_t iface_type) { + return l4vbus_subinterface_supported(dev_type, iface_type); +}