kernel/
lib.rs

1// SPDX-License-Identifier: GPL-2.0
2
3//! The `kernel` crate.
4//!
5//! This crate contains the kernel APIs that have been ported or wrapped for
6//! usage by Rust code in the kernel and is shared by all of them.
7//!
8//! In other words, all the rest of the Rust code in the kernel (e.g. kernel
9//! modules written in Rust) depends on [`core`] and this crate.
10//!
11//! If you need a kernel C API that is not ported or wrapped yet here, then
12//! do so first instead of bypassing this crate.
13
14#![no_std]
15//
16// Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on
17// the unstable features in use.
18//
19// Stable since Rust 1.79.0.
20#![feature(inline_const)]
21//
22// Stable since Rust 1.81.0.
23#![feature(lint_reasons)]
24//
25// Stable since Rust 1.82.0.
26#![feature(raw_ref_op)]
27//
28// Stable since Rust 1.83.0.
29#![feature(const_maybe_uninit_as_mut_ptr)]
30#![feature(const_mut_refs)]
31#![feature(const_ptr_write)]
32#![feature(const_refs_to_cell)]
33//
34// Expected to become stable.
35#![feature(arbitrary_self_types)]
36//
37// To be determined.
38#![feature(used_with_arg)]
39//
40// `feature(derive_coerce_pointee)` is expected to become stable. Before Rust
41// 1.84.0, it did not exist, so enable the predecessor features.
42#![cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, feature(derive_coerce_pointee))]
43#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(coerce_unsized))]
44#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(dispatch_from_dyn))]
45#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(unsize))]
46//
47// `feature(file_with_nul)` is expected to become stable. Before Rust 1.89.0, it did not exist, so
48// enable it conditionally.
49#![cfg_attr(CONFIG_RUSTC_HAS_FILE_WITH_NUL, feature(file_with_nul))]
50
51// Ensure conditional compilation based on the kernel configuration works;
52// otherwise we may silently break things like initcall handling.
53#[cfg(not(CONFIG_RUST))]
54compile_error!("Missing kernel configuration for conditional compilation");
55
56// Allow proc-macros to refer to `::kernel` inside the `kernel` crate (this crate).
57extern crate self as kernel;
58
59pub use ffi;
60
61pub mod acpi;
62pub mod alloc;
63#[cfg(CONFIG_AUXILIARY_BUS)]
64pub mod auxiliary;
65pub mod bits;
66#[cfg(CONFIG_BLOCK)]
67pub mod block;
68pub mod bug;
69#[doc(hidden)]
70pub mod build_assert;
71pub mod clk;
72#[cfg(CONFIG_CONFIGFS_FS)]
73pub mod configfs;
74pub mod cpu;
75#[cfg(CONFIG_CPU_FREQ)]
76pub mod cpufreq;
77pub mod cpumask;
78pub mod cred;
79pub mod device;
80pub mod device_id;
81pub mod devres;
82pub mod dma;
83pub mod driver;
84#[cfg(CONFIG_DRM = "y")]
85pub mod drm;
86pub mod error;
87pub mod faux;
88#[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
89pub mod firmware;
90pub mod fmt;
91pub mod fs;
92pub mod init;
93pub mod io;
94pub mod ioctl;
95pub mod jump_label;
96#[cfg(CONFIG_KUNIT)]
97pub mod kunit;
98pub mod list;
99pub mod miscdevice;
100pub mod mm;
101#[cfg(CONFIG_NET)]
102pub mod net;
103pub mod of;
104#[cfg(CONFIG_PM_OPP)]
105pub mod opp;
106pub mod page;
107#[cfg(CONFIG_PCI)]
108pub mod pci;
109pub mod pid_namespace;
110pub mod platform;
111pub mod prelude;
112pub mod print;
113pub mod rbtree;
114pub mod regulator;
115pub mod revocable;
116pub mod security;
117pub mod seq_file;
118pub mod sizes;
119mod static_assert;
120#[doc(hidden)]
121pub mod std_vendor;
122pub mod str;
123pub mod sync;
124pub mod task;
125pub mod time;
126pub mod tracepoint;
127pub mod transmute;
128pub mod types;
129pub mod uaccess;
130pub mod workqueue;
131pub mod xarray;
132
133#[doc(hidden)]
134pub use bindings;
135pub use macros;
136pub use uapi;
137
138/// Prefix to appear before log messages printed from within the `kernel` crate.
139const __LOG_PREFIX: &[u8] = b"rust_kernel\0";
140
141/// The top level entrypoint to implementing a kernel module.
142///
143/// For any teardown or cleanup operations, your type may implement [`Drop`].
144pub trait Module: Sized + Sync + Send {
145    /// Called at module initialization time.
146    ///
147    /// Use this method to perform whatever setup or registration your module
148    /// should do.
149    ///
150    /// Equivalent to the `module_init` macro in the C API.
151    fn init(module: &'static ThisModule) -> error::Result<Self>;
152}
153
154/// A module that is pinned and initialised in-place.
155pub trait InPlaceModule: Sync + Send {
156    /// Creates an initialiser for the module.
157    ///
158    /// It is called when the module is loaded.
159    fn init(module: &'static ThisModule) -> impl pin_init::PinInit<Self, error::Error>;
160}
161
162impl<T: Module> InPlaceModule for T {
163    fn init(module: &'static ThisModule) -> impl pin_init::PinInit<Self, error::Error> {
164        let initer = move |slot: *mut Self| {
165            let m = <Self as Module>::init(module)?;
166
167            // SAFETY: `slot` is valid for write per the contract with `pin_init_from_closure`.
168            unsafe { slot.write(m) };
169            Ok(())
170        };
171
172        // SAFETY: On success, `initer` always fully initialises an instance of `Self`.
173        unsafe { pin_init::pin_init_from_closure(initer) }
174    }
175}
176
177/// Metadata attached to a [`Module`] or [`InPlaceModule`].
178pub trait ModuleMetadata {
179    /// The name of the module as specified in the `module!` macro.
180    const NAME: &'static crate::str::CStr;
181}
182
183/// Equivalent to `THIS_MODULE` in the C API.
184///
185/// C header: [`include/linux/init.h`](srctree/include/linux/init.h)
186pub struct ThisModule(*mut bindings::module);
187
188// SAFETY: `THIS_MODULE` may be used from all threads within a module.
189unsafe impl Sync for ThisModule {}
190
191impl ThisModule {
192    /// Creates a [`ThisModule`] given the `THIS_MODULE` pointer.
193    ///
194    /// # Safety
195    ///
196    /// The pointer must be equal to the right `THIS_MODULE`.
197    pub const unsafe fn from_ptr(ptr: *mut bindings::module) -> ThisModule {
198        ThisModule(ptr)
199    }
200
201    /// Access the raw pointer for this module.
202    ///
203    /// It is up to the user to use it correctly.
204    pub const fn as_ptr(&self) -> *mut bindings::module {
205        self.0
206    }
207}
208
209#[cfg(not(any(testlib, test)))]
210#[panic_handler]
211fn panic(info: &core::panic::PanicInfo<'_>) -> ! {
212    pr_emerg!("{}\n", info);
213    // SAFETY: FFI call.
214    unsafe { bindings::BUG() };
215}
216
217/// Produces a pointer to an object from a pointer to one of its fields.
218///
219/// If you encounter a type mismatch due to the [`Opaque`] type, then use [`Opaque::cast_into`] or
220/// [`Opaque::cast_from`] to resolve the mismatch.
221///
222/// [`Opaque`]: crate::types::Opaque
223/// [`Opaque::cast_into`]: crate::types::Opaque::cast_into
224/// [`Opaque::cast_from`]: crate::types::Opaque::cast_from
225///
226/// # Safety
227///
228/// The pointer passed to this macro, and the pointer returned by this macro, must both be in
229/// bounds of the same allocation.
230///
231/// # Examples
232///
233/// ```
234/// # use kernel::container_of;
235/// struct Test {
236///     a: u64,
237///     b: u32,
238/// }
239///
240/// let test = Test { a: 10, b: 20 };
241/// let b_ptr: *const _ = &test.b;
242/// // SAFETY: The pointer points at the `b` field of a `Test`, so the resulting pointer will be
243/// // in-bounds of the same allocation as `b_ptr`.
244/// let test_alias = unsafe { container_of!(b_ptr, Test, b) };
245/// assert!(core::ptr::eq(&test, test_alias));
246/// ```
247#[macro_export]
248macro_rules! container_of {
249    ($field_ptr:expr, $Container:ty, $($fields:tt)*) => {{
250        let offset: usize = ::core::mem::offset_of!($Container, $($fields)*);
251        let field_ptr = $field_ptr;
252        let container_ptr = field_ptr.byte_sub(offset).cast::<$Container>();
253        $crate::assert_same_type(field_ptr, (&raw const (*container_ptr).$($fields)*).cast_mut());
254        container_ptr
255    }}
256}
257
258/// Helper for [`container_of!`].
259#[doc(hidden)]
260pub fn assert_same_type<T>(_: T, _: T) {}
261
262/// Helper for `.rs.S` files.
263#[doc(hidden)]
264#[macro_export]
265macro_rules! concat_literals {
266    ($( $asm:literal )* ) => {
267        ::core::concat!($($asm),*)
268    };
269}
270
271/// Wrapper around `asm!` configured for use in the kernel.
272///
273/// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!`
274/// syntax.
275// For x86, `asm!` uses intel syntax by default, but we want to use at&t syntax in the kernel.
276#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
277#[macro_export]
278macro_rules! asm {
279    ($($asm:expr),* ; $($rest:tt)*) => {
280        ::core::arch::asm!( $($asm)*, options(att_syntax), $($rest)* )
281    };
282}
283
284/// Wrapper around `asm!` configured for use in the kernel.
285///
286/// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!`
287/// syntax.
288// For non-x86 arches we just pass through to `asm!`.
289#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
290#[macro_export]
291macro_rules! asm {
292    ($($asm:expr),* ; $($rest:tt)*) => {
293        ::core::arch::asm!( $($asm)*, $($rest)* )
294    };
295}
296
297/// Gets the C string file name of a [`Location`].
298///
299/// If `file_with_nul()` is not available, returns a string that warns about it.
300///
301/// [`Location`]: core::panic::Location
302///
303/// # Examples
304///
305/// ```
306/// # use kernel::file_from_location;
307///
308/// #[track_caller]
309/// fn foo() {
310///     let caller = core::panic::Location::caller();
311///
312///     // Output:
313///     // - A path like "rust/kernel/example.rs" if file_with_nul() is available.
314///     // - "<Location::file_with_nul() not supported>" otherwise.
315///     let caller_file = file_from_location(caller);
316///
317///     // Prints out the message with caller's file name.
318///     pr_info!("foo() called in file {caller_file:?}\n");
319///
320///     # if cfg!(CONFIG_RUSTC_HAS_FILE_WITH_NUL) {
321///     #     assert_eq!(Ok(caller.file()), caller_file.to_str());
322///     # }
323/// }
324///
325/// # foo();
326/// ```
327#[inline]
328pub fn file_from_location<'a>(loc: &'a core::panic::Location<'a>) -> &'a core::ffi::CStr {
329    #[cfg(CONFIG_RUSTC_HAS_FILE_WITH_NUL)]
330    {
331        loc.file_with_nul()
332    }
333
334    #[cfg(not(CONFIG_RUSTC_HAS_FILE_WITH_NUL))]
335    {
336        let _ = loc;
337        c"<Location::file_with_nul() not supported>"
338    }
339}