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 ratelimit;
126pub mod rbtree;
127pub mod regulator;
128pub mod revocable;
129pub mod safety;
130pub mod scatterlist;
131pub mod security;
132pub mod seq_file;
133#[cfg(CONFIG_RUST_SERIAL_DEV_BUS_ABSTRACTIONS)]
134pub mod serdev;
135pub mod sizes;
136#[cfg(CONFIG_SOC_BUS)]
137pub mod soc;
138#[doc(hidden)]
139pub mod std_vendor;
140pub mod str;
141pub mod sync;
142pub mod task;
143pub mod time;
144pub mod tracepoint;
145pub mod transmute;
146pub mod types;
147pub mod uaccess;
148#[cfg(CONFIG_USB = "y")]
149pub mod usb;
150pub mod workqueue;
151pub mod xarray;
152
153#[doc(hidden)]
154pub use bindings;
155pub use macros;
156pub use module::{
157    InPlaceModule,
158    Module,
159    ModuleMetadata,
160    ThisModule, //
161};
162pub use uapi;
163
164/// Prefix to appear before log messages printed from within the `kernel` crate.
165const __LOG_PREFIX: &[u8] = b"rust_kernel\0";
166
167/// Dummy module type for `#[vtable]` `impl` blocks within the `kernel` crate (e.g. KUnit tests).
168// The `allow` is needed since it may be unused (e.g. KUnit tests may be disabled).
169#[allow(dead_code)]
170struct LocalModule;
171
172impl ModuleMetadata for LocalModule {
173    const NAME: &'static str::CStr = c"rust_kernel";
174
175    const THIS_MODULE: ThisModule = {
176        // SAFETY: `try_module_get`/`module_put` handle null module pointers gracefully.
177        unsafe { ThisModule::from_ptr(core::ptr::null_mut()) }
178    };
179}
180
181#[cfg(not(testlib))]
182#[panic_handler]
183fn panic(info: &core::panic::PanicInfo<'_>) -> ! {
184    pr_emerg!("{}\n", info);
185    // SAFETY: FFI call.
186    unsafe { bindings::BUG() };
187}
188
189/// Produces a pointer to an object from a pointer to one of its fields.
190///
191/// If you encounter a type mismatch due to the [`Opaque`] type, then use [`Opaque::cast_into`] or
192/// [`Opaque::cast_from`] to resolve the mismatch.
193///
194/// [`Opaque`]: crate::types::Opaque
195/// [`Opaque::cast_into`]: crate::types::Opaque::cast_into
196/// [`Opaque::cast_from`]: crate::types::Opaque::cast_from
197///
198/// # Safety
199///
200/// The pointer passed to this macro, and the pointer returned by this macro, must both be in
201/// bounds of the same allocation.
202///
203/// # Examples
204///
205/// ```
206/// # use kernel::container_of;
207/// struct Test {
208///     a: u64,
209///     b: u32,
210/// }
211///
212/// let test = Test { a: 10, b: 20 };
213/// let b_ptr: *const _ = &test.b;
214/// // SAFETY: The pointer points at the `b` field of a `Test`, so the resulting pointer will be
215/// // in-bounds of the same allocation as `b_ptr`.
216/// let test_alias = unsafe { container_of!(b_ptr, Test, b) };
217/// assert!(core::ptr::eq(&test, test_alias));
218/// ```
219#[macro_export]
220macro_rules! container_of {
221    ($field_ptr:expr, $Container:ty, $($fields:tt)*) => {{
222        let offset: usize = ::core::mem::offset_of!($Container, $($fields)*);
223        let field_ptr = $field_ptr;
224        let container_ptr = field_ptr.byte_sub(offset).cast::<$Container>();
225        $crate::assert_same_type(field_ptr, (&raw const (*container_ptr).$($fields)*).cast_mut());
226        container_ptr
227    }}
228}
229
230/// Helper for [`container_of!`].
231#[doc(hidden)]
232pub fn assert_same_type<T>(_: T, _: T) {}
233
234/// Helper for `.rs.S` files.
235#[doc(hidden)]
236#[macro_export]
237macro_rules! concat_literals {
238    ($( $asm:literal )* ) => {
239        ::core::concat!($($asm),*)
240    };
241}
242
243/// Wrapper around `asm!` configured for use in the kernel.
244///
245/// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!`
246/// syntax.
247// For x86, `asm!` uses intel syntax by default, but we want to use at&t syntax in the kernel.
248#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
249#[macro_export]
250macro_rules! asm {
251    ($($asm:expr),* ; $($rest:tt)*) => {
252        ::core::arch::asm!( $($asm)*, options(att_syntax), $($rest)* )
253    };
254}
255
256/// Wrapper around `asm!` configured for use in the kernel.
257///
258/// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!`
259/// syntax.
260// For non-x86 arches we just pass through to `asm!`.
261#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
262#[macro_export]
263macro_rules! asm {
264    ($($asm:expr),* ; $($rest:tt)*) => {
265        ::core::arch::asm!( $($asm)*, $($rest)* )
266    };
267}
268
269/// Gets the C string file name of a [`Location`].
270///
271/// If `Location::file_as_c_str()` is not available, returns a string that warns about it.
272///
273/// [`Location`]: core::panic::Location
274///
275/// # Examples
276///
277/// ```
278/// # use kernel::file_from_location;
279///
280/// #[track_caller]
281/// fn foo() {
282///     let caller = core::panic::Location::caller();
283///
284///     // Output:
285///     // - A path like "rust/kernel/example.rs" if `file_as_c_str()` is available.
286///     // - "<Location::file_as_c_str() not supported>" otherwise.
287///     let caller_file = file_from_location(caller);
288///
289///     // Prints out the message with caller's file name.
290///     pr_info!("foo() called in file {caller_file:?}\n");
291///
292///     # if cfg!(CONFIG_RUSTC_HAS_FILE_WITH_NUL) {
293///     #     assert_eq!(Ok(caller.file()), caller_file.to_str());
294///     # }
295/// }
296///
297/// # foo();
298/// ```
299#[inline]
300pub fn file_from_location<'a>(loc: &'a core::panic::Location<'a>) -> &'a core::ffi::CStr {
301    #[cfg(CONFIG_RUSTC_HAS_FILE_AS_C_STR)]
302    {
303        loc.file_as_c_str()
304    }
305
306    #[cfg(all(CONFIG_RUSTC_HAS_FILE_WITH_NUL, not(CONFIG_RUSTC_HAS_FILE_AS_C_STR)))]
307    {
308        loc.file_with_nul()
309    }
310
311    #[cfg(not(CONFIG_RUSTC_HAS_FILE_WITH_NUL))]
312    {
313        let _ = loc;
314        c"<Location::file_as_c_str() not supported>"
315    }
316}