You need to sign in or sign up before continuing.
提交 08f09adb 编写于 作者: W Wedson Almeida Filho 提交者: Zheng Zengkai

rust: add `kernel` crate

maillist inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I5J75G
CVE: NA

Reference: https://lore.kernel.org/rust-for-linux/CANiq72nDcJLSB3pLhkdqGdLitfmqqCUVVfkY5EjP9AcwVv9B4A@mail.gmail.com/T/#t

--------------------------------

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.
Co-developed-by: NAlex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: NAlex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: NGeoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: NGeoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: NFinn Behrens <me@kloenk.de>
Signed-off-by: NFinn Behrens <me@kloenk.de>
Co-developed-by: NAdam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: NAdam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: NMichael Ellerman <mpe@ellerman.id.au>
Signed-off-by: NMichael Ellerman <mpe@ellerman.id.au>
Co-developed-by: NSumera Priyadarsini <sylphrenadin@gmail.com>
Signed-off-by: NSumera Priyadarsini <sylphrenadin@gmail.com>
Co-developed-by: NSven Van Asbroeck <thesven73@gmail.com>
Signed-off-by: NSven Van Asbroeck <thesven73@gmail.com>
Co-developed-by: NGary Guo <gary@garyguo.net>
Signed-off-by: NGary Guo <gary@garyguo.net>
Co-developed-by: NBoris-Chengbiao Zhou <bobo1239@web.de>
Signed-off-by: NBoris-Chengbiao Zhou <bobo1239@web.de>
Co-developed-by: NBoqun Feng <boqun.feng@gmail.com>
Signed-off-by: NBoqun Feng <boqun.feng@gmail.com>
Co-developed-by: NFox Chen <foxhlchen@gmail.com>
Signed-off-by: NFox Chen <foxhlchen@gmail.com>
Co-developed-by: NDan Robertson <daniel.robertson@starlab.io>
Signed-off-by: NDan Robertson <daniel.robertson@starlab.io>
Co-developed-by: NViktor Garske <viktor@v-gar.de>
Signed-off-by: NViktor Garske <viktor@v-gar.de>
Co-developed-by: NDariusz Sosnowski <dsosnowski@dsosnowski.pl>
Signed-off-by: NDariusz Sosnowski <dsosnowski@dsosnowski.pl>
Co-developed-by: NLéo Lanteri Thauvin <leseulartichaut@gmail.com>
Signed-off-by: NLéo Lanteri Thauvin <leseulartichaut@gmail.com>
Co-developed-by: NNiklas Mohrin <dev@niklasmohrin.de>
Signed-off-by: NNiklas Mohrin <dev@niklasmohrin.de>
Co-developed-by: NGioh Kim <gurugio@gmail.com>
Signed-off-by: NGioh Kim <gurugio@gmail.com>
Co-developed-by: NDaniel Xu <dxu@dxuuu.xyz>
Signed-off-by: NDaniel Xu <dxu@dxuuu.xyz>
Co-developed-by: NMilan Landaverde <milan@mdaverde.com>
Signed-off-by: NMilan Landaverde <milan@mdaverde.com>
Co-developed-by: NMorgan Bartlett <mjmouse9999@gmail.com>
Signed-off-by: NMorgan Bartlett <mjmouse9999@gmail.com>
Co-developed-by: NMaciej Falkowski <m.falkowski@samsung.com>
Signed-off-by: NMaciej Falkowski <m.falkowski@samsung.com>
Co-developed-by: NJiapeng Chong <jiapeng.chong@linux.alibaba.com>
Signed-off-by: NJiapeng Chong <jiapeng.chong@linux.alibaba.com>
Co-developed-by: NNándor István Krácser <bonifaido@gmail.com>
Signed-off-by: NNándor István Krácser <bonifaido@gmail.com>
Co-developed-by: NDavid Gow <davidgow@google.com>
Signed-off-by: NDavid Gow <davidgow@google.com>
Signed-off-by: NWedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: NMiguel Ojeda <ojeda@kernel.org>
Signed-off-by: NMiguel Ojeda <ojeda@kernel.org>
Signed-off-by: NWeilong Chen <chenweilong@huawei.com>
上级 a8c2dff0
// SPDX-License-Identifier: GPL-2.0
//! Allocator support.
use core::alloc::{GlobalAlloc, Layout};
use core::ptr;
use crate::bindings;
use crate::c_types;
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 c_types::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 c_types::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 c_types::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
}
}
// SPDX-License-Identifier: GPL-2.0
//! Amba devices and drivers.
//!
//! C header: [`include/linux/amba/bus.h`](../../../../include/linux/amba/bus.h)
use crate::{
bindings, c_types, device, driver, error::from_kernel_result, io_mem::Resource, power,
str::CStr, to_result, types::PointerWrapper, Result, ThisModule,
};
/// A registration of an amba driver.
pub type Registration<T> = driver::Registration<Adapter<T>>;
/// Id of an Amba device.
#[derive(Clone, Copy)]
pub struct DeviceId {
/// Device id.
pub id: u32,
/// Mask that identifies which bits are valid in the device id.
pub mask: u32,
}
// SAFETY: `ZERO` is all zeroed-out and `to_rawid` stores `offset` in `amba_id::data`.
unsafe impl const driver::RawDeviceId for DeviceId {
type RawType = bindings::amba_id;
const ZERO: Self::RawType = bindings::amba_id {
id: 0,
mask: 0,
data: core::ptr::null_mut(),
};
fn to_rawid(&self, offset: isize) -> Self::RawType {
bindings::amba_id {
id: self.id,
mask: self.mask,
data: offset as _,
}
}
}
/// An amba driver.
pub trait Driver {
/// Data stored on device by driver.
type Data: PointerWrapper + Send + Sync + driver::DeviceRemoval = ();
/// The type that implements the power-management operations.
///
/// The default is a type that implements no power-management operations. Drivers that do
/// implement them need to specify the type (commonly [`Self`]).
type PowerOps: power::Operations<Data = Self::Data> = power::NoOperations<Self::Data>;
/// The type holding information about each device id supported by the driver.
type IdInfo: 'static = ();
/// The table of device ids supported by the driver.
const ID_TABLE: Option<driver::IdTable<'static, DeviceId, Self::IdInfo>> = None;
/// Probes for the device with the given id.
fn probe(dev: &mut Device, id_info: Option<&Self::IdInfo>) -> Result<Self::Data>;
/// Cleans any resources up that are associated with the device.
///
/// This is called when the driver is detached from the device.
fn remove(_data: &Self::Data) {}
}
/// An adapter for the registration of Amba drivers.
pub struct Adapter<T: Driver>(T);
impl<T: Driver> driver::DriverOps for Adapter<T> {
type RegType = bindings::amba_driver;
unsafe fn register(
reg: *mut bindings::amba_driver,
name: &'static CStr,
module: &'static ThisModule,
) -> Result {
// SAFETY: By the safety requirements of this function (defined in the trait definition),
// `reg` is non-null and valid.
let amba = unsafe { &mut *reg };
amba.drv.name = name.as_char_ptr();
amba.drv.owner = module.0;
amba.probe = Some(probe_callback::<T>);
amba.remove = Some(remove_callback::<T>);
if let Some(t) = T::ID_TABLE {
amba.id_table = t.as_ref();
}
if cfg!(CONFIG_PM) {
// SAFETY: `probe_callback` sets the driver data after calling `T::Data::into_pointer`,
// and we guarantee that `T::Data` is the same as `T::PowerOps::Data` by a constraint
// in the type declaration.
amba.drv.pm = unsafe { power::OpsTable::<T::PowerOps>::build() };
}
// SAFETY: By the safety requirements of this function, `reg` is valid and fully
// initialised.
to_result(|| unsafe { bindings::amba_driver_register(reg) })
}
unsafe fn unregister(reg: *mut bindings::amba_driver) {
// SAFETY: By the safety requirements of this function (defined in the trait definition),
// `reg` was passed (and updated) by a previous successful call to `amba_driver_register`.
unsafe { bindings::amba_driver_unregister(reg) };
}
}
unsafe extern "C" fn probe_callback<T: Driver>(
adev: *mut bindings::amba_device,
aid: *const bindings::amba_id,
) -> c_types::c_int {
from_kernel_result! {
// SAFETY: `adev` is valid by the contract with the C code. `dev` is alive only for the
// duration of this call, so it is guaranteed to remain alive for the lifetime of `dev`.
let mut dev = unsafe { Device::from_ptr(adev) };
// SAFETY: `aid` is valid by the requirements the contract with the C code.
let offset = unsafe { (*aid).data };
let info = if offset.is_null() {
None
} else {
// SAFETY: The offset comes from a previous call to `offset_from` in `IdArray::new`,
// which guarantees that the resulting pointer is within the table.
let ptr = unsafe { aid.cast::<u8>().offset(offset as _).cast::<Option<T::IdInfo>>() };
// SAFETY: The id table has a static lifetime, so `ptr` is guaranteed to be valid for
// read.
unsafe { (&*ptr).as_ref() }
};
let data = T::probe(&mut dev, info)?;
let ptr = T::Data::into_pointer(data);
// SAFETY: `adev` is valid for write by the contract with the C code.
unsafe { bindings::amba_set_drvdata(adev, ptr as _) };
Ok(0)
}
}
unsafe extern "C" fn remove_callback<T: Driver>(adev: *mut bindings::amba_device) {
// SAFETY: `adev` is valid by the contract with the C code.
let ptr = unsafe { bindings::amba_get_drvdata(adev) };
// SAFETY: The value returned by `amba_get_drvdata` was stored by a previous call to
// `amba_set_drvdata` in `probe_callback` above; the value comes from a call to
// `T::Data::into_pointer`.
let data = unsafe { T::Data::from_pointer(ptr) };
T::remove(&data);
<T::Data as driver::DeviceRemoval>::device_remove(&data);
}
/// An Amba device.
///
/// # Invariants
///
/// The field `ptr` is non-null and valid for the lifetime of the object.
pub struct Device {
ptr: *mut bindings::amba_device,
res: Option<Resource>,
}
impl Device {
/// Creates a new device from the given pointer.
///
/// # Safety
///
/// `ptr` must be non-null and valid. It must remain valid for the lifetime of the returned
/// instance.
unsafe fn from_ptr(ptr: *mut bindings::amba_device) -> Self {
// SAFETY: The safety requirements of the function ensure that `ptr` is valid.
let dev = unsafe { &mut *ptr };
// INVARIANT: The safety requirements of the function ensure the lifetime invariant.
Self {
ptr,
res: Resource::new(dev.res.start, dev.res.end),
}
}
/// Returns the io mem resource associated with the device, if there is one.
///
/// Ownership of the resource is transferred to the caller, so subsequent calls to this
/// function will return [`None`].
pub fn take_resource(&mut self) -> Option<Resource> {
self.res.take()
}
/// Returns the index-th irq associated with the device, if one exists.
pub fn irq(&self, index: usize) -> Option<u32> {
// SAFETY: By the type invariants, `self.ptr` is valid for read.
let dev = unsafe { &*self.ptr };
if index >= dev.irq.len() || dev.irq[index] == 0 {
None
} else {
Some(dev.irq[index])
}
}
}
// SAFETY: The device returned by `raw_device` is the raw Amba device.
unsafe impl device::RawDevice for Device {
fn raw_device(&self) -> *mut bindings::device {
// SAFETY: By the type invariants, we know that `self.ptr` is non-null and valid.
unsafe { &mut (*self.ptr).dev }
}
}
/// Declares a kernel module that exposes a single amba driver.
///
/// # Examples
///
/// ```ignore
/// # use kernel::{amba, define_amba_id_table, module_amba_driver};
/// #
/// struct MyDriver;
/// impl amba::Driver for MyDriver {
/// // [...]
/// # fn probe(_dev: &mut amba::Device, _id: Option<&Self::IdInfo>) -> Result {
/// # Ok(())
/// # }
/// # define_amba_id_table! {(), [
/// # ({ id: 0x00041061, mask: 0x000fffff }, None),
/// # ]}
/// }
///
/// module_amba_driver! {
/// type: MyDriver,
/// name: b"module_name",
/// author: b"Author name",
/// license: b"GPL",
/// }
/// ```
#[macro_export]
macro_rules! module_amba_driver {
($($f:tt)*) => {
$crate::module_driver!(<T>, $crate::amba::Adapter<T>, { $($f)* });
};
}
/// Defines the id table for amba devices.
///
/// # Examples
///
/// ```
/// # use kernel::{amba, define_amba_id_table};
/// #
/// # struct Sample;
/// # impl kernel::amba::Driver for Sample {
/// # fn probe(_dev: &mut amba::Device, _id: Option<&Self::IdInfo>) -> Result {
/// # Ok(())
/// # }
/// define_amba_id_table! {(), [
/// ({ id: 0x00041061, mask: 0x000fffff }, None),
/// ]}
/// # }
/// ```
#[macro_export]
macro_rules! define_amba_id_table {
($data_type:ty, $($t:tt)*) => {
type IdInfo = $data_type;
$crate::define_id_table!(ID_TABLE, $crate::amba::DeviceId, $data_type, $($t)*);
};
}
// SPDX-License-Identifier: GPL-2.0
//! Bindings.
//!
//! Imports the generated bindings by `bindgen`.
// See https://github.com/rust-lang/rust-bindgen/issues/1651.
#![cfg_attr(test, allow(deref_nullptr))]
#![cfg_attr(test, allow(unaligned_references))]
#![cfg_attr(test, allow(unsafe_op_in_unsafe_fn))]
#![allow(
clippy::all,
non_camel_case_types,
non_upper_case_globals,
non_snake_case,
improper_ctypes,
unreachable_pub,
unsafe_op_in_unsafe_fn
)]
mod bindings_raw {
// Use glob import here to expose all helpers.
// Symbols defined within the module will take precedence to the glob import.
pub use super::bindings_helper::*;
use crate::c_types;
include!(concat!(env!("OBJTREE"), "/rust/bindings_generated.rs"));
}
// When both a directly exposed symbol and a helper exists for the same function,
// the directly exposed symbol is preferred and the helper becomes dead code, so
// ignore the warning here.
#[allow(dead_code)]
mod bindings_helper {
// Import the generated bindings for types.
use super::bindings_raw::*;
use crate::c_types;
include!(concat!(
env!("OBJTREE"),
"/rust/bindings_helpers_generated.rs"
));
}
pub use bindings_raw::*;
pub const GFP_KERNEL: gfp_t = BINDINGS_GFP_KERNEL;
pub const __GFP_ZERO: gfp_t = BINDINGS___GFP_ZERO;
pub const __GFP_HIGHMEM: gfp_t = ___GFP_HIGHMEM;
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Header that contains the code (mostly headers) for which Rust bindings
* will be automatically generated by `bindgen`.
*
* Sorted alphabetically.
*/
#include <kunit/test.h>
#include <linux/amba/bus.h>
#include <linux/cdev.h>
#include <linux/clk.h>
#include <linux/errname.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/gpio/driver.h>
#include <linux/hw_random.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irqdomain.h>
#include <linux/irq.h>
#include <linux/miscdevice.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/netfilter_arp.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/poll.h>
#include <linux/random.h>
#include <linux/security.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/uaccess.h>
#include <linux/uio.h>
#include <uapi/linux/android/binder.h>
/* `bindgen` gets confused at certain things. */
const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL;
const gfp_t BINDINGS___GFP_ZERO = __GFP_ZERO;
const __poll_t BINDINGS_EPOLLIN = EPOLLIN;
const __poll_t BINDINGS_EPOLLOUT = EPOLLOUT;
const __poll_t BINDINGS_EPOLLERR = EPOLLERR;
const __poll_t BINDINGS_EPOLLHUP = EPOLLHUP;
// SPDX-License-Identifier: GPL-2.0
//! Build-time assert.
/// Fails the build if the code path calling `build_error!` can possibly be executed.
///
/// If the macro is executed in const context, `build_error!` will panic.
/// If the compiler or optimizer cannot guarantee that `build_error!` can never
/// be called, a build error will be triggered.
///
/// # Examples
/// ```
/// # use kernel::build_error;
/// #[inline]
/// fn foo(a: usize) -> usize {
/// a.checked_add(1).unwrap_or_else(|| build_error!("overflow"))
/// }
///
/// assert_eq!(foo(usize::MAX - 1), usize::MAX); // OK.
/// // foo(usize::MAX); // Fails to compile.
/// ```
#[macro_export]
macro_rules! build_error {
() => {{
$crate::build_error("")
}};
($msg:expr) => {{
$crate::build_error($msg)
}};
}
/// Asserts that a boolean expression is `true` at compile time.
///
/// If the condition is evaluated to `false` in const context, `build_assert!`
/// will panic. If the compiler or optimizer cannot guarantee the condition will
/// be evaluated to `true`, a build error will be triggered.
///
/// [`static_assert!`] should be preferred to `build_assert!` whenever possible.
///
/// # Examples
///
/// These examples show that different types of [`assert!`] will trigger errors
/// at different stage of compilation. It is preferred to err as early as
/// possible, so [`static_assert!`] should be used whenever possible.
// TODO: Could be `compile_fail` when supported.
/// ```ignore
/// fn foo() {
/// static_assert!(1 > 1); // Compile-time error
/// build_assert!(1 > 1); // Build-time error
/// assert!(1 > 1); // Run-time error
/// }
/// ```
///
/// When the condition refers to generic parameters or parameters of an inline function,
/// [`static_assert!`] cannot be used. Use `build_assert!` in this scenario.
/// ```
/// fn foo<const N: usize>() {
/// // `static_assert!(N > 1);` is not allowed
/// build_assert!(N > 1); // Build-time check
/// assert!(N > 1); // Run-time check
/// }
///
/// #[inline]
/// fn bar(n: usize) {
/// // `static_assert!(n > 1);` is not allowed
/// build_assert!(n > 1); // Build-time check
/// assert!(n > 1); // Run-time check
/// }
/// ```
#[macro_export]
macro_rules! build_assert {
($cond:expr $(,)?) => {{
if !$cond {
$crate::build_error(concat!("assertion failed: ", stringify!($cond)));
}
}};
($cond:expr, $msg:expr) => {{
if !$cond {
$crate::build_error($msg);
}
}};
}
// SPDX-License-Identifier: GPL-2.0
//! C types for the bindings.
//!
//! The bindings generated by `bindgen` use these types to map to the C ones.
//!
//! C's standard integer types may differ in width depending on
//! the architecture, thus we need to conditionally compile those.
#![allow(non_camel_case_types)]
#[cfg(any(target_arch = "arm", target_arch = "x86", target_arch = "riscv32",))]
mod c {
/// C `void` type.
pub type c_void = core::ffi::c_void;
/// C `char` type.
pub type c_char = i8;
/// C `signed char` type.
pub type c_schar = i8;
/// C `unsigned char` type.
pub type c_uchar = u8;
/// C `short` type.
pub type c_short = i16;
/// C `unsigned short` type.
pub type c_ushort = u16;
/// C `int` type.
pub type c_int = i32;
/// C `unsigned int` type.
pub type c_uint = u32;
/// C `long` type.
pub type c_long = i32;
/// C `unsigned long` type.
pub type c_ulong = u32;
/// C `long long` type.
pub type c_longlong = i64;
/// C `unsigned long long` type.
pub type c_ulonglong = u64;
/// C `ssize_t` type (typically defined in `<sys/types.h>` by POSIX).
///
/// For some 32-bit architectures like this one, the kernel defines it as
/// `int`, i.e. it is an [`i32`].
pub type c_ssize_t = isize;
/// C `size_t` type (typically defined in `<stddef.h>`).
///
/// For some 32-bit architectures like this one, the kernel defines it as
/// `unsigned int`, i.e. it is an [`u32`].
pub type c_size_t = usize;
}
#[cfg(any(
target_arch = "aarch64",
target_arch = "x86_64",
target_arch = "powerpc64",
target_arch = "riscv64",
))]
mod c {
/// C `void` type.
pub type c_void = core::ffi::c_void;
/// C `char` type.
pub type c_char = i8;
/// C `signed char` type.
pub type c_schar = i8;
/// C `unsigned char` type.
pub type c_uchar = u8;
/// C `short` type.
pub type c_short = i16;
/// C `unsigned short` type.
pub type c_ushort = u16;
/// C `int` type.
pub type c_int = i32;
/// C `unsigned int` type.
pub type c_uint = u32;
/// C `long` type.
pub type c_long = i64;
/// C `unsigned long` type.
pub type c_ulong = u64;
/// C `long long` type.
pub type c_longlong = i64;
/// C `unsigned long long` type.
pub type c_ulonglong = u64;
/// C `ssize_t` type (typically defined in `<sys/types.h>` by POSIX).
///
/// For 64-bit architectures like this one, the kernel defines it as
/// `long`, i.e. it is an [`i64`].
pub type c_ssize_t = isize;
/// C `size_t` type (typically defined in `<stddef.h>`).
///
/// For 64-bit architectures like this one, the kernel defines it as
/// `unsigned long`, i.e. it is an [`u64`].
pub type c_size_t = usize;
}
pub use c::*;
// SPDX-License-Identifier: GPL-2.0
//! Character devices.
//!
//! Also called "char devices", `chrdev`, `cdev`.
//!
//! C header: [`include/linux/cdev.h`](../../../../include/linux/cdev.h)
//!
//! Reference: <https://www.kernel.org/doc/html/latest/core-api/kernel-api.html#char-devices>
use alloc::boxed::Box;
use core::convert::TryInto;
use core::marker::PhantomPinned;
use core::pin::Pin;
use crate::bindings;
use crate::c_types;
use crate::error::{code::*, Error, Result};
use crate::file;
use crate::str::CStr;
/// Character device.
///
/// # Invariants
///
/// - [`self.0`] is valid and non-null.
/// - [`(*self.0).ops`] is valid, non-null and has static lifetime.
/// - [`(*self.0).owner`] is valid and, if non-null, has module lifetime.
struct Cdev(*mut bindings::cdev);
impl Cdev {
fn alloc(
fops: &'static bindings::file_operations,
module: &'static crate::ThisModule,
) -> Result<Self> {
// SAFETY: FFI call.
let cdev = unsafe { bindings::cdev_alloc() };
if cdev.is_null() {
return Err(ENOMEM);
}
// SAFETY: `cdev` is valid and non-null since `cdev_alloc()`
// returned a valid pointer which was null-checked.
unsafe {
(*cdev).ops = fops;
(*cdev).owner = module.0;
}
// INVARIANTS:
// - [`self.0`] is valid and non-null.
// - [`(*self.0).ops`] is valid, non-null and has static lifetime,
// because it was coerced from a reference with static lifetime.
// - [`(*self.0).owner`] is valid and, if non-null, has module lifetime,
// guaranteed by the [`ThisModule`] invariant.
Ok(Self(cdev))
}
fn add(&mut self, dev: bindings::dev_t, count: c_types::c_uint) -> Result {
// SAFETY: According to the type invariants:
// - [`self.0`] can be safely passed to [`bindings::cdev_add`].
// - [`(*self.0).ops`] will live at least as long as [`self.0`].
// - [`(*self.0).owner`] will live at least as long as the
// module, which is an implicit requirement.
let rc = unsafe { bindings::cdev_add(self.0, dev, count) };
if rc != 0 {
return Err(Error::from_kernel_errno(rc));
}
Ok(())
}
}
impl Drop for Cdev {
fn drop(&mut self) {
// SAFETY: [`self.0`] is valid and non-null by the type invariants.
unsafe {
bindings::cdev_del(self.0);
}
}
}
struct RegistrationInner<const N: usize> {
dev: bindings::dev_t,
used: usize,
cdevs: [Option<Cdev>; N],
_pin: PhantomPinned,
}
/// Character device registration.
///
/// May contain up to a fixed number (`N`) of devices. Must be pinned.
pub struct Registration<const N: usize> {
name: &'static CStr,
minors_start: u16,
this_module: &'static crate::ThisModule,
inner: Option<RegistrationInner<N>>,
}
impl<const N: usize> Registration<{ N }> {
/// Creates a [`Registration`] object for a character device.
///
/// This does *not* register the device: see [`Self::register()`].
///
/// This associated function is intended to be used when you need to avoid
/// a memory allocation, e.g. when the [`Registration`] is a member of
/// a bigger structure inside your [`crate::Module`] instance. If you
/// are going to pin the registration right away, call
/// [`Self::new_pinned()`] instead.
pub fn new(
name: &'static CStr,
minors_start: u16,
this_module: &'static crate::ThisModule,
) -> Self {
Registration {
name,
minors_start,
this_module,
inner: None,
}
}
/// Creates a pinned [`Registration`] object for a character device.
///
/// This does *not* register the device: see [`Self::register()`].
pub fn new_pinned(
name: &'static CStr,
minors_start: u16,
this_module: &'static crate::ThisModule,
) -> Result<Pin<Box<Self>>> {
Ok(Pin::from(Box::try_new(Self::new(
name,
minors_start,
this_module,
))?))
}
/// Registers a character device.
///
/// You may call this once per device type, up to `N` times.
pub fn register<T: file::Operations<OpenData = ()>>(self: Pin<&mut Self>) -> Result {
// SAFETY: We must ensure that we never move out of `this`.
let this = unsafe { self.get_unchecked_mut() };
if this.inner.is_none() {
let mut dev: bindings::dev_t = 0;
// SAFETY: Calling unsafe function. `this.name` has `'static`
// lifetime.
let res = unsafe {
bindings::alloc_chrdev_region(
&mut dev,
this.minors_start.into(),
N.try_into()?,
this.name.as_char_ptr(),
)
};
if res != 0 {
return Err(Error::from_kernel_errno(res));
}
const NONE: Option<Cdev> = None;
this.inner = Some(RegistrationInner {
dev,
used: 0,
cdevs: [NONE; N],
_pin: PhantomPinned,
});
}
let mut inner = this.inner.as_mut().unwrap();
if inner.used == N {
return Err(EINVAL);
}
// SAFETY: The adapter doesn't retrieve any state yet, so it's compatible with any
// registration.
let fops = unsafe { file::OperationsVtable::<Self, T>::build() };
let mut cdev = Cdev::alloc(fops, this.this_module)?;
cdev.add(inner.dev + inner.used as bindings::dev_t, 1)?;
inner.cdevs[inner.used].replace(cdev);
inner.used += 1;
Ok(())
}
}
impl<const N: usize> file::OpenAdapter<()> for Registration<{ N }> {
unsafe fn convert(_inode: *mut bindings::inode, _file: *mut bindings::file) -> *const () {
// TODO: Update the SAFETY comment on the call to `FileOperationsVTable::build` above once
// this is updated to retrieve state.
&()
}
}
// SAFETY: `Registration` does not expose any of its state across threads
// (it is fine for multiple threads to have a shared reference to it).
unsafe impl<const N: usize> Sync for Registration<{ N }> {}
impl<const N: usize> Drop for Registration<{ N }> {
fn drop(&mut self) {
if let Some(inner) = self.inner.as_mut() {
// Replicate kernel C behaviour: drop [`Cdev`]s before calling
// [`bindings::unregister_chrdev_region`].
for i in 0..inner.used {
inner.cdevs[i].take();
}
// SAFETY: [`self.inner`] is Some, so [`inner.dev`] was previously
// created using [`bindings::alloc_chrdev_region`].
unsafe {
bindings::unregister_chrdev_region(inner.dev, N.try_into().unwrap());
}
}
}
}
// SPDX-License-Identifier: GPL-2.0
//! Common clock framework.
//!
//! C header: [`include/linux/clk.h`](../../../../include/linux/clk.h)
use crate::{bindings, error::Result, to_result};
use core::mem::ManuallyDrop;
/// Represents `struct clk *`.
///
/// # Invariants
///
/// The pointer is valid.
pub struct Clk(*mut bindings::clk);
impl Clk {
/// Creates new clock structure from a raw pointer.
///
/// # Safety
///
/// The pointer must be valid.
pub unsafe fn new(clk: *mut bindings::clk) -> Self {
Self(clk)
}
/// Returns value of the rate field of `struct clk`.
pub fn get_rate(&self) -> usize {
// SAFETY: The pointer is valid by the type invariant.
unsafe { bindings::clk_get_rate(self.0) as usize }
}
/// Prepares and enables the underlying hardware clock.
///
/// This function should not be called in atomic context.
pub fn prepare_enable(self) -> Result<EnabledClk> {
// SAFETY: The pointer is valid by the type invariant.
to_result(|| unsafe { bindings::clk_prepare_enable(self.0) })?;
Ok(EnabledClk(self))
}
}
impl Drop for Clk {
fn drop(&mut self) {
// SAFETY: The pointer is valid by the type invariant.
unsafe { bindings::clk_put(self.0) };
}
}
// SAFETY: `Clk` is not restricted to a single thread so it is safe
// to move it between threads.
unsafe impl Send for Clk {}
/// A clock variant that is prepared and enabled.
pub struct EnabledClk(Clk);
impl EnabledClk {
/// Returns value of the rate field of `struct clk`.
pub fn get_rate(&self) -> usize {
self.0.get_rate()
}
/// Disables and later unprepares the underlying hardware clock prematurely.
///
/// This function should not be called in atomic context.
pub fn disable_unprepare(self) -> Clk {
let mut clk = ManuallyDrop::new(self);
// SAFETY: The pointer is valid by the type invariant.
unsafe { bindings::clk_disable_unprepare(clk.0 .0) };
core::mem::replace(&mut clk.0, Clk(core::ptr::null_mut()))
}
}
impl Drop for EnabledClk {
fn drop(&mut self) {
// SAFETY: The pointer is valid by the type invariant.
unsafe { bindings::clk_disable_unprepare(self.0 .0) };
}
}
// SPDX-License-Identifier: GPL-2.0
//! Credentials management.
//!
//! C header: [`include/linux/cred.h`](../../../../include/linux/cred.h)
//!
//! Reference: <https://www.kernel.org/doc/html/latest/security/credentials.html>
use crate::{bindings, AlwaysRefCounted};
use core::cell::UnsafeCell;
/// Wraps the kernel's `struct cred`.
///
/// # Invariants
///
/// Instances of this type are always ref-counted, that is, a call to `get_cred` ensures that the
/// allocation remains valid at least until the matching call to `put_cred`.
#[repr(transparent)]
pub struct Credential(pub(crate) UnsafeCell<bindings::cred>);
impl Credential {
/// Creates a reference to a [`Credential`] from a valid pointer.
///
/// # Safety
///
/// The caller must ensure that `ptr` is valid and remains valid for the lifetime of the
/// returned [`Credential`] reference.
pub(crate) unsafe fn from_ptr<'a>(ptr: *const bindings::cred) -> &'a Self {
// SAFETY: The safety requirements guarantee the validity of the dereference, while the
// `Credential` type being transparent makes the cast ok.
unsafe { &*ptr.cast() }
}
}
// SAFETY: The type invariants guarantee that `Credential` is always ref-counted.
unsafe impl AlwaysRefCounted for Credential {
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
unsafe { bindings::get_cred(self.0.get()) };
}
unsafe fn dec_ref(obj: core::ptr::NonNull<Self>) {
// SAFETY: The safety requirements guarantee that the refcount is nonzero.
unsafe { bindings::put_cred(obj.cast().as_ptr()) };
}
}
// SPDX-License-Identifier: GPL-2.0
//! Generic devices that are part of the kernel's driver model.
//!
//! C header: [`include/linux/device.h`](../../../../include/linux/device.h)
#[cfg(CONFIG_COMMON_CLK)]
use crate::{clk::Clk, error::from_kernel_err_ptr};
use crate::{
bindings,
revocable::{Revocable, RevocableGuard},
str::CStr,
sync::{NeedsLockClass, RevocableMutex, RevocableMutexGuard, UniqueRef},
Result,
};
use core::{
fmt,
ops::{Deref, DerefMut},
pin::Pin,
};
#[cfg(CONFIG_PRINTK)]
use crate::{c_str, c_types};
/// A raw device.
///
/// # Safety
///
/// Implementers must ensure that the `*mut device` returned by [`RawDevice::raw_device`] is
/// related to `self`, that is, actions on it will affect `self`. For example, if one calls
/// `get_device`, then the refcount on the device represented by `self` will be incremented.
///
/// Additionally, implementers must ensure that the device is never renamed. Commit a5462516aa994
/// has details on why `device_rename` should not be used.
pub unsafe trait RawDevice {
/// Returns the raw `struct device` related to `self`.
fn raw_device(&self) -> *mut bindings::device;
/// Returns the name of the device.
fn name(&self) -> &CStr {
let ptr = self.raw_device();
// SAFETY: `ptr` is valid because `self` keeps it alive.
let name = unsafe { bindings::dev_name(ptr) };
// SAFETY: The name of the device remains valid while it is alive (because the device is
// never renamed, per the safety requirement of this trait). This is guaranteed to be the
// case because the reference to `self` outlives the one of the returned `CStr` (enforced
// by the compiler because of their lifetimes).
unsafe { CStr::from_char_ptr(name) }
}
/// Lookups a clock producer consumed by this device.
///
/// Returns a managed reference to the clock producer.
#[cfg(CONFIG_COMMON_CLK)]
fn clk_get(&self, id: Option<&CStr>) -> Result<Clk> {
let id_ptr = match id {
Some(cstr) => cstr.as_char_ptr(),
None => core::ptr::null(),
};
// SAFETY: `id_ptr` is optional and may be either a valid pointer
// from the type invariant or NULL otherwise.
let clk_ptr = unsafe { from_kernel_err_ptr(bindings::clk_get(self.raw_device(), id_ptr)) }?;
// SAFETY: Clock is initialized with valid pointer returned from `bindings::clk_get` call.
unsafe { Ok(Clk::new(clk_ptr)) }
}
/// Prints an emergency-level message (level 0) prefixed with device information.
///
/// More details are available from [`dev_emerg`].
fn pr_emerg(&self, args: fmt::Arguments<'_>) {
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
unsafe { self.printk(bindings::KERN_EMERG, args) };
}
/// Prints an alert-level message (level 1) prefixed with device information.
///
/// More details are available from [`dev_alert`].
fn pr_alert(&self, args: fmt::Arguments<'_>) {
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
unsafe { self.printk(bindings::KERN_ALERT, args) };
}
/// Prints a critical-level message (level 2) prefixed with device information.
///
/// More details are available from [`dev_crit`].
fn pr_crit(&self, args: fmt::Arguments<'_>) {
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
unsafe { self.printk(bindings::KERN_CRIT, args) };
}
/// Prints an error-level message (level 3) prefixed with device information.
///
/// More details are available from [`dev_err`].
fn pr_err(&self, args: fmt::Arguments<'_>) {
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
unsafe { self.printk(bindings::KERN_ERR, args) };
}
/// Prints a warning-level message (level 4) prefixed with device information.
///
/// More details are available from [`dev_warn`].
fn pr_warn(&self, args: fmt::Arguments<'_>) {
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
unsafe { self.printk(bindings::KERN_WARNING, args) };
}
/// Prints a notice-level message (level 5) prefixed with device information.
///
/// More details are available from [`dev_notice`].
fn pr_notice(&self, args: fmt::Arguments<'_>) {
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
unsafe { self.printk(bindings::KERN_NOTICE, args) };
}
/// Prints an info-level message (level 6) prefixed with device information.
///
/// More details are available from [`dev_info`].
fn pr_info(&self, args: fmt::Arguments<'_>) {
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
unsafe { self.printk(bindings::KERN_INFO, args) };
}
/// Prints a debug-level message (level 7) prefixed with device information.
///
/// More details are available from [`dev_dbg`].
fn pr_dbg(&self, args: fmt::Arguments<'_>) {
if cfg!(debug_assertions) {
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
unsafe { self.printk(bindings::KERN_DEBUG, args) };
}
}
/// Prints the provided message to the console.
///
/// # Safety
///
/// Callers must ensure that `klevel` is null-terminated; in particular, one of the
/// `KERN_*`constants, for example, `KERN_CRIT`, `KERN_ALERT`, etc.
#[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))]
unsafe fn printk(&self, klevel: &[u8], msg: fmt::Arguments<'_>) {
// SAFETY: `klevel` is null-terminated and one of the kernel constants. `self.raw_device`
// is valid because `self` is valid. The "%pA" format string expects a pointer to
// `fmt::Arguments`, which is what we're passing as the last argument.
#[cfg(CONFIG_PRINTK)]
unsafe {
bindings::_dev_printk(
klevel as *const _ as *const c_types::c_char,
self.raw_device(),
c_str!("%pA").as_char_ptr(),
&msg as *const _ as *const c_types::c_void,
)
};
}
}
/// A ref-counted device.
///
/// # Invariants
///
/// `ptr` is valid, non-null, and has a non-zero reference count. One of the references is owned by
/// `self`, and will be decremented when `self` is dropped.
pub struct Device {
pub(crate) ptr: *mut bindings::device,
}
// SAFETY: `Device` only holds a pointer to a C device, which is safe to be used from any thread.
unsafe impl Send for Device {}
// SAFETY: `Device` only holds a pointer to a C device, references to which are safe to be used
// from any thread.
unsafe impl Sync for Device {}
impl Device {
/// Creates a new device instance.
///
/// # Safety
///
/// Callers must ensure that `ptr` is valid, non-null, and has a non-zero reference count.
pub unsafe fn new(ptr: *mut bindings::device) -> Self {
// SAFETY: By the safety requirements, ptr is valid and its refcounted will be incremented.
unsafe { bindings::get_device(ptr) };
// INVARIANT: The safety requirements satisfy all but one invariant, which is that `self`
// owns a reference. This is satisfied by the call to `get_device` above.
Self { ptr }
}
/// Creates a new device instance from an existing [`RawDevice`] instance.
pub fn from_dev(dev: &dyn RawDevice) -> Self {
// SAFETY: The requirements are satisfied by the existence of `RawDevice` and its safety
// requirements.
unsafe { Self::new(dev.raw_device()) }
}
}
// SAFETY: The device returned by `raw_device` is the one for which we hold a reference.
unsafe impl RawDevice for Device {
fn raw_device(&self) -> *mut bindings::device {
self.ptr
}
}
impl Drop for Device {
fn drop(&mut self) {
// SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to
// relinquish it now.
unsafe { bindings::put_device(self.ptr) };
}
}
/// Device data.
///
/// When a device is removed (for whatever reason, for example, because the device was unplugged or
/// because the user decided to unbind the driver), the driver is given a chance to clean its state
/// up, and all io resources should ideally not be used anymore.
///
/// However, the device data is reference-counted because other subsystems hold pointers to it. So
/// some device state must be freed and not used anymore, while others must remain accessible.
///
/// This struct separates the device data into three categories:
/// 1. Registrations: are destroyed when the device is removed, but before the io resources
/// become inaccessible.
/// 2. Io resources: are available until the device is removed.
/// 3. General data: remain available as long as the ref count is nonzero.
///
/// This struct implements the `DeviceRemoval` trait so that it can clean resources up even if not
/// explicitly called by the device drivers.
pub struct Data<T, U, V> {
registrations: RevocableMutex<T>,
resources: Revocable<U>,
general: V,
}
/// Safely creates an new reference-counted instance of [`Data`].
#[doc(hidden)]
#[macro_export]
macro_rules! new_device_data {
($reg:expr, $res:expr, $gen:expr, $name:literal) => {{
static mut CLASS1: core::mem::MaybeUninit<$crate::bindings::lock_class_key> =
core::mem::MaybeUninit::uninit();
static mut CLASS2: core::mem::MaybeUninit<$crate::bindings::lock_class_key> =
core::mem::MaybeUninit::uninit();
let regs = $reg;
let res = $res;
let gen = $gen;
let name = $crate::c_str!($name);
// SAFETY: `CLASS1` and `CLASS2` are never used by Rust code directly; the C portion of the
// kernel may change it though.
unsafe {
$crate::device::Data::try_new(
regs,
res,
gen,
name,
CLASS1.as_mut_ptr(),
CLASS2.as_mut_ptr(),
)
}
}};
}
impl<T, U, V> Data<T, U, V> {
/// Creates a new instance of `Data`.
///
/// It is recommended that the [`new_device_data`] macro be used as it automatically creates
/// the lock classes.
///
/// # Safety
///
/// `key1` and `key2` must point to valid memory locations and remain valid until `self` is
/// dropped.
pub unsafe fn try_new(
registrations: T,
resources: U,
general: V,
name: &'static CStr,
key1: *mut bindings::lock_class_key,
key2: *mut bindings::lock_class_key,
) -> Result<Pin<UniqueRef<Self>>> {
let mut ret = Pin::from(UniqueRef::try_new(Self {
// SAFETY: We call `RevocableMutex::init` below.
registrations: unsafe { RevocableMutex::new(registrations) },
resources: Revocable::new(resources),
general,
})?);
// SAFETY: `Data::registrations` is pinned when `Data` is.
let pinned = unsafe { ret.as_mut().map_unchecked_mut(|d| &mut d.registrations) };
// SAFETY: The safety requirements of this function satisfy those of `RevocableMutex::init`.
unsafe { pinned.init(name, key1, key2) };
Ok(ret)
}
/// Returns the resources if they're still available.
pub fn resources(&self) -> Option<RevocableGuard<'_, U>> {
self.resources.try_access()
}
/// Returns the locked registrations if they're still available.
pub fn registrations(&self) -> Option<RevocableMutexGuard<'_, T>> {
self.registrations.try_write()
}
}
impl<T, U, V> crate::driver::DeviceRemoval for Data<T, U, V> {
fn device_remove(&self) {
// We revoke the registrations first so that resources are still available to them during
// unregistration.
self.registrations.revoke();
// Release resources now. General data remains available.
self.resources.revoke();
}
}
impl<T, U, V> Deref for Data<T, U, V> {
type Target = V;
fn deref(&self) -> &V {
&self.general
}
}
impl<T, U, V> DerefMut for Data<T, U, V> {
fn deref_mut(&mut self) -> &mut V {
&mut self.general
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! dev_printk {
($method:ident, $dev:expr, $($f:tt)*) => {
{
// We have an explicity `use` statement here so that callers of this macro are not
// required to explicitly use the `RawDevice` trait to use its functions.
use $crate::device::RawDevice;
($dev).$method(core::format_args!($($f)*));
}
}
}
/// Prints an emergency-level message (level 0) prefixed with device information.
///
/// This level should be used if the system is unusable.
///
/// Equivalent to the kernel's `dev_emerg` macro.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
/// [`core::fmt`] and [`alloc::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
///
/// # Examples
///
/// ```
/// # use kernel::device::Device;
///
/// fn example(dev: &Device) {
/// dev_emerg!(dev, "hello {}\n", "there");
/// }
/// ```
#[macro_export]
macro_rules! dev_emerg {
($($f:tt)*) => { $crate::dev_printk!(pr_emerg, $($f)*); }
}
/// Prints an alert-level message (level 1) prefixed with device information.
///
/// This level should be used if action must be taken immediately.
///
/// Equivalent to the kernel's `dev_alert` macro.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
/// [`core::fmt`] and [`alloc::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
///
/// # Examples
///
/// ```
/// # use kernel::device::Device;
///
/// fn example(dev: &Device) {
/// dev_alert!(dev, "hello {}\n", "there");
/// }
/// ```
#[macro_export]
macro_rules! dev_alert {
($($f:tt)*) => { $crate::dev_printk!(pr_alert, $($f)*); }
}
/// Prints a critical-level message (level 2) prefixed with device information.
///
/// This level should be used in critical conditions.
///
/// Equivalent to the kernel's `dev_crit` macro.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
/// [`core::fmt`] and [`alloc::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
///
/// # Examples
///
/// ```
/// # use kernel::device::Device;
///
/// fn example(dev: &Device) {
/// dev_crit!(dev, "hello {}\n", "there");
/// }
/// ```
#[macro_export]
macro_rules! dev_crit {
($($f:tt)*) => { $crate::dev_printk!(pr_crit, $($f)*); }
}
/// Prints an error-level message (level 3) prefixed with device information.
///
/// This level should be used in error conditions.
///
/// Equivalent to the kernel's `dev_err` macro.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
/// [`core::fmt`] and [`alloc::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
///
/// # Examples
///
/// ```
/// # use kernel::device::Device;
///
/// fn example(dev: &Device) {
/// dev_err!(dev, "hello {}\n", "there");
/// }
/// ```
#[macro_export]
macro_rules! dev_err {
($($f:tt)*) => { $crate::dev_printk!(pr_err, $($f)*); }
}
/// Prints a warning-level message (level 4) prefixed with device information.
///
/// This level should be used in warning conditions.
///
/// Equivalent to the kernel's `dev_warn` macro.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
/// [`core::fmt`] and [`alloc::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
///
/// # Examples
///
/// ```
/// # use kernel::device::Device;
///
/// fn example(dev: &Device) {
/// dev_warn!(dev, "hello {}\n", "there");
/// }
/// ```
#[macro_export]
macro_rules! dev_warn {
($($f:tt)*) => { $crate::dev_printk!(pr_warn, $($f)*); }
}
/// Prints a notice-level message (level 5) prefixed with device information.
///
/// This level should be used in normal but significant conditions.
///
/// Equivalent to the kernel's `dev_notice` macro.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
/// [`core::fmt`] and [`alloc::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
///
/// # Examples
///
/// ```
/// # use kernel::device::Device;
///
/// fn example(dev: &Device) {
/// dev_notice!(dev, "hello {}\n", "there");
/// }
/// ```
#[macro_export]
macro_rules! dev_notice {
($($f:tt)*) => { $crate::dev_printk!(pr_notice, $($f)*); }
}
/// Prints an info-level message (level 6) prefixed with device information.
///
/// This level should be used for informational messages.
///
/// Equivalent to the kernel's `dev_info` macro.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
/// [`core::fmt`] and [`alloc::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
///
/// # Examples
///
/// ```
/// # use kernel::device::Device;
///
/// fn example(dev: &Device) {
/// dev_info!(dev, "hello {}\n", "there");
/// }
/// ```
#[macro_export]
macro_rules! dev_info {
($($f:tt)*) => { $crate::dev_printk!(pr_info, $($f)*); }
}
/// Prints a debug-level message (level 7) prefixed with device information.
///
/// This level should be used for debug messages.
///
/// Equivalent to the kernel's `dev_dbg` macro, except that it doesn't support dynamic debug yet.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
/// [`core::fmt`] and [`alloc::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
///
/// # Examples
///
/// ```
/// # use kernel::device::Device;
///
/// fn example(dev: &Device) {
/// dev_dbg!(dev, "hello {}\n", "there");
/// }
/// ```
#[macro_export]
macro_rules! dev_dbg {
($($f:tt)*) => { $crate::dev_printk!(pr_dbg, $($f)*); }
}
// SPDX-License-Identifier: GPL-2.0
//! Generic support for drivers of different buses (e.g., PCI, Platform, Amba, etc.).
//!
//! Each bus/subsystem is expected to implement [`DriverOps`], which allows drivers to register
//! using the [`Registration`] class.
use crate::{error::code::*, str::CStr, sync::Ref, Result, ThisModule};
use alloc::boxed::Box;
use core::{cell::UnsafeCell, marker::PhantomData, ops::Deref, pin::Pin};
/// A subsystem (e.g., PCI, Platform, Amba, etc.) that allows drivers to be written for it.
pub trait DriverOps {
/// The type that holds information about the registration. This is typically a struct defined
/// by the C portion of the kernel.
type RegType: Default;
/// Registers a driver.
///
/// # Safety
///
/// `reg` must point to valid, initialised, and writable memory. It may be modified by this
/// function to hold registration state.
///
/// On success, `reg` must remain pinned and valid until the matching call to
/// [`DriverOps::unregister`].
unsafe fn register(
reg: *mut Self::RegType,
name: &'static CStr,
module: &'static ThisModule,
) -> Result;
/// Unregisters a driver previously registered with [`DriverOps::register`].
///
/// # Safety
///
/// `reg` must point to valid writable memory, initialised by a previous successful call to
/// [`DriverOps::register`].
unsafe fn unregister(reg: *mut Self::RegType);
}
/// The registration of a driver.
pub struct Registration<T: DriverOps> {
is_registered: bool,
concrete_reg: UnsafeCell<T::RegType>,
}
// SAFETY: `Registration` has no fields or methods accessible via `&Registration`, so it is safe to
// share references to it with multiple threads as nothing can be done.
unsafe impl<T: DriverOps> Sync for Registration<T> {}
impl<T: DriverOps> Registration<T> {
/// Creates a new instance of the registration object.
pub fn new() -> Self {
Self {
is_registered: false,
concrete_reg: UnsafeCell::new(T::RegType::default()),
}
}
/// Allocates a pinned registration object and registers it.
///
/// Returns a pinned heap-allocated representation of the registration.
pub fn new_pinned(name: &'static CStr, module: &'static ThisModule) -> Result<Pin<Box<Self>>> {
let mut reg = Pin::from(Box::try_new(Self::new())?);
reg.as_mut().register(name, module)?;
Ok(reg)
}
/// Registers a driver with its subsystem.
///
/// It must be pinned because the memory block that represents the registration is potentially
/// self-referential.
pub fn register(
self: Pin<&mut Self>,
name: &'static CStr,
module: &'static ThisModule,
) -> Result {
// SAFETY: We never move out of `this`.
let this = unsafe { self.get_unchecked_mut() };
if this.is_registered {
// Already registered.
return Err(EINVAL);
}
// SAFETY: `concrete_reg` was initialised via its default constructor. It is only freed
// after `Self::drop` is called, which first calls `T::unregister`.
unsafe { T::register(this.concrete_reg.get(), name, module) }?;
this.is_registered = true;
Ok(())
}
}
impl<T: DriverOps> Default for Registration<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: DriverOps> Drop for Registration<T> {
fn drop(&mut self) {
if self.is_registered {
// SAFETY: This path only runs if a previous call to `T::register` completed
// successfully.
unsafe { T::unregister(self.concrete_reg.get()) };
}
}
}
/// Conversion from a device id to a raw device id.
///
/// This is meant to be implemented by buses/subsystems so that they can use [`IdTable`] to
/// guarantee (at compile-time) zero-termination of device id tables provided by drivers.
///
/// # Safety
///
/// Implementers must ensure that:
/// - [`RawDeviceId::ZERO`] is actually a zeroed-out version of the raw device id.
/// - [`RawDeviceId::to_rawid`] stores `offset` in the context/data field of the raw device id so
/// that buses can recover the pointer to the data.
pub unsafe trait RawDeviceId {
/// The raw type that holds the device id.
///
/// Id tables created from [`Self`] are going to hold this type in its zero-terminated array.
type RawType: Copy;
/// A zeroed-out representation of the raw device id.
///
/// Id tables created from [`Self`] use [`Self::ZERO`] as the sentinel to indicate the end of
/// the table.
const ZERO: Self::RawType;
/// Converts an id into a raw id.
///
/// `offset` is the offset from the memory location where the raw device id is stored to the
/// location where its associated context information is stored. Implementations must store
/// this in the appropriate context/data field of the raw type.
fn to_rawid(&self, offset: isize) -> Self::RawType;
}
/// A zero-terminated device id array, followed by context data.
#[repr(C)]
pub struct IdArray<T: RawDeviceId, U, const N: usize> {
ids: [T::RawType; N],
sentinel: T::RawType,
id_infos: [Option<U>; N],
}
impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
/// Creates a new instance of the array.
///
/// The contents are derived from the given identifiers and context information.
pub const fn new(ids: [T; N], infos: [Option<U>; N]) -> Self
where
T: ~const RawDeviceId + Copy,
{
let mut array = Self {
ids: [T::ZERO; N],
sentinel: T::ZERO,
id_infos: infos,
};
let mut i = 0usize;
while i < N {
// SAFETY: Both pointers are within `array` (or one byte beyond), consequently they are
// derived from the same allocated object. We are using a `u8` pointer, whose size 1,
// so the pointers are necessarily 1-byte aligned.
let offset = unsafe {
(&array.id_infos[i] as *const _ as *const u8)
.offset_from(&array.ids[i] as *const _ as _)
};
array.ids[i] = ids[i].to_rawid(offset);
i += 1;
}
array
}
/// Returns an `IdTable` backed by `self`.
///
/// This is used to essentially erase the array size.
pub const fn as_table(&self) -> IdTable<'_, T, U> {
IdTable {
first: &self.ids[0],
_p: PhantomData,
}
}
}
/// A device id table.
///
/// The table is guaranteed to be zero-terminated and to be followed by an array of context data of
/// type `Option<U>`.
pub struct IdTable<'a, T: RawDeviceId, U> {
first: &'a T::RawType,
_p: PhantomData<&'a U>,
}
impl<T: RawDeviceId, U> const AsRef<T::RawType> for IdTable<'_, T, U> {
fn as_ref(&self) -> &T::RawType {
self.first
}
}
/// Counts the number of parenthesis-delimited, comma-separated items.
///
/// # Examples
///
/// ```
/// # use kernel::count_paren_items;
///
/// assert_eq!(0, count_paren_items!());
/// assert_eq!(1, count_paren_items!((A)));
/// assert_eq!(1, count_paren_items!((A),));
/// assert_eq!(2, count_paren_items!((A), (B)));
/// assert_eq!(2, count_paren_items!((A), (B),));
/// assert_eq!(3, count_paren_items!((A), (B), (C)));
/// assert_eq!(3, count_paren_items!((A), (B), (C),));
/// ```
#[macro_export]
macro_rules! count_paren_items {
(($($item:tt)*), $($remaining:tt)*) => { 1 + $crate::count_paren_items!($($remaining)*) };
(($($item:tt)*)) => { 1 };
() => { 0 };
}
/// Converts a comma-separated list of pairs into an array with the first element. That is, it
/// discards the second element of the pair.
///
/// Additionally, it automatically introduces a type if the first element is warpped in curly
/// braces, for example, if it's `{v: 10}`, it becomes `X { v: 10 }`; this is to avoid repeating
/// the type.
///
/// # Examples
///
/// ```
/// # use kernel::first_item;
///
/// #[derive(PartialEq, Debug)]
/// struct X {
/// v: u32,
/// }
///
/// assert_eq!([] as [X; 0], first_item!(X, ));
/// assert_eq!([X { v: 10 }], first_item!(X, ({ v: 10 }, Y)));
/// assert_eq!([X { v: 10 }], first_item!(X, ({ v: 10 }, Y),));
/// assert_eq!([X { v: 10 }], first_item!(X, (X { v: 10 }, Y)));
/// assert_eq!([X { v: 10 }], first_item!(X, (X { v: 10 }, Y),));
/// assert_eq!([X { v: 10 }, X { v: 20 }], first_item!(X, ({ v: 10 }, Y), ({ v: 20 }, Y)));
/// assert_eq!([X { v: 10 }, X { v: 20 }], first_item!(X, ({ v: 10 }, Y), ({ v: 20 }, Y),));
/// assert_eq!([X { v: 10 }, X { v: 20 }], first_item!(X, (X { v: 10 }, Y), (X { v: 20 }, Y)));
/// assert_eq!([X { v: 10 }, X { v: 20 }], first_item!(X, (X { v: 10 }, Y), (X { v: 20 }, Y),));
/// assert_eq!([X { v: 10 }, X { v: 20 }, X { v: 30 }],
/// first_item!(X, ({ v: 10 }, Y), ({ v: 20 }, Y), ({v: 30}, Y)));
/// assert_eq!([X { v: 10 }, X { v: 20 }, X { v: 30 }],
/// first_item!(X, ({ v: 10 }, Y), ({ v: 20 }, Y), ({v: 30}, Y),));
/// assert_eq!([X { v: 10 }, X { v: 20 }, X { v: 30 }],
/// first_item!(X, (X { v: 10 }, Y), (X { v: 20 }, Y), (X {v: 30}, Y)));
/// assert_eq!([X { v: 10 }, X { v: 20 }, X { v: 30 }],
/// first_item!(X, (X { v: 10 }, Y), (X { v: 20 }, Y), (X {v: 30}, Y),));
/// ```
#[macro_export]
macro_rules! first_item {
($id_type:ty, $(({$($first:tt)*}, $second:expr)),* $(,)?) => {
{
type IdType = $id_type;
[$(IdType{$($first)*},)*]
}
};
($id_type:ty, $(($first:expr, $second:expr)),* $(,)?) => { [$($first,)*] };
}
/// Converts a comma-separated list of pairs into an array with the second element. That is, it
/// discards the first element of the pair.
///
/// # Examples
///
/// ```
/// # use kernel::second_item;
///
/// assert_eq!([] as [u32; 0], second_item!());
/// assert_eq!([10u32], second_item!((X, 10u32)));
/// assert_eq!([10u32], second_item!((X, 10u32),));
/// assert_eq!([10u32], second_item!(({X}, 10u32)));
/// assert_eq!([10u32], second_item!(({X}, 10u32),));
/// assert_eq!([10u32, 20], second_item!((X, 10u32), (X, 20)));
/// assert_eq!([10u32, 20], second_item!((X, 10u32), (X, 20),));
/// assert_eq!([10u32, 20], second_item!(({X}, 10u32), ({X}, 20)));
/// assert_eq!([10u32, 20], second_item!(({X}, 10u32), ({X}, 20),));
/// assert_eq!([10u32, 20, 30], second_item!((X, 10u32), (X, 20), (X, 30)));
/// assert_eq!([10u32, 20, 30], second_item!((X, 10u32), (X, 20), (X, 30),));
/// assert_eq!([10u32, 20, 30], second_item!(({X}, 10u32), ({X}, 20), ({X}, 30)));
/// assert_eq!([10u32, 20, 30], second_item!(({X}, 10u32), ({X}, 20), ({X}, 30),));
/// ```
#[macro_export]
macro_rules! second_item {
($(({$($first:tt)*}, $second:expr)),* $(,)?) => { [$($second,)*] };
($(($first:expr, $second:expr)),* $(,)?) => { [$($second,)*] };
}
/// Defines a new constant [`IdArray`] with a concise syntax.
///
/// It is meant to be used by buses and subsystems to create a similar macro with their device id
/// type already specified, i.e., with fewer parameters to the end user.
///
/// # Examples
///
// TODO: Exported but not usable by kernel modules (requires `const_trait_impl`).
/// ```ignore
/// #![feature(const_trait_impl)]
/// # use kernel::{define_id_array, driver::RawDeviceId};
///
/// #[derive(Copy, Clone)]
/// struct Id(u32);
///
/// // SAFETY: `ZERO` is all zeroes and `to_rawid` stores `offset` as the second element of the raw
/// // device id pair.
/// unsafe impl const RawDeviceId for Id {
/// type RawType = (u64, isize);
/// const ZERO: Self::RawType = (0, 0);
/// fn to_rawid(&self, offset: isize) -> Self::RawType {
/// (self.0 as u64 + 1, offset)
/// }
/// }
///
/// define_id_array!(A1, Id, (), []);
/// define_id_array!(A2, Id, &'static [u8], [(Id(10), None)]);
/// define_id_array!(A3, Id, &'static [u8], [(Id(10), Some(b"id1")), ]);
/// define_id_array!(A4, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), Some(b"id2"))]);
/// define_id_array!(A5, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), Some(b"id2")), ]);
/// define_id_array!(A6, Id, &'static [u8], [(Id(10), None), (Id(20), Some(b"id2")), ]);
/// define_id_array!(A7, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), None), ]);
/// define_id_array!(A8, Id, &'static [u8], [(Id(10), None), (Id(20), None), ]);
/// ```
#[macro_export]
macro_rules! define_id_array {
($table_name:ident, $id_type:ty, $data_type:ty, [ $($t:tt)* ]) => {
const $table_name:
$crate::driver::IdArray<$id_type, $data_type, { $crate::count_paren_items!($($t)*) }> =
$crate::driver::IdArray::new(
$crate::first_item!($id_type, $($t)*), $crate::second_item!($($t)*));
};
}
/// Defines a new constant [`IdTable`] with a concise syntax.
///
/// It is meant to be used by buses and subsystems to create a similar macro with their device id
/// type already specified, i.e., with fewer parameters to the end user.
///
/// # Examples
///
// TODO: Exported but not usable by kernel modules (requires `const_trait_impl`).
/// ```ignore
/// #![feature(const_trait_impl)]
/// # use kernel::{define_id_table, driver::RawDeviceId};
///
/// #[derive(Copy, Clone)]
/// struct Id(u32);
///
/// // SAFETY: `ZERO` is all zeroes and `to_rawid` stores `offset` as the second element of the raw
/// // device id pair.
/// unsafe impl const RawDeviceId for Id {
/// type RawType = (u64, isize);
/// const ZERO: Self::RawType = (0, 0);
/// fn to_rawid(&self, offset: isize) -> Self::RawType {
/// (self.0 as u64 + 1, offset)
/// }
/// }
///
/// define_id_table!(T1, Id, &'static [u8], [(Id(10), None)]);
/// define_id_table!(T2, Id, &'static [u8], [(Id(10), Some(b"id1")), ]);
/// define_id_table!(T3, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), Some(b"id2"))]);
/// define_id_table!(T4, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), Some(b"id2")), ]);
/// define_id_table!(T5, Id, &'static [u8], [(Id(10), None), (Id(20), Some(b"id2")), ]);
/// define_id_table!(T6, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), None), ]);
/// define_id_table!(T7, Id, &'static [u8], [(Id(10), None), (Id(20), None), ]);
/// ```
#[macro_export]
macro_rules! define_id_table {
($table_name:ident, $id_type:ty, $data_type:ty, [ $($t:tt)* ]) => {
const $table_name: Option<$crate::driver::IdTable<'static, $id_type, $data_type>> = {
$crate::define_id_array!(ARRAY, $id_type, $data_type, [ $($t)* ]);
Some(ARRAY.as_table())
};
};
}
/// Custom code within device removal.
pub trait DeviceRemoval {
/// Cleans resources up when the device is removed.
///
/// This is called when a device is removed and offers implementers the chance to run some code
/// that cleans state up.
fn device_remove(&self);
}
impl DeviceRemoval for () {
fn device_remove(&self) {}
}
impl<T: DeviceRemoval> DeviceRemoval for Ref<T> {
fn device_remove(&self) {
self.deref().device_remove();
}
}
impl<T: DeviceRemoval> DeviceRemoval for Box<T> {
fn device_remove(&self) {
self.deref().device_remove();
}
}
/// A kernel module that only registers the given driver on init.
///
/// This is a helper struct to make it easier to define single-functionality modules, in this case,
/// modules that offer a single driver.
pub struct Module<T: DriverOps> {
_driver: Pin<Box<Registration<T>>>,
}
impl<T: DriverOps> crate::Module for Module<T> {
fn init(name: &'static CStr, module: &'static ThisModule) -> Result<Self> {
Ok(Self {
_driver: Registration::new_pinned(name, module)?,
})
}
}
/// Declares a kernel module that exposes a single driver.
///
/// It is meant to be used as a helper by other subsystems so they can more easily expose their own
/// macros.
#[macro_export]
macro_rules! module_driver {
(<$gen_type:ident>, $driver_ops:ty, { type: $type:ty, $($f:tt)* }) => {
type Ops<$gen_type> = $driver_ops;
type ModuleType = $crate::driver::Module<Ops<$type>>;
$crate::prelude::module! {
type: ModuleType,
$($f)*
}
}
}
// 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 crate::str::CStr;
use crate::{bindings, c_types};
use alloc::{
alloc::{AllocError, LayoutError},
collections::TryReserveError,
};
use core::convert::From;
use core::fmt;
use core::num::TryFromIntError;
use core::str::{self, Utf8Error};
/// Contains the C-compatible error codes.
pub mod code {
macro_rules! declare_err {
($err:tt $(,)? $($doc:expr),+) => {
$(
#[doc = $doc]
)*
pub const $err: super::Error = super::Error(-(crate::bindings::$err as i32));
};
}
declare_err!(EPERM, "Operation not permitted.");
declare_err!(ENOENT, "No such file or directory.");
declare_err!(ESRCH, "No such process.");
declare_err!(EINTR, "Interrupted system call.");
declare_err!(EIO, "I/O error.");
declare_err!(ENXIO, "No such device or address.");
declare_err!(E2BIG, "Argument list too long.");
declare_err!(ENOEXEC, "Exec format error.");
declare_err!(EBADF, "Bad file number.");
declare_err!(ECHILD, "Exec format error.");
declare_err!(EAGAIN, "Try again.");
declare_err!(ENOMEM, "Out of memory.");
declare_err!(EACCES, "Permission denied.");
declare_err!(EFAULT, "Bad address.");
declare_err!(ENOTBLK, "Block device required.");
declare_err!(EBUSY, "Device or resource busy.");
declare_err!(EEXIST, "File exists.");
declare_err!(EXDEV, "Cross-device link.");
declare_err!(ENODEV, "No such device.");
declare_err!(ENOTDIR, "Not a directory.");
declare_err!(EISDIR, "Is a directory.");
declare_err!(EINVAL, "Invalid argument.");
declare_err!(ENFILE, "File table overflow.");
declare_err!(EMFILE, "Too many open files.");
declare_err!(ENOTTY, "Not a typewriter.");
declare_err!(ETXTBSY, "Text file busy.");
declare_err!(EFBIG, "File too large.");
declare_err!(ENOSPC, "No space left on device.");
declare_err!(ESPIPE, "Illegal seek.");
declare_err!(EROFS, "Read-only file system.");
declare_err!(EMLINK, "Too many links.");
declare_err!(EPIPE, "Broken pipe.");
declare_err!(EDOM, "Math argument out of domain of func.");
declare_err!(ERANGE, "Math result not representable.");
declare_err!(EDEADLK, "Resource deadlock would occur");
declare_err!(ENAMETOOLONG, "File name too long");
declare_err!(ENOLCK, "No record locks available");
declare_err!(
ENOSYS,
"Invalid system call number.",
"",
"This error code is special: arch syscall entry code will return",
"[`ENOSYS`] if users try to call a syscall that doesn't exist.",
"To keep failures of syscalls that really do exist distinguishable from",
"failures due to attempts to use a nonexistent syscall, syscall",
"implementations should refrain from returning [`ENOSYS`]."
);
declare_err!(ENOTEMPTY, "Directory not empty.");
declare_err!(ELOOP, "Too many symbolic links encountered.");
declare_err!(EWOULDBLOCK, "Operation would block.");
declare_err!(ENOMSG, "No message of desired type.");
declare_err!(EIDRM, "Identifier removed.");
declare_err!(ECHRNG, "Channel number out of range.");
declare_err!(EL2NSYNC, "Level 2 not synchronized.");
declare_err!(EL3HLT, "Level 3 halted.");
declare_err!(EL3RST, "Level 3 reset.");
declare_err!(ELNRNG, "Link number out of range.");
declare_err!(EUNATCH, "Protocol driver not attached.");
declare_err!(ENOCSI, "No CSI structure available.");
declare_err!(EL2HLT, "Level 2 halted.");
declare_err!(EBADE, "Invalid exchange.");
declare_err!(EBADR, "Invalid request descriptor.");
declare_err!(EXFULL, "Exchange full.");
declare_err!(ENOANO, "No anode.");
declare_err!(EBADRQC, "Invalid request code.");
declare_err!(EBADSLT, "Invalid slot.");
declare_err!(EDEADLOCK, "Resource deadlock would occur.");
declare_err!(EBFONT, "Bad font file format.");
declare_err!(ENOSTR, "Device not a stream.");
declare_err!(ENODATA, "No data available.");
declare_err!(ETIME, "Timer expired.");
declare_err!(ENOSR, "Out of streams resources.");
declare_err!(ENONET, "Machine is not on the network.");
declare_err!(ENOPKG, "Package not installed.");
declare_err!(EREMOTE, "Object is remote.");
declare_err!(ENOLINK, "Link has been severed.");
declare_err!(EADV, "Advertise error.");
declare_err!(ESRMNT, "Srmount error.");
declare_err!(ECOMM, "Communication error on send.");
declare_err!(EPROTO, "Protocol error.");
declare_err!(EMULTIHOP, "Multihop attempted.");
declare_err!(EDOTDOT, "RFS specific error.");
declare_err!(EBADMSG, "Not a data message.");
declare_err!(EOVERFLOW, "Value too large for defined data type.");
declare_err!(ENOTUNIQ, "Name not unique on network.");
declare_err!(EBADFD, "File descriptor in bad state.");
declare_err!(EREMCHG, "Remote address changed.");
declare_err!(ELIBACC, "Can not access a needed shared library.");
declare_err!(ELIBBAD, "Accessing a corrupted shared library.");
declare_err!(ELIBSCN, ".lib section in a.out corrupted.");
declare_err!(ELIBMAX, "Attempting to link in too many shared libraries.");
declare_err!(ELIBEXEC, "Cannot exec a shared library directly.");
declare_err!(EILSEQ, "Illegal byte sequence.");
declare_err!(ERESTART, "Interrupted system call should be restarted.");
declare_err!(ESTRPIPE, "Streams pipe error.");
declare_err!(EUSERS, "Too many users.");
declare_err!(ENOTSOCK, "Socket operation on non-socket.");
declare_err!(EDESTADDRREQ, "Destination address required.");
declare_err!(EMSGSIZE, "Message too long.");
declare_err!(EPROTOTYPE, "Protocol wrong type for socket.");
declare_err!(ENOPROTOOPT, "Protocol not available.");
declare_err!(EPROTONOSUPPORT, "Protocol not supported.");
declare_err!(ESOCKTNOSUPPORT, "Socket type not supported.");
declare_err!(EOPNOTSUPP, "Operation not supported on transport endpoint.");
declare_err!(EPFNOSUPPORT, "Protocol family not supported.");
declare_err!(EAFNOSUPPORT, "Address family not supported by protocol.");
declare_err!(EADDRINUSE, "Address already in use.");
declare_err!(EADDRNOTAVAIL, "Cannot assign requested address.");
declare_err!(ENETDOWN, "Network is down.");
declare_err!(ENETUNREACH, "Network is unreachable.");
declare_err!(ENETRESET, "Network dropped connection because of reset.");
declare_err!(ECONNABORTED, "Software caused connection abort.");
declare_err!(ECONNRESET, "Connection reset by peer.");
declare_err!(ENOBUFS, "No buffer space available.");
declare_err!(EISCONN, "Transport endpoint is already connected.");
declare_err!(ENOTCONN, "Transport endpoint is not connected.");
declare_err!(ESHUTDOWN, "Cannot send after transport endpoint shutdown.");
declare_err!(ETOOMANYREFS, "Too many references: cannot splice.");
declare_err!(ETIMEDOUT, "Connection timed out.");
declare_err!(ECONNREFUSED, "Connection refused.");
declare_err!(EHOSTDOWN, "Host is down.");
declare_err!(EHOSTUNREACH, "No route to host.");
declare_err!(EALREADY, "Operation already in progress.");
declare_err!(EINPROGRESS, "Operation now in progress.");
declare_err!(ESTALE, "Stale file handle.");
declare_err!(EUCLEAN, "Structure needs cleaning.");
declare_err!(ENOTNAM, "Not a XENIX named type file.");
declare_err!(ENAVAIL, "No XENIX semaphores available.");
declare_err!(EISNAM, "Is a named type file.");
declare_err!(EREMOTEIO, "Remote I/O error.");
declare_err!(EDQUOT, "Quota exceeded.");
declare_err!(ENOMEDIUM, "No medium found.");
declare_err!(EMEDIUMTYPE, "Wrong medium type.");
declare_err!(ECANCELED, "Operation Canceled.");
declare_err!(ENOKEY, "Required key not available.");
declare_err!(EKEYEXPIRED, "Key has expired.");
declare_err!(EKEYREVOKED, "Key has been revoked.");
declare_err!(EKEYREJECTED, "Key was rejected by service.");
declare_err!(EOWNERDEAD, "Owner died.", "", "For robust mutexes.");
declare_err!(ENOTRECOVERABLE, "State not recoverable.");
declare_err!(ERFKILL, "Operation not possible due to RF-kill.");
declare_err!(EHWPOISON, "Memory page has hardware error.");
declare_err!(ERESTARTSYS, "Restart the system call.");
declare_err!(ENOTSUPP, "Operation is not supported.");
}
/// 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(c_types::c_int);
impl Error {
/// Creates an [`Error`] from a kernel error code.
///
/// It is a bug to pass an out-of-range `errno`. `EINVAL` would
/// be returned in such a case.
pub(crate) fn from_kernel_errno(errno: c_types::c_int) -> Error {
if errno < -(bindings::MAX_ERRNO as i32) || errno >= 0 {
// TODO: Make it a `WARN_ONCE` once available.
crate::pr_warn!(
"attempted to create `Error` with out of range `errno`: {}",
errno
);
return code::EINVAL;
}
// INVARIANT: The check above ensures the type invariant
// will hold.
Error(errno)
}
/// Creates an [`Error`] from a kernel error code.
///
/// # Safety
///
/// `errno` must be within error code range (i.e. `>= -MAX_ERRNO && < 0`).
pub(crate) unsafe fn from_kernel_errno_unchecked(errno: c_types::c_int) -> Error {
// INVARIANT: The contract ensures the type invariant
// will hold.
Error(errno)
}
/// Returns the kernel error code.
pub fn to_kernel_errno(self) -> c_types::c_int {
self.0
}
/// Returns a string representing the error, if one exists.
#[cfg(not(testlib))]
pub fn name(&self) -> Option<&'static CStr> {
// SAFETY: Just an FFI call, there are no extra safety requirements.
let ptr = unsafe { bindings::errname(-self.0) };
if ptr.is_null() {
None
} else {
// SAFETY: The string returned by `errname` is static and `NUL`-terminated.
Some(unsafe { CStr::from_char_ptr(ptr) })
}
}
/// Returns a string representing the error, if one exists.
///
/// When `testlib` is configured, this always returns `None` to avoid the dependency on a
/// kernel function so that tests that use this (e.g., by calling [`Result::unwrap`]) can still
/// run in userspace.
#[cfg(testlib)]
pub fn name(&self) -> Option<&'static CStr> {
None
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.name() {
// Print out number if no name can be found.
None => f.debug_tuple("Error").field(&-self.0).finish(),
// SAFETY: These strings are ASCII-only.
Some(name) => f
.debug_tuple(unsafe { str::from_utf8_unchecked(name) })
.finish(),
}
}
}
impl From<TryFromIntError> for Error {
fn from(_: TryFromIntError) -> Error {
code::EINVAL
}
}
impl From<Utf8Error> for Error {
fn from(_: Utf8Error) -> Error {
code::EINVAL
}
}
impl From<TryReserveError> for Error {
fn from(_: TryReserveError) -> Error {
code::ENOMEM
}
}
impl From<LayoutError> for Error {
fn from(_: LayoutError) -> Error {
code::ENOMEM
}
}
impl From<core::fmt::Error> for Error {
fn from(_: core::fmt::Error) -> Error {
code::EINVAL
}
}
impl From<core::convert::Infallible> for Error {
fn from(e: core::convert::Infallible) -> Error {
match e {}
}
}
/// 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>;
impl From<AllocError> for Error {
fn from(_: AllocError) -> Error {
code::ENOMEM
}
}
// # Invariant: `-bindings::MAX_ERRNO` fits in an `i16`.
crate::static_assert!(bindings::MAX_ERRNO <= -(i16::MIN as i32) as u32);
pub(crate) fn from_kernel_result_helper<T>(r: Result<T>) -> T
where
T: From<i16>,
{
match r {
Ok(v) => v,
// NO-OVERFLOW: negative `errno`s are no smaller than `-bindings::MAX_ERRNO`,
// `-bindings::MAX_ERRNO` fits in an `i16` as per invariant above,
// therefore a negative `errno` always fits in an `i16` and will not overflow.
Err(e) => T::from(e.to_kernel_errno() as i16),
}
}
/// Transforms a [`crate::error::Result<T>`] to a kernel C integer result.
///
/// This is useful when calling Rust functions that return [`crate::error::Result<T>`]
/// from inside `extern "C"` functions that need to return an integer
/// error result.
///
/// `T` should be convertible to an `i16` via `From<i16>`.
///
/// # Examples
///
/// ```ignore
/// # use kernel::from_kernel_result;
/// # use kernel::c_types;
/// # use kernel::bindings;
/// unsafe extern "C" fn probe_callback(
/// pdev: *mut bindings::platform_device,
/// ) -> c_types::c_int {
/// from_kernel_result! {
/// let ptr = devm_alloc(pdev)?;
/// bindings::platform_set_drvdata(pdev, ptr);
/// Ok(0)
/// }
/// }
/// ```
macro_rules! from_kernel_result {
($($tt:tt)*) => {{
$crate::error::from_kernel_result_helper((|| {
$($tt)*
})())
}};
}
pub(crate) use from_kernel_result;
/// Transform a kernel "error pointer" to a normal pointer.
///
/// Some kernel C API functions return an "error pointer" which optionally
/// embeds an `errno`. Callers are supposed to check the returned pointer
/// for errors. This function performs the check and converts the "error pointer"
/// to a normal pointer in an idiomatic fashion.
///
/// # Examples
///
/// ```ignore
/// # use kernel::from_kernel_err_ptr;
/// # use kernel::c_types;
/// # use kernel::bindings;
/// fn devm_platform_ioremap_resource(
/// pdev: &mut PlatformDevice,
/// index: u32,
/// ) -> Result<*mut c_types::c_void> {
/// // SAFETY: FFI call.
/// unsafe {
/// from_kernel_err_ptr(bindings::devm_platform_ioremap_resource(
/// pdev.to_ptr(),
/// index,
/// ))
/// }
/// }
/// ```
// TODO: Remove `dead_code` marker once an in-kernel client is available.
#[allow(dead_code)]
pub(crate) fn from_kernel_err_ptr<T>(ptr: *mut T) -> Result<*mut T> {
// CAST: Casting a pointer to `*const c_types::c_void` is always valid.
let const_ptr: *const c_types::c_void = ptr.cast();
// SAFETY: The FFI function does not deref the pointer.
if unsafe { bindings::IS_ERR(const_ptr) } {
// SAFETY: The FFI function does not deref the pointer.
let err = unsafe { bindings::PTR_ERR(const_ptr) };
// CAST: If `IS_ERR()` returns `true`,
// then `PTR_ERR()` is guaranteed to return a
// negative value greater-or-equal to `-bindings::MAX_ERRNO`,
// which always fits in an `i16`, as per the invariant above.
// And an `i16` always fits in an `i32`. So casting `err` to
// an `i32` can never overflow, and is always valid.
//
// SAFETY: `IS_ERR()` ensures `err` is a
// negative value greater-or-equal to `-bindings::MAX_ERRNO`.
return Err(unsafe { Error::from_kernel_errno_unchecked(err as i32) });
}
Ok(ptr)
}
/// Calls a kernel function that returns an integer error code on failure and converts the result
/// to a [`Result`].
pub fn to_result(func: impl FnOnce() -> c_types::c_int) -> Result {
let err = func();
if err < 0 {
Err(Error::from_kernel_errno(err))
} else {
Ok(())
}
}
此差异已折叠。
// SPDX-License-Identifier: GPL-2.0
//! Support for gpio device drivers.
//!
//! C header: [`include/linux/gpio/driver.h`](../../../../include/linux/gpio/driver.h)
use crate::{
bindings, c_types, device, error::code::*, error::from_kernel_result, types::PointerWrapper,
Error, Result,
};
use core::{
cell::UnsafeCell,
marker::{PhantomData, PhantomPinned},
pin::Pin,
};
#[cfg(CONFIG_GPIOLIB_IRQCHIP)]
pub use irqchip::{ChipWithIrqChip, RegistrationWithIrqChip};
/// The direction of a gpio line.
pub enum LineDirection {
/// Direction is input.
In = bindings::GPIO_LINE_DIRECTION_IN as _,
/// Direction is output.
Out = bindings::GPIO_LINE_DIRECTION_OUT as _,
}
/// A gpio chip.
pub trait Chip {
/// Context data associated with the gpio chip.
///
/// It determines the type of the context data passed to each of the methods of the trait.
type Data: PointerWrapper + Sync + Send;
/// The methods to use to populate [`struct gpio_chip`]. This is typically populated with
/// [`declare_gpio_chip_operations`].
const TO_USE: ToUse;
/// Returns the direction of the given gpio line.
fn get_direction(
_data: <Self::Data as PointerWrapper>::Borrowed<'_>,
_offset: u32,
) -> Result<LineDirection> {
Err(ENOTSUPP)
}
/// Configures the direction as input of the given gpio line.
fn direction_input(
_data: <Self::Data as PointerWrapper>::Borrowed<'_>,
_offset: u32,
) -> Result {
Err(EIO)
}
/// Configures the direction as output of the given gpio line.
///
/// The value that will be initially output is also specified.
fn direction_output(
_data: <Self::Data as PointerWrapper>::Borrowed<'_>,
_offset: u32,
_value: bool,
) -> Result {
Err(ENOTSUPP)
}
/// Returns the current value of the given gpio line.
fn get(_data: <Self::Data as PointerWrapper>::Borrowed<'_>, _offset: u32) -> Result<bool> {
Err(EIO)
}
/// Sets the value of the given gpio line.
fn set(_data: <Self::Data as PointerWrapper>::Borrowed<'_>, _offset: u32, _value: bool) {}
}
/// Represents which fields of [`struct gpio_chip`] should be populated with pointers.
///
/// This is typically populated with the [`declare_gpio_chip_operations`] macro.
pub struct ToUse {
/// The `get_direction` field of [`struct gpio_chip`].
pub get_direction: bool,
/// The `direction_input` field of [`struct gpio_chip`].
pub direction_input: bool,
/// The `direction_output` field of [`struct gpio_chip`].
pub direction_output: bool,
/// The `get` field of [`struct gpio_chip`].
pub get: bool,
/// The `set` field of [`struct gpio_chip`].
pub set: bool,
}
/// A constant version where all values are set to `false`, that is, all supported fields will be
/// set to null pointers.
pub const USE_NONE: ToUse = ToUse {
get_direction: false,
direction_input: false,
direction_output: false,
get: false,
set: false,
};
/// Defines the [`Chip::TO_USE`] field based on a list of fields to be populated.
#[macro_export]
macro_rules! declare_gpio_chip_operations {
() => {
const TO_USE: $crate::gpio::ToUse = $crate::gpio::USE_NONE;
};
($($i:ident),+) => {
#[allow(clippy::needless_update)]
const TO_USE: $crate::gpio::ToUse =
$crate::gpio::ToUse {
$($i: true),+ ,
..$crate::gpio::USE_NONE
};
};
}
/// A registration of a gpio chip.
pub struct Registration<T: Chip> {
gc: UnsafeCell<bindings::gpio_chip>,
parent: Option<device::Device>,
_p: PhantomData<T>,
_pin: PhantomPinned,
}
impl<T: Chip> Registration<T> {
/// Creates a new [`Registration`] but does not register it yet.
///
/// It is allowed to move.
pub fn new() -> Self {
Self {
parent: None,
gc: UnsafeCell::new(bindings::gpio_chip::default()),
_pin: PhantomPinned,
_p: PhantomData,
}
}
/// Registers a gpio chip with the rest of the kernel.
pub fn register(
self: Pin<&mut Self>,
gpio_count: u16,
base: Option<i32>,
parent: &dyn device::RawDevice,
data: T::Data,
) -> Result {
if self.parent.is_some() {
// Already registered.
return Err(EINVAL);
}
// SAFETY: We never move out of `this`.
let this = unsafe { self.get_unchecked_mut() };
{
let gc = this.gc.get_mut();
// Set up the callbacks.
gc.request = Some(bindings::gpiochip_generic_request);
gc.free = Some(bindings::gpiochip_generic_free);
if T::TO_USE.get_direction {
gc.get_direction = Some(get_direction_callback::<T>);
}
if T::TO_USE.direction_input {
gc.direction_input = Some(direction_input_callback::<T>);
}
if T::TO_USE.direction_output {
gc.direction_output = Some(direction_output_callback::<T>);
}
if T::TO_USE.get {
gc.get = Some(get_callback::<T>);
}
if T::TO_USE.set {
gc.set = Some(set_callback::<T>);
}
// When a base is not explicitly given, use -1 for one to be picked.
if let Some(b) = base {
gc.base = b;
} else {
gc.base = -1;
}
gc.ngpio = gpio_count;
gc.parent = parent.raw_device();
gc.label = parent.name().as_char_ptr();
// TODO: Define `gc.owner` as well.
}
let data_pointer = <T::Data as PointerWrapper>::into_pointer(data);
// SAFETY: `gc` was initilised above, so it is valid.
let ret = unsafe {
bindings::gpiochip_add_data_with_key(
this.gc.get(),
data_pointer as _,
core::ptr::null_mut(),
core::ptr::null_mut(),
)
};
if ret < 0 {
// SAFETY: `data_pointer` was returned by `into_pointer` above.
unsafe { T::Data::from_pointer(data_pointer) };
return Err(Error::from_kernel_errno(ret));
}
this.parent = Some(device::Device::from_dev(parent));
Ok(())
}
}
// SAFETY: `Registration` doesn't offer any methods or access to fields when shared between threads
// or CPUs, so it is safe to share it.
unsafe impl<T: Chip> Sync for Registration<T> {}
// SAFETY: Registration with and unregistration from the gpio subsystem can happen from any thread.
// Additionally, `T::Data` (which is dropped during unregistration) is `Send`, so it is ok to move
// `Registration` to different threads.
#[allow(clippy::non_send_fields_in_send_ty)]
unsafe impl<T: Chip> Send for Registration<T> {}
impl<T: Chip> Default for Registration<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Chip> Drop for Registration<T> {
/// Removes the registration from the kernel if it has completed successfully before.
fn drop(&mut self) {
if self.parent.is_some() {
// Get a pointer to the data stored in chip before destroying it.
// SAFETY: `gc` was during registration, which is guaranteed to have succeeded (because
// `parent` is `Some(_)`, so it remains valid.
let data_pointer = unsafe { bindings::gpiochip_get_data(self.gc.get()) };
// SAFETY: By the same argument above, `gc` is still valid.
unsafe { bindings::gpiochip_remove(self.gc.get()) };
// Free data as well.
// SAFETY: `data_pointer` was returned by `into_pointer` during registration.
unsafe { <T::Data as PointerWrapper>::from_pointer(data_pointer) };
}
}
}
unsafe extern "C" fn get_direction_callback<T: Chip>(
gc: *mut bindings::gpio_chip,
offset: c_types::c_uint,
) -> c_types::c_int {
from_kernel_result! {
// SAFETY: The value stored as chip data was returned by `into_pointer` during registration.
let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc)) };
Ok(T::get_direction(data, offset)? as i32)
}
}
unsafe extern "C" fn direction_input_callback<T: Chip>(
gc: *mut bindings::gpio_chip,
offset: c_types::c_uint,
) -> c_types::c_int {
from_kernel_result! {
// SAFETY: The value stored as chip data was returned by `into_pointer` during registration.
let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc)) };
T::direction_input(data, offset)?;
Ok(0)
}
}
unsafe extern "C" fn direction_output_callback<T: Chip>(
gc: *mut bindings::gpio_chip,
offset: c_types::c_uint,
value: c_types::c_int,
) -> c_types::c_int {
from_kernel_result! {
// SAFETY: The value stored as chip data was returned by `into_pointer` during registration.
let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc)) };
T::direction_output(data, offset, value != 0)?;
Ok(0)
}
}
unsafe extern "C" fn get_callback<T: Chip>(
gc: *mut bindings::gpio_chip,
offset: c_types::c_uint,
) -> c_types::c_int {
from_kernel_result! {
// SAFETY: The value stored as chip data was returned by `into_pointer` during registration.
let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc)) };
let v = T::get(data, offset)?;
Ok(v as _)
}
}
unsafe extern "C" fn set_callback<T: Chip>(
gc: *mut bindings::gpio_chip,
offset: c_types::c_uint,
value: c_types::c_int,
) {
// SAFETY: The value stored as chip data was returned by `into_pointer` during registration.
let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc)) };
T::set(data, offset, value != 0);
}
#[cfg(CONFIG_GPIOLIB_IRQCHIP)]
mod irqchip {
use super::*;
use crate::irq;
/// A gpio chip that includes an irq chip.
pub trait ChipWithIrqChip: Chip {
/// Implements the irq flow for the gpio chip.
fn handle_irq_flow(
_data: <Self::Data as PointerWrapper>::Borrowed<'_>,
_desc: &irq::Descriptor,
_domain: &irq::Domain,
);
}
/// A registration of a gpio chip that includes an irq chip.
pub struct RegistrationWithIrqChip<T: ChipWithIrqChip> {
reg: Registration<T>,
irq_chip: UnsafeCell<bindings::irq_chip>,
parent_irq: u32,
}
impl<T: ChipWithIrqChip> RegistrationWithIrqChip<T> {
/// Creates a new [`RegistrationWithIrqChip`] but does not register it yet.
///
/// It is allowed to move.
pub fn new() -> Self {
Self {
reg: Registration::new(),
irq_chip: UnsafeCell::new(bindings::irq_chip::default()),
parent_irq: 0,
}
}
/// Registers a gpio chip and its irq chip with the rest of the kernel.
pub fn register<U: irq::Chip<Data = T::Data>>(
mut self: Pin<&mut Self>,
gpio_count: u16,
base: Option<i32>,
parent: &dyn device::RawDevice,
data: T::Data,
parent_irq: u32,
) -> Result {
if self.reg.parent.is_some() {
// Already registered.
return Err(EINVAL);
}
// SAFETY: We never move out of `this`.
let this = unsafe { self.as_mut().get_unchecked_mut() };
// Initialise the irq_chip.
{
let irq_chip = this.irq_chip.get_mut();
irq_chip.name = parent.name().as_char_ptr();
// SAFETY: The gpio subsystem configures a pointer to `gpio_chip` as the irq chip
// data, so we use `IrqChipAdapter` to convert to the `T::Data`, which is the same
// as `irq::Chip::Data` per the bound above.
unsafe { irq::init_chip::<IrqChipAdapter<U>>(irq_chip) };
}
// Initialise gc irq state.
{
let girq = &mut this.reg.gc.get_mut().irq;
girq.chip = this.irq_chip.get();
// SAFETY: By leaving `parent_handler_data` set to `null`, the gpio subsystem
// initialises it to a pointer to the gpio chip, which is what `FlowHandler<T>`
// expects.
girq.parent_handler = unsafe { irq::new_flow_handler::<FlowHandler<T>>() };
girq.num_parents = 1;
girq.parents = &mut this.parent_irq;
this.parent_irq = parent_irq;
girq.default_type = bindings::IRQ_TYPE_NONE;
girq.handler = Some(bindings::handle_bad_irq);
}
// SAFETY: `reg` is pinned when `self` is.
let pinned = unsafe { self.map_unchecked_mut(|r| &mut r.reg) };
pinned.register(gpio_count, base, parent, data)
}
}
impl<T: ChipWithIrqChip> Default for RegistrationWithIrqChip<T> {
fn default() -> Self {
Self::new()
}
}
// SAFETY: `RegistrationWithIrqChip` doesn't offer any methods or access to fields when shared
// between threads or CPUs, so it is safe to share it.
unsafe impl<T: ChipWithIrqChip> Sync for RegistrationWithIrqChip<T> {}
// SAFETY: Registration with and unregistration from the gpio subsystem (including irq chips for
// them) can happen from any thread. Additionally, `T::Data` (which is dropped during
// unregistration) is `Send`, so it is ok to move `Registration` to different threads.
#[allow(clippy::non_send_fields_in_send_ty)]
unsafe impl<T: ChipWithIrqChip> Send for RegistrationWithIrqChip<T> where T::Data: Send {}
struct FlowHandler<T: ChipWithIrqChip>(PhantomData<T>);
impl<T: ChipWithIrqChip> irq::FlowHandler for FlowHandler<T> {
type Data = *mut bindings::gpio_chip;
fn handle_irq_flow(gc: *mut bindings::gpio_chip, desc: &irq::Descriptor) {
// SAFETY: `FlowHandler` is only used in gpio chips, and it is removed when the gpio is
// unregistered, so we know that `gc` must still be valid. We also know that the value
// stored as gpio data was returned by `T::Data::into_pointer` again because
// `FlowHandler` is a private structure only used in this way.
let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc)) };
// SAFETY: `gc` is valid (see comment above), so we can dereference it.
let domain = unsafe { irq::Domain::from_ptr((*gc).irq.domain) };
T::handle_irq_flow(data, desc, &domain);
}
}
/// Adapter from an irq chip with `gpio_chip` pointer as context to one where the gpio chip
/// data is passed as context.
struct IrqChipAdapter<T: irq::Chip>(PhantomData<T>);
impl<T: irq::Chip> irq::Chip for IrqChipAdapter<T> {
type Data = *mut bindings::gpio_chip;
const TO_USE: irq::ToUse = T::TO_USE;
fn ack(gc: *mut bindings::gpio_chip, irq_data: &irq::IrqData) {
// SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the
// gpio chip is known to come from `T::Data`, and only valid while the gpio chip is
// registered, so `gc` is valid.
let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc as _)) };
T::ack(data, irq_data);
}
fn mask(gc: *mut bindings::gpio_chip, irq_data: &irq::IrqData) {
// SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the
// gpio chip is known to come from `T::Data`, and only valid while the gpio chip is
// registered, so `gc` is valid.
let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc as _)) };
T::mask(data, irq_data);
}
fn unmask(gc: *mut bindings::gpio_chip, irq_data: &irq::IrqData) {
// SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the
// gpio chip is known to come from `T::Data`, and only valid while the gpio chip is
// registered, so `gc` is valid.
let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc as _)) };
T::unmask(data, irq_data);
}
fn set_type(
gc: *mut bindings::gpio_chip,
irq_data: &mut irq::LockedIrqData,
flow_type: u32,
) -> Result<irq::ExtraResult> {
// SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the
// gpio chip is known to come from `T::Data`, and only valid while the gpio chip is
// registered, so `gc` is valid.
let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc as _)) };
T::set_type(data, irq_data, flow_type)
}
fn set_wake(gc: *mut bindings::gpio_chip, irq_data: &irq::IrqData, on: bool) -> Result {
// SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the
// gpio chip is known to come from `T::Data`, and only valid while the gpio chip is
// registered, so `gc` is valid.
let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc as _)) };
T::set_wake(data, irq_data, on)
}
}
}
// SPDX-License-Identifier: GPL-2.0
//! Hardware Random Number Generator.
//!
//! C header: [`include/linux/hw_random.h`](../../../../include/linux/hw_random.h)
use alloc::{boxed::Box, slice::from_raw_parts_mut};
use crate::{
bindings, c_types, error::code::*, error::from_kernel_result, str::CString, to_result,
types::PointerWrapper, Result, ScopeGuard,
};
use core::{cell::UnsafeCell, fmt, marker::PhantomData, pin::Pin};
/// This trait is implemented in order to provide callbacks to `struct hwrng`.
pub trait Operations {
/// The methods to use to populate [`struct hwrng`].
const TO_USE: ToUse;
/// The pointer type that will be used to hold user-defined data type.
type Data: PointerWrapper + Send + Sync = ();
/// Initialization callback, can be left undefined.
fn init(_data: <Self::Data as PointerWrapper>::Borrowed<'_>) -> Result {
Err(EINVAL)
}
/// Cleanup callback, can be left undefined.
fn cleanup(_data: Self::Data) {}
/// Read data into the provided buffer.
/// Drivers can fill up to max bytes of data into the buffer.
/// The buffer is aligned for any type and its size is a multiple of 4 and >= 32 bytes.
fn read(
data: <Self::Data as PointerWrapper>::Borrowed<'_>,
buffer: &mut [u8],
wait: bool,
) -> Result<u32>;
}
/// Registration structure for Hardware Random Number Generator driver.
pub struct Registration<T: Operations> {
hwrng: UnsafeCell<bindings::hwrng>,
name: Option<CString>,
registered: bool,
_p: PhantomData<T>,
}
impl<T: Operations> Registration<T> {
/// Creates new instance of registration.
///
/// The data must be registered.
pub fn new() -> Self {
Self {
hwrng: UnsafeCell::new(bindings::hwrng::default()),
name: None,
registered: false,
_p: PhantomData,
}
}
/// Returns a registered and pinned, heap-allocated representation of the registration.
pub fn new_pinned(
name: fmt::Arguments<'_>,
quality: u16,
data: T::Data,
) -> Result<Pin<Box<Self>>> {
let mut reg = Pin::from(Box::try_new(Self::new())?);
reg.as_mut().register(name, quality, data)?;
Ok(reg)
}
/// Registers a hwrng device within the rest of the kernel.
///
/// It must be pinned because the memory block that represents
/// the registration may be self-referential.
pub fn register(
self: Pin<&mut Self>,
name: fmt::Arguments<'_>,
quality: u16,
data: T::Data,
) -> Result {
// SAFETY: We never move out of `this`.
let this = unsafe { self.get_unchecked_mut() };
if this.registered {
return Err(EINVAL);
}
let data_pointer = data.into_pointer();
// SAFETY: `data_pointer` comes from the call to `data.into_pointer()` above.
let guard = ScopeGuard::new(|| unsafe {
T::Data::from_pointer(data_pointer);
});
let name = CString::try_from_fmt(name)?;
// SAFETY: Registration is pinned and contains allocated and set to zero `bindings::hwrng` structure.
Self::init_hwrng(
unsafe { &mut *this.hwrng.get() },
&name,
quality,
data_pointer,
);
// SAFETY: `bindings::hwrng` is initialized above which guarantees safety.
to_result(|| unsafe { bindings::hwrng_register(this.hwrng.get()) })?;
this.registered = true;
this.name = Some(name);
guard.dismiss();
Ok(())
}
fn init_hwrng(
hwrng: &mut bindings::hwrng,
name: &CString,
quality: u16,
data: *const c_types::c_void,
) {
hwrng.name = name.as_char_ptr();
hwrng.init = if T::TO_USE.init {
Some(Self::init_callback)
} else {
None
};
hwrng.cleanup = if T::TO_USE.cleanup {
Some(Self::cleanup_callback)
} else {
None
};
hwrng.data_present = None;
hwrng.data_read = None;
hwrng.read = Some(Self::read_callback);
hwrng.priv_ = data as _;
hwrng.quality = quality;
// SAFETY: All fields are properly initialized as
// remaining fields `list`, `ref` and `cleanup_done` are already
// zeroed by `bindings::hwrng::default()` call.
}
unsafe extern "C" fn init_callback(rng: *mut bindings::hwrng) -> c_types::c_int {
from_kernel_result! {
// SAFETY: `priv` private data field was initialized during creation of
// the `bindings::hwrng` in `Self::init_hwrng` method. This callback is only
// called once the driver is registered.
let data = unsafe { T::Data::borrow((*rng).priv_ as *const _) };
T::init(data)?;
Ok(0)
}
}
unsafe extern "C" fn cleanup_callback(rng: *mut bindings::hwrng) {
// SAFETY: `priv` private data field was initialized during creation of
// the `bindings::hwrng` in `Self::init_hwrng` method. This callback is only
// called once the driver is registered.
let data = unsafe { T::Data::from_pointer((*rng).priv_ as *const _) };
T::cleanup(data);
}
unsafe extern "C" fn read_callback(
rng: *mut bindings::hwrng,
data: *mut c_types::c_void,
max: usize,
wait: bindings::bool_,
) -> c_types::c_int {
from_kernel_result! {
// SAFETY: `priv` private data field was initialized during creation of
// the `bindings::hwrng` in `Self::init_hwrng` method. This callback is only
// called once the driver is registered.
let drv_data = unsafe { T::Data::borrow((*rng).priv_ as *const _) };
// SAFETY: Slice is created from `data` and `max` arguments that are C's buffer
// along with its size in bytes that are safe for this conversion.
let buffer = unsafe { from_raw_parts_mut(data as *mut u8, max) };
let ret = T::read(drv_data, buffer, wait)?;
Ok(ret as _)
}
}
}
impl<T: Operations> Default for Registration<T> {
fn default() -> Self {
Self::new()
}
}
/// Represents which callbacks of [`struct hwrng`] should be populated with pointers.
pub struct ToUse {
/// The `init` field of [`struct hwrng`].
pub init: bool,
/// The `cleanup` field of [`struct hwrng`].
pub cleanup: bool,
}
/// A constant version where all values are to set to `false`, that is, all supported fields will
/// be set to null pointers.
pub const USE_NONE: ToUse = ToUse {
init: false,
cleanup: false,
};
/// Defines the [`Operations::TO_USE`] field based on a list of fields to be populated.
#[macro_export]
macro_rules! declare_hwrng_operations {
() => {
const TO_USE: $crate::hwrng::ToUse = $crate::hwrng::USE_NONE;
};
($($i:ident),+) => {
#[allow(clippy::needless_update)]
const TO_USE: kernel::hwrng::ToUse =
$crate::hwrng::ToUse {
$($i: true),+ ,
..$crate::hwrng::USE_NONE
};
};
}
// SAFETY: `Registration` does not expose any of its state across threads.
unsafe impl<T: Operations> Sync for Registration<T> {}
// SAFETY: `Registration` is not restricted to a single thread,
// its `T::Data` is also `Send` so it may be moved to different threads.
#[allow(clippy::non_send_fields_in_send_ty)]
unsafe impl<T: Operations> Send for Registration<T> {}
impl<T: Operations> Drop for Registration<T> {
/// Removes the registration from the kernel if it has completed successfully before.
fn drop(&mut self) {
// SAFETY: The instance of Registration<T> is unregistered only
// after being initialized and registered before.
if self.registered {
unsafe { bindings::hwrng_unregister(self.hwrng.get()) };
}
}
}
// SPDX-License-Identifier: GPL-2.0
//! Buffers used in IO.
use crate::Result;
use alloc::vec::Vec;
use core::mem::{size_of, MaybeUninit};
/// Represents a buffer to be read from during IO.
pub trait IoBufferReader {
/// Returns the number of bytes left to be read from the io buffer.
///
/// Note that even reading less than this number of bytes may fail.
fn len(&self) -> usize;
/// Returns `true` if no data is available in the io buffer.
fn is_empty(&self) -> bool {
self.len() == 0
}
/// Reads raw data from the io buffer into a raw kernel buffer.
///
/// # Safety
///
/// The output buffer must be valid.
unsafe fn read_raw(&mut self, out: *mut u8, len: usize) -> Result;
/// Reads all data remaining in the io buffer.
///
/// Returns `EFAULT` if the address does not currently point to mapped, readable memory.
fn read_all(&mut self) -> Result<Vec<u8>> {
let mut data = Vec::<u8>::new();
data.try_resize(self.len(), 0)?;
// SAFETY: The output buffer is valid as we just allocated it.
unsafe { self.read_raw(data.as_mut_ptr(), data.len())? };
Ok(data)
}
/// Reads a byte slice from the io buffer.
///
/// Returns `EFAULT` if the byte slice is bigger than the remaining size of the user slice or
/// if the address does not currently point to mapped, readable memory.
fn read_slice(&mut self, data: &mut [u8]) -> Result {
// SAFETY: The output buffer is valid as it's coming from a live reference.
unsafe { self.read_raw(data.as_mut_ptr(), data.len()) }
}
/// Reads the contents of a plain old data (POD) type from the io buffer.
fn read<T: ReadableFromBytes>(&mut self) -> Result<T> {
let mut out = MaybeUninit::<T>::uninit();
// SAFETY: The buffer is valid as it was just allocated.
unsafe { self.read_raw(out.as_mut_ptr() as _, size_of::<T>()) }?;
// SAFETY: We just initialised the data.
Ok(unsafe { out.assume_init() })
}
}
/// Represents a buffer to be written to during IO.
pub trait IoBufferWriter {
/// Returns the number of bytes left to be written into the io buffer.
///
/// Note that even writing less than this number of bytes may fail.
fn len(&self) -> usize;
/// Returns `true` if the io buffer cannot hold any additional data.
fn is_empty(&self) -> bool {
self.len() == 0
}
/// Writes zeroes to the io buffer.
///
/// Differently from the other write functions, `clear` will zero as much as it can and update
/// the writer internal state to reflect this. It will, however, return an error if it cannot
/// clear `len` bytes.
///
/// For example, if a caller requests that 100 bytes be cleared but a segfault happens after
/// 20 bytes, then EFAULT is returned and the writer is advanced by 20 bytes.
fn clear(&mut self, len: usize) -> Result;
/// Writes a byte slice into the io buffer.
///
/// Returns `EFAULT` if the byte slice is bigger than the remaining size of the io buffer or if
/// the address does not currently point to mapped, writable memory.
fn write_slice(&mut self, data: &[u8]) -> Result {
// SAFETY: The input buffer is valid as it's coming from a live reference.
unsafe { self.write_raw(data.as_ptr(), data.len()) }
}
/// Writes raw data to the io buffer from a raw kernel buffer.
///
/// # Safety
///
/// The input buffer must be valid.
unsafe fn write_raw(&mut self, data: *const u8, len: usize) -> Result;
/// Writes the contents of the given data into the io buffer.
fn write<T: WritableToBytes>(&mut self, data: &T) -> Result {
// SAFETY: The input buffer is valid as it's coming from a live
// reference to a type that implements `WritableToBytes`.
unsafe { self.write_raw(data as *const T as _, size_of::<T>()) }
}
}
/// Specifies that a type is safely readable from byte slices.
///
/// Not all types can be safely read from byte slices; examples from
/// <https://doc.rust-lang.org/reference/behavior-considered-undefined.html> include `bool`
/// that must be either `0` or `1`, and `char` that cannot be a surrogate or above `char::MAX`.
///
/// # Safety
///
/// Implementers must ensure that the type is made up only of types that can be safely read from
/// arbitrary byte sequences (e.g., `u32`, `u64`, etc.).
pub unsafe trait ReadableFromBytes {}
// SAFETY: All bit patterns are acceptable values of the types below.
unsafe impl ReadableFromBytes for u8 {}
unsafe impl ReadableFromBytes for u16 {}
unsafe impl ReadableFromBytes for u32 {}
unsafe impl ReadableFromBytes for u64 {}
unsafe impl ReadableFromBytes for usize {}
unsafe impl ReadableFromBytes for i8 {}
unsafe impl ReadableFromBytes for i16 {}
unsafe impl ReadableFromBytes for i32 {}
unsafe impl ReadableFromBytes for i64 {}
unsafe impl ReadableFromBytes for isize {}
/// Specifies that a type is safely writable to byte slices.
///
/// This means that we don't read undefined values (which leads to UB) in preparation for writing
/// to the byte slice. It also ensures that no potentially sensitive information is leaked into the
/// byte slices.
///
/// # Safety
///
/// A type must not include padding bytes and must be fully initialised to safely implement
/// [`WritableToBytes`] (i.e., it doesn't contain [`MaybeUninit`] fields). A composition of
/// writable types in a structure is not necessarily writable because it may result in padding
/// bytes.
pub unsafe trait WritableToBytes {}
// SAFETY: Initialised instances of the following types have no uninitialised portions.
unsafe impl WritableToBytes for u8 {}
unsafe impl WritableToBytes for u16 {}
unsafe impl WritableToBytes for u32 {}
unsafe impl WritableToBytes for u64 {}
unsafe impl WritableToBytes for usize {}
unsafe impl WritableToBytes for i8 {}
unsafe impl WritableToBytes for i16 {}
unsafe impl WritableToBytes for i32 {}
unsafe impl WritableToBytes for i64 {}
unsafe impl WritableToBytes for isize {}
// SPDX-License-Identifier: GPL-2.0
//! Memory-mapped IO.
//!
//! C header: [`include/asm-generic/io.h`](../../../../include/asm-generic/io.h)
#![allow(dead_code)]
use crate::{bindings, error::code::*, Result};
use core::convert::TryInto;
/// Represents a memory resource.
pub struct Resource {
offset: bindings::resource_size_t,
size: bindings::resource_size_t,
}
impl Resource {
pub(crate) fn new(
start: bindings::resource_size_t,
end: bindings::resource_size_t,
) -> Option<Self> {
if start == 0 {
return None;
}
Some(Self {
offset: start,
size: end.checked_sub(start)?.checked_add(1)?,
})
}
}
/// Represents a memory block of at least `SIZE` bytes.
///
/// # Invariants
///
/// `ptr` is a non-null and valid address of at least `SIZE` bytes and returned by an `ioremap`
/// variant. `ptr` is also 8-byte aligned.
///
/// # Examples
///
/// ```
/// # use kernel::prelude::*;
/// use kernel::io_mem::{IoMem, Resource};
///
/// fn test(res: Resource) -> Result {
/// // Create an io mem block of at least 100 bytes.
/// // SAFETY: No DMA operations are initiated through `mem`.
/// let mem = unsafe { IoMem::<100>::try_new(res) }?;
///
/// // Read one byte from offset 10.
/// let v = mem.readb(10);
///
/// // Write value to offset 20.
/// mem.writeb(v, 20);
///
/// Ok(())
/// }
///
/// ```
pub struct IoMem<const SIZE: usize> {
ptr: usize,
}
macro_rules! define_read {
($(#[$attr:meta])* $name:ident, $try_name:ident, $type_name:ty) => {
/// Reads IO data from the given offset known, at compile time.
///
/// If the offset is not known at compile time, the build will fail.
$(#[$attr])*
pub fn $name(&self, offset: usize) -> $type_name {
Self::check_offset::<$type_name>(offset);
let ptr = self.ptr.wrapping_add(offset);
// SAFETY: The type invariants guarantee that `ptr` is a valid pointer. The check above
// guarantees that the code won't build if `offset` makes the read go out of bounds
// (including the type size).
unsafe { bindings::$name(ptr as _) }
}
/// Reads IO data from the given offset.
///
/// It fails if/when the offset (plus the type size) is out of bounds.
$(#[$attr])*
pub fn $try_name(&self, offset: usize) -> Result<$type_name> {
if !Self::offset_ok::<$type_name>(offset) {
return Err(EINVAL);
}
let ptr = self.ptr.wrapping_add(offset);
// SAFETY: The type invariants guarantee that `ptr` is a valid pointer. The check above
// returns an error if `offset` would make the read go out of bounds (including the
// type size).
Ok(unsafe { bindings::$name(ptr as _) })
}
};
}
macro_rules! define_write {
($(#[$attr:meta])* $name:ident, $try_name:ident, $type_name:ty) => {
/// Writes IO data to the given offset, known at compile time.
///
/// If the offset is not known at compile time, the build will fail.
$(#[$attr])*
pub fn $name(&self, value: $type_name, offset: usize) {
Self::check_offset::<$type_name>(offset);
let ptr = self.ptr.wrapping_add(offset);
// SAFETY: The type invariants guarantee that `ptr` is a valid pointer. The check above
// guarantees that the code won't link if `offset` makes the write go out of bounds
// (including the type size).
unsafe { bindings::$name(value, ptr as _) }
}
/// Writes IO data to the given offset.
///
/// It fails if/when the offset (plus the type size) is out of bounds.
$(#[$attr])*
pub fn $try_name(&self, value: $type_name, offset: usize) -> Result {
if !Self::offset_ok::<$type_name>(offset) {
return Err(EINVAL);
}
let ptr = self.ptr.wrapping_add(offset);
// SAFETY: The type invariants guarantee that `ptr` is a valid pointer. The check above
// returns an error if `offset` would make the write go out of bounds (including the
// type size).
unsafe { bindings::$name(value, ptr as _) };
Ok(())
}
};
}
impl<const SIZE: usize> IoMem<SIZE> {
/// Tries to create a new instance of a memory block.
///
/// The resource described by `res` is mapped into the CPU's address space so that it can be
/// accessed directly. It is also consumed by this function so that it can't be mapped again
/// to a different address.
///
/// # Safety
///
/// Callers must ensure that either (a) the resulting interface cannot be used to initiate DMA
/// operations, or (b) that DMA operations initiated via the returned interface use DMA handles
/// allocated through the `dma` module.
pub unsafe fn try_new(res: Resource) -> Result<Self> {
// Check that the resource has at least `SIZE` bytes in it.
if res.size < SIZE.try_into()? {
return Err(EINVAL);
}
// To be able to check pointers at compile time based only on offsets, we need to guarantee
// that the base pointer is minimally aligned. So we conservatively expect at least 8 bytes.
if res.offset % 8 != 0 {
crate::pr_err!("Physical address is not 64-bit aligned: {:x}", res.offset);
return Err(EDOM);
}
// Try to map the resource.
// SAFETY: Just mapping the memory range.
let addr = unsafe { bindings::ioremap(res.offset, res.size as _) };
if addr.is_null() {
Err(ENOMEM)
} else {
// INVARIANT: `addr` is non-null and was returned by `ioremap`, so it is valid. It is
// also 8-byte aligned because we checked it above.
Ok(Self { ptr: addr as usize })
}
}
const fn offset_ok<T>(offset: usize) -> bool {
let type_size = core::mem::size_of::<T>();
if let Some(end) = offset.checked_add(type_size) {
end <= SIZE && offset % type_size == 0
} else {
false
}
}
fn offset_ok_of_val<T: ?Sized>(offset: usize, value: &T) -> bool {
let value_size = core::mem::size_of_val(value);
let value_alignment = core::mem::align_of_val(value);
if let Some(end) = offset.checked_add(value_size) {
end <= SIZE && offset % value_alignment == 0
} else {
false
}
}
const fn check_offset<T>(offset: usize) {
crate::build_assert!(Self::offset_ok::<T>(offset), "IoMem offset overflow");
}
/// Copy memory block from an i/o memory by filling the specified buffer with it.
///
/// # Examples
/// ```
/// use kernel::io_mem::{self, IoMem, Resource};
///
/// fn test(res: Resource) -> Result {
/// // Create an i/o memory block of at least 100 bytes.
/// let mem = unsafe { IoMem::<100>::try_new(res) }?;
///
/// let mut buffer: [u8; 32] = [0; 32];
///
/// // Memcpy 16 bytes from an offset 10 of i/o memory block into the buffer.
/// mem.try_memcpy_fromio(&mut buffer[..16], 10)?;
///
/// Ok(())
/// }
/// ```
pub fn try_memcpy_fromio(&self, buffer: &mut [u8], offset: usize) -> Result {
if !Self::offset_ok_of_val(offset, buffer) {
return Err(EINVAL);
}
let ptr = self.ptr.wrapping_add(offset);
// SAFETY:
// - The type invariants guarantee that `ptr` is a valid pointer.
// - The bounds of `buffer` are checked with a call to `offset_ok_of_val()`.
unsafe {
bindings::memcpy_fromio(
buffer.as_mut_ptr() as *mut _,
ptr as *const _,
buffer.len() as _,
)
};
Ok(())
}
define_read!(readb, try_readb, u8);
define_read!(readw, try_readw, u16);
define_read!(readl, try_readl, u32);
define_read!(
#[cfg(CONFIG_64BIT)]
readq,
try_readq,
u64
);
define_read!(readb_relaxed, try_readb_relaxed, u8);
define_read!(readw_relaxed, try_readw_relaxed, u16);
define_read!(readl_relaxed, try_readl_relaxed, u32);
define_read!(
#[cfg(CONFIG_64BIT)]
readq_relaxed,
try_readq_relaxed,
u64
);
define_write!(writeb, try_writeb, u8);
define_write!(writew, try_writew, u16);
define_write!(writel, try_writel, u32);
define_write!(
#[cfg(CONFIG_64BIT)]
writeq,
try_writeq,
u64
);
define_write!(writeb_relaxed, try_writeb_relaxed, u8);
define_write!(writew_relaxed, try_writew_relaxed, u16);
define_write!(writel_relaxed, try_writel_relaxed, u32);
define_write!(
#[cfg(CONFIG_64BIT)]
writeq_relaxed,
try_writeq_relaxed,
u64
);
}
impl<const SIZE: usize> Drop for IoMem<SIZE> {
fn drop(&mut self) {
// SAFETY: By the type invariant, `self.ptr` is a value returned by a previous successful
// call to `ioremap`.
unsafe { bindings::iounmap(self.ptr as _) };
}
}
// SPDX-License-Identifier: GPL-2.0
//! IO vector iterators.
//!
//! C header: [`include/linux/uio.h`](../../../../include/linux/uio.h)
use crate::{
bindings,
error::code::*,
io_buffer::{IoBufferReader, IoBufferWriter},
Result,
};
/// Wraps the kernel's `struct iov_iter`.
///
/// # Invariants
///
/// The pointer `IovIter::ptr` is non-null and valid.
pub struct IovIter {
ptr: *mut bindings::iov_iter,
}
impl IovIter {
fn common_len(&self) -> usize {
// SAFETY: `IovIter::ptr` is guaranteed to be valid by the type invariants.
unsafe { (*self.ptr).count }
}
/// Constructs a new [`struct iov_iter`] wrapper.
///
/// # Safety
///
/// The pointer `ptr` must be non-null and valid for the lifetime of the object.
pub(crate) unsafe fn from_ptr(ptr: *mut bindings::iov_iter) -> Self {
// INVARIANTS: the safety contract ensures the type invariant will hold.
Self { ptr }
}
}
impl IoBufferWriter for IovIter {
fn len(&self) -> usize {
self.common_len()
}
fn clear(&mut self, mut len: usize) -> Result {
while len > 0 {
// SAFETY: `IovIter::ptr` is guaranteed to be valid by the type invariants.
let written = unsafe { bindings::iov_iter_zero(len, self.ptr) };
if written == 0 {
return Err(EFAULT);
}
len -= written;
}
Ok(())
}
unsafe fn write_raw(&mut self, data: *const u8, len: usize) -> Result {
let res = unsafe { bindings::copy_to_iter(data as _, len, self.ptr) };
if res != len {
Err(EFAULT)
} else {
Ok(())
}
}
}
impl IoBufferReader for IovIter {
fn len(&self) -> usize {
self.common_len()
}
unsafe fn read_raw(&mut self, out: *mut u8, len: usize) -> Result {
let res = unsafe { bindings::copy_from_iter(out as _, len, self.ptr) };
if res != len {
Err(EFAULT)
} else {
Ok(())
}
}
}
此差异已折叠。
// SPDX-License-Identifier: GPL-2.0
//! Kernel async functionality.
#[cfg(CONFIG_NET)]
pub mod net;
// SPDX-License-Identifier: GPL-2.0
//! Async networking.
use crate::{bindings, c_types, error::code::*, net, sync::NoWaitLock, types::Opaque, Result};
use core::{
future::Future,
marker::{PhantomData, PhantomPinned},
ops::Deref,
pin::Pin,
task::{Context, Poll, Waker},
};
/// A socket listening on a TCP port.
///
/// The [`TcpListener::accept`] method is meant to be used in async contexts.
pub struct TcpListener {
listener: net::TcpListener,
}
impl TcpListener {
/// Creates a new TCP listener.
///
/// It is configured to listen on the given socket address for the given namespace.
pub fn try_new(ns: &net::Namespace, addr: &net::SocketAddr) -> Result<Self> {
Ok(Self {
listener: net::TcpListener::try_new(ns, addr)?,
})
}
/// Accepts a new connection.
///
/// Returns a future that when ready indicates the result of the accept operation; on success,
/// it contains the newly-accepted tcp stream.
pub fn accept(&self) -> impl Future<Output = Result<TcpStream>> + '_ {
SocketFuture::from_listener(
self,
bindings::BINDINGS_EPOLLIN | bindings::BINDINGS_EPOLLERR,
|| {
Ok(TcpStream {
stream: self.listener.accept(false)?,
})
},
)
}
}
impl Deref for TcpListener {
type Target = net::TcpListener;
fn deref(&self) -> &Self::Target {
&self.listener
}
}
/// A connected TCP socket.
///
/// The potentially blocking methods (e.g., [`TcpStream::read`], [`TcpStream::write`]) are meant
/// to be used in async contexts.
///
/// # Examples
///
/// ```
/// # use kernel::prelude::*;
/// # use kernel::kasync::net::TcpStream;
/// async fn echo_server(stream: TcpStream) -> Result {
/// let mut buf = [0u8; 1024];
/// loop {
/// let n = stream.read(&mut buf).await?;
/// if n == 0 {
/// return Ok(());
/// }
/// stream.write_all(&buf[..n]).await?;
/// }
/// }
/// ```
pub struct TcpStream {
stream: net::TcpStream,
}
impl TcpStream {
/// Reads data from a connected socket.
///
/// Returns a future that when ready indicates the result of the read operation; on success, it
/// contains the number of bytes read, which will be zero if the connection is closed.
pub fn read<'a>(&'a self, buf: &'a mut [u8]) -> impl Future<Output = Result<usize>> + 'a {
SocketFuture::from_stream(
self,
bindings::BINDINGS_EPOLLIN | bindings::BINDINGS_EPOLLHUP | bindings::BINDINGS_EPOLLERR,
|| self.stream.read(buf, false),
)
}
/// Writes data to the connected socket.
///
/// Returns a future that when ready indicates the result of the write operation; on success, it
/// contains the number of bytes written.
pub fn write<'a>(&'a self, buf: &'a [u8]) -> impl Future<Output = Result<usize>> + 'a {
SocketFuture::from_stream(
self,
bindings::BINDINGS_EPOLLOUT | bindings::BINDINGS_EPOLLHUP | bindings::BINDINGS_EPOLLERR,
|| self.stream.write(buf, false),
)
}
/// Writes all the data to the connected socket.
///
/// Returns a future that when ready indicates the result of the write operation; on success, it
/// has written all the data.
pub async fn write_all<'a>(&'a self, buf: &'a [u8]) -> Result {
let mut rem = buf;
while !rem.is_empty() {
let n = self.write(rem).await?;
rem = &rem[n..];
}
Ok(())
}
}
impl Deref for TcpStream {
type Target = net::TcpStream;
fn deref(&self) -> &Self::Target {
&self.stream
}
}
/// A future for a socket operation.
///
/// # Invariants
///
/// `sock` is always non-null and valid for the duration of the lifetime of the instance.
struct SocketFuture<'a, Out, F: FnMut() -> Result<Out> + Send + 'a> {
sock: *mut bindings::socket,
mask: u32,
is_queued: bool,
wq_entry: Opaque<bindings::wait_queue_entry>,
waker: NoWaitLock<Option<Waker>>,
_p: PhantomData<&'a ()>,
_pin: PhantomPinned,
operation: F,
}
// SAFETY: A kernel socket can be used from any thread, `wq_entry` is only used on drop and when
// `is_queued` is initially `false`.
unsafe impl<Out, F: FnMut() -> Result<Out> + Send> Send for SocketFuture<'_, Out, F> {}
impl<'a, Out, F: FnMut() -> Result<Out> + Send + 'a> SocketFuture<'a, Out, F> {
/// Creates a new socket future.
///
/// # Safety
///
/// Callers must ensure that `sock` is non-null, valid, and remains valid for the lifetime
/// (`'a`) of the returned instance.
unsafe fn new(sock: *mut bindings::socket, mask: u32, operation: F) -> Self {
Self {
sock,
mask,
is_queued: false,
wq_entry: Opaque::uninit(),
waker: NoWaitLock::new(None),
operation,
_p: PhantomData,
_pin: PhantomPinned,
}
}
/// Creates a new socket future for a tcp listener.
fn from_listener(listener: &'a TcpListener, mask: u32, operation: F) -> Self {
// SAFETY: The socket is guaranteed to remain valid because it is bound to the reference to
// the listener (whose existence guarantees the socket remains valid).
unsafe { Self::new(listener.listener.sock, mask, operation) }
}
/// Creates a new socket future for a tcp stream.
fn from_stream(stream: &'a TcpStream, mask: u32, operation: F) -> Self {
// SAFETY: The socket is guaranteed to remain valid because it is bound to the reference to
// the stream (whose existence guarantees the socket remains valid).
unsafe { Self::new(stream.stream.sock, mask, operation) }
}
/// Callback called when the socket changes state.
///
/// If the state matches the one we're waiting on, we wake up the task so that the future can be
/// polled again.
unsafe extern "C" fn wake_callback(
wq_entry: *mut bindings::wait_queue_entry,
_mode: c_types::c_uint,
_flags: c_types::c_int,
key: *mut c_types::c_void,
) -> c_types::c_int {
let mask = key as u32;
// SAFETY: The future is valid while this callback is called because we remove from the
// queue on drop.
//
// There is a potential soundness issue here because we're generating a shared reference to
// `Self` while `Self::poll` has a mutable (unique) reference. However, for `!Unpin` types
// (like `Self`), `&mut T` is treated as `*mut T` per
// https://github.com/rust-lang/rust/issues/63818 -- so we avoid the unsoundness. Once a
// more definitive solution is available, we can change this to use it.
let s = unsafe { &*crate::container_of!(wq_entry, Self, wq_entry) };
if mask & s.mask == 0 {
// Nothing to do as this notification doesn't interest us.
return 0;
}
// If we can't acquire the waker lock, the waker is in the process of being modified. Our
// attempt to acquire the lock will be reported to the lock owner, so it will trigger the
// wake up.
if let Some(guard) = s.waker.try_lock() {
if let Some(ref w) = *guard {
let cloned = w.clone();
drop(guard);
cloned.wake();
return 1;
}
}
0
}
/// Poll the future once.
///
/// It calls the operation and converts `EAGAIN` errors into a pending state.
fn poll_once(self: Pin<&mut Self>) -> Poll<Result<Out>> {
// SAFETY: We never move out of `this`.
let this = unsafe { self.get_unchecked_mut() };
match (this.operation)() {
Ok(s) => Poll::Ready(Ok(s)),
Err(e) => {
if e == EAGAIN {
Poll::Pending
} else {
Poll::Ready(Err(e))
}
}
}
}
/// Updates the waker stored in the future.
///
/// It automatically triggers a wake up on races with the reactor.
fn set_waker(&self, waker: &Waker) {
if let Some(mut guard) = self.waker.try_lock() {
let old = core::mem::replace(&mut *guard, Some(waker.clone()));
let contention = guard.unlock();
drop(old);
if !contention {
return;
}
}
// We either couldn't store the waker because the existing one is being awakened, or the
// reactor tried to acquire the lock while we held it (contention). In either case, we just
// wake it up to ensure we don't miss any notification.
waker.wake_by_ref();
}
}
impl<Out, F: FnMut() -> Result<Out> + Send> Future for SocketFuture<'_, Out, F> {
type Output = Result<Out>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match self.as_mut().poll_once() {
Poll::Ready(r) => Poll::Ready(r),
Poll::Pending => {
// Store away the latest waker every time we may `Pending`.
self.set_waker(cx.waker());
if self.is_queued {
// Nothing else to do was the waiter is already queued.
return Poll::Pending;
}
// SAFETY: We never move out of `this`.
let this = unsafe { self.as_mut().get_unchecked_mut() };
this.is_queued = true;
// SAFETY: `wq_entry` is valid for write.
unsafe {
bindings::init_waitqueue_func_entry(
this.wq_entry.get(),
Some(Self::wake_callback),
)
};
// SAFETY: `wq_entry` was just initialised above and is valid for read/write.
// By the type invariants, the socket is always valid.
unsafe {
bindings::add_wait_queue(
core::ptr::addr_of_mut!((*this.sock).wq.wait),
this.wq_entry.get(),
)
};
// If the future wasn't queued yet, we need to poll again in case it reached
// the desired state between the last poll and being queued (in which case we
// would have missed the notification).
self.poll_once()
}
}
}
}
impl<Out, F: FnMut() -> Result<Out> + Send> Drop for SocketFuture<'_, Out, F> {
fn drop(&mut self) {
if !self.is_queued {
return;
}
// SAFETY: `wq_entry` is initialised because `is_queued` is set to `true`, so it is valid
// for read/write. By the type invariants, the socket is always valid.
unsafe {
bindings::remove_wait_queue(
core::ptr::addr_of_mut!((*self.sock).wq.wait),
self.wq_entry.get(),
)
};
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
// SPDX-License-Identifier: GPL-2.0
//! Devicetree and Open Firmware abstractions.
//!
//! C header: [`include/linux/of_*.h`](../../../../include/linux/of_*.h)
use crate::{bindings, driver, str::BStr};
/// An open firmware device id.
#[derive(Clone, Copy)]
pub enum DeviceId {
/// An open firmware device id where only a compatible string is specified.
Compatible(&'static BStr),
}
/// Defines a const open firmware device id table that also carries per-entry data/context/info.
///
/// The name of the const is `OF_DEVICE_ID_TABLE`, which is what buses are expected to name their
/// open firmware tables.
///
/// # Examples
///
/// ```
/// # use kernel::define_of_id_table;
/// use kernel::of;
///
/// define_of_id_table! {u32, [
/// (of::DeviceId::Compatible(b"test-device1,test-device2"), Some(0xff)),
/// (of::DeviceId::Compatible(b"test-device3"), None),
/// ]};
/// ```
#[macro_export]
macro_rules! define_of_id_table {
($data_type:ty, $($t:tt)*) => {
$crate::define_id_table!(OF_DEVICE_ID_TABLE, $crate::of::DeviceId, $data_type, $($t)*);
};
}
// SAFETY: `ZERO` is all zeroed-out and `to_rawid` stores `offset` in `of_device_id::data`.
unsafe impl const driver::RawDeviceId for DeviceId {
type RawType = bindings::of_device_id;
const ZERO: Self::RawType = bindings::of_device_id {
name: [0; 32],
type_: [0; 32],
compatible: [0; 128],
data: core::ptr::null(),
};
fn to_rawid(&self, offset: isize) -> Self::RawType {
let DeviceId::Compatible(compatible) = self;
let mut id = Self::ZERO;
let mut i = 0;
while i < compatible.len() {
// If `compatible` does not fit in `id.compatible`, an "index out of bounds" build time
// error will be triggered.
id.compatible[i] = compatible[i] as _;
i += 1;
}
id.compatible[i] = b'\0' as _;
id.data = offset as _;
id
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册