forked from Rust-for-Linux/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]> Co-developed-by: Alex Gaynor <[email protected]> Signed-off-by: Alex Gaynor <[email protected]> Co-developed-by: Geoffrey Thomas <[email protected]> Signed-off-by: Geoffrey Thomas <[email protected]> Co-developed-by: Finn Behrens <[email protected]> Signed-off-by: Finn Behrens <[email protected]> Co-developed-by: Adam Bratschi-Kaye <[email protected]> Signed-off-by: Adam Bratschi-Kaye <[email protected]> Co-developed-by: Sven Van Asbroeck <[email protected]> Signed-off-by: Sven Van Asbroeck <[email protected]> Co-developed-by: Gary Guo <[email protected]> Signed-off-by: Gary Guo <[email protected]> Co-developed-by: Boris-Chengbiao Zhou <[email protected]> Signed-off-by: Boris-Chengbiao Zhou <[email protected]> Co-developed-by: Boqun Feng <[email protected]> Signed-off-by: Boqun Feng <[email protected]> Co-developed-by: Fox Chen <[email protected]> Signed-off-by: Fox Chen <[email protected]> Co-developed-by: Viktor Garske <[email protected]> Signed-off-by: Viktor Garske <[email protected]> Co-developed-by: Dariusz Sosnowski <[email protected]> Signed-off-by: Dariusz Sosnowski <[email protected]> Co-developed-by: Léo Lanteri Thauvin <[email protected]> Signed-off-by: Léo Lanteri Thauvin <[email protected]> Co-developed-by: Niklas Mohrin <[email protected]> Signed-off-by: Niklas Mohrin <[email protected]> Co-developed-by: Milan Landaverde <[email protected]> Signed-off-by: Milan Landaverde <[email protected]> Co-developed-by: Morgan Bartlett <[email protected]> Signed-off-by: Morgan Bartlett <[email protected]> Co-developed-by: Maciej Falkowski <[email protected]> Signed-off-by: Maciej Falkowski <[email protected]> Co-developed-by: Nándor István Krácser <[email protected]> Signed-off-by: Nándor István Krácser <[email protected]> Co-developed-by: David Gow <[email protected]> Signed-off-by: David Gow <[email protected]> Co-developed-by: John Baublitz <[email protected]> Signed-off-by: John Baublitz <[email protected]> Co-developed-by: Björn Roy Baron <[email protected]> Signed-off-by: Björn Roy Baron <[email protected]> Signed-off-by: Wedson Almeida Filho <[email protected]> Co-developed-by: Miguel Ojeda <[email protected]> Signed-off-by: Miguel Ojeda <[email protected]>
- Loading branch information
Showing
6 changed files
with
491 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
//! Allocator support. | ||
use core::alloc::{GlobalAlloc, Layout}; | ||
use core::ptr; | ||
|
||
use crate::bindings; | ||
|
||
struct KernelAllocator; | ||
|
||
unsafe impl GlobalAlloc for KernelAllocator { | ||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 { | ||
// `krealloc()` is used instead of `kmalloc()` because the latter is | ||
// an inline function and cannot be bound to as a result. | ||
unsafe { bindings::krealloc(ptr::null(), layout.size(), bindings::GFP_KERNEL) as *mut u8 } | ||
} | ||
|
||
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { | ||
unsafe { | ||
bindings::kfree(ptr as *const core::ffi::c_void); | ||
} | ||
} | ||
} | ||
|
||
#[global_allocator] | ||
static ALLOCATOR: KernelAllocator = KernelAllocator; | ||
|
||
// `rustc` only generates these for some crate types. Even then, we would need | ||
// to extract the object file that has them from the archive. For the moment, | ||
// let's generate them ourselves instead. | ||
// | ||
// Note that `#[no_mangle]` implies exported too, nowadays. | ||
#[no_mangle] | ||
fn __rust_alloc(size: usize, _align: usize) -> *mut u8 { | ||
unsafe { bindings::krealloc(core::ptr::null(), size, bindings::GFP_KERNEL) as *mut u8 } | ||
} | ||
|
||
#[no_mangle] | ||
fn __rust_dealloc(ptr: *mut u8, _size: usize, _align: usize) { | ||
unsafe { bindings::kfree(ptr as *const core::ffi::c_void) }; | ||
} | ||
|
||
#[no_mangle] | ||
fn __rust_realloc(ptr: *mut u8, _old_size: usize, _align: usize, new_size: usize) -> *mut u8 { | ||
unsafe { | ||
bindings::krealloc( | ||
ptr as *const core::ffi::c_void, | ||
new_size, | ||
bindings::GFP_KERNEL, | ||
) as *mut u8 | ||
} | ||
} | ||
|
||
#[no_mangle] | ||
fn __rust_alloc_zeroed(size: usize, _align: usize) -> *mut u8 { | ||
unsafe { | ||
bindings::krealloc( | ||
core::ptr::null(), | ||
size, | ||
bindings::GFP_KERNEL | bindings::__GFP_ZERO, | ||
) as *mut u8 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
//! Kernel errors. | ||
//! | ||
//! C header: [`include/uapi/asm-generic/errno-base.h`](../../../include/uapi/asm-generic/errno-base.h) | ||
use alloc::collections::TryReserveError; | ||
|
||
/// Contains the C-compatible error codes. | ||
pub mod code { | ||
/// Out of memory. | ||
pub const ENOMEM: super::Error = super::Error(-(crate::bindings::ENOMEM as i32)); | ||
} | ||
|
||
/// Generic integer kernel error. | ||
/// | ||
/// The kernel defines a set of integer generic error codes based on C and | ||
/// POSIX ones. These codes may have a more specific meaning in some contexts. | ||
/// | ||
/// # Invariants | ||
/// | ||
/// The value is a valid `errno` (i.e. `>= -MAX_ERRNO && < 0`). | ||
#[derive(Clone, Copy, PartialEq, Eq)] | ||
pub struct Error(core::ffi::c_int); | ||
|
||
impl Error { | ||
/// Returns the kernel error code. | ||
pub fn to_kernel_errno(self) -> core::ffi::c_int { | ||
self.0 | ||
} | ||
} | ||
|
||
impl From<TryReserveError> for Error { | ||
fn from(_: TryReserveError) -> Error { | ||
code::ENOMEM | ||
} | ||
} | ||
|
||
/// A [`Result`] with an [`Error`] error type. | ||
/// | ||
/// To be used as the return type for functions that may fail. | ||
/// | ||
/// # Error codes in C and Rust | ||
/// | ||
/// In C, it is common that functions indicate success or failure through | ||
/// their return value; modifying or returning extra data through non-`const` | ||
/// pointer parameters. In particular, in the kernel, functions that may fail | ||
/// typically return an `int` that represents a generic error code. We model | ||
/// those as [`Error`]. | ||
/// | ||
/// In Rust, it is idiomatic to model functions that may fail as returning | ||
/// a [`Result`]. Since in the kernel many functions return an error code, | ||
/// [`Result`] is a type alias for a [`core::result::Result`] that uses | ||
/// [`Error`] as its error type. | ||
/// | ||
/// Note that even if a function does not return anything when it succeeds, | ||
/// it should still be modeled as returning a `Result` rather than | ||
/// just an [`Error`]. | ||
pub type Result<T = ()> = core::result::Result<T, Error>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
//! The `kernel` crate. | ||
//! | ||
//! This crate contains the kernel APIs that have been ported or wrapped for | ||
//! usage by Rust code in the kernel and is shared by all of them. | ||
//! | ||
//! In other words, all the rest of the Rust code in the kernel (e.g. kernel | ||
//! modules written in Rust) depends on [`core`], [`alloc`] and this crate. | ||
//! | ||
//! If you need a kernel C API that is not ported or wrapped yet here, then | ||
//! do so first instead of bypassing this crate. | ||
#![no_std] | ||
#![feature(core_ffi_c)] | ||
|
||
// Ensure conditional compilation based on the kernel configuration works; | ||
// otherwise we may silently break things like initcall handling. | ||
#[cfg(not(CONFIG_RUST))] | ||
compile_error!("Missing kernel configuration for conditional compilation"); | ||
|
||
#[cfg(not(test))] | ||
#[cfg(not(testlib))] | ||
mod allocator; | ||
pub mod error; | ||
pub mod prelude; | ||
pub mod print; | ||
pub mod str; | ||
|
||
#[doc(hidden)] | ||
pub use bindings; | ||
pub use macros; | ||
|
||
/// Prefix to appear before log messages printed from within the `kernel` crate. | ||
const __LOG_PREFIX: &[u8] = b"rust_kernel\0"; | ||
|
||
/// The top level entrypoint to implementing a kernel module. | ||
/// | ||
/// For any teardown or cleanup operations, your type may implement [`Drop`]. | ||
pub trait Module: Sized + Sync { | ||
/// Called at module initialization time. | ||
/// | ||
/// Use this method to perform whatever setup or registration your module | ||
/// should do. | ||
/// | ||
/// Equivalent to the `module_init` macro in the C API. | ||
fn init(module: &'static ThisModule) -> error::Result<Self>; | ||
} | ||
|
||
/// Equivalent to `THIS_MODULE` in the C API. | ||
/// | ||
/// C header: `include/linux/export.h` | ||
pub struct ThisModule(*mut bindings::module); | ||
|
||
// SAFETY: `THIS_MODULE` may be used from all threads within a module. | ||
unsafe impl Sync for ThisModule {} | ||
|
||
impl ThisModule { | ||
/// Creates a [`ThisModule`] given the `THIS_MODULE` pointer. | ||
/// | ||
/// # Safety | ||
/// | ||
/// The pointer must be equal to the right `THIS_MODULE`. | ||
pub const unsafe fn from_ptr(ptr: *mut bindings::module) -> ThisModule { | ||
ThisModule(ptr) | ||
} | ||
} | ||
|
||
#[cfg(not(any(testlib, test)))] | ||
#[panic_handler] | ||
fn panic(info: &core::panic::PanicInfo<'_>) -> ! { | ||
pr_emerg!("{}\n", info); | ||
// SAFETY: FFI call. | ||
unsafe { bindings::BUG() }; | ||
// Bindgen currently does not recognize `__noreturn` so `BUG` returns `()` | ||
// instead of `!`. See <https://github.com/rust-lang/rust-bindgen/issues/2094>. | ||
loop {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
//! The `kernel` prelude. | ||
//! | ||
//! These are the most common items used by Rust code in the kernel, | ||
//! intended to be imported by all Rust code, for convenience. | ||
//! | ||
//! # Examples | ||
//! | ||
//! ``` | ||
//! use kernel::prelude::*; | ||
//! ``` | ||
pub use super::{ | ||
error::{Error, Result}, | ||
pr_emerg, pr_info, ThisModule, | ||
}; | ||
pub use alloc::{boxed::Box, vec::Vec}; | ||
pub use core::pin::Pin; | ||
pub use macros::module; |
Oops, something went wrong.