Skip to content
Snippets Groups Projects
Commit e3610441 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'rust-6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux

Pull rust updates from Miguel Ojeda:
 "Toolchain and infrastructure:

   - Finish the move to custom FFI integer types started in the previous
     cycle and finally map 'long' to 'isize' and 'char' to 'u8'. Do a
     few cleanups on top thanks to that.

   - Start to use 'derive(CoercePointee)' on Rust >= 1.84.0.

     This is a major milestone on the path to build the kernel using
     only stable Rust features. In particular, previously we were using
     the unstable features 'coerce_unsized', 'dispatch_from_dyn' and
     'unsize', and now we will use the new 'derive_coerce_pointee' one,
     which is on track to stabilization. This new feature is a macro
     that essentially expands into code that internally uses the
     unstable features that we were using before, without having to
     expose those.

     With it, stable Rust users, including the kernel, will be able to
     build custom smart pointers that work with trait objects, e.g.:

         fn f(p: &Arc<dyn Display>) {
             pr_info!("{p}\n");
         }

         let a: Arc<dyn Display> = Arc::new(42i32, GFP_KERNEL)?;
         let b: Arc<dyn Display> = Arc::new("hello there", GFP_KERNEL)?;

         f(&a); // Prints "42".
         f(&b); // Prints "hello there".

     Together with the 'arbitrary_self_types' feature that we started
     using in the previous cycle, using our custom smart pointers like
     'Arc' will eventually only rely in stable Rust.

   - Introduce 'PROCMACROLDFLAGS' environment variable to allow to link
     Rust proc macros using different flags than those used for linking
     Rust host programs (e.g. when 'rustc' uses a different C library
     than the host programs' one), which Android needs.

   - Help kernel builds under macOS with Rust enabled by accomodating
     other naming conventions for dynamic libraries (i.e. '.so' vs.
     '.dylib') which are used for Rust procedural macros. The actual
     support for macOS (i.e. the rest of the pieces needed) is provided
     out-of-tree by others, following the policy used for other parts of
     the kernel by Kbuild.

   - Run Clippy for 'rusttest' code too and clean the bits it spotted.

   - Provide Clippy with the minimum supported Rust version to improve
     the suggestions it gives.

   - Document 'bindgen' 0.71.0 regression.

  'kernel' crate:

   - 'build_error!': move users of the hidden function to the documented
     macro, prevent such uses in the future by moving the function
     elsewhere and add the macro to the prelude.

   - 'types' module: add improved version of 'ForeignOwnable::borrow_mut'
     (which was removed in the past since it was problematic); change
     'ForeignOwnable' pointer type to '*mut'.

   - 'alloc' module: implement 'Display' for 'Box' and align the 'Debug'
     implementation to it; add example (doctest) for 'ArrayLayout::new()'

   - 'sync' module: document 'PhantomData' in 'Arc'; use
     'NonNull::new_unchecked' in 'ForeignOwnable for Arc' impl.

   - 'uaccess' module: accept 'Vec's with different allocators in
     'UserSliceReader::read_all'.

   - 'workqueue' module: enable run-testing a couple more doctests.

   - 'error' module: simplify 'from_errno()'.

   - 'block' module: fix formatting in code documentation (a lint to catch
     these is being implemented).

   - Avoid 'unwrap()'s in doctests, which also improves the examples by
     showing how kernel code is supposed to be written.

   - Avoid 'as' casts with 'cast{,_mut}' calls which are a bit safer.

  And a few other cleanups"

* tag 'rust-6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux: (32 commits)
  kbuild: rust: add PROCMACROLDFLAGS
  rust: uaccess: generalize userSliceReader to support any Vec
  rust: kernel: add improved version of `ForeignOwnable::borrow_mut`
  rust: kernel: reorder `ForeignOwnable` items
  rust: kernel: change `ForeignOwnable` pointer to mut
  rust: arc: split unsafe block, add missing comment
  rust: types: avoid `as` casts
  rust: arc: use `NonNull::new_unchecked`
  rust: use derive(CoercePointee) on rustc >= 1.84.0
  rust: alloc: add doctest for `ArrayLayout::new()`
  rust: init: update `stack_try_pin_init` examples
  rust: error: import `kernel`'s `LayoutError` instead of `core`'s
  rust: str: replace unwraps with question mark operators
  rust: page: remove unnecessary helper function from doctest
  rust: rbtree: remove unwrap in asserts
  rust: init: replace unwraps with question mark operators
  rust: use host dylib naming convention to support macOS
  rust: add `build_error!` to the prelude
  rust: kernel: move `build_error` hidden function to prevent mistakes
  rust: use the `build_error!` macro, not the hidden function
  ...
parents 1d6d3992 ceff0757
No related branches found
No related tags found
No related merge requests found
Showing
with 200 additions and 75 deletions
# SPDX-License-Identifier: GPL-2.0
msrv = "1.78.0"
check-private-items = true
disallowed-macros = [
......
......@@ -22,6 +22,7 @@
*.dtb.S
*.dtbo.S
*.dwo
*.dylib
*.elf
*.gcno
*.gcda
......
......@@ -91,6 +91,17 @@ HOSTRUSTFLAGS
-------------
Additional flags to be passed to $(HOSTRUSTC) when building host programs.
PROCMACROLDFLAGS
----------------
Flags to be passed when linking Rust proc macros. Since proc macros are loaded
by rustc at build time, they must be linked in a way that is compatible with
the rustc toolchain being used.
For instance, it can be useful when rustc uses a different C library than
the one the user wants to use for host programs.
If unset, it defaults to the flags passed when linking host programs.
HOSTLDFLAGS
-----------
Additional flags to be passed when linking host programs.
......
......@@ -497,6 +497,7 @@ KBUILD_HOSTRUSTFLAGS := $(rust_common_flags) -O -Cstrip=debuginfo \
-Zallow-features= $(HOSTRUSTFLAGS)
KBUILD_HOSTLDFLAGS := $(HOST_LFS_LDFLAGS) $(HOSTLDFLAGS)
KBUILD_HOSTLDLIBS := $(HOST_LFS_LIBS) $(HOSTLDLIBS)
KBUILD_PROCMACROLDFLAGS := $(or $(PROCMACROLDFLAGS),$(KBUILD_HOSTLDFLAGS))
# Make variables (CC, etc...)
CPP = $(CC) -E
......@@ -621,7 +622,7 @@ export HOSTRUSTC KBUILD_HOSTRUSTFLAGS
export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL
export PERL PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ ZSTD
export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS LDFLAGS_MODULE
export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS KBUILD_PROCMACROLDFLAGS LDFLAGS_MODULE
export KBUILD_USERCFLAGS KBUILD_USERLDFLAGS
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS KBUILD_LDFLAGS
......@@ -1571,7 +1572,7 @@ MRPROPER_FILES += include/config include/generated \
certs/x509.genkey \
vmlinux-gdb.py \
rpmbuild \
rust/libmacros.so
rust/libmacros.so rust/libmacros.dylib
# clean - Delete most, but leave enough to build external modules
#
......
......@@ -931,7 +931,7 @@ fn draw_all(&mut self, data: impl Iterator<Item = u8>) {
/// They must remain valid for the duration of the function call.
#[no_mangle]
pub unsafe extern "C" fn drm_panic_qr_generate(
url: *const i8,
url: *const kernel::ffi::c_char,
data: *mut u8,
data_len: usize,
data_size: usize,
......
......@@ -129,6 +129,9 @@ config CC_HAS_COUNTED_BY
# https://github.com/llvm/llvm-project/pull/112636
depends on !(CC_IS_CLANG && CLANG_VERSION < 190103)
config RUSTC_HAS_COERCE_POINTEE
def_bool RUSTC_VERSION >= 108400
config PAHOLE_VERSION
int
default $(shell,$(srctree)/scripts/pahole-version.sh $(PAHOLE))
......@@ -2000,8 +2003,10 @@ config BINDGEN_VERSION_TEXT
string
depends on RUST
# The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0
# (https://github.com/rust-lang/rust-bindgen/pull/2678). It can be removed when
# the minimum version is upgraded past that (0.69.1 already fixed the issue).
# (https://github.com/rust-lang/rust-bindgen/pull/2678) and 0.71.0
# (https://github.com/rust-lang/rust-bindgen/pull/3040). It can be removed
# when the minimum version is upgraded past the latter (0.69.1 and 0.71.1
# both fixed the issue).
default "$(shell,$(BINDGEN) --version workaround-for-0.69.0 2>/dev/null)"
#
......
......@@ -11,9 +11,6 @@ always-$(CONFIG_RUST) += exports_core_generated.h
obj-$(CONFIG_RUST) += helpers/helpers.o
CFLAGS_REMOVE_helpers/helpers.o = -Wmissing-prototypes -Wmissing-declarations
always-$(CONFIG_RUST) += libmacros.so
no-clean-files += libmacros.so
always-$(CONFIG_RUST) += bindings/bindings_generated.rs bindings/bindings_helpers_generated.rs
obj-$(CONFIG_RUST) += bindings.o kernel.o
always-$(CONFIG_RUST) += exports_helpers_generated.h \
......@@ -38,9 +35,14 @@ obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.o
always-$(subst y,$(CONFIG_RUST),$(CONFIG_JUMP_LABEL)) += kernel/generated_arch_static_branch_asm.rs
# Avoids running `$(RUSTC)` for the sysroot when it may not be available.
# Avoids running `$(RUSTC)` when it may not be available.
ifdef CONFIG_RUST
libmacros_name := $(shell MAKEFLAGS= $(RUSTC) --print file-names --crate-name macros --crate-type proc-macro - </dev/null)
libmacros_extension := $(patsubst libmacros.%,%,$(libmacros_name))
always-$(CONFIG_RUST) += $(libmacros_name)
# `$(rust_flags)` is passed in case the user added `--sysroot`.
rustc_sysroot := $(shell MAKEFLAGS= $(RUSTC) $(rust_flags) --print sysroot)
rustc_host_target := $(shell $(RUSTC) --version --verbose | grep -F 'host: ' | cut -d' ' -f2)
......@@ -109,17 +111,17 @@ 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 \
--extern bindings --extern uapi
rustdoc-kernel: $(src)/kernel/lib.rs rustdoc-core rustdoc-ffi rustdoc-macros \
rustdoc-compiler_builtins $(obj)/libmacros.so \
rustdoc-compiler_builtins $(obj)/$(libmacros_name) \
$(obj)/bindings.o FORCE
+$(call if_changed,rustdoc)
quiet_cmd_rustc_test_library = RUSTC TL $<
quiet_cmd_rustc_test_library = $(RUSTC_OR_CLIPPY_QUIET) TL $<
cmd_rustc_test_library = \
OBJTREE=$(abspath $(objtree)) \
$(RUSTC) $(rust_common_flags) \
$(RUSTC_OR_CLIPPY) $(rust_common_flags) \
@$(objtree)/include/generated/rustc_cfg $(rustc_target_flags) \
--crate-type $(if $(rustc_test_library_proc),proc-macro,rlib) \
--out-dir $(objtree)/$(obj)/test --cfg testlib \
......@@ -187,10 +189,10 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
# We cannot use `-Zpanic-abort-tests` because some tests are dynamic,
# so for the moment we skip `-Cpanic=abort`.
quiet_cmd_rustc_test = RUSTC T $<
quiet_cmd_rustc_test = $(RUSTC_OR_CLIPPY_QUIET) T $<
cmd_rustc_test = \
OBJTREE=$(abspath $(objtree)) \
$(RUSTC) --test $(rust_common_flags) \
$(RUSTC_OR_CLIPPY) --test $(rust_common_flags) \
@$(objtree)/include/generated/rustc_cfg \
$(rustc_target_flags) --out-dir $(objtree)/$(obj)/test \
-L$(objtree)/$(obj)/test \
......@@ -359,13 +361,13 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
cmd_rustc_procmacro = \
$(RUSTC_OR_CLIPPY) $(rust_common_flags) \
-Clinker-flavor=gcc -Clinker=$(HOSTCC) \
-Clink-args='$(call escsq,$(KBUILD_HOSTLDFLAGS))' \
-Clink-args='$(call escsq,$(KBUILD_PROCMACROLDFLAGS))' \
--emit=dep-info=$(depfile) --emit=link=$@ --extern proc_macro \
--crate-type proc-macro \
--crate-name $(patsubst lib%.so,%,$(notdir $@)) $<
--crate-name $(patsubst lib%.$(libmacros_extension),%,$(notdir $@)) $<
# Procedural macros can only be used with the `rustc` that compiled it.
$(obj)/libmacros.so: $(src)/macros/lib.rs FORCE
$(obj)/$(libmacros_name): $(src)/macros/lib.rs FORCE
+$(call if_changed_dep,rustc_procmacro)
quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L $@
......@@ -382,7 +384,7 @@ quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L
$(cmd_objtool)
rust-analyzer:
$(Q)$(srctree)/scripts/generate_rust_analyzer.py \
$(Q)MAKEFLAGS= $(srctree)/scripts/generate_rust_analyzer.py \
--cfgs='core=$(core-cfgs)' \
$(realpath $(srctree)) $(realpath $(objtree)) \
$(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \
......@@ -443,7 +445,7 @@ $(obj)/uapi.o: $(src)/uapi/lib.rs \
$(obj)/kernel.o: private rustc_target_flags = --extern ffi \
--extern build_error --extern macros --extern bindings --extern uapi
$(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/build_error.o \
$(obj)/libmacros.so $(obj)/bindings.o $(obj)/uapi.o FORCE
$(obj)/$(libmacros_name) $(obj)/bindings.o $(obj)/uapi.o FORCE
+$(call if_changed_rule,rustc_library)
ifdef CONFIG_JUMP_LABEL
......
......@@ -10,4 +10,39 @@
#![no_std]
pub use core::ffi::*;
macro_rules! alias {
($($name:ident = $ty:ty;)*) => {$(
#[allow(non_camel_case_types, missing_docs)]
pub type $name = $ty;
// Check size compatibility with `core`.
const _: () = assert!(
core::mem::size_of::<$name>() == core::mem::size_of::<core::ffi::$name>()
);
)*}
}
alias! {
// `core::ffi::c_char` is either `i8` or `u8` depending on architecture. In the kernel, we use
// `-funsigned-char` so it's always mapped to `u8`.
c_char = u8;
c_schar = i8;
c_uchar = u8;
c_short = i16;
c_ushort = u16;
c_int = i32;
c_uint = u32;
// In the kernel, `intptr_t` is defined to be `long` in all platforms, so we can map the type to
// `isize`.
c_long = isize;
c_ulong = usize;
c_longlong = i64;
c_ulonglong = u64;
}
pub use core::ffi::c_void;
......@@ -123,7 +123,7 @@ pub mod flags {
/// [`Allocator`] is designed to be implemented as a ZST; [`Allocator`] functions do not operate on
/// an object instance.
///
/// In order to be able to support `#[derive(SmartPointer)]` later on, we need to avoid a design
/// In order to be able to support `#[derive(CoercePointee)]` later on, we need to avoid a design
/// that requires an `Allocator` to be instantiated, hence its functions must not contain any kind
/// of `self` parameter.
///
......
......@@ -354,22 +354,30 @@ impl<T: 'static, A> ForeignOwnable for Box<T, A>
A: Allocator,
{
type Borrowed<'a> = &'a T;
type BorrowedMut<'a> = &'a mut T;
fn into_foreign(self) -> *const crate::ffi::c_void {
Box::into_raw(self) as _
fn into_foreign(self) -> *mut crate::ffi::c_void {
Box::into_raw(self).cast()
}
unsafe fn from_foreign(ptr: *const crate::ffi::c_void) -> Self {
unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> Self {
// SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
// call to `Self::into_foreign`.
unsafe { Box::from_raw(ptr as _) }
unsafe { Box::from_raw(ptr.cast()) }
}
unsafe fn borrow<'a>(ptr: *const crate::ffi::c_void) -> &'a T {
unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> &'a T {
// SAFETY: The safety requirements of this method ensure that the object remains alive and
// immutable for the duration of 'a.
unsafe { &*ptr.cast() }
}
unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> &'a mut T {
let ptr = ptr.cast();
// SAFETY: The safety requirements of this method ensure that the pointer is valid and that
// nothing else will access the value for the duration of 'a.
unsafe { &mut *ptr }
}
}
impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>>
......@@ -377,19 +385,20 @@ impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>>
A: Allocator,
{
type Borrowed<'a> = Pin<&'a T>;
type BorrowedMut<'a> = Pin<&'a mut T>;
fn into_foreign(self) -> *const crate::ffi::c_void {
fn into_foreign(self) -> *mut crate::ffi::c_void {
// 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) }).cast()
}
unsafe fn from_foreign(ptr: *const crate::ffi::c_void) -> Self {
unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> Self {
// SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
// call to `Self::into_foreign`.
unsafe { Pin::new_unchecked(Box::from_raw(ptr as _)) }
unsafe { Pin::new_unchecked(Box::from_raw(ptr.cast())) }
}
unsafe fn borrow<'a>(ptr: *const crate::ffi::c_void) -> Pin<&'a T> {
unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> Pin<&'a T> {
// SAFETY: The safety requirements for this function ensure that the object is still alive,
// so it is safe to dereference the raw pointer.
// The safety requirements of `from_foreign` also ensure that the object remains alive for
......@@ -399,6 +408,18 @@ unsafe fn borrow<'a>(ptr: *const crate::ffi::c_void) -> Pin<&'a T> {
// SAFETY: This pointer originates from a `Pin<Box<T>>`.
unsafe { Pin::new_unchecked(r) }
}
unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> Pin<&'a mut T> {
let ptr = ptr.cast();
// SAFETY: The safety requirements for this function ensure that the object is still alive,
// so it is safe to dereference the raw pointer.
// The safety requirements of `from_foreign` also ensure that the object remains alive for
// the lifetime of the returned value.
let r = unsafe { &mut *ptr };
// SAFETY: This pointer originates from a `Pin<Box<T>>`.
unsafe { Pin::new_unchecked(r) }
}
}
impl<T, A> Deref for Box<T, A>
......@@ -427,13 +448,23 @@ fn deref_mut(&mut self) -> &mut T {
}
}
impl<T, A> fmt::Display for Box<T, A>
where
T: ?Sized + fmt::Display,
A: Allocator,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<T as fmt::Display>::fmt(&**self, f)
}
}
impl<T, A> fmt::Debug for Box<T, A>
where
T: ?Sized + fmt::Debug,
A: Allocator,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
<T as fmt::Debug>::fmt(&**self, f)
}
}
......
......@@ -43,6 +43,25 @@ pub const fn empty() -> Self {
/// # Errors
///
/// When `len * size_of::<T>()` overflows or when `len * size_of::<T>() > isize::MAX`.
///
/// # Examples
///
/// ```
/// # use kernel::alloc::layout::{ArrayLayout, LayoutError};
/// let layout = ArrayLayout::<i32>::new(15)?;
/// assert_eq!(layout.len(), 15);
///
/// // Errors because `len * size_of::<T>()` overflows.
/// let layout = ArrayLayout::<i32>::new(isize::MAX as usize);
/// assert!(layout.is_err());
///
/// // Errors because `len * size_of::<i32>() > isize::MAX`,
/// // even though `len < isize::MAX`.
/// let layout = ArrayLayout::<i32>::new(isize::MAX as usize / 2);
/// assert!(layout.is_err());
///
/// # Ok::<(), Error>(())
/// ```
pub const fn new(len: usize) -> Result<Self, LayoutError> {
match len.checked_mul(core::mem::size_of::<T>()) {
Some(size) if size <= ISIZE_MAX => {
......
......@@ -174,9 +174,9 @@ pub fn build<T: Operations>(
///
/// # Invariants
///
/// - `gendisk` must always point to an initialized and valid `struct gendisk`.
/// - `gendisk` was added to the VFS through a call to
/// `bindings::device_add_disk`.
/// - `gendisk` must always point to an initialized and valid `struct gendisk`.
/// - `gendisk` was added to the VFS through a call to
/// `bindings::device_add_disk`.
pub struct GenDisk<T: Operations> {
_tagset: Arc<TagSet<T>>,
gendisk: *mut bindings::gendisk,
......
......@@ -9,6 +9,7 @@
block::mq::request::RequestDataWrapper,
block::mq::Request,
error::{from_result, Result},
prelude::*,
types::ARef,
};
use core::{marker::PhantomData, sync::atomic::AtomicU64, sync::atomic::Ordering};
......@@ -35,7 +36,7 @@ pub trait Operations: Sized {
/// Called by the kernel to poll the device for completed requests. Only
/// used for poll queues.
fn poll() -> bool {
crate::build_error(crate::error::VTABLE_DEFAULT_ERROR)
build_error!(crate::error::VTABLE_DEFAULT_ERROR)
}
}
......
......@@ -2,6 +2,9 @@
//! Build-time assert.
#[doc(hidden)]
pub use build_error::build_error;
/// 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.
......@@ -11,7 +14,6 @@
/// # Examples
///
/// ```
/// # use kernel::build_error;
/// #[inline]
/// fn foo(a: usize) -> usize {
/// a.checked_add(1).unwrap_or_else(|| build_error!("overflow"))
......@@ -23,10 +25,10 @@
#[macro_export]
macro_rules! build_error {
() => {{
$crate::build_error("")
$crate::build_assert::build_error("")
}};
($msg:expr) => {{
$crate::build_error($msg)
$crate::build_assert::build_error($msg)
}};
}
......@@ -73,12 +75,12 @@ macro_rules! build_error {
macro_rules! build_assert {
($cond:expr $(,)?) => {{
if !$cond {
$crate::build_error(concat!("assertion failed: ", stringify!($cond)));
$crate::build_assert::build_error(concat!("assertion failed: ", stringify!($cond)));
}
}};
($cond:expr, $msg:expr) => {{
if !$cond {
$crate::build_error($msg);
$crate::build_assert::build_error($msg);
}
}};
}
......@@ -173,10 +173,10 @@ unsafe fn printk(&self, klevel: &[u8], msg: fmt::Arguments<'_>) {
#[cfg(CONFIG_PRINTK)]
unsafe {
bindings::_dev_printk(
klevel as *const _ as *const core::ffi::c_char,
klevel as *const _ as *const crate::ffi::c_char,
self.as_raw(),
c_str!("%pA").as_char_ptr(),
&msg as *const _ as *const core::ffi::c_void,
&msg as *const _ as *const crate::ffi::c_void,
)
};
}
......
......@@ -4,9 +4,10 @@
//!
//! C header: [`include/uapi/asm-generic/errno-base.h`](srctree/include/uapi/asm-generic/errno-base.h)
use crate::{alloc::AllocError, str::CStr};
use core::alloc::LayoutError;
use crate::{
alloc::{layout::LayoutError, AllocError},
str::CStr,
};
use core::fmt;
use core::num::NonZeroI32;
......@@ -101,19 +102,16 @@ impl Error {
/// It is a bug to pass an out-of-range `errno`. `EINVAL` would
/// be returned in such a case.
pub fn from_errno(errno: crate::ffi::c_int) -> Error {
if errno < -(bindings::MAX_ERRNO as i32) || errno >= 0 {
if let Some(error) = Self::try_from_errno(errno) {
error
} else {
// TODO: Make it a `WARN_ONCE` once available.
crate::pr_warn!(
"attempted to create `Error` with out of range `errno`: {}",
errno
);
return code::EINVAL;
code::EINVAL
}
// INVARIANT: The check above ensures the type invariant
// will hold.
// SAFETY: `errno` is checked above to be in a valid range.
unsafe { Error::from_errno_unchecked(errno) }
}
/// Creates an [`Error`] from a kernel error code.
......@@ -153,11 +151,8 @@ pub(crate) fn to_blk_status(self) -> bindings::blk_status_t {
/// Returns the error encoded as a pointer.
pub fn to_ptr<T>(self) -> *mut T {
#[cfg_attr(target_pointer_width = "32", allow(clippy::useless_conversion))]
// SAFETY: `self.0` is a valid error due to its invariant.
unsafe {
bindings::ERR_PTR(self.0.get().into()) as *mut _
}
unsafe { bindings::ERR_PTR(self.0.get() as _) as *mut _ }
}
/// Returns a string representing the error, if one exists.
......
......@@ -12,7 +12,7 @@
/// One of the following: `bindings::request_firmware`, `bindings::firmware_request_nowarn`,
/// `bindings::firmware_request_platform`, `bindings::request_firmware_direct`.
struct FwFunc(
unsafe extern "C" fn(*mut *const bindings::firmware, *const i8, *mut bindings::device) -> i32,
unsafe extern "C" fn(*mut *const bindings::firmware, *const u8, *mut bindings::device) -> i32,
);
impl FwFunc {
......
......@@ -290,9 +290,17 @@ macro_rules! stack_pin_init {
///
/// ```rust,ignore
/// # #![expect(clippy::disallowed_names)]
/// # use kernel::{init, pin_init, stack_try_pin_init, init::*, sync::Mutex, new_mutex};
/// # use kernel::{
/// # init,
/// # pin_init,
/// # stack_try_pin_init,
/// # init::*,
/// # sync::Mutex,
/// # new_mutex,
/// # alloc::AllocError,
/// # };
/// # use macros::pin_data;
/// # use core::{alloc::AllocError, pin::Pin};
/// # use core::pin::Pin;
/// #[pin_data]
/// struct Foo {
/// #[pin]
......@@ -316,9 +324,17 @@ macro_rules! stack_pin_init {
///
/// ```rust,ignore
/// # #![expect(clippy::disallowed_names)]
/// # use kernel::{init, pin_init, stack_try_pin_init, init::*, sync::Mutex, new_mutex};
/// # use kernel::{
/// # init,
/// # pin_init,
/// # stack_try_pin_init,
/// # init::*,
/// # sync::Mutex,
/// # new_mutex,
/// # alloc::AllocError,
/// # };
/// # use macros::pin_data;
/// # use core::{alloc::AllocError, pin::Pin};
/// # use core::pin::Pin;
/// #[pin_data]
/// struct Foo {
/// #[pin]
......@@ -1076,8 +1092,9 @@ pub fn uninit<T, E>() -> impl Init<MaybeUninit<T>, E> {
/// ```rust
/// use kernel::{alloc::KBox, error::Error, init::init_array_from_fn};
/// let array: KBox<[usize; 1_000]> =
/// KBox::init::<Error>(init_array_from_fn(|i| i), GFP_KERNEL).unwrap();
/// KBox::init::<Error>(init_array_from_fn(|i| i), GFP_KERNEL)?;
/// assert_eq!(array.len(), 1_000);
/// # Ok::<(), Error>(())
/// ```
pub fn init_array_from_fn<I, const N: usize, T, E>(
mut make_init: impl FnMut(usize) -> I,
......@@ -1120,8 +1137,9 @@ pub fn init_array_from_fn<I, const N: usize, T, E>(
/// ```rust
/// use kernel::{sync::{Arc, Mutex}, init::pin_init_array_from_fn, new_mutex};
/// let array: Arc<[Mutex<usize>; 1_000]> =
/// Arc::pin_init(pin_init_array_from_fn(|i| new_mutex!(i)), GFP_KERNEL).unwrap();
/// Arc::pin_init(pin_init_array_from_fn(|i| new_mutex!(i)), GFP_KERNEL)?;
/// assert_eq!(array.len(), 1_000);
/// # Ok::<(), Error>(())
/// ```
pub fn pin_init_array_from_fn<I, const N: usize, T, E>(
mut make_init: impl FnMut(usize) -> I,
......
......@@ -13,11 +13,12 @@
#![no_std]
#![feature(arbitrary_self_types)]
#![feature(coerce_unsized)]
#![feature(dispatch_from_dyn)]
#![cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, feature(derive_coerce_pointee))]
#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(coerce_unsized))]
#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(dispatch_from_dyn))]
#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(unsize))]
#![feature(inline_const)]
#![feature(lint_reasons)]
#![feature(unsize)]
// Ensure conditional compilation based on the kernel configuration works;
// otherwise we may silently break things like initcall handling.
......@@ -32,7 +33,8 @@
pub mod alloc;
#[cfg(CONFIG_BLOCK)]
pub mod block;
mod build_assert;
#[doc(hidden)]
pub mod build_assert;
pub mod cred;
pub mod device;
pub mod error;
......@@ -74,9 +76,6 @@
pub use macros;
pub use uapi;
#[doc(hidden)]
pub use build_error::build_error;
/// Prefix to appear before log messages printed from within the `kernel` crate.
const __LOG_PREFIX: &[u8] = b"rust_kernel\0";
......
......@@ -7,7 +7,7 @@
use crate::alloc::{AllocError, Flags};
use crate::prelude::*;
use crate::sync::{Arc, ArcBorrow, UniqueArc};
use core::marker::{PhantomPinned, Unsize};
use core::marker::PhantomPinned;
use core::ops::Deref;
use core::pin::Pin;
use core::sync::atomic::{AtomicBool, Ordering};
......@@ -159,6 +159,7 @@ fn try_new_list_arc(&self) -> bool {
///
/// [`List`]: crate::list::List
#[repr(transparent)]
#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))]
pub struct ListArc<T, const ID: u64 = 0>
where
T: ListArcSafe<ID> + ?Sized,
......@@ -443,18 +444,20 @@ fn as_ref(&self) -> &Arc<T> {
// This is to allow coercion from `ListArc<T>` to `ListArc<U>` if `T` can be converted to the
// dynamically-sized type (DST) `U`.
#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
impl<T, U, const ID: u64> core::ops::CoerceUnsized<ListArc<U, ID>> for ListArc<T, ID>
where
T: ListArcSafe<ID> + Unsize<U> + ?Sized,
T: ListArcSafe<ID> + core::marker::Unsize<U> + ?Sized,
U: ListArcSafe<ID> + ?Sized,
{
}
// This is to allow `ListArc<U>` to be dispatched on when `ListArc<T>` can be coerced into
// `ListArc<U>`.
#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
impl<T, U, const ID: u64> core::ops::DispatchFromDyn<ListArc<U, ID>> for ListArc<T, ID>
where
T: ListArcSafe<ID> + Unsize<U> + ?Sized,
T: ListArcSafe<ID> + core::marker::Unsize<U> + ?Sized,
U: ListArcSafe<ID> + ?Sized,
{
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment