Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rust: add `kernel` crate

The `kernel` crate currently includes all the abstractions that wrap
kernel features written in C.

These abstractions call the C side of the kernel via the generated
bindings with the `bindgen` tool. Modules developed in Rust should
never call the bindings themselves.

In the future, as the abstractions grow in number, we may need
to split this crate into several, possibly following a similar
subdivision in subsystems as the kernel itself and/or moving
the code to the actual subsystems.

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: Finn Behrens <me@kloenk.de>
Signed-off-by: Finn Behrens <me@kloenk.de>
Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Sven Van Asbroeck <thesven73@gmail.com>
Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Co-developed-by: Fox Chen <foxhlchen@gmail.com>
Signed-off-by: Fox Chen <foxhlchen@gmail.com>
Co-developed-by: Viktor Garske <viktor@v-gar.de>
Signed-off-by: Viktor Garske <viktor@v-gar.de>
Co-developed-by: Dariusz Sosnowski <dsosnowski@dsosnowski.pl>
Signed-off-by: Dariusz Sosnowski <dsosnowski@dsosnowski.pl>
Co-developed-by: Léo Lanteri Thauvin <leseulartichaut@gmail.com>
Signed-off-by: Léo Lanteri Thauvin <leseulartichaut@gmail.com>
Co-developed-by: Niklas Mohrin <dev@niklasmohrin.de>
Signed-off-by: Niklas Mohrin <dev@niklasmohrin.de>
Co-developed-by: Milan Landaverde <milan@mdaverde.com>
Signed-off-by: Milan Landaverde <milan@mdaverde.com>
Co-developed-by: Morgan Bartlett <mjmouse9999@gmail.com>
Signed-off-by: Morgan Bartlett <mjmouse9999@gmail.com>
Co-developed-by: Maciej Falkowski <m.falkowski@samsung.com>
Signed-off-by: Maciej Falkowski <m.falkowski@samsung.com>
Co-developed-by: Nándor István Krácser <bonifaido@gmail.com>
Signed-off-by: Nándor István Krácser <bonifaido@gmail.com>
Co-developed-by: David Gow <davidgow@google.com>
Signed-off-by: David Gow <davidgow@google.com>
Co-developed-by: John Baublitz <john.m.baublitz@gmail.com>
Signed-off-by: John Baublitz <john.m.baublitz@gmail.com>
Co-developed-by: Björn Roy Baron <bjorn3_gh@protonmail.com>
Signed-off-by: Björn Roy Baron <bjorn3_gh@protonmail.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: Miguel Ojeda <ojeda@kernel.org>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>

authored by

Wedson Almeida Filho and committed by
Miguel Ojeda
247b365d 8326ac05

