mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 02:05:33 +00:00
Merge branch 'rust-next' of https://github.com/Rust-for-Linux/linux.git
# Conflicts: # rust/kernel/miscdevice.rs # rust/kernel/security.rs
This commit is contained in:
commit
7a7dd09ee4
@ -1,5 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
msrv = "1.78.0"
|
||||
|
||||
check-private-items = true
|
||||
|
||||
disallowed-macros = [
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -22,6 +22,7 @@
|
||||
*.dtb.S
|
||||
*.dtbo.S
|
||||
*.dwo
|
||||
*.dylib
|
||||
*.elf
|
||||
*.gcno
|
||||
*.gcda
|
||||
|
2
Makefile
2
Makefile
@ -1575,7 +1575,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 @@ impl QrImage<'_> {
|
||||
/// 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,
|
||||
|
@ -2003,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 \
|
||||
@ -363,10 +365,10 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
|
||||
-Clink-args='$(call escsq,$(KBUILD_HOSTLDFLAGS))' \
|
||||
--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 $@
|
||||
@ -383,7 +385,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)) \
|
||||
@ -473,7 +475,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
|
||||
|
37
rust/ffi.rs
37
rust/ffi.rs
@ -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;
|
||||
|
@ -427,13 +427,23 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,9 +174,9 @@ impl GenDiskBuilder {
|
||||
///
|
||||
/// # 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 @@ use crate::{
|
||||
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 @@ impl Device {
|
||||
#[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,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
@ -101,19 +101,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 +150,8 @@ impl Error {
|
||||
|
||||
/// 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 @@ use core::ptr::NonNull;
|
||||
/// 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 {
|
||||
|
@ -37,7 +37,8 @@ pub use ffi;
|
||||
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 device_id;
|
||||
@ -88,9 +89,6 @@ pub use bindings;
|
||||
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";
|
||||
|
||||
|
@ -12,18 +12,14 @@ use crate::{
|
||||
bindings,
|
||||
device::Device,
|
||||
error::{to_result, Error, Result, VTABLE_DEFAULT_ERROR},
|
||||
ffi::{c_int, c_long, c_uint, c_ulong},
|
||||
fs::File,
|
||||
prelude::*,
|
||||
seq_file::SeqFile,
|
||||
str::CStr,
|
||||
types::{ForeignOwnable, Opaque},
|
||||
};
|
||||
use core::{
|
||||
ffi::{c_int, c_long, c_uint, c_ulong},
|
||||
marker::PhantomData,
|
||||
mem::MaybeUninit,
|
||||
pin::Pin,
|
||||
};
|
||||
use core::{marker::PhantomData, mem::MaybeUninit, pin::Pin};
|
||||
|
||||
/// Options for creating a misc device.
|
||||
#[derive(Copy, Clone)]
|
||||
@ -134,7 +130,7 @@ pub trait MiscDevice: Sized {
|
||||
_cmd: u32,
|
||||
_arg: usize,
|
||||
) -> Result<isize> {
|
||||
kernel::build_error!(VTABLE_DEFAULT_ERROR)
|
||||
build_error!(VTABLE_DEFAULT_ERROR)
|
||||
}
|
||||
|
||||
/// Handler for ioctls.
|
||||
@ -151,7 +147,7 @@ pub trait MiscDevice: Sized {
|
||||
_cmd: u32,
|
||||
_arg: usize,
|
||||
) -> Result<isize> {
|
||||
kernel::build_error!(VTABLE_DEFAULT_ERROR)
|
||||
build_error!(VTABLE_DEFAULT_ERROR)
|
||||
}
|
||||
|
||||
/// Show info for this fd.
|
||||
@ -160,7 +156,7 @@ pub trait MiscDevice: Sized {
|
||||
_m: &SeqFile,
|
||||
_file: &File,
|
||||
) {
|
||||
kernel::build_error!(VTABLE_DEFAULT_ERROR)
|
||||
build_error!(VTABLE_DEFAULT_ERROR)
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,7 +275,7 @@ unsafe extern "C" fn fops_ioctl<T: MiscDevice>(
|
||||
// * There is no active fdget_pos region on the file on this thread.
|
||||
let file = unsafe { File::from_raw_file(file) };
|
||||
|
||||
match T::ioctl(device, file, cmd, arg as usize) {
|
||||
match T::ioctl(device, file, cmd, arg) {
|
||||
Ok(ret) => ret as c_long,
|
||||
Err(err) => err.to_errno() as c_long,
|
||||
}
|
||||
@ -304,7 +300,7 @@ unsafe extern "C" fn fops_compat_ioctl<T: MiscDevice>(
|
||||
// * There is no active fdget_pos region on the file on this thread.
|
||||
let file = unsafe { File::from_raw_file(file) };
|
||||
|
||||
match T::compat_ioctl(device, file, cmd, arg as usize) {
|
||||
match T::compat_ioctl(device, file, cmd, arg) {
|
||||
Ok(ret) => ret as c_long,
|
||||
Err(err) => err.to_errno() as c_long,
|
||||
}
|
||||
|
@ -587,17 +587,17 @@ pub trait Driver {
|
||||
|
||||
/// Issues a PHY software reset.
|
||||
fn soft_reset(_dev: &mut Device) -> Result {
|
||||
kernel::build_error(VTABLE_DEFAULT_ERROR)
|
||||
build_error!(VTABLE_DEFAULT_ERROR)
|
||||
}
|
||||
|
||||
/// Sets up device-specific structures during discovery.
|
||||
fn probe(_dev: &mut Device) -> Result {
|
||||
kernel::build_error(VTABLE_DEFAULT_ERROR)
|
||||
build_error!(VTABLE_DEFAULT_ERROR)
|
||||
}
|
||||
|
||||
/// Probes the hardware to determine what abilities it has.
|
||||
fn get_features(_dev: &mut Device) -> Result {
|
||||
kernel::build_error(VTABLE_DEFAULT_ERROR)
|
||||
build_error!(VTABLE_DEFAULT_ERROR)
|
||||
}
|
||||
|
||||
/// Returns true if this is a suitable driver for the given phydev.
|
||||
@ -609,32 +609,32 @@ pub trait Driver {
|
||||
/// Configures the advertisement and resets auto-negotiation
|
||||
/// if auto-negotiation is enabled.
|
||||
fn config_aneg(_dev: &mut Device) -> Result {
|
||||
kernel::build_error(VTABLE_DEFAULT_ERROR)
|
||||
build_error!(VTABLE_DEFAULT_ERROR)
|
||||
}
|
||||
|
||||
/// Determines the negotiated speed and duplex.
|
||||
fn read_status(_dev: &mut Device) -> Result<u16> {
|
||||
kernel::build_error(VTABLE_DEFAULT_ERROR)
|
||||
build_error!(VTABLE_DEFAULT_ERROR)
|
||||
}
|
||||
|
||||
/// Suspends the hardware, saving state if needed.
|
||||
fn suspend(_dev: &mut Device) -> Result {
|
||||
kernel::build_error(VTABLE_DEFAULT_ERROR)
|
||||
build_error!(VTABLE_DEFAULT_ERROR)
|
||||
}
|
||||
|
||||
/// Resumes the hardware, restoring state if needed.
|
||||
fn resume(_dev: &mut Device) -> Result {
|
||||
kernel::build_error(VTABLE_DEFAULT_ERROR)
|
||||
build_error!(VTABLE_DEFAULT_ERROR)
|
||||
}
|
||||
|
||||
/// Overrides the default MMD read function for reading a MMD register.
|
||||
fn read_mmd(_dev: &mut Device, _devnum: u8, _regnum: u16) -> Result<u16> {
|
||||
kernel::build_error(VTABLE_DEFAULT_ERROR)
|
||||
build_error!(VTABLE_DEFAULT_ERROR)
|
||||
}
|
||||
|
||||
/// Overrides the default MMD write function for writing a MMD register.
|
||||
fn write_mmd(_dev: &mut Device, _devnum: u8, _regnum: u16, _val: u16) -> Result {
|
||||
kernel::build_error(VTABLE_DEFAULT_ERROR)
|
||||
build_error!(VTABLE_DEFAULT_ERROR)
|
||||
}
|
||||
|
||||
/// Callback for notification of link change.
|
||||
|
@ -19,7 +19,7 @@ pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec, VBox, VVec, Vec}
|
||||
#[doc(no_inline)]
|
||||
pub use macros::{module, pin_data, pinned_drop, vtable, Zeroable};
|
||||
|
||||
pub use super::build_assert;
|
||||
pub use super::{build_assert, build_error};
|
||||
|
||||
// `super::std_vendor` is hidden, which makes the macro inline for some reason.
|
||||
#[doc(no_inline)]
|
||||
|
@ -107,7 +107,7 @@ pub unsafe fn call_printk(
|
||||
// SAFETY: TODO.
|
||||
unsafe {
|
||||
bindings::_printk(
|
||||
format_string.as_ptr() as _,
|
||||
format_string.as_ptr(),
|
||||
module_name.as_ptr(),
|
||||
&args as *const _ as *const c_void,
|
||||
);
|
||||
@ -128,7 +128,7 @@ pub fn call_printk_cont(args: fmt::Arguments<'_>) {
|
||||
#[cfg(CONFIG_PRINTK)]
|
||||
unsafe {
|
||||
bindings::_printk(
|
||||
format_strings::CONT.as_ptr() as _,
|
||||
format_strings::CONT.as_ptr(),
|
||||
&args as *const _ as *const c_void,
|
||||
);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ impl SeqFile {
|
||||
bindings::seq_printf(
|
||||
self.inner.get(),
|
||||
c_str!("%pA").as_char_ptr(),
|
||||
&args as *const _ as *const core::ffi::c_void,
|
||||
&args as *const _ as *const crate::ffi::c_void,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ impl CStr {
|
||||
// to a `NUL`-terminated C string.
|
||||
let len = unsafe { bindings::strlen(ptr) } + 1;
|
||||
// SAFETY: Lifetime guaranteed by the safety precondition.
|
||||
let bytes = unsafe { core::slice::from_raw_parts(ptr as _, len as _) };
|
||||
let bytes = unsafe { core::slice::from_raw_parts(ptr as _, len) };
|
||||
// SAFETY: As `len` is returned by `strlen`, `bytes` does not contain interior `NUL`.
|
||||
// As we have added 1 to `len`, the last byte is known to be `NUL`.
|
||||
unsafe { Self::from_bytes_with_nul_unchecked(bytes) }
|
||||
@ -248,7 +248,7 @@ impl CStr {
|
||||
/// Returns a C pointer to the string.
|
||||
#[inline]
|
||||
pub const fn as_char_ptr(&self) -> *const crate::ffi::c_char {
|
||||
self.0.as_ptr() as _
|
||||
self.0.as_ptr()
|
||||
}
|
||||
|
||||
/// Convert the string to a byte slice without the trailing `NUL` byte.
|
||||
@ -522,6 +522,7 @@ macro_rules! c_str {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[expect(clippy::items_after_test_module)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@ -547,7 +548,7 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
const ALL_ASCII_CHARS: &'static str =
|
||||
const ALL_ASCII_CHARS: &str =
|
||||
"\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\
|
||||
\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f \
|
||||
!\"#$%&'()*+,-./0123456789:;<=>?@\
|
||||
@ -581,6 +582,7 @@ mod tests {
|
||||
fn test_cstr_as_str_unchecked() {
|
||||
let good_bytes = b"\xf0\x9f\x90\xA7\0";
|
||||
let checked_cstr = CStr::from_bytes_with_nul(good_bytes).unwrap();
|
||||
// SAFETY: The contents come from a string literal which contains valid UTF-8.
|
||||
let unchecked_str = unsafe { checked_cstr.as_str_unchecked() };
|
||||
assert_eq!(unchecked_str, "🐧");
|
||||
}
|
||||
@ -838,7 +840,7 @@ impl CString {
|
||||
// SAFETY: The buffer is valid for read because `f.bytes_written()` is bounded by `size`
|
||||
// (which the minimum buffer size) and is non-zero (we wrote at least the `NUL` terminator)
|
||||
// so `f.bytes_written() - 1` doesn't underflow.
|
||||
let ptr = unsafe { bindings::memchr(buf.as_ptr().cast(), 0, (f.bytes_written() - 1) as _) };
|
||||
let ptr = unsafe { bindings::memchr(buf.as_ptr().cast(), 0, f.bytes_written() - 1) };
|
||||
if !ptr.is_null() {
|
||||
return Err(EINVAL);
|
||||
}
|
||||
|
@ -127,6 +127,14 @@ mod std_vendor;
|
||||
/// ```
|
||||
pub struct Arc<T: ?Sized> {
|
||||
ptr: NonNull<ArcInner<T>>,
|
||||
// NB: this informs dropck that objects of type `ArcInner<T>` may be used in `<Arc<T> as
|
||||
// Drop>::drop`. Note that dropck already assumes that objects of type `T` may be used in
|
||||
// `<Arc<T> as Drop>::drop` and the distinction between `T` and `ArcInner<T>` is not presently
|
||||
// meaningful with respect to dropck - but this may change in the future so this is left here
|
||||
// out of an abundance of caution.
|
||||
//
|
||||
// See https://doc.rust-lang.org/nomicon/phantom-data.html#generic-parameters-and-drop-checking
|
||||
// for more detail on the semantics of dropck in the presence of `PhantomData`.
|
||||
_p: PhantomData<ArcInner<T>>,
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
alloc::Flags,
|
||||
bindings,
|
||||
error::Result,
|
||||
ffi::{c_ulong, c_void},
|
||||
ffi::c_void,
|
||||
prelude::*,
|
||||
transmute::{AsBytes, FromBytes},
|
||||
};
|
||||
@ -224,13 +224,9 @@ impl UserSliceReader {
|
||||
if len > self.length {
|
||||
return Err(EFAULT);
|
||||
}
|
||||
let Ok(len_ulong) = c_ulong::try_from(len) else {
|
||||
return Err(EFAULT);
|
||||
};
|
||||
// SAFETY: `out_ptr` points into a mutable slice of length `len_ulong`, so we may write
|
||||
// SAFETY: `out_ptr` points into a mutable slice of length `len`, so we may write
|
||||
// that many bytes to it.
|
||||
let res =
|
||||
unsafe { bindings::copy_from_user(out_ptr, self.ptr as *const c_void, len_ulong) };
|
||||
let res = unsafe { bindings::copy_from_user(out_ptr, self.ptr as *const c_void, len) };
|
||||
if res != 0 {
|
||||
return Err(EFAULT);
|
||||
}
|
||||
@ -259,9 +255,6 @@ impl UserSliceReader {
|
||||
if len > self.length {
|
||||
return Err(EFAULT);
|
||||
}
|
||||
let Ok(len_ulong) = c_ulong::try_from(len) else {
|
||||
return Err(EFAULT);
|
||||
};
|
||||
let mut out: MaybeUninit<T> = MaybeUninit::uninit();
|
||||
// SAFETY: The local variable `out` is valid for writing `size_of::<T>()` bytes.
|
||||
//
|
||||
@ -272,7 +265,7 @@ impl UserSliceReader {
|
||||
bindings::_copy_from_user(
|
||||
out.as_mut_ptr().cast::<c_void>(),
|
||||
self.ptr as *const c_void,
|
||||
len_ulong,
|
||||
len,
|
||||
)
|
||||
};
|
||||
if res != 0 {
|
||||
@ -335,12 +328,9 @@ impl UserSliceWriter {
|
||||
if len > self.length {
|
||||
return Err(EFAULT);
|
||||
}
|
||||
let Ok(len_ulong) = c_ulong::try_from(len) else {
|
||||
return Err(EFAULT);
|
||||
};
|
||||
// SAFETY: `data_ptr` points into an immutable slice of length `len_ulong`, so we may read
|
||||
// SAFETY: `data_ptr` points into an immutable slice of length `len`, so we may read
|
||||
// that many bytes from it.
|
||||
let res = unsafe { bindings::copy_to_user(self.ptr as *mut c_void, data_ptr, len_ulong) };
|
||||
let res = unsafe { bindings::copy_to_user(self.ptr as *mut c_void, data_ptr, len) };
|
||||
if res != 0 {
|
||||
return Err(EFAULT);
|
||||
}
|
||||
@ -359,9 +349,6 @@ impl UserSliceWriter {
|
||||
if len > self.length {
|
||||
return Err(EFAULT);
|
||||
}
|
||||
let Ok(len_ulong) = c_ulong::try_from(len) else {
|
||||
return Err(EFAULT);
|
||||
};
|
||||
// SAFETY: The reference points to a value of type `T`, so it is valid for reading
|
||||
// `size_of::<T>()` bytes.
|
||||
//
|
||||
@ -372,7 +359,7 @@ impl UserSliceWriter {
|
||||
bindings::_copy_to_user(
|
||||
self.ptr as *mut c_void,
|
||||
(value as *const T).cast::<c_void>(),
|
||||
len_ulong,
|
||||
len,
|
||||
)
|
||||
};
|
||||
if res != 0 {
|
||||
|
@ -69,6 +69,7 @@
|
||||
//! fn print_later(val: Arc<MyStruct>) {
|
||||
//! let _ = workqueue::system().enqueue(val);
|
||||
//! }
|
||||
//! # print_later(MyStruct::new(42).unwrap());
|
||||
//! ```
|
||||
//!
|
||||
//! The following example shows how multiple `work_struct` fields can be used:
|
||||
@ -126,6 +127,8 @@
|
||||
//! fn print_2_later(val: Arc<MyStruct>) {
|
||||
//! let _ = workqueue::system().enqueue::<Arc<MyStruct>, 2>(val);
|
||||
//! }
|
||||
//! # print_1_later(MyStruct::new(24, 25).unwrap());
|
||||
//! # print_2_later(MyStruct::new(41, 42).unwrap());
|
||||
//! ```
|
||||
//!
|
||||
//! C header: [`include/linux/workqueue.h`](srctree/include/linux/workqueue.h)
|
||||
|
@ -123,12 +123,12 @@ pub fn module(ts: TokenStream) -> TokenStream {
|
||||
/// used on the Rust side, it should not be possible to call the default
|
||||
/// implementation. This is done to ensure that we call the vtable methods
|
||||
/// through the C vtable, and not through the Rust vtable. Therefore, the
|
||||
/// default implementation should call `kernel::build_error`, which prevents
|
||||
/// default implementation should call `build_error!`, which prevents
|
||||
/// calls to this function at compile time:
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// # // Intentionally missing `use`s to simplify `rusttest`.
|
||||
/// kernel::build_error(VTABLE_DEFAULT_ERROR)
|
||||
/// build_error!(VTABLE_DEFAULT_ERROR)
|
||||
/// ```
|
||||
///
|
||||
/// Note that you might need to import [`kernel::error::VTABLE_DEFAULT_ERROR`].
|
||||
@ -145,11 +145,11 @@ pub fn module(ts: TokenStream) -> TokenStream {
|
||||
/// #[vtable]
|
||||
/// pub trait Operations: Send + Sync + Sized {
|
||||
/// fn foo(&self) -> Result<()> {
|
||||
/// kernel::build_error(VTABLE_DEFAULT_ERROR)
|
||||
/// build_error!(VTABLE_DEFAULT_ERROR)
|
||||
/// }
|
||||
///
|
||||
/// fn bar(&self) -> Result<()> {
|
||||
/// kernel::build_error(VTABLE_DEFAULT_ERROR)
|
||||
/// build_error!(VTABLE_DEFAULT_ERROR)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
|
@ -83,7 +83,7 @@ impl Drop for RustPrint {
|
||||
}
|
||||
|
||||
mod trace {
|
||||
use core::ffi::c_int;
|
||||
use kernel::ffi::c_int;
|
||||
|
||||
kernel::declare_trace! {
|
||||
/// # Safety
|
||||
|
@ -8,6 +8,7 @@ import json
|
||||
import logging
|
||||
import os
|
||||
import pathlib
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
def args_crates_cfgs(cfgs):
|
||||
@ -35,8 +36,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
|
||||
crates_cfgs = args_crates_cfgs(cfgs)
|
||||
|
||||
def append_crate(display_name, root_module, deps, cfg=[], is_workspace_member=True, is_proc_macro=False):
|
||||
crates_indexes[display_name] = len(crates)
|
||||
crates.append({
|
||||
crate = {
|
||||
"display_name": display_name,
|
||||
"root_module": str(root_module),
|
||||
"is_workspace_member": is_workspace_member,
|
||||
@ -47,7 +47,15 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
|
||||
"env": {
|
||||
"RUST_MODFILE": "This is only for rust-analyzer"
|
||||
}
|
||||
})
|
||||
}
|
||||
if is_proc_macro:
|
||||
proc_macro_dylib_name = subprocess.check_output(
|
||||
[os.environ["RUSTC"], "--print", "file-names", "--crate-name", display_name, "--crate-type", "proc-macro", "-"],
|
||||
stdin=subprocess.DEVNULL,
|
||||
).decode('utf-8').strip()
|
||||
crate["proc_macro_dylib_path"] = f"{objtree}/rust/{proc_macro_dylib_name}"
|
||||
crates_indexes[display_name] = len(crates)
|
||||
crates.append(crate)
|
||||
|
||||
# First, the ones in `rust/` since they are a bit special.
|
||||
append_crate(
|
||||
@ -70,7 +78,6 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
|
||||
[],
|
||||
is_proc_macro=True,
|
||||
)
|
||||
crates[-1]["proc_macro_dylib_path"] = f"{objtree}/rust/libmacros.so"
|
||||
|
||||
append_crate(
|
||||
"build_error",
|
||||
|
@ -123,8 +123,10 @@ fi
|
||||
# Non-stable and distributions' versions may have a version suffix, e.g. `-dev`.
|
||||
#
|
||||
# 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).
|
||||
rust_bindings_generator_output=$( \
|
||||
LC_ALL=C "$BINDGEN" --version workaround-for-0.69.0 2>/dev/null
|
||||
) || rust_bindings_generator_code=$?
|
||||
|
Loading…
x
Reference in New Issue
Block a user