summaryrefslogtreecommitdiff
path: root/rust/kernel/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/kernel/lib.rs')
-rw-r--r--rust/kernel/lib.rs132
1 files changed, 117 insertions, 15 deletions
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 6858e2f8a3ed..496ed32b0911 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -12,13 +12,18 @@
//! do so first instead of bypassing this crate.
#![no_std]
-#![feature(allocator_api)]
-#![feature(coerce_unsized)]
-#![feature(dispatch_from_dyn)]
-#![feature(new_uninit)]
-#![feature(offset_of)]
-#![feature(receiver_trait)]
-#![feature(unsize)]
+#![feature(arbitrary_self_types)]
+#![cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, feature(derive_coerce_pointee))]
+#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(coerce_unsized))]
+#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(dispatch_from_dyn))]
+#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(unsize))]
+#![feature(inline_const)]
+#![feature(lint_reasons)]
+// Stable in Rust 1.83
+#![feature(const_maybe_uninit_as_mut_ptr)]
+#![feature(const_mut_refs)]
+#![feature(const_ptr_write)]
+#![feature(const_refs_to_cell)]
// Ensure conditional compilation based on the kernel configuration works;
// otherwise we may silently break things like initcall handling.
@@ -28,19 +33,45 @@ compile_error!("Missing kernel configuration for conditional compilation");
// Allow proc-macros to refer to `::kernel` inside the `kernel` crate (this crate).
extern crate self as kernel;
-#[cfg(not(test))]
-#[cfg(not(testlib))]
-mod allocator;
-mod build_assert;
+pub use ffi;
+
+pub mod alloc;
+#[cfg(CONFIG_BLOCK)]
+pub mod block;
+#[doc(hidden)]
+pub mod build_assert;
+pub mod cred;
+pub mod device;
+pub mod device_id;
+pub mod devres;
+pub mod driver;
pub mod error;
+#[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
+pub mod firmware;
+pub mod fs;
pub mod init;
+pub mod io;
pub mod ioctl;
+pub mod jump_label;
#[cfg(CONFIG_KUNIT)]
pub mod kunit;
+pub mod list;
+pub mod miscdevice;
#[cfg(CONFIG_NET)]
pub mod net;
+pub mod of;
+pub mod page;
+#[cfg(CONFIG_PCI)]
+pub mod pci;
+pub mod pid_namespace;
+pub mod platform;
pub mod prelude;
pub mod print;
+pub mod rbtree;
+pub mod revocable;
+pub mod security;
+pub mod seq_file;
+pub mod sizes;
mod static_assert;
#[doc(hidden)]
pub mod std_vendor;
@@ -48,7 +79,10 @@ pub mod str;
pub mod sync;
pub mod task;
pub mod time;
+pub mod tracepoint;
+pub mod transmute;
pub mod types;
+pub mod uaccess;
pub mod workqueue;
#[doc(hidden)]
@@ -56,9 +90,6 @@ pub use bindings;
pub use macros;
pub use uapi;
-#[doc(hidden)]
-pub use build_error::build_error;
-
/// Prefix to appear before log messages printed from within the `kernel` crate.
const __LOG_PREFIX: &[u8] = b"rust_kernel\0";
@@ -75,9 +106,38 @@ pub trait Module: Sized + Sync + Send {
fn init(module: &'static ThisModule) -> error::Result<Self>;
}
+/// A module that is pinned and initialised in-place.
+pub trait InPlaceModule: Sync + Send {
+ /// Creates an initialiser for the module.
+ ///
+ /// It is called when the module is loaded.
+ fn init(module: &'static ThisModule) -> impl init::PinInit<Self, error::Error>;
+}
+
+impl<T: Module> InPlaceModule for T {
+ fn init(module: &'static ThisModule) -> impl init::PinInit<Self, error::Error> {
+ let initer = move |slot: *mut Self| {
+ let m = <Self as Module>::init(module)?;
+
+ // SAFETY: `slot` is valid for write per the contract with `pin_init_from_closure`.
+ unsafe { slot.write(m) };
+ Ok(())
+ };
+
+ // SAFETY: On success, `initer` always fully initialises an instance of `Self`.
+ unsafe { init::pin_init_from_closure(initer) }
+ }
+}
+
+/// Metadata attached to a [`Module`] or [`InPlaceModule`].
+pub trait ModuleMetadata {
+ /// The name of the module as specified in the `module!` macro.
+ const NAME: &'static crate::str::CStr;
+}
+
/// Equivalent to `THIS_MODULE` in the C API.
///
-/// C header: [`include/linux/export.h`](srctree/include/linux/export.h)
+/// C header: [`include/linux/init.h`](srctree/include/linux/init.h)
pub struct ThisModule(*mut bindings::module);
// SAFETY: `THIS_MODULE` may be used from all threads within a module.
@@ -92,6 +152,13 @@ impl ThisModule {
pub const unsafe fn from_ptr(ptr: *mut bindings::module) -> ThisModule {
ThisModule(ptr)
}
+
+ /// Access the raw pointer for this module.
+ ///
+ /// It is up to the user to use it correctly.
+ pub const fn as_ptr(&self) -> *mut bindings::module {
+ self.0
+ }
}
#[cfg(not(any(testlib, test)))]
@@ -133,3 +200,38 @@ macro_rules! container_of {
ptr.sub(offset) as *const $type
}}
}
+
+/// Helper for `.rs.S` files.
+#[doc(hidden)]
+#[macro_export]
+macro_rules! concat_literals {
+ ($( $asm:literal )* ) => {
+ ::core::concat!($($asm),*)
+ };
+}
+
+/// Wrapper around `asm!` configured for use in the kernel.
+///
+/// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!`
+/// syntax.
+// For x86, `asm!` uses intel syntax by default, but we want to use at&t syntax in the kernel.
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+#[macro_export]
+macro_rules! asm {
+ ($($asm:expr),* ; $($rest:tt)*) => {
+ ::core::arch::asm!( $($asm)*, options(att_syntax), $($rest)* )
+ };
+}
+
+/// Wrapper around `asm!` configured for use in the kernel.
+///
+/// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!`
+/// syntax.
+// For non-x86 arches we just pass through to `asm!`.
+#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+#[macro_export]
+macro_rules! asm {
+ ($($asm:expr),* ; $($rest:tt)*) => {
+ ::core::arch::asm!( $($asm)*, $($rest)* )
+ };
+}