+491
+64
rust/kernel/allocator.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! Allocator support. 4 + 5 + use core::alloc::{GlobalAlloc, Layout}; 6 + use core::ptr; 7 + 8 + use crate::bindings; 9 + 10 + struct KernelAllocator; 11 + 12 + unsafe impl GlobalAlloc for KernelAllocator { 13 + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { 14 + // `krealloc()` is used instead of `kmalloc()` because the latter is 15 + // an inline function and cannot be bound to as a result. 16 + unsafe { bindings::krealloc(ptr::null(), layout.size(), bindings::GFP_KERNEL) as *mut u8 } 17 + } 18 + 19 + unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { 20 + unsafe { 21 + bindings::kfree(ptr as *const core::ffi::c_void); 22 + } 23 + } 24 + } 25 + 26 + #[global_allocator] 27 + static ALLOCATOR: KernelAllocator = KernelAllocator; 28 + 29 + // `rustc` only generates these for some crate types. Even then, we would need 30 + // to extract the object file that has them from the archive. For the moment, 31 + // let's generate them ourselves instead. 32 + // 33 + // Note that `#[no_mangle]` implies exported too, nowadays. 34 + #[no_mangle] 35 + fn __rust_alloc(size: usize, _align: usize) -> *mut u8 { 36 + unsafe { bindings::krealloc(core::ptr::null(), size, bindings::GFP_KERNEL) as *mut u8 } 37 + } 38 + 39 + #[no_mangle] 40 + fn __rust_dealloc(ptr: *mut u8, _size: usize, _align: usize) { 41 + unsafe { bindings::kfree(ptr as *const core::ffi::c_void) }; 42 + } 43 + 44 + #[no_mangle] 45 + fn __rust_realloc(ptr: *mut u8, _old_size: usize, _align: usize, new_size: usize) -> *mut u8 { 46 + unsafe { 47 + bindings::krealloc( 48 + ptr as *const core::ffi::c_void, 49 + new_size, 50 + bindings::GFP_KERNEL, 51 + ) as *mut u8 52 + } 53 + } 54 + 55 + #[no_mangle] 56 + fn __rust_alloc_zeroed(size: usize, _align: usize) -> *mut u8 { 57 + unsafe { 58 + bindings::krealloc( 59 + core::ptr::null(), 60 + size, 61 + bindings::GFP_KERNEL | bindings::__GFP_ZERO, 62 + ) as *mut u8 63 + } 64 + }
+59
rust/kernel/error.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! Kernel errors. 4 + //! 5 + //! C header: [`include/uapi/asm-generic/errno-base.h`](../../../include/uapi/asm-generic/errno-base.h) 6 + 7 + use alloc::collections::TryReserveError; 8 + 9 + /// Contains the C-compatible error codes. 10 + pub mod code { 11 + /// Out of memory. 12 + pub const ENOMEM: super::Error = super::Error(-(crate::bindings::ENOMEM as i32)); 13 + } 14 + 15 + /// Generic integer kernel error. 16 + /// 17 + /// The kernel defines a set of integer generic error codes based on C and 18 + /// POSIX ones. These codes may have a more specific meaning in some contexts. 19 + /// 20 + /// # Invariants 21 + /// 22 + /// The value is a valid `errno` (i.e. `>= -MAX_ERRNO && < 0`). 23 + #[derive(Clone, Copy, PartialEq, Eq)] 24 + pub struct Error(core::ffi::c_int); 25 + 26 + impl Error { 27 + /// Returns the kernel error code. 28 + pub fn to_kernel_errno(self) -> core::ffi::c_int { 29 + self.0 30 + } 31 + } 32 + 33 + impl From<TryReserveError> for Error { 34 + fn from(_: TryReserveError) -> Error { 35 + code::ENOMEM 36 + } 37 + } 38 + 39 + /// A [`Result`] with an [`Error`] error type. 40 + /// 41 + /// To be used as the return type for functions that may fail. 42 + /// 43 + /// # Error codes in C and Rust 44 + /// 45 + /// In C, it is common that functions indicate success or failure through 46 + /// their return value; modifying or returning extra data through non-`const` 47 + /// pointer parameters. In particular, in the kernel, functions that may fail 48 + /// typically return an `int` that represents a generic error code. We model 49 + /// those as [`Error`]. 50 + /// 51 + /// In Rust, it is idiomatic to model functions that may fail as returning 52 + /// a [`Result`]. Since in the kernel many functions return an error code, 53 + /// [`Result`] is a type alias for a [`core::result::Result`] that uses 54 + /// [`Error`] as its error type. 55 + /// 56 + /// Note that even if a function does not return anything when it succeeds, 57 + /// it should still be modeled as returning a `Result` rather than 58 + /// just an [`Error`]. 59 + pub type Result<T = ()> = core::result::Result<T, Error>;
+78
rust/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`], [`alloc`] 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 + #![feature(core_ffi_c)] 16 + 17 + // Ensure conditional compilation based on the kernel configuration works; 18 + // otherwise we may silently break things like initcall handling. 19 + #[cfg(not(CONFIG_RUST))] 20 + compile_error!("Missing kernel configuration for conditional compilation"); 21 + 22 + #[cfg(not(test))] 23 + #[cfg(not(testlib))] 24 + mod allocator; 25 + pub mod error; 26 + pub mod prelude; 27 + pub mod print; 28 + pub mod str; 29 + 30 + #[doc(hidden)] 31 + pub use bindings; 32 + pub use macros; 33 + 34 + /// Prefix to appear before log messages printed from within the `kernel` crate. 35 + const __LOG_PREFIX: &[u8] = b"rust_kernel\0"; 36 + 37 + /// The top level entrypoint to implementing a kernel module. 38 + /// 39 + /// For any teardown or cleanup operations, your type may implement [`Drop`]. 40 + pub trait Module: Sized + Sync { 41 + /// Called at module initialization time. 42 + /// 43 + /// Use this method to perform whatever setup or registration your module 44 + /// should do. 45 + /// 46 + /// Equivalent to the `module_init` macro in the C API. 47 + fn init(module: &'static ThisModule) -> error::Result<Self>; 48 + } 49 + 50 + /// Equivalent to `THIS_MODULE` in the C API. 51 + /// 52 + /// C header: `include/linux/export.h` 53 + pub struct ThisModule(*mut bindings::module); 54 + 55 + // SAFETY: `THIS_MODULE` may be used from all threads within a module. 56 + unsafe impl Sync for ThisModule {} 57 + 58 + impl ThisModule { 59 + /// Creates a [`ThisModule`] given the `THIS_MODULE` pointer. 60 + /// 61 + /// # Safety 62 + /// 63 + /// The pointer must be equal to the right `THIS_MODULE`. 64 + pub const unsafe fn from_ptr(ptr: *mut bindings::module) -> ThisModule { 65 + ThisModule(ptr) 66 + } 67 + } 68 + 69 + #[cfg(not(any(testlib, test)))] 70 + #[panic_handler] 71 + fn panic(info: &core::panic::PanicInfo<'_>) -> ! { 72 + pr_emerg!("{}\n", info); 73 + // SAFETY: FFI call. 74 + unsafe { bindings::BUG() }; 75 + // Bindgen currently does not recognize `__noreturn` so `BUG` returns `()` 76 + // instead of `!`. See <https://github.com/rust-lang/rust-bindgen/issues/2094>. 77 + loop {} 78 + }
+20
rust/kernel/prelude.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! The `kernel` prelude. 4 + //! 5 + //! These are the most common items used by Rust code in the kernel, 6 + //! intended to be imported by all Rust code, for convenience. 7 + //! 8 + //! # Examples 9 + //! 10 + //! ``` 11 + //! use kernel::prelude::*; 12 + //! ``` 13 + 14 + pub use super::{ 15 + error::{Error, Result}, 16 + pr_emerg, pr_info, ThisModule, 17 + }; 18 + pub use alloc::{boxed::Box, vec::Vec}; 19 + pub use core::pin::Pin; 20 + pub use macros::module;
+198
rust/kernel/print.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! Printing facilities. 4 + //! 5 + //! C header: [`include/linux/printk.h`](../../../../include/linux/printk.h) 6 + //! 7 + //! Reference: <https://www.kernel.org/doc/html/latest/core-api/printk-basics.html> 8 + 9 + use core::{ 10 + ffi::{c_char, c_void}, 11 + fmt, 12 + }; 13 + 14 + use crate::str::RawFormatter; 15 + 16 + #[cfg(CONFIG_PRINTK)] 17 + use crate::bindings; 18 + 19 + // Called from `vsprintf` with format specifier `%pA`. 20 + #[no_mangle] 21 + unsafe fn rust_fmt_argument(buf: *mut c_char, end: *mut c_char, ptr: *const c_void) -> *mut c_char { 22 + use fmt::Write; 23 + // SAFETY: The C contract guarantees that `buf` is valid if it's less than `end`. 24 + let mut w = unsafe { RawFormatter::from_ptrs(buf.cast(), end.cast()) }; 25 + let _ = w.write_fmt(unsafe { *(ptr as *const fmt::Arguments<'_>) }); 26 + w.pos().cast() 27 + } 28 + 29 + /// Format strings. 30 + /// 31 + /// Public but hidden since it should only be used from public macros. 32 + #[doc(hidden)] 33 + pub mod format_strings { 34 + use crate::bindings; 35 + 36 + /// The length we copy from the `KERN_*` kernel prefixes. 37 + const LENGTH_PREFIX: usize = 2; 38 + 39 + /// The length of the fixed format strings. 40 + pub const LENGTH: usize = 10; 41 + 42 + /// Generates a fixed format string for the kernel's [`_printk`]. 43 + /// 44 + /// The format string is always the same for a given level, i.e. for a 45 + /// given `prefix`, which are the kernel's `KERN_*` constants. 46 + /// 47 + /// [`_printk`]: ../../../../include/linux/printk.h 48 + const fn generate(is_cont: bool, prefix: &[u8; 3]) -> [u8; LENGTH] { 49 + // Ensure the `KERN_*` macros are what we expect. 50 + assert!(prefix[0] == b'\x01'); 51 + if is_cont { 52 + assert!(prefix[1] == b'c'); 53 + } else { 54 + assert!(prefix[1] >= b'0' && prefix[1] <= b'7'); 55 + } 56 + assert!(prefix[2] == b'\x00'); 57 + 58 + let suffix: &[u8; LENGTH - LENGTH_PREFIX] = if is_cont { 59 + b"%pA\0\0\0\0\0" 60 + } else { 61 + b"%s: %pA\0" 62 + }; 63 + 64 + [ 65 + prefix[0], prefix[1], suffix[0], suffix[1], suffix[2], suffix[3], suffix[4], suffix[5], 66 + suffix[6], suffix[7], 67 + ] 68 + } 69 + 70 + // Generate the format strings at compile-time. 71 + // 72 + // This avoids the compiler generating the contents on the fly in the stack. 73 + // 74 + // Furthermore, `static` instead of `const` is used to share the strings 75 + // for all the kernel. 76 + pub static EMERG: [u8; LENGTH] = generate(false, bindings::KERN_EMERG); 77 + pub static INFO: [u8; LENGTH] = generate(false, bindings::KERN_INFO); 78 + } 79 + 80 + /// Prints a message via the kernel's [`_printk`]. 81 + /// 82 + /// Public but hidden since it should only be used from public macros. 83 + /// 84 + /// # Safety 85 + /// 86 + /// The format string must be one of the ones in [`format_strings`], and 87 + /// the module name must be null-terminated. 88 + /// 89 + /// [`_printk`]: ../../../../include/linux/_printk.h 90 + #[doc(hidden)] 91 + #[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))] 92 + pub unsafe fn call_printk( 93 + format_string: &[u8; format_strings::LENGTH], 94 + module_name: &[u8], 95 + args: fmt::Arguments<'_>, 96 + ) { 97 + // `_printk` does not seem to fail in any path. 98 + #[cfg(CONFIG_PRINTK)] 99 + unsafe { 100 + bindings::_printk( 101 + format_string.as_ptr() as _, 102 + module_name.as_ptr(), 103 + &args as *const _ as *const c_void, 104 + ); 105 + } 106 + } 107 + 108 + /// Performs formatting and forwards the string to [`call_printk`]. 109 + /// 110 + /// Public but hidden since it should only be used from public macros. 111 + #[doc(hidden)] 112 + #[cfg(not(testlib))] 113 + #[macro_export] 114 + #[allow(clippy::crate_in_macro_def)] 115 + macro_rules! print_macro ( 116 + // The non-continuation cases (most of them, e.g. `INFO`). 117 + ($format_string:path, $($arg:tt)+) => ( 118 + // SAFETY: This hidden macro should only be called by the documented 119 + // printing macros which ensure the format string is one of the fixed 120 + // ones. All `__LOG_PREFIX`s are null-terminated as they are generated 121 + // by the `module!` proc macro or fixed values defined in a kernel 122 + // crate. 123 + unsafe { 124 + $crate::print::call_printk( 125 + &$format_string, 126 + crate::__LOG_PREFIX, 127 + format_args!($($arg)+), 128 + ); 129 + } 130 + ); 131 + ); 132 + 133 + /// Stub for doctests 134 + #[cfg(testlib)] 135 + #[macro_export] 136 + macro_rules! print_macro ( 137 + ($format_string:path, $e:expr, $($arg:tt)+) => ( 138 + () 139 + ); 140 + ); 141 + 142 + // We could use a macro to generate these macros. However, doing so ends 143 + // up being a bit ugly: it requires the dollar token trick to escape `$` as 144 + // well as playing with the `doc` attribute. Furthermore, they cannot be easily 145 + // imported in the prelude due to [1]. So, for the moment, we just write them 146 + // manually, like in the C side; while keeping most of the logic in another 147 + // macro, i.e. [`print_macro`]. 148 + // 149 + // [1]: https://github.com/rust-lang/rust/issues/52234 150 + 151 + /// Prints an emergency-level message (level 0). 152 + /// 153 + /// Use this level if the system is unusable. 154 + /// 155 + /// Equivalent to the kernel's [`pr_emerg`] macro. 156 + /// 157 + /// Mimics the interface of [`std::print!`]. See [`core::fmt`] and 158 + /// `alloc::format!` for information about the formatting syntax. 159 + /// 160 + /// [`pr_emerg`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_emerg 161 + /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html 162 + /// 163 + /// # Examples 164 + /// 165 + /// ``` 166 + /// pr_emerg!("hello {}\n", "there"); 167 + /// ``` 168 + #[macro_export] 169 + macro_rules! pr_emerg ( 170 + ($($arg:tt)*) => ( 171 + $crate::print_macro!($crate::print::format_strings::EMERG, $($arg)*) 172 + ) 173 + ); 174 + 175 + /// Prints an info-level message (level 6). 176 + /// 177 + /// Use this level for informational messages. 178 + /// 179 + /// Equivalent to the kernel's [`pr_info`] macro. 180 + /// 181 + /// Mimics the interface of [`std::print!`]. See [`core::fmt`] and 182 + /// `alloc::format!` for information about the formatting syntax. 183 + /// 184 + /// [`pr_info`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_info 185 + /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html 186 + /// 187 + /// # Examples 188 + /// 189 + /// ``` 190 + /// pr_info!("hello {}\n", "there"); 191 + /// ``` 192 + #[macro_export] 193 + #[doc(alias = "print")] 194 + macro_rules! pr_info ( 195 + ($($arg:tt)*) => ( 196 + $crate::print_macro!($crate::print::format_strings::INFO, $($arg)*) 197 + ) 198 + );
+72
rust/kernel/str.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! String representations. 4 + 5 + use core::fmt; 6 + 7 + /// Allows formatting of [`fmt::Arguments`] into a raw buffer. 8 + /// 9 + /// It does not fail if callers write past the end of the buffer so that they can calculate the 10 + /// size required to fit everything. 11 + /// 12 + /// # Invariants 13 + /// 14 + /// The memory region between `pos` (inclusive) and `end` (exclusive) is valid for writes if `pos` 15 + /// is less than `end`. 16 + pub(crate) struct RawFormatter { 17 + // Use `usize` to use `saturating_*` functions. 18 + #[allow(dead_code)] 19 + beg: usize, 20 + pos: usize, 21 + end: usize, 22 + } 23 + 24 + impl RawFormatter { 25 + /// Creates a new instance of [`RawFormatter`] with the given buffer pointers. 26 + /// 27 + /// # Safety 28 + /// 29 + /// If `pos` is less than `end`, then the region between `pos` (inclusive) and `end` 30 + /// (exclusive) must be valid for writes for the lifetime of the returned [`RawFormatter`]. 31 + pub(crate) unsafe fn from_ptrs(pos: *mut u8, end: *mut u8) -> Self { 32 + // INVARIANT: The safety requierments guarantee the type invariants. 33 + Self { 34 + beg: pos as _, 35 + pos: pos as _, 36 + end: end as _, 37 + } 38 + } 39 + 40 + /// Returns the current insert position. 41 + /// 42 + /// N.B. It may point to invalid memory. 43 + pub(crate) fn pos(&self) -> *mut u8 { 44 + self.pos as _ 45 + } 46 + } 47 + 48 + impl fmt::Write for RawFormatter { 49 + fn write_str(&mut self, s: &str) -> fmt::Result { 50 + // `pos` value after writing `len` bytes. This does not have to be bounded by `end`, but we 51 + // don't want it to wrap around to 0. 52 + let pos_new = self.pos.saturating_add(s.len()); 53 + 54 + // Amount that we can copy. `saturating_sub` ensures we get 0 if `pos` goes past `end`. 55 + let len_to_copy = core::cmp::min(pos_new, self.end).saturating_sub(self.pos); 56 + 57 + if len_to_copy > 0 { 58 + // SAFETY: If `len_to_copy` is non-zero, then we know `pos` has not gone past `end` 59 + // yet, so it is valid for write per the type invariants. 60 + unsafe { 61 + core::ptr::copy_nonoverlapping( 62 + s.as_bytes().as_ptr(), 63 + self.pos as *mut u8, 64 + len_to_copy, 65 + ) 66 + }; 67 + } 68 + 69 + self.pos = pos_new; 70 + Ok(()) 71 + } 72 + }