rust: use custom FFI integer types

Currently FFI integer types are defined in libcore. This commit creates
the `ffi` crate and asks bindgen to use that crate for FFI integer types
instead of `core::ffi`.

This commit is preparatory and no type changes are made in this commit
yet.

Signed-off-by: Gary Guo <gary@garyguo.net>
Link: https://lore.kernel.org/r/20240913213041.395655-4-gary@garyguo.net
[ Added `rustdoc`, `rusttest` and KUnit tests support. Rebased on top of
  `rust-next` (e.g. migrated more `core::ffi` cases). Reworded crate
  docs slightly and formatted. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
Gary Guo 2024-09-13 22:29:23 +01:00 committed by Miguel Ojeda
parent 2fd6f55c04
commit d072acda48
23 changed files with 107 additions and 83 deletions

View File

@ -3,7 +3,7 @@
# Where to place rustdoc generated documentation # Where to place rustdoc generated documentation
rustdoc_output := $(objtree)/Documentation/output/rust/rustdoc rustdoc_output := $(objtree)/Documentation/output/rust/rustdoc
obj-$(CONFIG_RUST) += core.o compiler_builtins.o obj-$(CONFIG_RUST) += core.o compiler_builtins.o ffi.o
always-$(CONFIG_RUST) += exports_core_generated.h always-$(CONFIG_RUST) += exports_core_generated.h
# Missing prototypes are expected in the helpers since these are exported # Missing prototypes are expected in the helpers since these are exported
@ -103,10 +103,13 @@ rustdoc-core: $(RUST_LIB_SRC)/core/src/lib.rs FORCE
rustdoc-compiler_builtins: $(src)/compiler_builtins.rs rustdoc-core FORCE rustdoc-compiler_builtins: $(src)/compiler_builtins.rs rustdoc-core FORCE
+$(call if_changed,rustdoc) +$(call if_changed,rustdoc)
rustdoc-kernel: private rustc_target_flags = \ rustdoc-ffi: $(src)/ffi.rs rustdoc-core FORCE
+$(call if_changed,rustdoc)
rustdoc-kernel: private rustc_target_flags = --extern ffi \
--extern build_error --extern macros=$(objtree)/$(obj)/libmacros.so \ --extern build_error --extern macros=$(objtree)/$(obj)/libmacros.so \
--extern bindings --extern uapi --extern bindings --extern uapi
rustdoc-kernel: $(src)/kernel/lib.rs rustdoc-core rustdoc-macros \ rustdoc-kernel: $(src)/kernel/lib.rs rustdoc-core rustdoc-ffi rustdoc-macros \
rustdoc-compiler_builtins $(obj)/libmacros.so \ rustdoc-compiler_builtins $(obj)/libmacros.so \
$(obj)/bindings.o FORCE $(obj)/bindings.o FORCE
+$(call if_changed,rustdoc) +$(call if_changed,rustdoc)
@ -124,12 +127,15 @@ quiet_cmd_rustc_test_library = RUSTC TL $<
rusttestlib-build_error: $(src)/build_error.rs FORCE rusttestlib-build_error: $(src)/build_error.rs FORCE
+$(call if_changed,rustc_test_library) +$(call if_changed,rustc_test_library)
rusttestlib-ffi: $(src)/ffi.rs FORCE
+$(call if_changed,rustc_test_library)
rusttestlib-macros: private rustc_target_flags = --extern proc_macro rusttestlib-macros: private rustc_target_flags = --extern proc_macro
rusttestlib-macros: private rustc_test_library_proc = yes rusttestlib-macros: private rustc_test_library_proc = yes
rusttestlib-macros: $(src)/macros/lib.rs FORCE rusttestlib-macros: $(src)/macros/lib.rs FORCE
+$(call if_changed,rustc_test_library) +$(call if_changed,rustc_test_library)
rusttestlib-kernel: private rustc_target_flags = \ rusttestlib-kernel: private rustc_target_flags = --extern ffi \
--extern build_error --extern macros \ --extern build_error --extern macros \
--extern bindings --extern uapi --extern bindings --extern uapi
rusttestlib-kernel: $(src)/kernel/lib.rs \ rusttestlib-kernel: $(src)/kernel/lib.rs \
@ -137,10 +143,12 @@ rusttestlib-kernel: $(src)/kernel/lib.rs \
$(obj)/libmacros.so $(obj)/bindings.o FORCE $(obj)/libmacros.so $(obj)/bindings.o FORCE
+$(call if_changed,rustc_test_library) +$(call if_changed,rustc_test_library)
rusttestlib-bindings: $(src)/bindings/lib.rs FORCE rusttestlib-bindings: private rustc_target_flags = --extern ffi
rusttestlib-bindings: $(src)/bindings/lib.rs rusttestlib-ffi FORCE
+$(call if_changed,rustc_test_library) +$(call if_changed,rustc_test_library)
rusttestlib-uapi: $(src)/uapi/lib.rs FORCE rusttestlib-uapi: private rustc_target_flags = --extern ffi
rusttestlib-uapi: $(src)/uapi/lib.rs rusttestlib-ffi FORCE
+$(call if_changed,rustc_test_library) +$(call if_changed,rustc_test_library)
quiet_cmd_rustdoc_test = RUSTDOC T $< quiet_cmd_rustdoc_test = RUSTDOC T $<
@ -160,7 +168,7 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \ mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \
OBJTREE=$(abspath $(objtree)) \ OBJTREE=$(abspath $(objtree)) \
$(RUSTDOC) --test $(rust_flags) \ $(RUSTDOC) --test $(rust_flags) \
-L$(objtree)/$(obj) --extern kernel \ -L$(objtree)/$(obj) --extern ffi --extern kernel \
--extern build_error --extern macros \ --extern build_error --extern macros \
--extern bindings --extern uapi \ --extern bindings --extern uapi \
--no-run --crate-name kernel -Zunstable-options \ --no-run --crate-name kernel -Zunstable-options \
@ -198,9 +206,9 @@ rusttest-macros: $(src)/macros/lib.rs \
+$(call if_changed,rustc_test) +$(call if_changed,rustc_test)
+$(call if_changed,rustdoc_test) +$(call if_changed,rustdoc_test)
rusttest-kernel: private rustc_target_flags = \ rusttest-kernel: private rustc_target_flags = --extern ffi \
--extern build_error --extern macros --extern bindings --extern uapi --extern build_error --extern macros --extern bindings --extern uapi
rusttest-kernel: $(src)/kernel/lib.rs rusttestlib-kernel \ rusttest-kernel: $(src)/kernel/lib.rs rusttestlib-ffi rusttestlib-kernel \
rusttestlib-build_error rusttestlib-macros rusttestlib-bindings \ rusttestlib-build_error rusttestlib-macros rusttestlib-bindings \
rusttestlib-uapi FORCE rusttestlib-uapi FORCE
+$(call if_changed,rustc_test) +$(call if_changed,rustc_test)
@ -273,7 +281,7 @@ bindgen_c_flags_final = $(bindgen_c_flags_lto) -fno-builtin -D__BINDGEN__
quiet_cmd_bindgen = BINDGEN $@ quiet_cmd_bindgen = BINDGEN $@
cmd_bindgen = \ cmd_bindgen = \
$(BINDGEN) $< $(bindgen_target_flags) \ $(BINDGEN) $< $(bindgen_target_flags) \
--use-core --with-derive-default --ctypes-prefix core::ffi --no-layout-tests \ --use-core --with-derive-default --ctypes-prefix ffi --no-layout-tests \
--no-debug '.*' --enable-function-attribute-detection \ --no-debug '.*' --enable-function-attribute-detection \
-o $@ -- $(bindgen_c_flags_final) -DMODULE \ -o $@ -- $(bindgen_c_flags_final) -DMODULE \
$(bindgen_target_cflags) $(bindgen_target_extra) $(bindgen_target_cflags) $(bindgen_target_extra)
@ -401,18 +409,23 @@ $(obj)/compiler_builtins.o: $(src)/compiler_builtins.rs $(obj)/core.o FORCE
$(obj)/build_error.o: $(src)/build_error.rs $(obj)/compiler_builtins.o FORCE $(obj)/build_error.o: $(src)/build_error.rs $(obj)/compiler_builtins.o FORCE
+$(call if_changed_rule,rustc_library) +$(call if_changed_rule,rustc_library)
$(obj)/ffi.o: $(src)/ffi.rs $(obj)/compiler_builtins.o FORCE
+$(call if_changed_rule,rustc_library)
$(obj)/bindings.o: private rustc_target_flags = --extern ffi
$(obj)/bindings.o: $(src)/bindings/lib.rs \ $(obj)/bindings.o: $(src)/bindings/lib.rs \
$(obj)/compiler_builtins.o \ $(obj)/ffi.o \
$(obj)/bindings/bindings_generated.rs \ $(obj)/bindings/bindings_generated.rs \
$(obj)/bindings/bindings_helpers_generated.rs FORCE $(obj)/bindings/bindings_helpers_generated.rs FORCE
+$(call if_changed_rule,rustc_library) +$(call if_changed_rule,rustc_library)
$(obj)/uapi.o: private rustc_target_flags = --extern ffi
$(obj)/uapi.o: $(src)/uapi/lib.rs \ $(obj)/uapi.o: $(src)/uapi/lib.rs \
$(obj)/compiler_builtins.o \ $(obj)/ffi.o \
$(obj)/uapi/uapi_generated.rs FORCE $(obj)/uapi/uapi_generated.rs FORCE
+$(call if_changed_rule,rustc_library) +$(call if_changed_rule,rustc_library)
$(obj)/kernel.o: private rustc_target_flags = \ $(obj)/kernel.o: private rustc_target_flags = --extern ffi \
--extern build_error --extern macros --extern bindings --extern uapi --extern build_error --extern macros --extern bindings --extern uapi
$(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/build_error.o \ $(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/build_error.o \
$(obj)/libmacros.so $(obj)/bindings.o $(obj)/uapi.o FORCE $(obj)/libmacros.so $(obj)/bindings.o $(obj)/uapi.o FORCE

13
rust/ffi.rs Normal file
View File

@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
//! Foreign function interface (FFI) types.
//!
//! This crate provides mapping from C primitive types to Rust ones.
//!
//! The Rust [`core`] crate provides [`core::ffi`], which maps integer types to the platform default
//! C ABI. The kernel does not use [`core::ffi`], so it can customise the mapping that deviates from
//! the platform default.
#![no_std]
pub use core::ffi::*;

View File

@ -58,7 +58,7 @@ fn aligned_size(new_layout: Layout) -> usize {
/// ///
/// One of the following: `krealloc`, `vrealloc`, `kvrealloc`. /// One of the following: `krealloc`, `vrealloc`, `kvrealloc`.
struct ReallocFunc( struct ReallocFunc(
unsafe extern "C" fn(*const core::ffi::c_void, usize, u32) -> *mut core::ffi::c_void, unsafe extern "C" fn(*const crate::ffi::c_void, usize, u32) -> *mut crate::ffi::c_void,
); );
impl ReallocFunc { impl ReallocFunc {

View File

@ -24,10 +24,10 @@
extern "C" { extern "C" {
#[link_name = "aligned_alloc"] #[link_name = "aligned_alloc"]
fn libc_aligned_alloc(align: usize, size: usize) -> *mut core::ffi::c_void; fn libc_aligned_alloc(align: usize, size: usize) -> *mut crate::ffi::c_void;
#[link_name = "free"] #[link_name = "free"]
fn libc_free(ptr: *mut core::ffi::c_void); fn libc_free(ptr: *mut crate::ffi::c_void);
} }
// SAFETY: // SAFETY:

View File

@ -355,17 +355,17 @@ impl<T: 'static, A> ForeignOwnable for Box<T, A>
{ {
type Borrowed<'a> = &'a T; type Borrowed<'a> = &'a T;
fn into_foreign(self) -> *const core::ffi::c_void { fn into_foreign(self) -> *const crate::ffi::c_void {
Box::into_raw(self) as _ Box::into_raw(self) as _
} }
unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self { unsafe fn from_foreign(ptr: *const crate::ffi::c_void) -> Self {
// SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
// call to `Self::into_foreign`. // call to `Self::into_foreign`.
unsafe { Box::from_raw(ptr as _) } unsafe { Box::from_raw(ptr as _) }
} }
unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> &'a T { unsafe fn borrow<'a>(ptr: *const crate::ffi::c_void) -> &'a T {
// SAFETY: The safety requirements of this method ensure that the object remains alive and // SAFETY: The safety requirements of this method ensure that the object remains alive and
// immutable for the duration of 'a. // immutable for the duration of 'a.
unsafe { &*ptr.cast() } unsafe { &*ptr.cast() }
@ -378,18 +378,18 @@ impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>>
{ {
type Borrowed<'a> = Pin<&'a T>; type Borrowed<'a> = Pin<&'a T>;
fn into_foreign(self) -> *const core::ffi::c_void { fn into_foreign(self) -> *const crate::ffi::c_void {
// SAFETY: We are still treating the box as pinned. // SAFETY: We are still treating the box as pinned.
Box::into_raw(unsafe { Pin::into_inner_unchecked(self) }) as _ Box::into_raw(unsafe { Pin::into_inner_unchecked(self) }) as _
} }
unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self { unsafe fn from_foreign(ptr: *const crate::ffi::c_void) -> Self {
// SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
// call to `Self::into_foreign`. // call to `Self::into_foreign`.
unsafe { Pin::new_unchecked(Box::from_raw(ptr as _)) } unsafe { Pin::new_unchecked(Box::from_raw(ptr as _)) }
} }
unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Pin<&'a T> { unsafe fn borrow<'a>(ptr: *const crate::ffi::c_void) -> Pin<&'a T> {
// SAFETY: The safety requirements for this function ensure that the object is still alive, // SAFETY: The safety requirements for this function ensure that the object is still alive,
// so it is safe to dereference the raw pointer. // so it is safe to dereference the raw pointer.
// The safety requirements of `from_foreign` also ensure that the object remains alive for // The safety requirements of `from_foreign` also ensure that the object remains alive for

View File

@ -131,7 +131,7 @@ impl<T: Operations> OperationsVTable<T> {
unsafe extern "C" fn poll_callback( unsafe extern "C" fn poll_callback(
_hctx: *mut bindings::blk_mq_hw_ctx, _hctx: *mut bindings::blk_mq_hw_ctx,
_iob: *mut bindings::io_comp_batch, _iob: *mut bindings::io_comp_batch,
) -> core::ffi::c_int { ) -> crate::ffi::c_int {
T::poll().into() T::poll().into()
} }
@ -145,9 +145,9 @@ impl<T: Operations> OperationsVTable<T> {
/// for the same context. /// for the same context.
unsafe extern "C" fn init_hctx_callback( unsafe extern "C" fn init_hctx_callback(
_hctx: *mut bindings::blk_mq_hw_ctx, _hctx: *mut bindings::blk_mq_hw_ctx,
_tagset_data: *mut core::ffi::c_void, _tagset_data: *mut crate::ffi::c_void,
_hctx_idx: core::ffi::c_uint, _hctx_idx: crate::ffi::c_uint,
) -> core::ffi::c_int { ) -> crate::ffi::c_int {
from_result(|| Ok(0)) from_result(|| Ok(0))
} }
@ -159,7 +159,7 @@ impl<T: Operations> OperationsVTable<T> {
/// This function may only be called by blk-mq C infrastructure. /// This function may only be called by blk-mq C infrastructure.
unsafe extern "C" fn exit_hctx_callback( unsafe extern "C" fn exit_hctx_callback(
_hctx: *mut bindings::blk_mq_hw_ctx, _hctx: *mut bindings::blk_mq_hw_ctx,
_hctx_idx: core::ffi::c_uint, _hctx_idx: crate::ffi::c_uint,
) { ) {
} }
@ -176,9 +176,9 @@ impl<T: Operations> OperationsVTable<T> {
unsafe extern "C" fn init_request_callback( unsafe extern "C" fn init_request_callback(
_set: *mut bindings::blk_mq_tag_set, _set: *mut bindings::blk_mq_tag_set,
rq: *mut bindings::request, rq: *mut bindings::request,
_hctx_idx: core::ffi::c_uint, _hctx_idx: crate::ffi::c_uint,
_numa_node: core::ffi::c_uint, _numa_node: crate::ffi::c_uint,
) -> core::ffi::c_int { ) -> crate::ffi::c_int {
from_result(|| { from_result(|| {
// SAFETY: By the safety requirements of this function, `rq` points // SAFETY: By the safety requirements of this function, `rq` points
// to a valid allocation. // to a valid allocation.
@ -203,7 +203,7 @@ impl<T: Operations> OperationsVTable<T> {
unsafe extern "C" fn exit_request_callback( unsafe extern "C" fn exit_request_callback(
_set: *mut bindings::blk_mq_tag_set, _set: *mut bindings::blk_mq_tag_set,
rq: *mut bindings::request, rq: *mut bindings::request,
_hctx_idx: core::ffi::c_uint, _hctx_idx: crate::ffi::c_uint,
) { ) {
// SAFETY: The tagset invariants guarantee that all requests are allocated with extra memory // SAFETY: The tagset invariants guarantee that all requests are allocated with extra memory
// for the request data. // for the request data.

View File

@ -25,7 +25,7 @@ fn new(buffer: &'a mut [u8]) -> Result<RawWriter<'a>> {
} }
pub(crate) fn from_array<const N: usize>( pub(crate) fn from_array<const N: usize>(
a: &'a mut [core::ffi::c_char; N], a: &'a mut [crate::ffi::c_char; N],
) -> Result<RawWriter<'a>> { ) -> Result<RawWriter<'a>> {
Self::new( Self::new(
// SAFETY: the buffer of `a` is valid for read and write as `u8` for // SAFETY: the buffer of `a` is valid for read and write as `u8` for

View File

@ -53,7 +53,7 @@ pub fn new(
queue_depth: num_tags, queue_depth: num_tags,
cmd_size, cmd_size,
flags: bindings::BLK_MQ_F_SHOULD_MERGE, flags: bindings::BLK_MQ_F_SHOULD_MERGE,
driver_data: core::ptr::null_mut::<core::ffi::c_void>(), driver_data: core::ptr::null_mut::<crate::ffi::c_void>(),
nr_maps: num_maps, nr_maps: num_maps,
..tag_set ..tag_set
} }

View File

@ -100,7 +100,7 @@ impl Error {
/// ///
/// It is a bug to pass an out-of-range `errno`. `EINVAL` would /// It is a bug to pass an out-of-range `errno`. `EINVAL` would
/// be returned in such a case. /// be returned in such a case.
pub fn from_errno(errno: core::ffi::c_int) -> Error { pub fn from_errno(errno: crate::ffi::c_int) -> Error {
if errno < -(bindings::MAX_ERRNO as i32) || errno >= 0 { if errno < -(bindings::MAX_ERRNO as i32) || errno >= 0 {
// TODO: Make it a `WARN_ONCE` once available. // TODO: Make it a `WARN_ONCE` once available.
crate::pr_warn!( crate::pr_warn!(
@ -119,7 +119,7 @@ pub fn from_errno(errno: core::ffi::c_int) -> Error {
/// Creates an [`Error`] from a kernel error code. /// Creates an [`Error`] from a kernel error code.
/// ///
/// Returns [`None`] if `errno` is out-of-range. /// Returns [`None`] if `errno` is out-of-range.
const fn try_from_errno(errno: core::ffi::c_int) -> Option<Error> { const fn try_from_errno(errno: crate::ffi::c_int) -> Option<Error> {
if errno < -(bindings::MAX_ERRNO as i32) || errno >= 0 { if errno < -(bindings::MAX_ERRNO as i32) || errno >= 0 {
return None; return None;
} }
@ -133,7 +133,7 @@ const fn try_from_errno(errno: core::ffi::c_int) -> Option<Error> {
/// # Safety /// # Safety
/// ///
/// `errno` must be within error code range (i.e. `>= -MAX_ERRNO && < 0`). /// `errno` must be within error code range (i.e. `>= -MAX_ERRNO && < 0`).
const unsafe fn from_errno_unchecked(errno: core::ffi::c_int) -> Error { const unsafe fn from_errno_unchecked(errno: crate::ffi::c_int) -> Error {
// INVARIANT: The contract ensures the type invariant // INVARIANT: The contract ensures the type invariant
// will hold. // will hold.
// SAFETY: The caller guarantees `errno` is non-zero. // SAFETY: The caller guarantees `errno` is non-zero.
@ -141,7 +141,7 @@ const fn try_from_errno(errno: core::ffi::c_int) -> Option<Error> {
} }
/// Returns the kernel error code. /// Returns the kernel error code.
pub fn to_errno(self) -> core::ffi::c_int { pub fn to_errno(self) -> crate::ffi::c_int {
self.0.get() self.0.get()
} }
@ -259,7 +259,7 @@ fn from(e: core::convert::Infallible) -> Error {
/// Converts an integer as returned by a C kernel function to an error if it's negative, and /// Converts an integer as returned by a C kernel function to an error if it's negative, and
/// `Ok(())` otherwise. /// `Ok(())` otherwise.
pub fn to_result(err: core::ffi::c_int) -> Result { pub fn to_result(err: crate::ffi::c_int) -> Result {
if err < 0 { if err < 0 {
Err(Error::from_errno(err)) Err(Error::from_errno(err))
} else { } else {
@ -282,15 +282,15 @@ pub fn to_result(err: core::ffi::c_int) -> Result {
/// fn devm_platform_ioremap_resource( /// fn devm_platform_ioremap_resource(
/// pdev: &mut PlatformDevice, /// pdev: &mut PlatformDevice,
/// index: u32, /// index: u32,
/// ) -> Result<*mut core::ffi::c_void> { /// ) -> Result<*mut kernel::ffi::c_void> {
/// // SAFETY: `pdev` points to a valid platform device. There are no safety requirements /// // SAFETY: `pdev` points to a valid platform device. There are no safety requirements
/// // on `index`. /// // on `index`.
/// from_err_ptr(unsafe { bindings::devm_platform_ioremap_resource(pdev.to_ptr(), index) }) /// from_err_ptr(unsafe { bindings::devm_platform_ioremap_resource(pdev.to_ptr(), index) })
/// } /// }
/// ``` /// ```
pub fn from_err_ptr<T>(ptr: *mut T) -> Result<*mut T> { pub fn from_err_ptr<T>(ptr: *mut T) -> Result<*mut T> {
// CAST: Casting a pointer to `*const core::ffi::c_void` is always valid. // CAST: Casting a pointer to `*const crate::ffi::c_void` is always valid.
let const_ptr: *const core::ffi::c_void = ptr.cast(); let const_ptr: *const crate::ffi::c_void = ptr.cast();
// SAFETY: The FFI function does not deref the pointer. // SAFETY: The FFI function does not deref the pointer.
if unsafe { bindings::IS_ERR(const_ptr) } { if unsafe { bindings::IS_ERR(const_ptr) } {
// SAFETY: The FFI function does not deref the pointer. // SAFETY: The FFI function does not deref the pointer.
@ -306,7 +306,7 @@ pub fn from_err_ptr<T>(ptr: *mut T) -> Result<*mut T> {
// //
// SAFETY: `IS_ERR()` ensures `err` is a // SAFETY: `IS_ERR()` ensures `err` is a
// negative value greater-or-equal to `-bindings::MAX_ERRNO`. // negative value greater-or-equal to `-bindings::MAX_ERRNO`.
return Err(unsafe { Error::from_errno_unchecked(err as core::ffi::c_int) }); return Err(unsafe { Error::from_errno_unchecked(err as crate::ffi::c_int) });
} }
Ok(ptr) Ok(ptr)
} }
@ -326,7 +326,7 @@ pub fn from_err_ptr<T>(ptr: *mut T) -> Result<*mut T> {
/// # use kernel::bindings; /// # use kernel::bindings;
/// unsafe extern "C" fn probe_callback( /// unsafe extern "C" fn probe_callback(
/// pdev: *mut bindings::platform_device, /// pdev: *mut bindings::platform_device,
/// ) -> core::ffi::c_int { /// ) -> kernel::ffi::c_int {
/// from_result(|| { /// from_result(|| {
/// let ptr = devm_alloc(pdev)?; /// let ptr = devm_alloc(pdev)?;
/// bindings::platform_set_drvdata(pdev, ptr); /// bindings::platform_set_drvdata(pdev, ptr);

View File

@ -133,7 +133,7 @@
//! # } //! # }
//! # // `Error::from_errno` is `pub(crate)` in the `kernel` crate, thus provide a workaround. //! # // `Error::from_errno` is `pub(crate)` in the `kernel` crate, thus provide a workaround.
//! # trait FromErrno { //! # trait FromErrno {
//! # fn from_errno(errno: core::ffi::c_int) -> Error { //! # fn from_errno(errno: kernel::ffi::c_int) -> Error {
//! # // Dummy error that can be constructed outside the `kernel` crate. //! # // Dummy error that can be constructed outside the `kernel` crate.
//! # Error::from(core::fmt::Error) //! # Error::from(core::fmt::Error)
//! # } //! # }

View File

@ -27,6 +27,8 @@
// Allow proc-macros to refer to `::kernel` inside the `kernel` crate (this crate). // Allow proc-macros to refer to `::kernel` inside the `kernel` crate (this crate).
extern crate self as kernel; extern crate self as kernel;
pub use ffi;
pub mod alloc; pub mod alloc;
#[cfg(CONFIG_BLOCK)] #[cfg(CONFIG_BLOCK)]
pub mod block; pub mod block;

View File

@ -314,7 +314,7 @@ impl<T: Driver> Adapter<T> {
/// `phydev` must be passed by the corresponding callback in `phy_driver`. /// `phydev` must be passed by the corresponding callback in `phy_driver`.
unsafe extern "C" fn soft_reset_callback( unsafe extern "C" fn soft_reset_callback(
phydev: *mut bindings::phy_device, phydev: *mut bindings::phy_device,
) -> core::ffi::c_int { ) -> crate::ffi::c_int {
from_result(|| { from_result(|| {
// SAFETY: This callback is called only in contexts // SAFETY: This callback is called only in contexts
// where we hold `phy_device->lock`, so the accessors on // where we hold `phy_device->lock`, so the accessors on
@ -328,7 +328,7 @@ impl<T: Driver> Adapter<T> {
/// # Safety /// # Safety
/// ///
/// `phydev` must be passed by the corresponding callback in `phy_driver`. /// `phydev` must be passed by the corresponding callback in `phy_driver`.
unsafe extern "C" fn probe_callback(phydev: *mut bindings::phy_device) -> core::ffi::c_int { unsafe extern "C" fn probe_callback(phydev: *mut bindings::phy_device) -> crate::ffi::c_int {
from_result(|| { from_result(|| {
// SAFETY: This callback is called only in contexts // SAFETY: This callback is called only in contexts
// where we can exclusively access `phy_device` because // where we can exclusively access `phy_device` because
@ -345,7 +345,7 @@ impl<T: Driver> Adapter<T> {
/// `phydev` must be passed by the corresponding callback in `phy_driver`. /// `phydev` must be passed by the corresponding callback in `phy_driver`.
unsafe extern "C" fn get_features_callback( unsafe extern "C" fn get_features_callback(
phydev: *mut bindings::phy_device, phydev: *mut bindings::phy_device,
) -> core::ffi::c_int { ) -> crate::ffi::c_int {
from_result(|| { from_result(|| {
// SAFETY: This callback is called only in contexts // SAFETY: This callback is called only in contexts
// where we hold `phy_device->lock`, so the accessors on // where we hold `phy_device->lock`, so the accessors on
@ -359,7 +359,7 @@ impl<T: Driver> Adapter<T> {
/// # Safety /// # Safety
/// ///
/// `phydev` must be passed by the corresponding callback in `phy_driver`. /// `phydev` must be passed by the corresponding callback in `phy_driver`.
unsafe extern "C" fn suspend_callback(phydev: *mut bindings::phy_device) -> core::ffi::c_int { unsafe extern "C" fn suspend_callback(phydev: *mut bindings::phy_device) -> crate::ffi::c_int {
from_result(|| { from_result(|| {
// SAFETY: The C core code ensures that the accessors on // SAFETY: The C core code ensures that the accessors on
// `Device` are okay to call even though `phy_device->lock` // `Device` are okay to call even though `phy_device->lock`
@ -373,7 +373,7 @@ impl<T: Driver> Adapter<T> {
/// # Safety /// # Safety
/// ///
/// `phydev` must be passed by the corresponding callback in `phy_driver`. /// `phydev` must be passed by the corresponding callback in `phy_driver`.
unsafe extern "C" fn resume_callback(phydev: *mut bindings::phy_device) -> core::ffi::c_int { unsafe extern "C" fn resume_callback(phydev: *mut bindings::phy_device) -> crate::ffi::c_int {
from_result(|| { from_result(|| {
// SAFETY: The C core code ensures that the accessors on // SAFETY: The C core code ensures that the accessors on
// `Device` are okay to call even though `phy_device->lock` // `Device` are okay to call even though `phy_device->lock`
@ -389,7 +389,7 @@ impl<T: Driver> Adapter<T> {
/// `phydev` must be passed by the corresponding callback in `phy_driver`. /// `phydev` must be passed by the corresponding callback in `phy_driver`.
unsafe extern "C" fn config_aneg_callback( unsafe extern "C" fn config_aneg_callback(
phydev: *mut bindings::phy_device, phydev: *mut bindings::phy_device,
) -> core::ffi::c_int { ) -> crate::ffi::c_int {
from_result(|| { from_result(|| {
// SAFETY: This callback is called only in contexts // SAFETY: This callback is called only in contexts
// where we hold `phy_device->lock`, so the accessors on // where we hold `phy_device->lock`, so the accessors on
@ -405,7 +405,7 @@ impl<T: Driver> Adapter<T> {
/// `phydev` must be passed by the corresponding callback in `phy_driver`. /// `phydev` must be passed by the corresponding callback in `phy_driver`.
unsafe extern "C" fn read_status_callback( unsafe extern "C" fn read_status_callback(
phydev: *mut bindings::phy_device, phydev: *mut bindings::phy_device,
) -> core::ffi::c_int { ) -> crate::ffi::c_int {
from_result(|| { from_result(|| {
// SAFETY: This callback is called only in contexts // SAFETY: This callback is called only in contexts
// where we hold `phy_device->lock`, so the accessors on // where we hold `phy_device->lock`, so the accessors on
@ -421,7 +421,7 @@ impl<T: Driver> Adapter<T> {
/// `phydev` must be passed by the corresponding callback in `phy_driver`. /// `phydev` must be passed by the corresponding callback in `phy_driver`.
unsafe extern "C" fn match_phy_device_callback( unsafe extern "C" fn match_phy_device_callback(
phydev: *mut bindings::phy_device, phydev: *mut bindings::phy_device,
) -> core::ffi::c_int { ) -> crate::ffi::c_int {
// SAFETY: This callback is called only in contexts // SAFETY: This callback is called only in contexts
// where we hold `phy_device->lock`, so the accessors on // where we hold `phy_device->lock`, so the accessors on
// `Device` are okay to call. // `Device` are okay to call.

View File

@ -184,7 +184,7 @@ pub const fn is_empty(&self) -> bool {
/// last at least `'a`. When `CStr` is alive, the memory pointed by `ptr` /// last at least `'a`. When `CStr` is alive, the memory pointed by `ptr`
/// must not be mutated. /// must not be mutated.
#[inline] #[inline]
pub unsafe fn from_char_ptr<'a>(ptr: *const core::ffi::c_char) -> &'a Self { pub unsafe fn from_char_ptr<'a>(ptr: *const crate::ffi::c_char) -> &'a Self {
// SAFETY: The safety precondition guarantees `ptr` is a valid pointer // SAFETY: The safety precondition guarantees `ptr` is a valid pointer
// to a `NUL`-terminated C string. // to a `NUL`-terminated C string.
let len = unsafe { bindings::strlen(ptr) } + 1; let len = unsafe { bindings::strlen(ptr) } + 1;
@ -247,7 +247,7 @@ pub unsafe fn from_bytes_with_nul_unchecked_mut(bytes: &mut [u8]) -> &mut CStr {
/// Returns a C pointer to the string. /// Returns a C pointer to the string.
#[inline] #[inline]
pub const fn as_char_ptr(&self) -> *const core::ffi::c_char { pub const fn as_char_ptr(&self) -> *const crate::ffi::c_char {
self.0.as_ptr() as _ self.0.as_ptr() as _
} }

View File

@ -332,11 +332,11 @@ pub fn into_unique_or_drop(self) -> Option<Pin<UniqueArc<T>>> {
impl<T: 'static> ForeignOwnable for Arc<T> { impl<T: 'static> ForeignOwnable for Arc<T> {
type Borrowed<'a> = ArcBorrow<'a, T>; type Borrowed<'a> = ArcBorrow<'a, T>;
fn into_foreign(self) -> *const core::ffi::c_void { fn into_foreign(self) -> *const crate::ffi::c_void {
ManuallyDrop::new(self).ptr.as_ptr() as _ ManuallyDrop::new(self).ptr.as_ptr() as _
} }
unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> ArcBorrow<'a, T> { unsafe fn borrow<'a>(ptr: *const crate::ffi::c_void) -> ArcBorrow<'a, T> {
// By the safety requirement of this function, we know that `ptr` came from // By the safety requirement of this function, we know that `ptr` came from
// a previous call to `Arc::into_foreign`. // a previous call to `Arc::into_foreign`.
let inner = NonNull::new(ptr as *mut ArcInner<T>).unwrap(); let inner = NonNull::new(ptr as *mut ArcInner<T>).unwrap();
@ -346,7 +346,7 @@ unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> ArcBorrow<'a, T> {
unsafe { ArcBorrow::new(inner) } unsafe { ArcBorrow::new(inner) }
} }
unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self { unsafe fn from_foreign(ptr: *const crate::ffi::c_void) -> Self {
// SAFETY: By the safety requirement of this function, we know that `ptr` came from // SAFETY: By the safety requirement of this function, we know that `ptr` came from
// a previous call to `Arc::into_foreign`, which guarantees that `ptr` is valid and // a previous call to `Arc::into_foreign`, which guarantees that `ptr` is valid and
// holds a reference count increment that is transferrable to us. // holds a reference count increment that is transferrable to us.

View File

@ -7,6 +7,7 @@
use super::{lock::Backend, lock::Guard, LockClassKey}; use super::{lock::Backend, lock::Guard, LockClassKey};
use crate::{ use crate::{
ffi::{c_int, c_long},
init::PinInit, init::PinInit,
pin_init, pin_init,
str::CStr, str::CStr,
@ -14,7 +15,6 @@
time::Jiffies, time::Jiffies,
types::Opaque, types::Opaque,
}; };
use core::ffi::{c_int, c_long};
use core::marker::PhantomPinned; use core::marker::PhantomPinned;
use core::ptr; use core::ptr;
use macros::pin_data; use macros::pin_data;

View File

@ -49,7 +49,7 @@ pub unsafe trait Backend {
/// remain valid for read indefinitely. /// remain valid for read indefinitely.
unsafe fn init( unsafe fn init(
ptr: *mut Self::State, ptr: *mut Self::State,
name: *const core::ffi::c_char, name: *const crate::ffi::c_char,
key: *mut bindings::lock_class_key, key: *mut bindings::lock_class_key,
); );

View File

@ -96,7 +96,7 @@ unsafe impl super::Backend for MutexBackend {
unsafe fn init( unsafe fn init(
ptr: *mut Self::State, ptr: *mut Self::State,
name: *const core::ffi::c_char, name: *const crate::ffi::c_char,
key: *mut bindings::lock_class_key, key: *mut bindings::lock_class_key,
) { ) {
// SAFETY: The safety requirements ensure that `ptr` is valid for writes, and `name` and // SAFETY: The safety requirements ensure that `ptr` is valid for writes, and `name` and

View File

@ -95,7 +95,7 @@ unsafe impl super::Backend for SpinLockBackend {
unsafe fn init( unsafe fn init(
ptr: *mut Self::State, ptr: *mut Self::State,
name: *const core::ffi::c_char, name: *const crate::ffi::c_char,
key: *mut bindings::lock_class_key, key: *mut bindings::lock_class_key,
) { ) {
// SAFETY: The safety requirements ensure that `ptr` is valid for writes, and `name` and // SAFETY: The safety requirements ensure that `ptr` is valid for writes, and `name` and

View File

@ -4,13 +4,9 @@
//! //!
//! C header: [`include/linux/sched.h`](srctree/include/linux/sched.h). //! C header: [`include/linux/sched.h`](srctree/include/linux/sched.h).
use crate::ffi::{c_int, c_long, c_uint};
use crate::types::Opaque; use crate::types::Opaque;
use core::{ use core::{marker::PhantomData, ops::Deref, ptr};
ffi::{c_int, c_long, c_uint},
marker::PhantomData,
ops::Deref,
ptr,
};
/// A sentinel value used for infinite timeouts. /// A sentinel value used for infinite timeouts.
pub const MAX_SCHEDULE_TIMEOUT: c_long = c_long::MAX; pub const MAX_SCHEDULE_TIMEOUT: c_long = c_long::MAX;

View File

@ -12,10 +12,10 @@
pub const NSEC_PER_MSEC: i64 = bindings::NSEC_PER_MSEC as i64; pub const NSEC_PER_MSEC: i64 = bindings::NSEC_PER_MSEC as i64;
/// The time unit of Linux kernel. One jiffy equals (1/HZ) second. /// The time unit of Linux kernel. One jiffy equals (1/HZ) second.
pub type Jiffies = core::ffi::c_ulong; pub type Jiffies = crate::ffi::c_ulong;
/// The millisecond time unit. /// The millisecond time unit.
pub type Msecs = core::ffi::c_uint; pub type Msecs = crate::ffi::c_uint;
/// Converts milliseconds to jiffies. /// Converts milliseconds to jiffies.
#[inline] #[inline]

View File

@ -29,7 +29,7 @@ pub trait ForeignOwnable: Sized {
/// For example, it might be invalid, dangling or pointing to uninitialized memory. Using it in /// For example, it might be invalid, dangling or pointing to uninitialized memory. Using it in
/// any way except for [`ForeignOwnable::from_foreign`], [`ForeignOwnable::borrow`], /// any way except for [`ForeignOwnable::from_foreign`], [`ForeignOwnable::borrow`],
/// [`ForeignOwnable::try_from_foreign`] can result in undefined behavior. /// [`ForeignOwnable::try_from_foreign`] can result in undefined behavior.
fn into_foreign(self) -> *const core::ffi::c_void; fn into_foreign(self) -> *const crate::ffi::c_void;
/// Borrows a foreign-owned object. /// Borrows a foreign-owned object.
/// ///
@ -37,7 +37,7 @@ pub trait ForeignOwnable: Sized {
/// ///
/// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for
/// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet. /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Self::Borrowed<'a>; unsafe fn borrow<'a>(ptr: *const crate::ffi::c_void) -> Self::Borrowed<'a>;
/// Converts a foreign-owned object back to a Rust-owned one. /// Converts a foreign-owned object back to a Rust-owned one.
/// ///
@ -47,7 +47,7 @@ pub trait ForeignOwnable: Sized {
/// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet. /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
/// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] for /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] for
/// this object must have been dropped. /// this object must have been dropped.
unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self; unsafe fn from_foreign(ptr: *const crate::ffi::c_void) -> Self;
/// Tries to convert a foreign-owned object back to a Rust-owned one. /// Tries to convert a foreign-owned object back to a Rust-owned one.
/// ///
@ -58,7 +58,7 @@ pub trait ForeignOwnable: Sized {
/// ///
/// `ptr` must either be null or satisfy the safety requirements for /// `ptr` must either be null or satisfy the safety requirements for
/// [`ForeignOwnable::from_foreign`]. /// [`ForeignOwnable::from_foreign`].
unsafe fn try_from_foreign(ptr: *const core::ffi::c_void) -> Option<Self> { unsafe fn try_from_foreign(ptr: *const crate::ffi::c_void) -> Option<Self> {
if ptr.is_null() { if ptr.is_null() {
None None
} else { } else {
@ -72,13 +72,13 @@ unsafe fn try_from_foreign(ptr: *const core::ffi::c_void) -> Option<Self> {
impl ForeignOwnable for () { impl ForeignOwnable for () {
type Borrowed<'a> = (); type Borrowed<'a> = ();
fn into_foreign(self) -> *const core::ffi::c_void { fn into_foreign(self) -> *const crate::ffi::c_void {
core::ptr::NonNull::dangling().as_ptr() core::ptr::NonNull::dangling().as_ptr()
} }
unsafe fn borrow<'a>(_: *const core::ffi::c_void) -> Self::Borrowed<'a> {} unsafe fn borrow<'a>(_: *const crate::ffi::c_void) -> Self::Borrowed<'a> {}
unsafe fn from_foreign(_: *const core::ffi::c_void) -> Self {} unsafe fn from_foreign(_: *const crate::ffi::c_void) -> Self {}
} }
/// Runs a cleanup function/closure when dropped. /// Runs a cleanup function/closure when dropped.

View File

@ -8,10 +8,10 @@
alloc::Flags, alloc::Flags,
bindings, bindings,
error::Result, error::Result,
ffi::{c_ulong, c_void},
prelude::*, prelude::*,
transmute::{AsBytes, FromBytes}, transmute::{AsBytes, FromBytes},
}; };
use core::ffi::{c_ulong, c_void};
use core::mem::{size_of, MaybeUninit}; use core::mem::{size_of, MaybeUninit};
/// The type used for userspace addresses. /// The type used for userspace addresses.
@ -45,7 +45,7 @@
/// every byte in the region. /// every byte in the region.
/// ///
/// ```no_run /// ```no_run
/// use core::ffi::c_void; /// use kernel::ffi::c_void;
/// use kernel::error::Result; /// use kernel::error::Result;
/// use kernel::uaccess::{UserPtr, UserSlice}; /// use kernel::uaccess::{UserPtr, UserSlice};
/// ///
@ -67,7 +67,7 @@
/// Example illustrating a TOCTOU (time-of-check to time-of-use) bug. /// Example illustrating a TOCTOU (time-of-check to time-of-use) bug.
/// ///
/// ```no_run /// ```no_run
/// use core::ffi::c_void; /// use kernel::ffi::c_void;
/// use kernel::error::{code::EINVAL, Result}; /// use kernel::error::{code::EINVAL, Result};
/// use kernel::uaccess::{UserPtr, UserSlice}; /// use kernel::uaccess::{UserPtr, UserSlice};
/// ///

View File

@ -253,7 +253,7 @@ mod __module_init {{
#[doc(hidden)] #[doc(hidden)]
#[no_mangle] #[no_mangle]
#[link_section = \".init.text\"] #[link_section = \".init.text\"]
pub unsafe extern \"C\" fn init_module() -> core::ffi::c_int {{ pub unsafe extern \"C\" fn init_module() -> kernel::ffi::c_int {{
// SAFETY: This function is inaccessible to the outside due to the double // SAFETY: This function is inaccessible to the outside due to the double
// module wrapping it. It is called exactly once by the C side via its // module wrapping it. It is called exactly once by the C side via its
// unique name. // unique name.
@ -292,7 +292,7 @@ mod __module_init {{
#[doc(hidden)] #[doc(hidden)]
#[link_section = \"{initcall_section}\"] #[link_section = \"{initcall_section}\"]
#[used] #[used]
pub static __{name}_initcall: extern \"C\" fn() -> core::ffi::c_int = __{name}_init; pub static __{name}_initcall: extern \"C\" fn() -> kernel::ffi::c_int = __{name}_init;
#[cfg(not(MODULE))] #[cfg(not(MODULE))]
#[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)] #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)]
@ -307,7 +307,7 @@ mod __module_init {{
#[cfg(not(MODULE))] #[cfg(not(MODULE))]
#[doc(hidden)] #[doc(hidden)]
#[no_mangle] #[no_mangle]
pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{ pub extern \"C\" fn __{name}_init() -> kernel::ffi::c_int {{
// SAFETY: This function is inaccessible to the outside due to the double // SAFETY: This function is inaccessible to the outside due to the double
// module wrapping it. It is called exactly once by the C side via its // module wrapping it. It is called exactly once by the C side via its
// placement above in the initcall section. // placement above in the initcall section.
@ -330,7 +330,7 @@ mod __module_init {{
/// # Safety /// # Safety
/// ///
/// This function must only be called once. /// This function must only be called once.
unsafe fn __init() -> core::ffi::c_int {{ unsafe fn __init() -> kernel::ffi::c_int {{
match <{type_} as kernel::Module>::init(&super::super::THIS_MODULE) {{ match <{type_} as kernel::Module>::init(&super::super::THIS_MODULE) {{
Ok(m) => {{ Ok(m) => {{
// SAFETY: No data race, since `__MOD` can only be accessed by this // SAFETY: No data race, since `__MOD` can only be accessed by this