Skip to main content

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.87.0.
20#![feature(unsigned_is_multiple_of)]
21//
22// Stable since Rust 1.89.0.
23#![feature(generic_arg_infer)]
24//
25// Expected to become stable.
26#![feature(arbitrary_self_types)]
27#![feature(derive_coerce_pointee)]
28//
29// To be determined.
30#![feature(used_with_arg)]
31//
32// `feature(file_with_nul)` is stable since Rust 1.92.0. Before Rust 1.89.0, it did not exist, so
33// enable it conditionally.
34#![cfg_attr(CONFIG_RUSTC_HAS_FILE_WITH_NUL, feature(file_with_nul))]
35
36// Ensure conditional compilation based on the kernel configuration works;
37// otherwise we may silently break things like initcall handling.
38#[cfg(not(CONFIG_RUST))]
39compile_error!("Missing kernel configuration for conditional compilation");
40
41// Allow proc-macros to refer to `::kernel` inside the `kernel` crate (this crate).
42extern crate self as kernel;
43
44pub use ffi;
45
46pub mod acpi;
47pub mod alloc;
48#[cfg(CONFIG_AUXILIARY_BUS)]
49pub mod auxiliary;
50pub mod bitfield;
51pub mod bitmap;
52pub mod bits;
53#[cfg(CONFIG_BLOCK)]
54pub mod block;
55pub mod bug;
56pub mod build_assert;
57pub mod clk;
58#[cfg(CONFIG_CONFIGFS_FS)]
59pub mod configfs;
60pub mod cpu;
61#[cfg(CONFIG_CPU_FREQ)]
62pub mod cpufreq;
63pub mod cpumask;
64pub mod cred;
65pub mod debugfs;
66pub mod device;
67pub mod device_id;
68pub mod devres;
69pub mod dma;
70#[cfg(CONFIG_DMA_SHARED_BUFFER)]
71pub mod dma_buf;
72pub mod driver;
73#[cfg(CONFIG_DRM = "y")]
74pub mod drm;
75pub mod error;
76pub mod faux;
77#[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
78pub mod firmware;
79pub mod fmt;
80pub mod fs;
81#[cfg(CONFIG_RUST_FWCTL_ABSTRACTIONS)]
82pub mod fwctl;
83#[cfg(CONFIG_GPU_BUDDY = "y")]
84pub mod gpu;
85#[cfg(CONFIG_I2C = "y")]
86pub mod i2c;
87pub mod id_pool;
88#[doc(hidden)]
89pub mod impl_flags;
90pub mod init;
91pub mod interop;
92pub mod interrupt;
93pub mod io;
94pub mod ioctl;
95pub mod iommu;
96pub mod iov;
97pub mod irq;
98pub mod jump_label;
99#[cfg(CONFIG_KUNIT)]
100pub mod kunit;
101pub mod list;
102pub mod maple_tree;
103pub mod mem;
104pub mod miscdevice;
105pub mod mm;
106pub mod module;
107pub mod module_param;
108#[cfg(CONFIG_NET)]
109pub mod net;
110pub mod num;
111pub mod of;
112#[cfg(CONFIG_PM_OPP)]
113pub mod opp;
114pub mod page;
115#[cfg(CONFIG_PCI)]
116pub mod pci;
117pub mod pid_namespace;
118pub mod platform;
119pub mod prelude;
120pub mod print;
121pub mod processor;
122pub mod ptr;
123#[cfg(CONFIG_RUST_PWM_ABSTRACTIONS)]
124pub mod pwm;
125pub mod rbtree;
126pub mod regulator;
127pub mod revocable;
128pub mod safety;
129pub mod scatterlist;
130pub mod security;
131pub mod seq_file;
132#[cfg(CONFIG_RUST_SERIAL_DEV_BUS_ABSTRACTIONS)]
133pub mod serdev;
134pub mod sizes;
135#[cfg(CONFIG_SOC_BUS)]
136pub mod soc;
137#[doc(hidden)]
138pub mod std_vendor;
139pub mod str;
140pub mod sync;
141pub mod task;
142pub mod time;
143pub mod tracepoint;
144pub mod transmute;
145pub mod types;
146pub mod uaccess;
147#[cfg(CONFIG_USB = "y")]
148pub mod usb;
149pub mod workqueue;
150pub mod xarray;
151
152#[doc(hidden)]
153pub use bindings;
154pub use macros;
155pub use module::{
156    InPlaceModule,
157    Module,
158    ModuleMetadata,
159    ThisModule, //
160};
161pub use uapi;
162
163/// Prefix to appear before log messages printed from within the `kernel` crate.
164const __LOG_PREFIX: &[u8] = b"rust_kernel\0";
165
166/// Dummy module type for `#[vtable]` `impl` blocks within the `kernel` crate (e.g. KUnit tests).
167// The `allow` is needed since it may be unused (e.g. KUnit tests may be disabled).
168#[allow(dead_code)]
169struct LocalModule;
170
171impl ModuleMetadata for LocalModule {
172    const NAME: &'static str::CStr = c"rust_kernel";
173
174    const THIS_MODULE: ThisModule = {
175        // SAFETY: `try_module_get`/`module_put` handle null module pointers gracefully.
176        unsafe { ThisModule::from_ptr(core::ptr::null_mut()) }
177    };
178}
179
180#[cfg(not(testlib))]
181#[panic_handler]
182fn panic(info: &core::panic::PanicInfo<'_>) -> ! {
183    pr_emerg!("{}\n", info);
184    // SAFETY: FFI call.
185    unsafe { bindings::BUG() };
186}
187
188/// Produces a pointer to an object from a pointer to one of its fields.
189///
190/// If you encounter a type mismatch due to the [`Opaque`] type, then use [`Opaque::cast_into`] or
191/// [`Opaque::cast_from`] to resolve the mismatch.
192///
193/// [`Opaque`]: crate::types::Opaque
194/// [`Opaque::cast_into`]: crate::types::Opaque::cast_into
195/// [`Opaque::cast_from`]: crate::types::Opaque::cast_from
196///
197/// # Safety
198///
199/// The pointer passed to this macro, and the pointer returned by this macro, must both be in
200/// bounds of the same allocation.
201///
202/// # Examples
203///
204/// ```
205/// # use kernel::container_of;
206/// struct Test {
207///     a: u64,
208///     b: u32,
209/// }
210///
211/// let test = Test { a: 10, b: 20 };
212/// let b_ptr: *const _ = &test.b;
213/// // SAFETY: The pointer points at the `b` field of a `Test`, so the resulting pointer will be
214/// // in-bounds of the same allocation as `b_ptr`.
215/// let test_alias = unsafe { container_of!(b_ptr, Test, b) };
216/// assert!(core::ptr::eq(&test, test_alias));
217/// ```
218#[macro_export]
219macro_rules! container_of {
220    ($field_ptr:expr, $Container:ty, $($fields:tt)*) => {{
221        let offset: usize = ::core::mem::offset_of!($Container, $($fields)*);
222        let field_ptr = $field_ptr;
223        let container_ptr = field_ptr.byte_sub(offset).cast::<$Container>();
224        $crate::assert_same_type(field_ptr, (&raw const (*container_ptr).$($fields)*).cast_mut());
225        container_ptr
226    }}
227}
228
229/// Helper for [`container_of!`].
230#[doc(hidden)]
231pub fn assert_same_type<T>(_: T, _: T) {}
232
233/// Helper for `.rs.S` files.
234#[doc(hidden)]
235#[macro_export]
236macro_rules! concat_literals {
237    ($( $asm:literal )* ) => {
238        ::core::concat!($($asm),*)
239    };
240}
241
242/// Wrapper around `asm!` configured for use in the kernel.
243///
244/// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!`
245/// syntax.
246// For x86, `asm!` uses intel syntax by default, but we want to use at&t syntax in the kernel.
247#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
248#[macro_export]
249macro_rules! asm {
250    ($($asm:expr),* ; $($rest:tt)*) => {
251        ::core::arch::asm!( $($asm)*, options(att_syntax), $($rest)* )
252    };
253}
254
255/// Wrapper around `asm!` configured for use in the kernel.
256///
257/// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!`
258/// syntax.
259// For non-x86 arches we just pass through to `asm!`.
260#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
261#[macro_export]
262macro_rules! asm {
263    ($($asm:expr),* ; $($rest:tt)*) => {
264        ::core::arch::asm!( $($asm)*, $($rest)* )
265    };
266}
267
268/// Gets the C string file name of a [`Location`].
269///
270/// If `Location::file_as_c_str()` is not available, returns a string that warns about it.
271///
272/// [`Location`]: core::panic::Location
273///
274/// # Examples
275///
276/// ```
277/// # use kernel::file_from_location;
278///
279/// #[track_caller]
280/// fn foo() {
281///     let caller = core::panic::Location::caller();
282///
283///     // Output:
284///     // - A path like "rust/kernel/example.rs" if `file_as_c_str()` is available.
285///     // - "<Location::file_as_c_str() not supported>" otherwise.
286///     let caller_file = file_from_location(caller);
287///
288///     // Prints out the message with caller's file name.
289///     pr_info!("foo() called in file {caller_file:?}\n");
290///
291///     # if cfg!(CONFIG_RUSTC_HAS_FILE_WITH_NUL) {
292///     #     assert_eq!(Ok(caller.file()), caller_file.to_str());
293///     # }
294/// }
295///
296/// # foo();
297/// ```
298#[inline]
299pub fn file_from_location<'a>(loc: &'a core::panic::Location<'a>) -> &'a core::ffi::CStr {
300    #[cfg(CONFIG_RUSTC_HAS_FILE_AS_C_STR)]
301    {
302        loc.file_as_c_str()
303    }
304
305    #[cfg(all(CONFIG_RUSTC_HAS_FILE_WITH_NUL, not(CONFIG_RUSTC_HAS_FILE_AS_C_STR)))]
306    {
307        loc.file_with_nul()
308    }
309
310    #[cfg(not(CONFIG_RUSTC_HAS_FILE_WITH_NUL))]
311    {
312        let _ = loc;
313        c"<Location::file_as_c_str() not supported>"
314    }
315}