Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

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

- Bump the minimum Rust version to 1.85.0 (and 'bindgen' to 0.71.1).

As proposed in LPC 2025 and the Maintainers Summit [1], we are
going to follow Debian Stable's Rust versions as our minimum
versions.

Debian Trixie was released on 2025-08-09 with a Rust 1.85.0 and
'bindgen' 0.71.1 toolchain, which is a fair amount of time for e.g.
kernel developers to upgrade.

Other major distributions support a Rust version that is high
enough as well, including:

+ Arch Linux.
+ Fedora Linux.
+ Gentoo Linux.
+ Nix.
+ openSUSE Slowroll and openSUSE Tumbleweed.
+ Ubuntu 25.10 and 26.04 LTS. In addition, 24.04 LTS using
their versioned packages.

The merged patch series comes with the associated cleanups and
simplifications treewide that can be performed thanks to both
bumps, as well as documentation updates.

In addition, start using 'bindgen''s '--with-attribute-custom-enum'
feature to set the 'cfi_encoding' attribute for the 'lru_status'
enum used in Binder.

Link: https://lwn.net/Articles/1050174/ [1]

- Add experimental Kconfig option ('CONFIG_RUST_INLINE_HELPERS') that
inlines C helpers into Rust.

Essentially, it performs a step similar to LTO, but just for the
helpers, i.e. very local and fast.

It relies on 'llvm-link' and its '--internalize' flag, and requires
a compatible LLVM between Clang and 'rustc' (i.e. same major
version, 'CONFIG_RUSTC_CLANG_LLVM_COMPATIBLE'). It is only enabled
for two architectures for now.

The result is a measurable speedup in different workloads that
different users have tested. For instance, for the null block
driver, it amounts to a 2%.

- Support global per-version flags.

While we already have per-version flags in many places, we didn't
have a place to set global ones that depend on the compiler
version, i.e. in 'rust_common_flags', which sometimes is needed to
e.g. tweak the lints set per version.

Use that to allow the 'clippy::precedence' lint for Rust < 1.86.0,
since it had a change in behavior.

- Support overriding the crate name and apply it to Rust Binder,
which wanted the module to be called 'rust_binder'.

- Add the remaining '__rust_helper' annotations (started in the
previous cycle).

'kernel' crate:

- Introduce the 'const_assert!' macro: a more powerful version of
'static_assert!' that can refer to generics inside functions or
implementation bodies, e.g.:

fn f<const N: usize>() {
const_assert!(N > 1);
}

fn g<T>() {
const_assert!(size_of::<T>() > 0, "T cannot be ZST");
}

In addition, reorganize our set of build-time assertion macros
('{build,const,static_assert}!') to live in the 'build_assert'
module.

Finally, improve the docs as well to clarify how these are
different from one another and how to pick the right one to use,
and their equivalence (if any) to the existing C ones for extra
clarity.

- 'sizes' module: add 'SizeConstants' trait.

This gives us typed 'SZ_*' constants (avoiding casts) for use in
device address spaces where the address width depends on the
hardware (e.g. 32-bit MMIO windows, 64-bit GPU framebuffers, etc.),
e.g.:

let gpu_heap = 14 * u64::SZ_1M;
let mmio_window = u32::SZ_16M;

- 'clk' module: implement 'Send' and 'Sync' for 'Clk' and thus
simplify the users in Tyr and PWM.

- 'ptr' module: add 'const_align_up'.

- 'str' module: improve the documentation of the 'c_str!' macro to
explain that one should only use it for non-literal cases (for the
other case we instead use C string literals, e.g. 'c"abc"').

- Disallow the use of 'CStr::{as_ptr,from_ptr}' and clean one such
use in the 'task' module.

- 'sync' module: finish the move of 'ARef' and 'AlwaysRefCounted'
outside of the 'types' module, i.e. update the last remaining
instances and finally remove the re-exports.

- 'error' module: clarify that 'from_err_ptr' can return 'Ok(NULL)',
including runtime-tested examples.

The intention is to hopefully prevent UB that assumes the result of
the function is not 'NULL' if successful. This originated from a
case of UB I noticed in 'regulator' that created a 'NonNull' on it.

Timekeeping:

- Expand the example section in the 'HrTimer' documentation.

- Mark the 'ClockSource' trait as unsafe to ensure valid values for
'ktime_get()'.

- Add 'Delta::from_nanos()'.

'pin-init' crate:

- Replace the 'Zeroable' impls for 'Option<NonZero*>' with impls of
'ZeroableOption' for 'NonZero*'.

- Improve feature gate handling for unstable features.

- Declutter the documentation of implementations of 'Zeroable' for
tuples.

- Replace uses of 'addr_of[_mut]!' with '&raw [mut]'.

rust-analyzer:

- Add type annotations to 'generate_rust_analyzer.py'.

- Add support for scripts written in Rust ('generate_rust_target.rs',
'rustdoc_test_builder.rs', 'rustdoc_test_gen.rs').

- Refactor 'generate_rust_analyzer.py' to explicitly identify host
and target crates, improve readability, and reduce duplication.

And some other fixes, cleanups and improvements"

* tag 'rust-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux: (79 commits)
rust: sizes: add SizeConstants trait for device address space constants
rust: kernel: update `file_with_nul` comment
rust: kbuild: allow `clippy::precedence` for Rust < 1.86.0
rust: kbuild: support global per-version flags
rust: declare cfi_encoding for lru_status
docs: rust: general-information: use real example
docs: rust: general-information: simplify Kconfig example
docs: rust: quick-start: remove GDB/Binutils mention
docs: rust: quick-start: remove Nix "unstable channel" note
docs: rust: quick-start: remove Gentoo "testing" note
docs: rust: quick-start: add Ubuntu 26.04 LTS and remove subsection title
docs: rust: quick-start: update minimum Ubuntu version
docs: rust: quick-start: update Ubuntu versioned packages
docs: rust: quick-start: openSUSE provides `rust-src` package nowadays
rust: kbuild: remove "dummy parameter" workaround for `bindgen` < 0.71.1
rust: kbuild: update `bindgen --rust-target` version and replace comment
rust: rust_is_available: remove warning for `bindgen` < 0.69.5 && libclang >= 19.1
rust: rust_is_available: remove warning for `bindgen` 0.66.[01]
rust: bump `bindgen` minimum supported version to 0.71.1 (Debian Trixie)
rust: block: update `const_refs_to_static` MSRV TODO comment
...

+1396 -826
+11 -1
.clippy.toml
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 3 - msrv = "1.78.0" 3 + msrv = "1.85.0" 4 4 5 5 check-private-items = true 6 6 ··· 9 9 # it here, see: https://github.com/rust-lang/rust-clippy/issues/11303. 10 10 { path = "kernel::dbg", reason = "the `dbg!` macro is intended as a debugging tool", allow-invalid = true }, 11 11 ] 12 + 13 + [[disallowed-methods]] 14 + path = "core::ffi::CStr::as_ptr" 15 + replacement = "kernel::prelude::CStrExt::as_char_ptr" 16 + reason = "kernel's `char` is always unsigned, use `as_char_ptr` instead" 17 + 18 + [[disallowed-methods]] 19 + path = "core::ffi::CStr::from_ptr" 20 + replacement = "kernel::prelude::CStrExt::from_char_ptr" 21 + reason = "kernel's `char` is always unsigned, use `from_char_ptr` instead"
+4
.gitignore
··· 13 13 .* 14 14 *.a 15 15 *.asn1.[ch] 16 + *.bc 16 17 *.bin 17 18 *.bz2 18 19 *.c.[012]*.* ··· 185 184 186 185 # Rust analyzer configuration 187 186 /rust-project.json 187 + 188 + # bc language scripts (not LLVM bitcode) 189 + !kernel/time/timeconst.bc
+2 -2
Documentation/process/changes.rst
··· 31 31 ====================== =============== ======================================== 32 32 GNU C 8.1 gcc --version 33 33 Clang/LLVM (optional) 15.0.0 clang --version 34 - Rust (optional) 1.78.0 rustc --version 35 - bindgen (optional) 0.65.1 bindgen --version 34 + Rust (optional) 1.85.0 rustc --version 35 + bindgen (optional) 0.71.1 bindgen --version 36 36 GNU make 4.0 make --version 37 37 bash 4.2 bash --version 38 38 binutils 2.30 ld -v
+2 -2
Documentation/rust/general-information.rst
··· 157 157 158 158 .. code-block:: kconfig 159 159 160 - config RUSTC_VERSION_MIN_107900 161 - def_bool y if RUSTC_VERSION >= 107900 160 + config RUSTC_HAS_SPAN_FILE 161 + def_bool RUSTC_VERSION >= 108800
+20 -32
Documentation/rust/quick-start.rst
··· 57 57 Gentoo Linux 58 58 ************ 59 59 60 - Gentoo Linux (and especially the testing branch) provides recent Rust releases 61 - and thus it should generally work out of the box, e.g.:: 60 + Gentoo Linux provides recent Rust releases and thus it should generally work out 61 + of the box, e.g.:: 62 62 63 63 USE='rust-src rustfmt clippy' emerge dev-lang/rust dev-util/bindgen 64 64 ··· 68 68 Nix 69 69 *** 70 70 71 - Nix (unstable channel) provides recent Rust releases and thus it should 72 - generally work out of the box, e.g.:: 71 + Nix provides recent Rust releases and thus it should generally work out of the 72 + box, e.g.:: 73 73 74 74 { pkgs ? import <nixpkgs> {} }: 75 75 pkgs.mkShell { ··· 84 84 openSUSE Slowroll and openSUSE Tumbleweed provide recent Rust releases and thus 85 85 they should generally work out of the box, e.g.:: 86 86 87 - zypper install rust rust1.79-src rust-bindgen clang 87 + zypper install rust rust-src rust-bindgen clang 88 88 89 89 90 90 Ubuntu 91 91 ****** 92 92 93 - 25.04 94 - ~~~~~ 95 - 96 - The latest Ubuntu releases provide recent Rust releases and thus they should 93 + Ubuntu 25.10 and 26.04 LTS provide recent Rust releases and thus they should 97 94 generally work out of the box, e.g.:: 98 95 99 96 apt install rustc rust-src bindgen rustfmt rust-clippy ··· 109 112 releases, they require some additional configuration to be set, using 110 113 the versioned packages, e.g.:: 111 114 112 - apt install rustc-1.80 rust-1.80-src bindgen-0.65 rustfmt-1.80 \ 113 - rust-1.80-clippy 114 - ln -s /usr/lib/rust-1.80/bin/rustfmt /usr/bin/rustfmt-1.80 115 - ln -s /usr/lib/rust-1.80/bin/clippy-driver /usr/bin/clippy-driver-1.80 115 + apt install rustc-1.85 rust-1.85-src bindgen-0.71 rustfmt-1.85 \ 116 + rust-1.85-clippy 117 + ln -s /usr/lib/rust-1.85/bin/rustfmt /usr/bin/rustfmt-1.85 118 + ln -s /usr/lib/rust-1.85/bin/clippy-driver /usr/bin/clippy-driver-1.85 116 119 117 120 None of these packages set their tools as defaults; therefore they should be 118 121 specified explicitly, e.g.:: 119 122 120 - make LLVM=1 RUSTC=rustc-1.80 RUSTDOC=rustdoc-1.80 RUSTFMT=rustfmt-1.80 \ 121 - CLIPPY_DRIVER=clippy-driver-1.80 BINDGEN=bindgen-0.65 123 + make LLVM=1 RUSTC=rustc-1.85 RUSTDOC=rustdoc-1.85 RUSTFMT=rustfmt-1.85 \ 124 + CLIPPY_DRIVER=clippy-driver-1.85 BINDGEN=bindgen-0.71 122 125 123 - Alternatively, modify the ``PATH`` variable to place the Rust 1.80 binaries 126 + Alternatively, modify the ``PATH`` variable to place the Rust 1.85 binaries 124 127 first and set ``bindgen`` as the default, e.g.:: 125 128 126 - PATH=/usr/lib/rust-1.80/bin:$PATH 129 + PATH=/usr/lib/rust-1.85/bin:$PATH 127 130 update-alternatives --install /usr/bin/bindgen bindgen \ 128 - /usr/bin/bindgen-0.65 100 129 - update-alternatives --set bindgen /usr/bin/bindgen-0.65 131 + /usr/bin/bindgen-0.71 100 132 + update-alternatives --set bindgen /usr/bin/bindgen-0.71 130 133 131 - ``RUST_LIB_SRC`` needs to be set when using the versioned packages, e.g.:: 134 + ``RUST_LIB_SRC`` may need to be set when using the versioned packages, e.g.:: 132 135 133 - RUST_LIB_SRC=/usr/src/rustc-$(rustc-1.80 --version | cut -d' ' -f2)/library 136 + RUST_LIB_SRC=/usr/src/rustc-$(rustc-1.85 --version | cut -d' ' -f2)/library 134 137 135 138 For convenience, ``RUST_LIB_SRC`` can be exported to the global environment. 136 139 137 - In addition, ``bindgen-0.65`` is available in newer releases (24.04 LTS and 138 - 24.10), but it may not be available in older ones (20.04 LTS and 22.04 LTS), 140 + In addition, ``bindgen-0.71`` is available in newer releases (24.04 LTS), 141 + but it may not be available in older ones (20.04 LTS and 22.04 LTS), 139 142 thus ``bindgen`` may need to be built manually (please see below). 140 143 141 144 ··· 352 355 To dive deeper, take a look at the source code of the samples 353 356 at ``samples/rust/``, the Rust support code under ``rust/`` and 354 357 the ``Rust hacking`` menu under ``Kernel hacking``. 355 - 356 - If GDB/Binutils is used and Rust symbols are not getting demangled, the reason 357 - is the toolchain does not support Rust's new v0 mangling scheme yet. 358 - There are a few ways out: 359 - 360 - - Install a newer release (GDB >= 10.2, Binutils >= 2.36). 361 - 362 - - Some versions of GDB (e.g. vanilla GDB 10.1) are able to use 363 - the pre-demangled names embedded in the debug info (``CONFIG_DEBUG_INFO``).
+1
MAINTAINERS
··· 23166 23166 P: https://rust-for-linux.com/contributing 23167 23167 T: git https://github.com/Rust-for-Linux/linux.git rust-next 23168 23168 F: .clippy.toml 23169 + F: .rustfmt.toml 23169 23170 F: Documentation/rust/ 23170 23171 F: include/trace/events/rust_sample.h 23171 23172 F: rust/
+19 -2
Makefile
··· 487 487 -Wclippy::as_underscore \ 488 488 -Wclippy::cast_lossless \ 489 489 -Wclippy::ignored_unit_patterns \ 490 + -Aclippy::incompatible_msrv \ 490 491 -Wclippy::mut_mut \ 491 492 -Wclippy::needless_bitwise_bool \ 492 493 -Aclippy::needless_lifetimes \ ··· 496 495 -Wclippy::ptr_cast_constness \ 497 496 -Wclippy::ref_as_ptr \ 498 497 -Wclippy::undocumented_unsafe_blocks \ 498 + -Aclippy::uninlined_format_args \ 499 499 -Wclippy::unnecessary_safety_comment \ 500 500 -Wclippy::unnecessary_safety_doc \ 501 501 -Wrustdoc::missing_crate_level_docs \ ··· 507 505 KBUILD_HOSTCXXFLAGS := -Wall -O2 $(HOST_LFS_CFLAGS) $(HOSTCXXFLAGS) \ 508 506 -I $(srctree)/scripts/include 509 507 KBUILD_HOSTRUSTFLAGS := $(rust_common_flags) -O -Cstrip=debuginfo \ 510 - -Zallow-features= $(HOSTRUSTFLAGS) 508 + -Zallow-features= 511 509 KBUILD_HOSTLDFLAGS := $(HOST_LFS_LDFLAGS) $(HOSTLDFLAGS) 512 510 KBUILD_HOSTLDLIBS := $(HOST_LFS_LIBS) $(HOSTLDLIBS) 513 511 KBUILD_PROCMACROLDFLAGS := $(or $(PROCMACROLDFLAGS),$(KBUILD_HOSTLDFLAGS)) ··· 518 516 CC = $(LLVM_PREFIX)clang$(LLVM_SUFFIX) 519 517 LD = $(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX) 520 518 AR = $(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX) 519 + LLVM_LINK = $(LLVM_PREFIX)llvm-link$(LLVM_SUFFIX) 521 520 NM = $(LLVM_PREFIX)llvm-nm$(LLVM_SUFFIX) 522 521 OBJCOPY = $(LLVM_PREFIX)llvm-objcopy$(LLVM_SUFFIX) 523 522 OBJDUMP = $(LLVM_PREFIX)llvm-objdump$(LLVM_SUFFIX) ··· 632 629 export CLIPPY_CONF_DIR := $(srctree) 633 630 634 631 export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC HOSTPKG_CONFIG 635 - export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN 632 + export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN LLVM_LINK 636 633 export HOSTRUSTC KBUILD_HOSTRUSTFLAGS 637 634 export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL 638 635 export PERL PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX ··· 836 833 endif # CONFIG_TRACEPOINTS 837 834 838 835 export WARN_ON_UNUSED_TRACEPOINTS 836 + 837 + # Per-version Rust flags. These are like `rust_common_flags`, but may 838 + # depend on the Rust compiler version (e.g. using `rustc-min-version`). 839 + # 840 + # `-Aclippy::precedence`: the lint was extended in Rust 1.85.0 to 841 + # include bitmasking and shift operations. However, because it generated 842 + # many hits, in Rust 1.86.0 it was split into a new `precedence_bits` 843 + # lint which is not enabled by default. 844 + rust_common_flags_per_version := \ 845 + $(if $(call rustc-min-version,108600),,-Aclippy::precedence) 846 + 847 + rust_common_flags += $(rust_common_flags_per_version) 848 + KBUILD_HOSTRUSTFLAGS += $(rust_common_flags_per_version) $(HOSTRUSTFLAGS) 849 + KBUILD_RUSTFLAGS += $(rust_common_flags_per_version) 839 850 840 851 include $(srctree)/arch/$(SRCARCH)/Makefile 841 852
+1 -2
arch/Kconfig
··· 968 968 config HAVE_CFI_ICALL_NORMALIZE_INTEGERS_RUSTC 969 969 def_bool y 970 970 depends on HAVE_CFI_ICALL_NORMALIZE_INTEGERS 971 - depends on RUSTC_VERSION >= 107900 972 971 depends on ARM64 || X86_64 973 972 # With GCOV/KASAN we need this fix: https://github.com/rust-lang/rust/pull/129373 974 - depends on (RUSTC_LLVM_VERSION >= 190103 && RUSTC_VERSION >= 108200) || \ 973 + depends on RUSTC_LLVM_VERSION >= 190103 || \ 975 974 (!GCOV_KERNEL && !KASAN_GENERIC && !KASAN_SW_TAGS) 976 975 977 976 config CFI_PERMISSIVE
-8
arch/arm64/Kconfig
··· 292 292 config RUSTC_SUPPORTS_ARM64 293 293 def_bool y 294 294 depends on CPU_LITTLE_ENDIAN 295 - # Shadow call stack is only supported on certain rustc versions. 296 - # 297 - # When using the UNWIND_PATCH_PAC_INTO_SCS option, rustc version 1.80+ is 298 - # required due to use of the -Zfixed-x18 flag. 299 - # 300 - # Otherwise, rustc version 1.82+ is required due to use of the 301 - # -Zsanitizer=shadow-call-stack flag. 302 - depends on !SHADOW_CALL_STACK || RUSTC_VERSION >= 108200 || RUSTC_VERSION >= 108000 && UNWIND_PATCH_PAC_INTO_SCS 303 295 304 296 config CLANG_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS 305 297 def_bool CC_IS_CLANG
-3
arch/riscv/Kconfig
··· 232 232 config RUSTC_SUPPORTS_RISCV 233 233 def_bool y 234 234 depends on 64BIT 235 - # Shadow call stack requires rustc version 1.82+ due to use of the 236 - # -Zsanitizer=shadow-call-stack flag. 237 - depends on !SHADOW_CALL_STACK || RUSTC_VERSION >= 108200 238 235 239 236 config CLANG_SUPPORTS_DYNAMIC_FTRACE 240 237 def_bool CC_IS_CLANG
+1 -2
drivers/android/binder/Makefile
··· 5 5 rust_binder-y := \ 6 6 rust_binder_main.o \ 7 7 rust_binderfs.o \ 8 - rust_binder_events.o \ 9 - page_range_helper.o 8 + rust_binder_events.o
+3 -3
drivers/android/binder/page_range.rs
··· 683 683 unsafe { 684 684 bindings::list_lru_walk( 685 685 list_lru, 686 - Some(bindings::rust_shrink_free_page_wrap), 686 + Some(rust_shrink_free_page), 687 687 ptr::null_mut(), 688 688 nr_to_scan, 689 689 ) 690 690 } 691 691 } 692 692 693 - const LRU_SKIP: bindings::lru_status = bindings::lru_status_LRU_SKIP; 694 - const LRU_REMOVED_ENTRY: bindings::lru_status = bindings::lru_status_LRU_REMOVED_RETRY; 693 + const LRU_SKIP: bindings::lru_status = bindings::lru_status::LRU_SKIP; 694 + const LRU_REMOVED_ENTRY: bindings::lru_status = bindings::lru_status::LRU_REMOVED_RETRY; 695 695 696 696 /// # Safety 697 697 /// Called by the shrinker.
-24
drivers/android/binder/page_range_helper.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - 3 - /* C helper for page_range.rs to work around a CFI violation. 4 - * 5 - * Bindgen currently pretends that `enum lru_status` is the same as an integer. 6 - * This assumption is fine ABI-wise, but once you add CFI to the mix, it 7 - * triggers a CFI violation because `enum lru_status` gets a different CFI tag. 8 - * 9 - * This file contains a workaround until bindgen can be fixed. 10 - * 11 - * Copyright (C) 2025 Google LLC. 12 - */ 13 - #include "page_range_helper.h" 14 - 15 - unsigned int rust_shrink_free_page(struct list_head *item, 16 - struct list_lru_one *list, 17 - void *cb_arg); 18 - 19 - enum lru_status 20 - rust_shrink_free_page_wrap(struct list_head *item, struct list_lru_one *list, 21 - void *cb_arg) 22 - { 23 - return rust_shrink_free_page(item, list, cb_arg); 24 - }
-15
drivers/android/binder/page_range_helper.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - /* 3 - * Copyright (C) 2025 Google, Inc. 4 - */ 5 - 6 - #ifndef _LINUX_PAGE_RANGE_HELPER_H 7 - #define _LINUX_PAGE_RANGE_HELPER_H 8 - 9 - #include <linux/list_lru.h> 10 - 11 - enum lru_status 12 - rust_shrink_free_page_wrap(struct list_head *item, struct list_lru_one *list, 13 - void *cb_arg); 14 - 15 - #endif /* _LINUX_PAGE_RANGE_HELPER_H */
+2
drivers/android/binder/rust_binder_main.rs
··· 3 3 // Copyright (C) 2025 Google LLC. 4 4 5 5 //! Binder -- the Android IPC mechanism. 6 + 7 + #![crate_name = "rust_binder"] 6 8 #![recursion_limit = "256"] 7 9 #![allow( 8 10 clippy::as_underscore,
-12
drivers/gpu/drm/tyr/driver.rs
··· 53 53 pub(crate) gpu_info: GpuInfo, 54 54 } 55 55 56 - // Both `Clk` and `Regulator` do not implement `Send` or `Sync`, but they 57 - // should. There are patches on the mailing list to address this, but they have 58 - // not landed yet. 59 - // 60 - // For now, add this workaround so that this patch compiles with the promise 61 - // that it will be removed in a future patch. 62 - // 63 - // SAFETY: This will be removed in a future patch. 64 - unsafe impl Send for TyrData {} 65 - // SAFETY: This will be removed in a future patch. 66 - unsafe impl Sync for TyrData {} 67 - 68 56 fn issue_soft_reset(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result { 69 57 regs::GPU_CMD.write(dev, iomem, regs::GPU_CMD_SOFT_RESET)?; 70 58
+1 -5
drivers/gpu/nova-core/gsp/cmdq.rs
··· 293 293 let (slice_1, slice_2) = { 294 294 let (slice_1, slice_2) = self.driver_write_area(); 295 295 296 - #[allow(clippy::incompatible_msrv)] 297 296 (slice_1.as_flattened_mut(), slice_2.as_flattened_mut()) 298 297 }; 299 298 ··· 544 545 Delta::from_millis(1), 545 546 timeout, 546 547 ) 547 - .map(|(slice_1, slice_2)| { 548 - #[allow(clippy::incompatible_msrv)] 549 - (slice_1.as_flattened(), slice_2.as_flattened()) 550 - })?; 548 + .map(|(slice_1, slice_2)| (slice_1.as_flattened(), slice_2.as_flattened()))?; 551 549 552 550 // Extract the `GspMsgElement`. 553 551 let (header, slice_1) = GspMsgElement::from_bytes_prefix(slice_1).ok_or(EIO)?;
-3
drivers/gpu/nova-core/gsp/fw/r570_144.rs
··· 7 7 //! This module may not be directly used. Please abstract or re-export the needed symbols in the 8 8 //! parent module instead. 9 9 10 - #![cfg_attr(test, allow(deref_nullptr))] 11 - #![cfg_attr(test, allow(unaligned_references))] 12 - #![cfg_attr(test, allow(unsafe_op_in_unsafe_fn))] 13 10 #![allow( 14 11 dead_code, 15 12 clippy::all,
-15
drivers/pwm/pwm_th1520.rs
··· 99 99 clk: Clk, 100 100 } 101 101 102 - // This `unsafe` implementation is a temporary necessity because the underlying `kernel::clk::Clk` 103 - // type does not yet expose `Send` and `Sync` implementations. This block should be removed 104 - // as soon as the clock abstraction provides these guarantees directly. 105 - // TODO: Remove those unsafe impl's when Clk will support them itself. 106 - 107 - // SAFETY: The `devres` framework requires the driver's private data to be `Send` and `Sync`. 108 - // We can guarantee this because the PWM core synchronizes all callbacks, preventing concurrent 109 - // access to the contained `iomem` and `clk` resources. 110 - unsafe impl Send for Th1520PwmDriverData {} 111 - 112 - // SAFETY: The same reasoning applies as for `Send`. The PWM core's synchronization 113 - // guarantees that it is safe for multiple threads to have shared access (`&self`) 114 - // to the driver data during callbacks. 115 - unsafe impl Sync for Th1520PwmDriverData {} 116 - 117 102 impl pwm::PwmOps for Th1520PwmDriverData { 118 103 type WfHw = Th1520WfHw; 119 104
+16 -14
init/Kconfig
··· 82 82 int 83 83 default $(rustc-llvm-version) 84 84 85 + config RUSTC_LLVM_MAJOR_VERSION 86 + int 87 + default $(shell,expr $(rustc-llvm-version) / 10000) 88 + 89 + config RUSTC_CLANG_LLVM_COMPATIBLE 90 + bool 91 + default y if CC_IS_CLANG && RUSTC_LLVM_MAJOR_VERSION = $(shell,expr $(cc-version) / 10000) 92 + help 93 + This indicates whether Rust and Clang use LLVM of the same major 94 + version. 95 + 96 + Operations involving handling LLVM IR or bitcode (e.g. cross-language 97 + LTO) require the same LLVM major version to work properly. For best 98 + compatibility it is recommended that the exact same LLVM is used. 99 + 85 100 config ARCH_HAS_CC_CAN_LINK 86 101 bool 87 102 ··· 177 162 # ld.lld prior to 21.0.0 did not support KEEP within an overlay description 178 163 # https://github.com/llvm/llvm-project/pull/130661 179 164 def_bool LD_IS_BFD || LLD_VERSION >= 210000 180 - 181 - config RUSTC_HAS_SLICE_AS_FLATTENED 182 - def_bool RUSTC_VERSION >= 108000 183 - 184 - config RUSTC_HAS_COERCE_POINTEE 185 - def_bool RUSTC_VERSION >= 108400 186 165 187 166 config RUSTC_HAS_SPAN_FILE 188 167 def_bool RUSTC_VERSION >= 108800 ··· 2187 2178 depends on !DEBUG_INFO_BTF || (PAHOLE_HAS_LANG_EXCLUDE && !LTO) 2188 2179 depends on !CFI || HAVE_CFI_ICALL_NORMALIZE_INTEGERS_RUSTC 2189 2180 select CFI_ICALL_NORMALIZE_INTEGERS if CFI 2190 - depends on !CALL_PADDING || RUSTC_VERSION >= 108100 2191 2181 depends on !KASAN_SW_TAGS 2192 - depends on !(MITIGATION_RETHUNK && KASAN) || RUSTC_VERSION >= 108300 2193 2182 help 2194 2183 Enables Rust support in the kernel. 2195 2184 ··· 2211 2204 config BINDGEN_VERSION_TEXT 2212 2205 string 2213 2206 depends on RUST 2214 - # The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0 2215 - # (https://github.com/rust-lang/rust-bindgen/pull/2678) and 0.71.0 2216 - # (https://github.com/rust-lang/rust-bindgen/pull/3040). It can be removed 2217 - # when the minimum version is upgraded past the latter (0.69.1 and 0.71.1 2218 - # both fixed the issue). 2219 - default "$(shell,$(BINDGEN) --version workaround-for-0.69.0 2>/dev/null)" 2207 + default "$(shell,$(BINDGEN) --version 2>/dev/null)" 2220 2208 2221 2209 # 2222 2210 # Place an empty function call at each tracepoint site. Can be
+17
lib/Kconfig.debug
··· 3577 3577 3578 3578 If unsure, say N. 3579 3579 3580 + config RUST_INLINE_HELPERS 3581 + bool "Inline C helpers into Rust code (EXPERIMENTAL)" 3582 + depends on RUST && RUSTC_CLANG_LLVM_COMPATIBLE 3583 + depends on EXPERT 3584 + depends on ARM64 || X86_64 3585 + depends on !UML 3586 + help 3587 + Inlines C helpers into Rust code using Link Time Optimization. 3588 + 3589 + If this option is enabled, C helper functions declared in 3590 + rust/helpers/ are inlined into Rust code, which is helpful for 3591 + performance of Rust code. This requires a matching LLVM version for 3592 + Clang and rustc. 3593 + 3594 + If you are sure that you're using Clang and rustc with matching LLVM 3595 + versions, say Y. Otherwise say N. 3596 + 3580 3597 endmenu # "Rust" 3581 3598 3582 3599 endmenu # Kernel hacking
+36 -33
rust/Makefile
··· 6 6 obj-$(CONFIG_RUST) += core.o compiler_builtins.o ffi.o 7 7 always-$(CONFIG_RUST) += exports_core_generated.h 8 8 9 + ifdef CONFIG_RUST_INLINE_HELPERS 10 + always-$(CONFIG_RUST) += helpers/helpers.bc helpers/helpers_module.bc 11 + else 12 + obj-$(CONFIG_RUST) += helpers/helpers.o 13 + always-$(CONFIG_RUST) += exports_helpers_generated.h 14 + endif 9 15 # Missing prototypes are expected in the helpers since these are exported 10 16 # for Rust only, thus there is no header nor prototypes. 11 - obj-$(CONFIG_RUST) += helpers/helpers.o 12 17 CFLAGS_REMOVE_helpers/helpers.o = -Wmissing-prototypes -Wmissing-declarations 13 18 14 19 always-$(CONFIG_RUST) += bindings/bindings_generated.rs bindings/bindings_helpers_generated.rs 15 20 obj-$(CONFIG_RUST) += bindings.o pin_init.o kernel.o 16 - always-$(CONFIG_RUST) += exports_helpers_generated.h \ 17 - exports_bindings_generated.h exports_kernel_generated.h 21 + always-$(CONFIG_RUST) += exports_bindings_generated.h exports_kernel_generated.h 18 22 19 23 always-$(CONFIG_RUST) += uapi/uapi_generated.rs 20 24 obj-$(CONFIG_RUST) += uapi.o ··· 75 71 76 72 core-skip_flags := \ 77 73 --edition=2021 \ 78 - -Wunreachable_pub \ 79 - -Wrustdoc::unescaped_backticks 74 + -Wunreachable_pub 80 75 81 76 core-flags := \ 82 77 --edition=$(core-edition) \ ··· 86 83 wrap_proc_macro \ 87 84 $(if $(call rustc-min-version,108800),proc_macro_span_file proc_macro_span_location) 88 85 89 - # Stable since Rust 1.79.0: `feature(proc_macro_byte_character,proc_macro_c_str_literals)`. 90 86 proc_macro2-flags := \ 91 87 --cap-lints=allow \ 92 - -Zcrate-attr='feature(proc_macro_byte_character,proc_macro_c_str_literals)' \ 93 88 $(call cfgs-to-flags,$(proc_macro2-cfgs)) 94 89 95 90 quote-cfgs := \ ··· 119 118 $(call cfgs-to-flags,$(syn-cfgs)) 120 119 121 120 pin_init_internal-cfgs := \ 122 - kernel 121 + kernel USE_RUSTC_FEATURES 123 122 124 123 pin_init_internal-flags := \ 125 124 --extern proc_macro2 \ ··· 128 127 $(call cfgs-to-flags,$(pin_init_internal-cfgs)) 129 128 130 129 pin_init-cfgs := \ 131 - kernel 130 + kernel USE_RUSTC_FEATURES 132 131 133 132 pin_init-flags := \ 134 133 --extern pin_init_internal \ ··· 142 141 # Similarly, for doctests (https://github.com/rust-lang/rust/issues/146465). 143 142 doctests_modifiers_workaround := $(rustdoc_modifiers_workaround)$(if $(call rustc-min-version,109100),$(comma)sanitizer) 144 143 145 - # `rustc` recognizes `--remap-path-prefix` since 1.26.0, but `rustdoc` only 146 - # since Rust 1.81.0. Moreover, `rustdoc` ICEs on out-of-tree builds since Rust 147 - # 1.82.0 (https://github.com/rust-lang/rust/issues/138520). Thus workaround both 148 - # issues skipping the flag. The former also applies to `RUSTDOC TK`. 149 144 quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $< 150 145 cmd_rustdoc = \ 151 146 OBJTREE=$(abspath $(objtree)) \ 152 - $(RUSTDOC) $(filter-out $(skip_flags) --remap-path-prefix=% --remap-path-scope=%, \ 153 - $(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \ 147 + $(RUSTDOC) $(filter-out $(skip_flags) --remap-path-scope=%,$(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \ 154 148 $(rustc_target_flags) -L$(objtree)/$(obj) \ 155 149 -Zunstable-options --generate-link-to-definition \ 156 150 --output $(rustdoc_output) \ ··· 206 210 rustdoc-quote rustdoc-syn FORCE 207 211 +$(call if_changed,rustdoc) 208 212 209 - # Starting with Rust 1.82.0, skipping `-Wrustdoc::unescaped_backticks` should 210 - # not be needed -- see https://github.com/rust-lang/rust/pull/128307. 211 213 rustdoc-core: private skip_flags = $(core-skip_flags) 212 214 rustdoc-core: private rustc_target_flags = $(core-flags) 213 215 rustdoc-core: $(RUST_LIB_SRC)/core/src/lib.rs rustdoc-clean FORCE ··· 329 335 rm -rf $(objtree)/$(obj)/test/doctests/kernel; \ 330 336 mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \ 331 337 OBJTREE=$(abspath $(objtree)) \ 332 - $(RUSTDOC) --test $(filter-out --remap-path-prefix=% --remap-path-scope=%,$(rust_flags)) \ 338 + $(RUSTDOC) --test $(filter-out --remap-path-scope=%,$(rust_flags)) \ 333 339 -L$(objtree)/$(obj) --extern ffi --extern pin_init \ 334 340 --extern kernel --extern build_error --extern macros \ 335 341 --extern bindings --extern uapi \ ··· 441 447 # architecture instead of generating `usize`. 442 448 bindgen_c_flags_final = $(bindgen_c_flags_lto) -fno-builtin -D__BINDGEN__ 443 449 444 - # Each `bindgen` release may upgrade the list of Rust target versions. By 445 - # default, the highest stable release in their list is used. Thus we need to set 446 - # a `--rust-target` to avoid future `bindgen` releases emitting code that 447 - # `rustc` may not understand. On top of that, `bindgen` does not support passing 448 - # an unknown Rust target version. 449 - # 450 - # Therefore, the Rust target for `bindgen` can be only as high as the minimum 451 - # Rust version the kernel supports and only as high as the greatest stable Rust 452 - # target supported by the minimum `bindgen` version the kernel supports (that 453 - # is, if we do not test the actual `rustc`/`bindgen` versions running). 454 - # 455 - # Starting with `bindgen` 0.71.0, we will be able to set any future Rust version 456 - # instead, i.e. we will be able to set here our minimum supported Rust version. 450 + # `--rust-target` points to our minimum supported Rust version. 457 451 quiet_cmd_bindgen = BINDGEN $@ 458 452 cmd_bindgen = \ 459 - $(BINDGEN) $< $(bindgen_target_flags) --rust-target 1.68 \ 453 + $(BINDGEN) $< $(bindgen_target_flags) --rust-target 1.85 \ 460 454 --use-core --with-derive-default --ctypes-prefix ffi --no-layout-tests \ 461 455 --no-debug '.*' --enable-function-attribute-detection \ 462 456 -o $@ -- $(bindgen_c_flags_final) -DMODULE \ ··· 477 495 sed -Ei 's/pub fn rust_helper_([a-zA-Z0-9_]*)/#[link_name="rust_helper_\1"]\n pub fn \1/g' $@ 478 496 $(obj)/bindings/bindings_helpers_generated.rs: $(src)/helpers/helpers.c FORCE 479 497 $(call if_changed_dep,bindgen) 498 + 499 + quiet_cmd_rust_helper = HELPER $@ 500 + cmd_rust_helper = \ 501 + $(CC) $(filter-out $(CFLAGS_REMOVE_helpers/helpers.o), $(c_flags)) \ 502 + -c -g0 $< -emit-llvm -o $@ 503 + 504 + $(obj)/helpers/helpers.bc: private part-of-builtin := y 505 + $(obj)/helpers/helpers_module.bc: private part-of-module := y 506 + $(obj)/helpers/helpers.bc $(obj)/helpers/helpers_module.bc: $(src)/helpers/helpers.c FORCE 507 + +$(call if_changed_dep,rust_helper) 480 508 481 509 rust_exports = $(NM) -p --defined-only $(1) | awk '$$2~/(T|R|D|B)/ && $$3!~/__(pfx|cfi|odr_asan)/ { printf $(2),$$3 }' 482 510 ··· 568 576 OBJTREE=$(abspath $(objtree)) \ 569 577 $(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \ 570 578 $(filter-out $(skip_flags),$(rust_flags)) $(rustc_target_flags) \ 571 - --emit=dep-info=$(depfile) --emit=obj=$@ \ 579 + --emit=dep-info=$(depfile) --emit=$(if $(link_helper),llvm-bc=$(patsubst %.o,%.bc,$@),obj=$@) \ 572 580 --emit=metadata=$(dir $@)$(patsubst %.o,lib%.rmeta,$(notdir $@)) \ 573 581 --crate-type rlib -L$(objtree)/$(obj) \ 574 582 --crate-name $(patsubst %.o,%,$(notdir $@)) $< \ 575 583 --sysroot=/dev/null \ 576 584 -Zunstable-options \ 585 + $(if $(link_helper),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \ 586 + $(obj)/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \ 587 + $(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \ 588 + $(cmd_ld_single)) \ 577 589 $(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@) \ 578 590 $(cmd_objtool) 579 591 ··· 587 591 --cfgs='proc_macro2=$(proc_macro2-cfgs)' \ 588 592 --cfgs='quote=$(quote-cfgs)' \ 589 593 --cfgs='syn=$(syn-cfgs)' \ 594 + --cfgs='pin_init_internal=$(pin_init_internal-cfgs)' \ 595 + --cfgs='pin_init=$(pin_init-cfgs)' \ 590 596 $(realpath $(srctree)) $(realpath $(objtree)) \ 591 597 $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \ 592 598 > rust-project.json ··· 707 709 ifdef CONFIG_BUG 708 710 $(obj)/kernel.o: $(obj)/kernel/generated_arch_warn_asm.rs $(obj)/kernel/generated_arch_reachable_asm.rs 709 711 endif 712 + endif 713 + 714 + ifdef CONFIG_RUST_INLINE_HELPERS 715 + $(obj)/kernel.o: private link_helper = 1 716 + $(obj)/kernel.o: $(obj)/helpers/helpers.bc 710 717 endif 711 718 712 719 endif # CONFIG_RUST
+4 -4
rust/bindgen_parameters
··· 15 15 --opaque-type x86_msi_data 16 16 --opaque-type x86_msi_addr_lo 17 17 18 - # `try` is a reserved keyword since Rust 2018; solved in `bindgen` v0.59.2, 19 - # commit 2aed6b021680 ("context: Escape the try keyword properly"). 20 - --opaque-type kunit_try_catch 21 - 22 18 # If SMP is disabled, `arch_spinlock_t` is defined as a ZST which triggers a Rust 23 19 # warning. We don't need to peek into it anyway. 24 20 --opaque-type spinlock 21 + 22 + # enums that appear in indirect function calls should specify a cfi type 23 + --newtype-enum lru_status 24 + --with-attribute-custom-enum=lru_status='#[cfi_encoding="10lru_status"]' 25 25 26 26 # `seccomp`'s comment gets understood as a doctest 27 27 --no-doc-comments
-1
rust/bindings/bindings_helper.h
··· 149 149 #if IS_ENABLED(CONFIG_ANDROID_BINDER_IPC_RUST) 150 150 #include "../../drivers/android/binder/rust_binder.h" 151 151 #include "../../drivers/android/binder/rust_binder_events.h" 152 - #include "../../drivers/android/binder/page_range_helper.h" 153 152 #endif
+1 -4
rust/bindings/lib.rs
··· 9 9 //! using this crate. 10 10 11 11 #![no_std] 12 - // See <https://github.com/rust-lang/rust-bindgen/issues/1651>. 13 - #![cfg_attr(test, allow(deref_nullptr))] 14 - #![cfg_attr(test, allow(unaligned_references))] 15 - #![cfg_attr(test, allow(unsafe_op_in_unsafe_fn))] 16 12 #![allow( 17 13 clippy::all, 18 14 missing_docs, ··· 19 23 unreachable_pub, 20 24 unsafe_op_in_unsafe_fn 21 25 )] 26 + #![feature(cfi_encoding)] 22 27 23 28 #[allow(dead_code)] 24 29 #[allow(clippy::cast_lossless)]
+4 -1
rust/exports.c
··· 16 16 #define EXPORT_SYMBOL_RUST_GPL(sym) extern int sym; EXPORT_SYMBOL_GPL(sym) 17 17 18 18 #include "exports_core_generated.h" 19 - #include "exports_helpers_generated.h" 20 19 #include "exports_bindings_generated.h" 21 20 #include "exports_kernel_generated.h" 21 + 22 + #ifndef CONFIG_RUST_INLINE_HELPERS 23 + #include "exports_helpers_generated.h" 24 + #endif 22 25 23 26 // For modules using `rust/build_error.rs`. 24 27 #ifdef CONFIG_RUST_BUILD_ASSERT_ALLOW
+13 -11
rust/helpers/clk.c
··· 7 7 * CONFIG_HAVE_CLK or CONFIG_HAVE_CLK_PREPARE aren't set. 8 8 */ 9 9 #ifndef CONFIG_HAVE_CLK 10 - struct clk *rust_helper_clk_get(struct device *dev, const char *id) 10 + __rust_helper struct clk *rust_helper_clk_get(struct device *dev, 11 + const char *id) 11 12 { 12 13 return clk_get(dev, id); 13 14 } 14 15 15 - void rust_helper_clk_put(struct clk *clk) 16 + __rust_helper void rust_helper_clk_put(struct clk *clk) 16 17 { 17 18 clk_put(clk); 18 19 } 19 20 20 - int rust_helper_clk_enable(struct clk *clk) 21 + __rust_helper int rust_helper_clk_enable(struct clk *clk) 21 22 { 22 23 return clk_enable(clk); 23 24 } 24 25 25 - void rust_helper_clk_disable(struct clk *clk) 26 + __rust_helper void rust_helper_clk_disable(struct clk *clk) 26 27 { 27 28 clk_disable(clk); 28 29 } 29 30 30 - unsigned long rust_helper_clk_get_rate(struct clk *clk) 31 + __rust_helper unsigned long rust_helper_clk_get_rate(struct clk *clk) 31 32 { 32 33 return clk_get_rate(clk); 33 34 } 34 35 35 - int rust_helper_clk_set_rate(struct clk *clk, unsigned long rate) 36 + __rust_helper int rust_helper_clk_set_rate(struct clk *clk, unsigned long rate) 36 37 { 37 38 return clk_set_rate(clk, rate); 38 39 } 39 40 #endif 40 41 41 42 #ifndef CONFIG_HAVE_CLK_PREPARE 42 - int rust_helper_clk_prepare(struct clk *clk) 43 + __rust_helper int rust_helper_clk_prepare(struct clk *clk) 43 44 { 44 45 return clk_prepare(clk); 45 46 } 46 47 47 - void rust_helper_clk_unprepare(struct clk *clk) 48 + __rust_helper void rust_helper_clk_unprepare(struct clk *clk) 48 49 { 49 50 clk_unprepare(clk); 50 51 } 51 52 #endif 52 53 53 - struct clk *rust_helper_clk_get_optional(struct device *dev, const char *id) 54 + __rust_helper struct clk *rust_helper_clk_get_optional(struct device *dev, 55 + const char *id) 54 56 { 55 57 return clk_get_optional(dev, id); 56 58 } 57 59 58 - int rust_helper_clk_prepare_enable(struct clk *clk) 60 + __rust_helper int rust_helper_clk_prepare_enable(struct clk *clk) 59 61 { 60 62 return clk_prepare_enable(clk); 61 63 } 62 64 63 - void rust_helper_clk_disable_unprepare(struct clk *clk) 65 + __rust_helper void rust_helper_clk_disable_unprepare(struct clk *clk) 64 66 { 65 67 clk_disable_unprepare(clk); 66 68 }
+29
rust/helpers/helpers.c
··· 7 7 * Sorted alphabetically. 8 8 */ 9 9 10 + #include <linux/compiler_types.h> 11 + 12 + #ifdef __BINDGEN__ 13 + // Omit `inline` for bindgen as it ignores inline functions. 10 14 #define __rust_helper 15 + #else 16 + // The helper functions are all inline functions. 17 + // 18 + // We use `__always_inline` here to bypass LLVM inlining checks, in case the 19 + // helpers are inlined directly into Rust CGUs. 20 + // 21 + // The LLVM inlining checks are false positives: 22 + // * LLVM doesn't want to inline functions compiled with 23 + // `-fno-delete-null-pointer-checks` with code compiled without. 24 + // The C CGUs all have this enabled and Rust CGUs don't. Inlining is okay 25 + // since this is one of the hardening features that does not change the ABI, 26 + // and we shouldn't have null pointer dereferences in these helpers. 27 + // * LLVM doesn't want to inline functions with different list of builtins. C 28 + // side has `-fno-builtin-wcslen`; `wcslen` is not a Rust builtin, so they 29 + // should be compatible, but LLVM does not perform inlining due to attributes 30 + // mismatch. 31 + // * clang and Rust doesn't have the exact target string. Clang generates 32 + // `+cmov,+cx8,+fxsr` but Rust doesn't enable them (in fact, Rust will 33 + // complain if `-Ctarget-feature=+cmov,+cx8,+fxsr` is used). x86-64 always 34 + // enable these features, so they are in fact the same target string, but 35 + // LLVM doesn't understand this and so inlining is inhibited. This can be 36 + // bypassed with `--ignore-tti-inline-compatible`, but this is a hidden 37 + // option. 38 + #define __rust_helper __always_inline 39 + #endif 11 40 12 41 #include "atomic.c" 13 42 #include "atomic_ext.c"
+1 -1
rust/helpers/jump_label.c
··· 7 7 #include <linux/jump_label.h> 8 8 9 9 #ifndef CONFIG_JUMP_LABEL 10 - int rust_helper_static_key_count(struct static_key *key) 10 + __rust_helper int rust_helper_static_key_count(struct static_key *key) 11 11 { 12 12 return static_key_count(key); 13 13 }
+1 -7
rust/kernel/alloc/allocator/iter.rs
··· 42 42 return None; 43 43 } 44 44 45 - // TODO: Use `NonNull::add()` instead, once the minimum supported compiler version is 46 - // bumped to 1.80 or later. 47 - // 48 45 // SAFETY: `offset` is in the interval `[0, (self.page_count() - 1) * page::PAGE_SIZE]`, 49 46 // hence the resulting pointer is guaranteed to be within the same allocation. 50 - let ptr = unsafe { self.buf.as_ptr().add(offset) }; 51 - 52 - // SAFETY: `ptr` is guaranteed to be non-null given that it is derived from `self.buf`. 53 - let ptr = unsafe { NonNull::new_unchecked(ptr) }; 47 + let ptr = unsafe { self.buf.add(offset) }; 54 48 55 49 // SAFETY: 56 50 // - `ptr` is a valid pointer to a `Vmalloc` allocation.
+2 -27
rust/kernel/alloc/kbox.rs
··· 77 77 /// `self.0` is always properly aligned and either points to memory allocated with `A` or, for 78 78 /// zero-sized types, is a dangling, well aligned pointer. 79 79 #[repr(transparent)] 80 - #[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))] 81 - pub struct Box<#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, pointee)] T: ?Sized, A: Allocator>( 82 - NonNull<T>, 83 - PhantomData<A>, 84 - ); 85 - 86 - // This is to allow coercion from `Box<T, A>` to `Box<U, A>` if `T` can be converted to the 87 - // dynamically-sized type (DST) `U`. 88 - #[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))] 89 - impl<T, U, A> core::ops::CoerceUnsized<Box<U, A>> for Box<T, A> 90 - where 91 - T: ?Sized + core::marker::Unsize<U>, 92 - U: ?Sized, 93 - A: Allocator, 94 - { 95 - } 96 - 97 - // This is to allow `Box<U, A>` to be dispatched on when `Box<T, A>` can be coerced into `Box<U, 98 - // A>`. 99 - #[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))] 100 - impl<T, U, A> core::ops::DispatchFromDyn<Box<U, A>> for Box<T, A> 101 - where 102 - T: ?Sized + core::marker::Unsize<U>, 103 - U: ?Sized, 104 - A: Allocator, 105 - { 106 - } 80 + #[derive(core::marker::CoercePointee)] 81 + pub struct Box<#[pointee] T: ?Sized, A: Allocator>(NonNull<T>, PhantomData<A>); 107 82 108 83 /// Type alias for [`Box`] with a [`Kmalloc`] allocator. 109 84 ///
+3
rust/kernel/alloc/kvec/errors.rs
··· 15 15 } 16 16 17 17 impl<T> From<PushError<T>> for Error { 18 + #[inline] 18 19 fn from(_: PushError<T>) -> Error { 19 20 // Returning ENOMEM isn't appropriate because the system is not out of memory. The vector 20 21 // is just full and we are refusing to resize it. ··· 33 32 } 34 33 35 34 impl From<RemoveError> for Error { 35 + #[inline] 36 36 fn from(_: RemoveError) -> Error { 37 37 EINVAL 38 38 } ··· 57 55 } 58 56 59 57 impl<T> From<InsertError<T>> for Error { 58 + #[inline] 60 59 fn from(_: InsertError<T>) -> Error { 61 60 EINVAL 62 61 }
+1 -3
rust/kernel/block/mq/gen_disk.rs
··· 140 140 devnode: None, 141 141 alternative_gpt_sector: None, 142 142 get_unique_id: None, 143 - // TODO: Set to THIS_MODULE. Waiting for const_refs_to_static feature to 144 - // be merged (unstable in rustc 1.78 which is staged for linux 6.10) 145 - // <https://github.com/rust-lang/rust/issues/119618> 143 + // TODO: Set to `THIS_MODULE`. 146 144 owner: core::ptr::null_mut(), 147 145 pr_ops: core::ptr::null_mut(), 148 146 free_disk: None,
+158 -35
rust/kernel/build_assert.rs
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 3 - //! Build-time assert. 3 + //! Various assertions that happen during build-time. 4 + //! 5 + //! There are three types of build-time assertions that you can use: 6 + //! - [`static_assert!`] 7 + //! - [`const_assert!`] 8 + //! - [`build_assert!`] 9 + //! 10 + //! The ones towards the bottom of the list are more expressive, while the ones towards the top of 11 + //! the list are more robust and trigger earlier in the compilation pipeline. Therefore, you should 12 + //! prefer the ones towards the top of the list wherever possible. 13 + //! 14 + //! # Choosing the correct assertion 15 + //! 16 + //! If you're asserting outside any bodies (e.g. initializers or function bodies), you should use 17 + //! [`static_assert!`] as it is the only assertion that can be used in that context. 18 + //! 19 + //! Inside bodies, if your assertion condition does not depend on any variable or generics, you 20 + //! should use [`static_assert!`]. If the condition depends on generics, but not variables 21 + //! (including function arguments), you should use [`const_assert!`]. Otherwise, use 22 + //! [`build_assert!`]. The same is true regardless if the function is `const fn`. 23 + //! 24 + //! ``` 25 + //! // Outside any bodies. 26 + //! static_assert!(core::mem::size_of::<u8>() == 1); 27 + //! // `const_assert!` and `build_assert!` cannot be used here, they will fail to compile. 28 + //! 29 + //! #[inline(always)] 30 + //! fn foo<const N: usize>(v: usize) { 31 + //! static_assert!(core::mem::size_of::<u8>() == 1); // Preferred. 32 + //! const_assert!(core::mem::size_of::<u8>() == 1); // Discouraged. 33 + //! build_assert!(core::mem::size_of::<u8>() == 1); // Discouraged. 34 + //! 35 + //! // `static_assert!(N > 1);` is not allowed. 36 + //! const_assert!(N > 1); // Preferred. 37 + //! build_assert!(N > 1); // Discouraged. 38 + //! 39 + //! // `static_assert!(v > 1);` is not allowed. 40 + //! // `const_assert!(v > 1);` is not allowed. 41 + //! build_assert!(v > 1); // Works. 42 + //! } 43 + //! ``` 44 + //! 45 + //! # Detailed behavior 46 + //! 47 + //! `static_assert!()` is equivalent to `static_assert` in C. It requires `expr` to be a constant 48 + //! expression. This expression cannot refer to any generics. A `static_assert!(expr)` in a program 49 + //! is always evaluated, regardless if the function it appears in is used or not. This is also the 50 + //! only usable assertion outside a body. 51 + //! 52 + //! `const_assert!()` has no direct C equivalence. It is a more powerful version of 53 + //! `static_assert!()`, where it may refer to generics in a function. Note that due to the ability 54 + //! to refer to generics, the assertion is tied to a specific instance of a function. So if it is 55 + //! used in a generic function that is not instantiated, the assertion will not be checked. For this 56 + //! reason, `static_assert!()` is preferred wherever possible. 57 + //! 58 + //! `build_assert!()` is equivalent to `BUILD_BUG_ON`. It is even more powerful than 59 + //! `const_assert!()` because it can be used to check tautologies that depend on runtime value (this 60 + //! is the same as `BUILD_BUG_ON`). However, the assertion failure mechanism can possibly be 61 + //! undefined symbols and linker errors, it is not developer friendly to debug, so it is recommended 62 + //! to avoid it and prefer other two assertions where possible. 63 + 64 + pub use crate::{ 65 + build_assert, 66 + build_error, 67 + const_assert, 68 + static_assert, // 69 + }; 4 70 5 71 #[doc(hidden)] 6 72 pub use build_error::build_error; 73 + 74 + /// Static assert (i.e. compile-time assert). 75 + /// 76 + /// Similar to C11 [`_Static_assert`] and C++11 [`static_assert`]. 77 + /// 78 + /// An optional panic message can be supplied after the expression. 79 + /// Currently only a string literal without formatting is supported 80 + /// due to constness limitations of the [`assert!`] macro. 81 + /// 82 + /// The feature may be added to Rust in the future: see [RFC 2790]. 83 + /// 84 + /// You cannot refer to generics or variables with [`static_assert!`]. If you need to refer to 85 + /// generics, use [`const_assert!`]; if you need to refer to variables, use [`build_assert!`]. See 86 + /// the [module documentation](self). 87 + /// 88 + /// [`_Static_assert`]: https://en.cppreference.com/w/c/language/_Static_assert 89 + /// [`static_assert`]: https://en.cppreference.com/w/cpp/language/static_assert 90 + /// [RFC 2790]: https://github.com/rust-lang/rfcs/issues/2790 91 + /// 92 + /// # Examples 93 + /// 94 + /// ``` 95 + /// static_assert!(42 > 24); 96 + /// static_assert!(core::mem::size_of::<u8>() == 1); 97 + /// 98 + /// const X: &[u8] = b"bar"; 99 + /// static_assert!(X[1] == b'a'); 100 + /// 101 + /// const fn f(x: i32) -> i32 { 102 + /// x + 2 103 + /// } 104 + /// static_assert!(f(40) == 42); 105 + /// static_assert!(f(40) == 42, "f(x) must add 2 to the given input."); 106 + /// ``` 107 + #[macro_export] 108 + macro_rules! static_assert { 109 + ($condition:expr $(,$arg:literal)?) => { 110 + const _: () = ::core::assert!($condition $(,$arg)?); 111 + }; 112 + } 113 + 114 + /// Assertion during constant evaluation. 115 + /// 116 + /// This is a more powerful version of [`static_assert!`] that can refer to generics inside 117 + /// functions or implementation blocks. However, it also has a limitation where it can only appear 118 + /// in places where statements can appear; for example, you cannot use it as an item in the module. 119 + /// 120 + /// [`static_assert!`] should be preferred if no generics are referred to in the condition. You 121 + /// cannot refer to variables with [`const_assert!`] (even inside `const fn`); if you need the 122 + /// capability, use [`build_assert!`]. See the [module documentation](self). 123 + /// 124 + /// # Examples 125 + /// 126 + /// ``` 127 + /// fn foo<const N: usize>() { 128 + /// const_assert!(N > 1); 129 + /// } 130 + /// 131 + /// fn bar<T>() { 132 + /// const_assert!(size_of::<T>() > 0, "T cannot be ZST"); 133 + /// } 134 + /// ``` 135 + #[macro_export] 136 + macro_rules! const_assert { 137 + ($condition:expr $(,$arg:literal)?) => { 138 + const { ::core::assert!($condition $(,$arg)?) }; 139 + }; 140 + } 7 141 8 142 /// Fails the build if the code path calling `build_error!` can possibly be executed. 9 143 /// ··· 172 38 /// will panic. If the compiler or optimizer cannot guarantee the condition will 173 39 /// be evaluated to `true`, a build error will be triggered. 174 40 /// 175 - /// [`static_assert!`] should be preferred to `build_assert!` whenever possible. 176 - /// 177 - /// # Examples 178 - /// 179 - /// These examples show that different types of [`assert!`] will trigger errors 180 - /// at different stage of compilation. It is preferred to err as early as 181 - /// possible, so [`static_assert!`] should be used whenever possible. 182 - /// ```ignore 183 - /// fn foo() { 184 - /// static_assert!(1 > 1); // Compile-time error 185 - /// build_assert!(1 > 1); // Build-time error 186 - /// assert!(1 > 1); // Run-time error 187 - /// } 188 - /// ``` 189 - /// 190 - /// When the condition refers to generic parameters or parameters of an inline function, 191 - /// [`static_assert!`] cannot be used. Use `build_assert!` in this scenario. 192 - /// ``` 193 - /// fn foo<const N: usize>() { 194 - /// // `static_assert!(N > 1);` is not allowed 195 - /// build_assert!(N > 1); // Build-time check 196 - /// assert!(N > 1); // Run-time check 197 - /// } 198 - /// ``` 199 - /// 200 41 /// When a condition depends on a function argument, the function must be annotated with 201 42 /// `#[inline(always)]`. Without this attribute, the compiler may choose to not inline the 202 43 /// function, preventing it from optimizing out the error path. 203 - /// ``` 204 - /// #[inline(always)] 205 - /// fn bar(n: usize) { 206 - /// // `static_assert!(n > 1);` is not allowed 207 - /// build_assert!(n > 1); // Build-time check 208 - /// assert!(n > 1); // Run-time check 209 - /// } 210 - /// ``` 211 44 /// 212 - /// [`static_assert!`]: crate::static_assert! 45 + /// If the assertion condition does not depend on any variables or generics, you should use 46 + /// [`static_assert!`]. If the assertion condition does not depend on variables, but does depend on 47 + /// generics, you should use [`const_assert!`]. See the [module documentation](self). 48 + /// 49 + /// # Examples 50 + /// 51 + /// ``` 52 + /// #[inline(always)] // Important. 53 + /// fn bar(n: usize) { 54 + /// build_assert!(n > 1); 55 + /// } 56 + /// 57 + /// fn foo() { 58 + /// bar(2); 59 + /// } 60 + /// 61 + /// #[inline(always)] // Important. 62 + /// const fn const_bar(n: usize) { 63 + /// build_assert!(n > 1); 64 + /// } 65 + /// 66 + /// const _: () = const_bar(2); 67 + /// ``` 213 68 #[macro_export] 214 69 macro_rules! build_assert { 215 70 ($cond:expr $(,)?) => {{
+7
rust/kernel/clk.rs
··· 128 128 #[repr(transparent)] 129 129 pub struct Clk(*mut bindings::clk); 130 130 131 + // SAFETY: It is safe to call `clk_put` on another thread than where `clk_get` was called. 132 + unsafe impl Send for Clk {} 133 + 134 + // SAFETY: It is safe to call any combination of the `&self` methods in parallel, as the 135 + // methods are synchronized internally. 136 + unsafe impl Sync for Clk {} 137 + 131 138 impl Clk { 132 139 /// Gets [`Clk`] corresponding to a [`Device`] and a connection id. 133 140 ///
+37
rust/kernel/error.rs
··· 216 216 } 217 217 218 218 impl From<AllocError> for Error { 219 + #[inline] 219 220 fn from(_: AllocError) -> Error { 220 221 code::ENOMEM 221 222 } 222 223 } 223 224 224 225 impl From<TryFromIntError> for Error { 226 + #[inline] 225 227 fn from(_: TryFromIntError) -> Error { 226 228 code::EINVAL 227 229 } 228 230 } 229 231 230 232 impl From<Utf8Error> for Error { 233 + #[inline] 231 234 fn from(_: Utf8Error) -> Error { 232 235 code::EINVAL 233 236 } 234 237 } 235 238 236 239 impl From<LayoutError> for Error { 240 + #[inline] 237 241 fn from(_: LayoutError) -> Error { 238 242 code::ENOMEM 239 243 } 240 244 } 241 245 242 246 impl From<fmt::Error> for Error { 247 + #[inline] 243 248 fn from(_: fmt::Error) -> Error { 244 249 code::EINVAL 245 250 } 246 251 } 247 252 248 253 impl From<core::convert::Infallible> for Error { 254 + #[inline] 249 255 fn from(e: core::convert::Infallible) -> Error { 250 256 match e {} 251 257 } ··· 452 446 /// for errors. This function performs the check and converts the "error pointer" 453 447 /// to a normal pointer in an idiomatic fashion. 454 448 /// 449 + /// Note that a `NULL` pointer is not considered an error pointer, and is returned 450 + /// as-is, wrapped in [`Ok`]. 451 + /// 455 452 /// # Examples 456 453 /// 457 454 /// ```ignore ··· 468 459 /// // on `index`. 469 460 /// from_err_ptr(unsafe { bindings::devm_platform_ioremap_resource(pdev.to_ptr(), index) }) 470 461 /// } 462 + /// ``` 463 + /// 464 + /// ``` 465 + /// # use kernel::error::from_err_ptr; 466 + /// # mod bindings { 467 + /// # #![expect(clippy::missing_safety_doc)] 468 + /// # use kernel::prelude::*; 469 + /// # pub(super) unsafe fn einval_err_ptr() -> *mut kernel::ffi::c_void { 470 + /// # EINVAL.to_ptr() 471 + /// # } 472 + /// # pub(super) unsafe fn null_ptr() -> *mut kernel::ffi::c_void { 473 + /// # core::ptr::null_mut() 474 + /// # } 475 + /// # pub(super) unsafe fn non_null_ptr() -> *mut kernel::ffi::c_void { 476 + /// # 0x1234 as *mut kernel::ffi::c_void 477 + /// # } 478 + /// # } 479 + /// // SAFETY: ... 480 + /// let einval_err = from_err_ptr(unsafe { bindings::einval_err_ptr() }); 481 + /// assert_eq!(einval_err, Err(EINVAL)); 482 + /// 483 + /// // SAFETY: ... 484 + /// let null_ok = from_err_ptr(unsafe { bindings::null_ptr() }); 485 + /// assert_eq!(null_ok, Ok(core::ptr::null_mut())); 486 + /// 487 + /// // SAFETY: ... 488 + /// let non_null = from_err_ptr(unsafe { bindings::non_null_ptr() }).unwrap(); 489 + /// assert_ne!(non_null, core::ptr::null_mut()); 471 490 /// ``` 472 491 pub fn from_err_ptr<T>(ptr: *mut T) -> Result<*mut T> { 473 492 // CAST: Casting a pointer to `*const crate::ffi::c_void` is always valid.
+6 -7
rust/kernel/i2c.rs
··· 16 16 error::*, 17 17 of, 18 18 prelude::*, 19 - types::{ 20 - AlwaysRefCounted, 21 - Opaque, // 22 - }, // 19 + sync::aref::{ 20 + ARef, 21 + AlwaysRefCounted, // 22 + }, 23 + types::Opaque, // 23 24 }; 24 25 25 26 use core::{ ··· 31 30 NonNull, // 32 31 }, // 33 32 }; 34 - 35 - use kernel::types::ARef; 36 33 37 34 /// An I2C device id table. 38 35 #[repr(transparent)] ··· 415 416 kernel::impl_device_context_into_aref!(I2cAdapter); 416 417 417 418 // SAFETY: Instances of `I2cAdapter` are always reference-counted. 418 - unsafe impl crate::types::AlwaysRefCounted for I2cAdapter { 419 + unsafe impl AlwaysRefCounted for I2cAdapter { 419 420 fn inc_ref(&self) { 420 421 // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero. 421 422 unsafe { bindings::i2c_get_adapter(self.index()) };
+2 -36
rust/kernel/lib.rs
··· 16 16 // Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on 17 17 // the unstable features in use. 18 18 // 19 - // Stable since Rust 1.79.0. 20 - #![feature(generic_nonzero)] 21 - #![feature(inline_const)] 22 - #![feature(pointer_is_aligned)] 23 - #![feature(slice_ptr_len)] 24 - // 25 - // Stable since Rust 1.80.0. 26 - #![feature(slice_flatten)] 27 - // 28 - // Stable since Rust 1.81.0. 29 - #![feature(lint_reasons)] 30 - // 31 - // Stable since Rust 1.82.0. 32 - #![feature(raw_ref_op)] 33 - // 34 - // Stable since Rust 1.83.0. 35 - #![feature(const_maybe_uninit_as_mut_ptr)] 36 - #![feature(const_mut_refs)] 37 - #![feature(const_option)] 38 - #![feature(const_ptr_write)] 39 - #![feature(const_refs_to_cell)] 40 - // 41 - // Stable since Rust 1.84.0. 42 - #![feature(strict_provenance)] 43 - // 44 19 // Expected to become stable. 45 20 #![feature(arbitrary_self_types)] 21 + #![feature(derive_coerce_pointee)] 46 22 // 47 23 // To be determined. 48 24 #![feature(used_with_arg)] 49 25 // 50 - // `feature(derive_coerce_pointee)` is expected to become stable. Before Rust 51 - // 1.84.0, it did not exist, so enable the predecessor features. 52 - #![cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, feature(derive_coerce_pointee))] 53 - #![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(coerce_unsized))] 54 - #![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(dispatch_from_dyn))] 55 - #![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(unsize))] 56 - // 57 - // `feature(file_with_nul)` is expected to become stable. Before Rust 1.89.0, it did not exist, so 26 + // `feature(file_with_nul)` is stable since Rust 1.92.0. Before Rust 1.89.0, it did not exist, so 58 27 // enable it conditionally. 59 28 #![cfg_attr(CONFIG_RUSTC_HAS_FILE_WITH_NUL, feature(file_with_nul))] 60 29 ··· 46 77 #[cfg(CONFIG_BLOCK)] 47 78 pub mod block; 48 79 pub mod bug; 49 - #[doc(hidden)] 50 80 pub mod build_assert; 51 81 pub mod clk; 52 82 #[cfg(CONFIG_CONFIGFS_FS)] ··· 113 145 pub mod security; 114 146 pub mod seq_file; 115 147 pub mod sizes; 116 - pub mod slice; 117 148 #[cfg(CONFIG_SOC_BUS)] 118 149 pub mod soc; 119 - mod static_assert; 120 150 #[doc(hidden)] 121 151 pub mod std_vendor; 122 152 pub mod str;
+19 -3
rust/kernel/list.rs
··· 12 12 use pin_init::PinInit; 13 13 14 14 mod impl_list_item_mod; 15 + #[doc(inline)] 15 16 pub use self::impl_list_item_mod::{ 16 - impl_has_list_links, impl_has_list_links_self_ptr, impl_list_item, HasListLinks, HasSelfPtr, 17 + impl_has_list_links, 18 + impl_has_list_links_self_ptr, 19 + impl_list_item, 20 + HasListLinks, 21 + HasSelfPtr, // 17 22 }; 18 23 19 24 mod arc; 20 - pub use self::arc::{impl_list_arc_safe, AtomicTracker, ListArc, ListArcSafe, TryNewListArc}; 25 + #[doc(inline)] 26 + pub use self::arc::{ 27 + impl_list_arc_safe, 28 + AtomicTracker, 29 + ListArc, 30 + ListArcSafe, 31 + TryNewListArc, // 32 + }; 21 33 22 34 mod arc_field; 23 - pub use self::arc_field::{define_list_arc_field_getter, ListArcField}; 35 + #[doc(inline)] 36 + pub use self::arc_field::{ 37 + define_list_arc_field_getter, 38 + ListArcField, // 39 + }; 24 40 25 41 /// A linked list. 26 42 ///
+2 -21
rust/kernel/list/arc.rs
··· 82 82 /// [`AtomicTracker`]. However, it is also possible to defer the tracking to another struct 83 83 /// using also using this macro. 84 84 #[macro_export] 85 + #[doc(hidden)] 85 86 macro_rules! impl_list_arc_safe { 86 87 (impl$({$($generics:tt)*})? ListArcSafe<$num:tt> for $t:ty { untracked; } $($rest:tt)*) => { 87 88 impl$(<$($generics)*>)? $crate::list::ListArcSafe<$num> for $t { ··· 160 159 /// 161 160 /// [`List`]: crate::list::List 162 161 #[repr(transparent)] 163 - #[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))] 162 + #[derive(core::marker::CoercePointee)] 164 163 pub struct ListArc<T, const ID: u64 = 0> 165 164 where 166 165 T: ListArcSafe<ID> + ?Sized, ··· 441 440 fn as_ref(&self) -> &Arc<T> { 442 441 self.as_arc() 443 442 } 444 - } 445 - 446 - // This is to allow coercion from `ListArc<T>` to `ListArc<U>` if `T` can be converted to the 447 - // dynamically-sized type (DST) `U`. 448 - #[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))] 449 - impl<T, U, const ID: u64> core::ops::CoerceUnsized<ListArc<U, ID>> for ListArc<T, ID> 450 - where 451 - T: ListArcSafe<ID> + core::marker::Unsize<U> + ?Sized, 452 - U: ListArcSafe<ID> + ?Sized, 453 - { 454 - } 455 - 456 - // This is to allow `ListArc<U>` to be dispatched on when `ListArc<T>` can be coerced into 457 - // `ListArc<U>`. 458 - #[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))] 459 - impl<T, U, const ID: u64> core::ops::DispatchFromDyn<ListArc<U, ID>> for ListArc<T, ID> 460 - where 461 - T: ListArcSafe<ID> + core::marker::Unsize<U> + ?Sized, 462 - U: ListArcSafe<ID> + ?Sized, 463 - { 464 443 } 465 444 466 445 /// A utility for tracking whether a [`ListArc`] exists using an atomic.
+1
rust/kernel/list/arc_field.rs
··· 66 66 67 67 /// Defines getters for a [`ListArcField`]. 68 68 #[macro_export] 69 + #[doc(hidden)] 69 70 macro_rules! define_list_arc_field_getter { 70 71 ($pub:vis fn $name:ident(&self $(<$id:tt>)?) -> &$typ:ty { $field:ident } 71 72 $($rest:tt)*
+3
rust/kernel/list/impl_list_item_mod.rs
··· 29 29 30 30 /// Implements the [`HasListLinks`] trait for the given type. 31 31 #[macro_export] 32 + #[doc(hidden)] 32 33 macro_rules! impl_has_list_links { 33 34 ($(impl$({$($generics:tt)*})? 34 35 HasListLinks$(<$id:tt>)? ··· 75 74 76 75 /// Implements the [`HasListLinks`] and [`HasSelfPtr`] traits for the given type. 77 76 #[macro_export] 77 + #[doc(hidden)] 78 78 macro_rules! impl_has_list_links_self_ptr { 79 79 ($(impl$({$($generics:tt)*})? 80 80 HasSelfPtr<$item_type:ty $(, $id:tt)?> ··· 183 181 /// } 184 182 /// ``` 185 183 #[macro_export] 184 + #[doc(hidden)] 186 185 macro_rules! impl_list_item { 187 186 ( 188 187 $(impl$({$($generics:tt)*})? ListItem<$num:tt> for $self:ty {
+9 -15
rust/kernel/num/bounded.rs
··· 255 255 /// ``` 256 256 pub const fn new<const VALUE: $type>() -> Self { 257 257 // Statically assert that `VALUE` fits within the set number of bits. 258 - const { 259 - assert!(fits_within!(VALUE, $type, N)); 260 - } 258 + const_assert!(fits_within!(VALUE, $type, N)); 261 259 262 260 // SAFETY: `fits_within` confirmed that `VALUE` can be represented within 263 261 // `N` bits. ··· 285 287 /// The caller must ensure that `value` can be represented within `N` bits. 286 288 const unsafe fn __new(value: T) -> Self { 287 289 // Enforce the type invariants. 288 - const { 289 - // `N` cannot be zero. 290 - assert!(N != 0); 291 - // The backing type is at least as large as `N` bits. 292 - assert!(N <= T::BITS); 293 - } 290 + // `N` cannot be zero. 291 + const_assert!(N != 0); 292 + // The backing type is at least as large as `N` bits. 293 + const_assert!(N <= T::BITS); 294 294 295 295 // INVARIANT: The caller ensures `value` fits within `N` bits. 296 296 Self(value) ··· 402 406 /// assert_eq!(larger_v, v); 403 407 /// ``` 404 408 pub const fn extend<const M: u32>(self) -> Bounded<T, M> { 405 - const { 406 - assert!( 407 - M >= N, 408 - "Requested number of bits is less than the current representation." 409 - ); 410 - } 409 + const_assert!( 410 + M >= N, 411 + "Requested number of bits is less than the current representation." 412 + ); 411 413 412 414 // SAFETY: The value did fit within `N` bits, so it will all the more fit within 413 415 // the larger `M` bits.
+82 -28
rust/kernel/prelude.rs
··· 13 13 14 14 #[doc(no_inline)] 15 15 pub use core::{ 16 - mem::{align_of, align_of_val, size_of, size_of_val}, 17 - pin::Pin, 16 + mem::{ 17 + align_of, 18 + align_of_val, 19 + size_of, 20 + size_of_val, // 21 + }, 22 + pin::Pin, // 18 23 }; 19 24 20 25 pub use ::ffi::{ 21 - c_char, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, c_ulong, c_ulonglong, 22 - c_ushort, c_void, CStr, 26 + c_char, 27 + c_int, 28 + c_long, 29 + c_longlong, 30 + c_schar, 31 + c_short, 32 + c_uchar, 33 + c_uint, 34 + c_ulong, 35 + c_ulonglong, 36 + c_ushort, 37 + c_void, 38 + CStr, // 23 39 }; 24 40 25 - pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec, VBox, VVec, Vec}; 26 - 27 41 #[doc(no_inline)] 28 - pub use macros::{export, fmt, kunit_tests, module, vtable}; 42 + pub use macros::{ 43 + export, 44 + fmt, 45 + kunit_tests, 46 + module, 47 + vtable, // 48 + }; 29 49 30 - pub use pin_init::{init, pin_data, pin_init, pinned_drop, InPlaceWrite, Init, PinInit, Zeroable}; 50 + pub use pin_init::{ 51 + init, 52 + pin_data, 53 + pin_init, 54 + pinned_drop, 55 + InPlaceWrite, 56 + Init, 57 + PinInit, 58 + Zeroable, // 59 + }; 31 60 32 - pub use super::{build_assert, build_error}; 61 + pub use super::{ 62 + alloc::{ 63 + flags::*, 64 + Box, 65 + KBox, 66 + KVBox, 67 + KVVec, 68 + KVec, 69 + VBox, 70 + VVec, 71 + Vec, // 72 + }, 73 + build_assert, 74 + build_error, 75 + const_assert, 76 + current, 77 + dev_alert, 78 + dev_crit, 79 + dev_dbg, 80 + dev_emerg, 81 + dev_err, 82 + dev_info, 83 + dev_notice, 84 + dev_warn, 85 + error::{ 86 + code::*, 87 + Error, 88 + Result, // 89 + }, 90 + init::InPlaceInit, 91 + pr_alert, 92 + pr_crit, 93 + pr_debug, 94 + pr_emerg, 95 + pr_err, 96 + pr_info, 97 + pr_notice, 98 + pr_warn, 99 + static_assert, 100 + str::CStrExt as _, 101 + try_init, 102 + try_pin_init, 103 + uaccess::UserPtr, 104 + ThisModule, // 105 + }; 33 106 34 107 // `super::std_vendor` is hidden, which makes the macro inline for some reason. 35 108 #[doc(no_inline)] 36 109 pub use super::dbg; 37 - pub use super::{dev_alert, dev_crit, dev_dbg, dev_emerg, dev_err, dev_info, dev_notice, dev_warn}; 38 - pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn}; 39 - 40 - pub use super::{try_init, try_pin_init}; 41 - 42 - pub use super::static_assert; 43 - 44 - pub use super::error::{code::*, Error, Result}; 45 - 46 - pub use super::{str::CStrExt as _, ThisModule}; 47 - 48 - pub use super::init::InPlaceInit; 49 - 50 - pub use super::current; 51 - 52 - pub use super::uaccess::UserPtr; 53 - 54 - #[cfg(not(CONFIG_RUSTC_HAS_SLICE_AS_FLATTENED))] 55 - pub use super::slice::AsFlattened;
+35 -7
rust/kernel/ptr.rs
··· 11 11 }; 12 12 use core::num::NonZero; 13 13 14 + use crate::const_assert; 15 + 14 16 /// Type representing an alignment, which is always a power of two. 15 17 /// 16 18 /// It is used to validate that a given value is a valid alignment, and to perform masking and ··· 46 44 /// ``` 47 45 #[inline(always)] 48 46 pub const fn new<const ALIGN: usize>() -> Self { 49 - const { 50 - assert!( 51 - ALIGN.is_power_of_two(), 52 - "Provided alignment is not a power of two." 53 - ); 54 - } 47 + const_assert!( 48 + ALIGN.is_power_of_two(), 49 + "Provided alignment is not a power of two." 50 + ); 55 51 56 52 // INVARIANT: `align` is a power of two. 57 53 // SAFETY: `align` is a power of two, and thus non-zero. ··· 87 87 /// This is equivalent to [`align_of`], but with the return value provided as an [`Alignment`]. 88 88 #[inline(always)] 89 89 pub const fn of<T>() -> Self { 90 - #![allow(clippy::incompatible_msrv)] 91 90 // This cannot panic since alignments are always powers of two. 92 91 // 93 92 // We unfortunately cannot use `new` as it would require the `generic_const_exprs` feature. ··· 250 251 #[inline(always)] 251 252 fn size(p: *const Self) -> usize { 252 253 p.len() * size_of::<T>() 254 + } 255 + } 256 + 257 + /// Aligns `value` up to `align`. 258 + /// 259 + /// This is the const-compatible equivalent of [`Alignable::align_up`]. 260 + /// 261 + /// Returns [`None`] on overflow. 262 + /// 263 + /// # Examples 264 + /// 265 + /// ``` 266 + /// use kernel::{ 267 + /// ptr::{ 268 + /// const_align_up, 269 + /// Alignment, // 270 + /// }, 271 + /// sizes::SZ_4K, // 272 + /// }; 273 + /// 274 + /// assert_eq!(const_align_up(0x4f, Alignment::new::<16>()), Some(0x50)); 275 + /// assert_eq!(const_align_up(0x40, Alignment::new::<16>()), Some(0x40)); 276 + /// assert_eq!(const_align_up(1, Alignment::new::<SZ_4K>()), Some(SZ_4K)); 277 + /// ``` 278 + #[inline(always)] 279 + pub const fn const_align_up(value: usize, align: Alignment) -> Option<usize> { 280 + match value.checked_add(align.as_usize() - 1) { 281 + Some(v) => Some(v & align.mask()), 282 + None => None, 253 283 } 254 284 }
+128 -44
rust/kernel/sizes.rs
··· 3 3 //! Commonly used sizes. 4 4 //! 5 5 //! C headers: [`include/linux/sizes.h`](srctree/include/linux/sizes.h). 6 + //! 7 + //! The top-level `SZ_*` constants are [`usize`]-typed, for use in kernel page 8 + //! arithmetic and similar CPU-side work. 9 + //! 10 + //! The [`SizeConstants`] trait provides the same constants as associated constants 11 + //! on [`u32`], [`u64`], and [`usize`], for use in device address spaces where 12 + //! the address width depends on the hardware. Device drivers frequently need 13 + //! these constants as [`u64`] (or [`u32`]) rather than [`usize`], because 14 + //! device address spaces are sized independently of the CPU pointer width. 15 + //! 16 + //! # Examples 17 + //! 18 + //! ``` 19 + //! use kernel::{ 20 + //! page::PAGE_SIZE, 21 + //! sizes::{ 22 + //! SizeConstants, 23 + //! SZ_1M, // 24 + //! }, // 25 + //! }; 26 + //! 27 + //! // Module-level constants continue to work without a type qualifier. 28 + //! let num_pages_in_1m = SZ_1M / PAGE_SIZE; 29 + //! 30 + //! // Trait associated constants require a type qualifier. 31 + //! let heap_size = 14 * u64::SZ_1M; 32 + //! let small = u32::SZ_4K; 33 + //! ``` 6 34 7 - /// 0x00000400 8 - pub const SZ_1K: usize = bindings::SZ_1K as usize; 9 - /// 0x00000800 10 - pub const SZ_2K: usize = bindings::SZ_2K as usize; 11 - /// 0x00001000 12 - pub const SZ_4K: usize = bindings::SZ_4K as usize; 13 - /// 0x00002000 14 - pub const SZ_8K: usize = bindings::SZ_8K as usize; 15 - /// 0x00004000 16 - pub const SZ_16K: usize = bindings::SZ_16K as usize; 17 - /// 0x00008000 18 - pub const SZ_32K: usize = bindings::SZ_32K as usize; 19 - /// 0x00010000 20 - pub const SZ_64K: usize = bindings::SZ_64K as usize; 21 - /// 0x00020000 22 - pub const SZ_128K: usize = bindings::SZ_128K as usize; 23 - /// 0x00040000 24 - pub const SZ_256K: usize = bindings::SZ_256K as usize; 25 - /// 0x00080000 26 - pub const SZ_512K: usize = bindings::SZ_512K as usize; 27 - /// 0x00100000 28 - pub const SZ_1M: usize = bindings::SZ_1M as usize; 29 - /// 0x00200000 30 - pub const SZ_2M: usize = bindings::SZ_2M as usize; 31 - /// 0x00400000 32 - pub const SZ_4M: usize = bindings::SZ_4M as usize; 33 - /// 0x00800000 34 - pub const SZ_8M: usize = bindings::SZ_8M as usize; 35 - /// 0x01000000 36 - pub const SZ_16M: usize = bindings::SZ_16M as usize; 37 - /// 0x02000000 38 - pub const SZ_32M: usize = bindings::SZ_32M as usize; 39 - /// 0x04000000 40 - pub const SZ_64M: usize = bindings::SZ_64M as usize; 41 - /// 0x08000000 42 - pub const SZ_128M: usize = bindings::SZ_128M as usize; 43 - /// 0x10000000 44 - pub const SZ_256M: usize = bindings::SZ_256M as usize; 45 - /// 0x20000000 46 - pub const SZ_512M: usize = bindings::SZ_512M as usize; 47 - /// 0x40000000 48 - pub const SZ_1G: usize = bindings::SZ_1G as usize; 49 - /// 0x80000000 50 - pub const SZ_2G: usize = bindings::SZ_2G as usize; 35 + macro_rules! define_sizes { 36 + ($($type:ty),* $(,)?) => { 37 + define_sizes!(@internal [$($type),*] 38 + /// `0x0000_0400`. 39 + SZ_1K, 40 + /// `0x0000_0800`. 41 + SZ_2K, 42 + /// `0x0000_1000`. 43 + SZ_4K, 44 + /// `0x0000_2000`. 45 + SZ_8K, 46 + /// `0x0000_4000`. 47 + SZ_16K, 48 + /// `0x0000_8000`. 49 + SZ_32K, 50 + /// `0x0001_0000`. 51 + SZ_64K, 52 + /// `0x0002_0000`. 53 + SZ_128K, 54 + /// `0x0004_0000`. 55 + SZ_256K, 56 + /// `0x0008_0000`. 57 + SZ_512K, 58 + /// `0x0010_0000`. 59 + SZ_1M, 60 + /// `0x0020_0000`. 61 + SZ_2M, 62 + /// `0x0040_0000`. 63 + SZ_4M, 64 + /// `0x0080_0000`. 65 + SZ_8M, 66 + /// `0x0100_0000`. 67 + SZ_16M, 68 + /// `0x0200_0000`. 69 + SZ_32M, 70 + /// `0x0400_0000`. 71 + SZ_64M, 72 + /// `0x0800_0000`. 73 + SZ_128M, 74 + /// `0x1000_0000`. 75 + SZ_256M, 76 + /// `0x2000_0000`. 77 + SZ_512M, 78 + /// `0x4000_0000`. 79 + SZ_1G, 80 + /// `0x8000_0000`. 81 + SZ_2G, 82 + ); 83 + }; 84 + 85 + (@internal [$($type:ty),*] $($names_and_metas:tt)*) => { 86 + define_sizes!(@consts_and_trait $($names_and_metas)*); 87 + define_sizes!(@impls [$($type),*] $($names_and_metas)*); 88 + }; 89 + 90 + (@consts_and_trait $($(#[$meta:meta])* $name:ident,)*) => { 91 + $( 92 + $(#[$meta])* 93 + pub const $name: usize = bindings::$name as usize; 94 + )* 95 + 96 + /// Size constants for device address spaces. 97 + /// 98 + /// Implemented for [`u32`], [`u64`], and [`usize`] so drivers can 99 + /// choose the width that matches their hardware. All `SZ_*` values fit 100 + /// in a [`u32`], so all implementations are lossless. 101 + /// 102 + /// # Examples 103 + /// 104 + /// ``` 105 + /// use kernel::sizes::SizeConstants; 106 + /// 107 + /// let gpu_heap = 14 * u64::SZ_1M; 108 + /// let mmio_window = u32::SZ_16M; 109 + /// ``` 110 + pub trait SizeConstants { 111 + $( 112 + $(#[$meta])* 113 + const $name: Self; 114 + )* 115 + } 116 + }; 117 + 118 + (@impls [] $($(#[$meta:meta])* $name:ident,)*) => {}; 119 + 120 + (@impls [$first:ty $(, $rest:ty)*] $($(#[$meta:meta])* $name:ident,)*) => { 121 + impl SizeConstants for $first { 122 + $( 123 + const $name: Self = { 124 + assert!((self::$name as u128) <= (<$first>::MAX as u128)); 125 + self::$name as $first 126 + }; 127 + )* 128 + } 129 + 130 + define_sizes!(@impls [$($rest),*] $($(#[$meta])* $name,)*); 131 + }; 132 + } 133 + 134 + define_sizes!(u32, u64, usize);
-49
rust/kernel/slice.rs
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - 3 - //! Additional (and temporary) slice helpers. 4 - 5 - /// Extension trait providing a portable version of [`as_flattened`] and 6 - /// [`as_flattened_mut`]. 7 - /// 8 - /// In Rust 1.80, the previously unstable `slice::flatten` family of methods 9 - /// have been stabilized and renamed from `flatten` to `as_flattened`. 10 - /// 11 - /// This creates an issue for as long as the MSRV is < 1.80, as the same functionality is provided 12 - /// by different methods depending on the compiler version. 13 - /// 14 - /// This extension trait solves this by abstracting `as_flatten` and calling the correct method 15 - /// depending on the Rust version. 16 - /// 17 - /// This trait can be removed once the MSRV passes 1.80. 18 - /// 19 - /// [`as_flattened`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_flattened 20 - /// [`as_flattened_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_flattened_mut 21 - #[cfg(not(CONFIG_RUSTC_HAS_SLICE_AS_FLATTENED))] 22 - pub trait AsFlattened<T> { 23 - /// Takes a `&[[T; N]]` and flattens it to a `&[T]`. 24 - /// 25 - /// This is an portable layer on top of [`as_flattened`]; see its documentation for details. 26 - /// 27 - /// [`as_flattened`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_flattened 28 - fn as_flattened(&self) -> &[T]; 29 - 30 - /// Takes a `&mut [[T; N]]` and flattens it to a `&mut [T]`. 31 - /// 32 - /// This is an portable layer on top of [`as_flattened_mut`]; see its documentation for details. 33 - /// 34 - /// [`as_flattened_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_flattened_mut 35 - fn as_flattened_mut(&mut self) -> &mut [T]; 36 - } 37 - 38 - #[cfg(not(CONFIG_RUSTC_HAS_SLICE_AS_FLATTENED))] 39 - impl<T, const N: usize> AsFlattened<T> for [[T; N]] { 40 - #[allow(clippy::incompatible_msrv)] 41 - fn as_flattened(&self) -> &[T] { 42 - self.flatten() 43 - } 44 - 45 - #[allow(clippy::incompatible_msrv)] 46 - fn as_flattened_mut(&mut self) -> &mut [T] { 47 - self.flatten_mut() 48 - } 49 - }
-39
rust/kernel/static_assert.rs
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - 3 - //! Static assert. 4 - 5 - /// Static assert (i.e. compile-time assert). 6 - /// 7 - /// Similar to C11 [`_Static_assert`] and C++11 [`static_assert`]. 8 - /// 9 - /// An optional panic message can be supplied after the expression. 10 - /// Currently only a string literal without formatting is supported 11 - /// due to constness limitations of the [`assert!`] macro. 12 - /// 13 - /// The feature may be added to Rust in the future: see [RFC 2790]. 14 - /// 15 - /// [`_Static_assert`]: https://en.cppreference.com/w/c/language/_Static_assert 16 - /// [`static_assert`]: https://en.cppreference.com/w/cpp/language/static_assert 17 - /// [RFC 2790]: https://github.com/rust-lang/rfcs/issues/2790 18 - /// 19 - /// # Examples 20 - /// 21 - /// ``` 22 - /// static_assert!(42 > 24); 23 - /// static_assert!(core::mem::size_of::<u8>() == 1); 24 - /// 25 - /// const X: &[u8] = b"bar"; 26 - /// static_assert!(X[1] == b'a'); 27 - /// 28 - /// const fn f(x: i32) -> i32 { 29 - /// x + 2 30 - /// } 31 - /// static_assert!(f(40) == 42); 32 - /// static_assert!(f(40) == 42, "f(x) must add 2 to the given input."); 33 - /// ``` 34 - #[macro_export] 35 - macro_rules! static_assert { 36 - ($condition:expr $(,$arg:literal)?) => { 37 - const _: () = ::core::assert!($condition $(,$arg)?); 38 - }; 39 - }
+23 -4
rust/kernel/str.rs
··· 189 189 // 190 190 // - error[E0379]: functions in trait impls cannot be declared const 191 191 #[inline] 192 + #[expect(clippy::disallowed_methods, reason = "internal implementation")] 192 193 pub const fn as_char_ptr_in_const_context(c_str: &CStr) -> *const c_char { 193 194 c_str.as_ptr().cast() 194 195 } ··· 320 319 321 320 impl CStrExt for CStr { 322 321 #[inline] 322 + #[expect(clippy::disallowed_methods, reason = "internal implementation")] 323 323 unsafe fn from_char_ptr<'a>(ptr: *const c_char) -> &'a Self { 324 324 // SAFETY: The safety preconditions are the same as for `CStr::from_ptr`. 325 325 unsafe { CStr::from_ptr(ptr.cast()) } ··· 336 334 } 337 335 338 336 #[inline] 337 + #[expect(clippy::disallowed_methods, reason = "internal implementation")] 339 338 fn as_char_ptr(&self) -> *const c_char { 340 339 self.as_ptr().cast() 341 340 } ··· 379 376 } 380 377 } 381 378 382 - /// Creates a new [`CStr`] from a string literal. 379 + /// Creates a new [`CStr`] at compile time. 383 380 /// 384 - /// The string literal should not contain any `NUL` bytes. 381 + /// Rust supports C string literals since Rust 1.77, and they should be used instead of this macro 382 + /// where possible. This macro exists to allow static *non-literal* C strings to be created at 383 + /// compile time. This is most often used in other macros. 384 + /// 385 + /// # Panics 386 + /// 387 + /// This macro panics if the operand contains an interior `NUL` byte. 385 388 /// 386 389 /// # Examples 387 390 /// 388 391 /// ``` 389 392 /// # use kernel::c_str; 390 393 /// # use kernel::str::CStr; 391 - /// const MY_CSTR: &CStr = c_str!("My awesome CStr!"); 394 + /// // This is allowed, but `c"literal"` should be preferred for literals. 395 + /// const BAD: &CStr = c_str!("literal"); 396 + /// 397 + /// // `c_str!` is still needed for static non-literal C strings. 398 + /// const GOOD: &CStr = c_str!(concat!(file!(), ":", line!(), ": My CStr!")); 392 399 /// ``` 393 400 #[macro_export] 394 401 macro_rules! c_str { 402 + // NB: We could write `($str:lit) => compile_error!("use a C string literal instead");` here but 403 + // that would trigger when the literal is at the top of several macro expansions. That would be 404 + // too limiting to macro authors. 395 405 ($str:expr) => {{ 396 406 const S: &str = concat!($str, "\0"); 397 407 const C: &$crate::str::CStr = match $crate::str::CStr::from_bytes_with_nul(S.as_bytes()) { ··· 844 828 f.write_str("\0")?; 845 829 846 830 // SAFETY: The number of bytes that can be written to `f` is bounded by `size`, which is 847 - // `buf`'s capacity. The contents of the buffer have been initialised by writes to `f`. 831 + // `buf`'s capacity. The `Formatter` is created with `size` as its limit, and the `?` 832 + // operators on `write_fmt` and `write_str` above ensure that if writing exceeds this 833 + // limit, an error is returned early. The contents of the buffer have been initialised 834 + // by writes to `f`. 848 835 unsafe { buf.inc_len(f.bytes_written()) }; 849 836 850 837 // Check that there are no `NUL` bytes before the end.
+2 -19
rust/kernel/sync/arc.rs
··· 128 128 /// # Ok::<(), Error>(()) 129 129 /// ``` 130 130 #[repr(transparent)] 131 - #[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))] 131 + #[derive(core::marker::CoercePointee)] 132 132 pub struct Arc<T: ?Sized> { 133 133 ptr: NonNull<ArcInner<T>>, 134 134 // NB: this informs dropck that objects of type `ArcInner<T>` may be used in `<Arc<T> as ··· 181 181 unsafe { NonNull::new_unchecked(ptr.cast_mut()) } 182 182 } 183 183 } 184 - 185 - // This is to allow coercion from `Arc<T>` to `Arc<U>` if `T` can be converted to the 186 - // dynamically-sized type (DST) `U`. 187 - #[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))] 188 - impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Arc<U>> for Arc<T> {} 189 - 190 - // This is to allow `Arc<U>` to be dispatched on when `Arc<T>` can be coerced into `Arc<U>`. 191 - #[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))] 192 - impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Arc<T> {} 193 184 194 185 // SAFETY: It is safe to send `Arc<T>` to another thread when the underlying `T` is `Sync` because 195 186 // it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs ··· 538 547 /// # Ok::<(), Error>(()) 539 548 /// ``` 540 549 #[repr(transparent)] 541 - #[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))] 550 + #[derive(core::marker::CoercePointee)] 542 551 pub struct ArcBorrow<'a, T: ?Sized + 'a> { 543 552 inner: NonNull<ArcInner<T>>, 544 553 _p: PhantomData<&'a ()>, 545 - } 546 - 547 - // This is to allow `ArcBorrow<U>` to be dispatched on when `ArcBorrow<T>` can be coerced into 548 - // `ArcBorrow<U>`. 549 - #[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))] 550 - impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>> 551 - for ArcBorrow<'_, T> 552 - { 553 554 } 554 555 555 556 impl<T: ?Sized> Clone for ArcBorrow<'_, T> {
+3 -4
rust/kernel/task.rs
··· 6 6 7 7 use crate::{ 8 8 bindings, 9 - ffi::{c_int, c_long, c_uint}, 10 9 mm::MmWithUser, 11 10 pid_namespace::PidNamespace, 11 + prelude::*, 12 12 sync::aref::ARef, 13 13 types::{NotThreadSafe, Opaque}, 14 14 }; 15 15 use core::{ 16 - cmp::{Eq, PartialEq}, 17 16 ops::Deref, 18 - ptr, 17 + ptr, // 19 18 }; 20 19 21 20 /// A sentinel value used for infinite timeouts. ··· 418 419 let file = kernel::file_from_location(loc); 419 420 420 421 // SAFETY: `file.as_ptr()` is valid for reading and guaranteed to be nul-terminated. 421 - unsafe { crate::bindings::__might_sleep(file.as_ptr().cast(), loc.line() as i32) } 422 + unsafe { crate::bindings::__might_sleep(file.as_char_ptr(), loc.line() as i32) } 422 423 } 423 424 424 425 // SAFETY: Always safe to call.
+26 -6
rust/kernel/time.rs
··· 60 60 /// cases the user of the clock has to decide which clock is best suited for the 61 61 /// purpose. In most scenarios clock [`Monotonic`] is the best choice as it 62 62 /// provides a accurate monotonic notion of time (leap second smearing ignored). 63 - pub trait ClockSource { 63 + /// 64 + /// # Safety 65 + /// 66 + /// Implementers must ensure that `ktime_get()` returns a value in the inclusive range 67 + /// `0..=KTIME_MAX` (i.e., greater than or equal to 0 and less than or equal to 68 + /// `KTIME_MAX`, where `KTIME_MAX` equals `i64::MAX`). 69 + pub unsafe trait ClockSource { 64 70 /// The kernel clock ID associated with this clock source. 65 71 /// 66 72 /// This constant corresponds to the C side `clockid_t` value. ··· 74 68 75 69 /// Get the current time from the clock source. 76 70 /// 77 - /// The function must return a value in the range from 0 to `KTIME_MAX`. 71 + /// The function must return a value in the range `0..=KTIME_MAX`. 78 72 fn ktime_get() -> bindings::ktime_t; 79 73 } 80 74 ··· 91 85 /// count time that the system is suspended. 92 86 pub struct Monotonic; 93 87 94 - impl ClockSource for Monotonic { 88 + // SAFETY: The kernel's `ktime_get()` is guaranteed to return a value 89 + // in `0..=KTIME_MAX`. 90 + unsafe impl ClockSource for Monotonic { 95 91 const ID: bindings::clockid_t = bindings::CLOCK_MONOTONIC as bindings::clockid_t; 96 92 97 93 fn ktime_get() -> bindings::ktime_t { ··· 118 110 /// the clock will experience discontinuity around leap second adjustment. 119 111 pub struct RealTime; 120 112 121 - impl ClockSource for RealTime { 113 + // SAFETY: The kernel's `ktime_get_real()` is guaranteed to return a value 114 + // in `0..=KTIME_MAX`. 115 + unsafe impl ClockSource for RealTime { 122 116 const ID: bindings::clockid_t = bindings::CLOCK_REALTIME as bindings::clockid_t; 123 117 124 118 fn ktime_get() -> bindings::ktime_t { ··· 138 128 /// discontinuities if the time is changed using settimeofday(2) or similar. 139 129 pub struct BootTime; 140 130 141 - impl ClockSource for BootTime { 131 + // SAFETY: The kernel's `ktime_get_boottime()` is guaranteed to return a value 132 + // in `0..=KTIME_MAX`. 133 + unsafe impl ClockSource for BootTime { 142 134 const ID: bindings::clockid_t = bindings::CLOCK_BOOTTIME as bindings::clockid_t; 143 135 144 136 fn ktime_get() -> bindings::ktime_t { ··· 162 150 /// The acronym TAI refers to International Atomic Time. 163 151 pub struct Tai; 164 152 165 - impl ClockSource for Tai { 153 + // SAFETY: The kernel's `ktime_get_clocktai()` is guaranteed to return a value 154 + // in `0..=KTIME_MAX`. 155 + unsafe impl ClockSource for Tai { 166 156 const ID: bindings::clockid_t = bindings::CLOCK_TAI as bindings::clockid_t; 167 157 168 158 fn ktime_get() -> bindings::ktime_t { ··· 376 362 impl Delta { 377 363 /// A span of time equal to zero. 378 364 pub const ZERO: Self = Self { nanos: 0 }; 365 + 366 + /// Create a new [`Delta`] from a number of nanoseconds. 367 + #[inline] 368 + pub const fn from_nanos(nanos: i64) -> Self { 369 + Self { nanos } 370 + } 379 371 380 372 /// Create a new [`Delta`] from a number of microseconds. 381 373 ///
+336
rust/kernel/time/hrtimer.rs
··· 66 66 //! 67 67 //! A `restart` operation on a timer in the **stopped** state is equivalent to a 68 68 //! `start` operation. 69 + //! 70 + //! When a type implements both `HrTimerPointer` and `Clone`, it is possible to 71 + //! issue the `start` operation while the timer is in the **started** state. In 72 + //! this case the `start` operation is equivalent to the `restart` operation. 73 + //! 74 + //! # Examples 75 + //! 76 + //! ## Using an intrusive timer living in a [`Box`] 77 + //! 78 + //! ``` 79 + //! # use kernel::{ 80 + //! # alloc::flags, 81 + //! # impl_has_hr_timer, 82 + //! # prelude::*, 83 + //! # sync::{ 84 + //! # atomic::{ordering, Atomic}, 85 + //! # completion::Completion, 86 + //! # Arc, 87 + //! # }, 88 + //! # time::{ 89 + //! # hrtimer::{ 90 + //! # RelativeMode, HrTimer, HrTimerCallback, HrTimerPointer, 91 + //! # HrTimerRestart, HrTimerCallbackContext 92 + //! # }, 93 + //! # Delta, Monotonic, 94 + //! # }, 95 + //! # }; 96 + //! 97 + //! #[pin_data] 98 + //! struct Shared { 99 + //! #[pin] 100 + //! flag: Atomic<u64>, 101 + //! #[pin] 102 + //! cond: Completion, 103 + //! } 104 + //! 105 + //! impl Shared { 106 + //! fn new() -> impl PinInit<Self> { 107 + //! pin_init!(Self { 108 + //! flag <- Atomic::new(0), 109 + //! cond <- Completion::new(), 110 + //! }) 111 + //! } 112 + //! } 113 + //! 114 + //! #[pin_data] 115 + //! struct BoxIntrusiveHrTimer { 116 + //! #[pin] 117 + //! timer: HrTimer<Self>, 118 + //! shared: Arc<Shared>, 119 + //! } 120 + //! 121 + //! impl BoxIntrusiveHrTimer { 122 + //! fn new() -> impl PinInit<Self, kernel::error::Error> { 123 + //! try_pin_init!(Self { 124 + //! timer <- HrTimer::new(), 125 + //! shared: Arc::pin_init(Shared::new(), flags::GFP_KERNEL)?, 126 + //! }) 127 + //! } 128 + //! } 129 + //! 130 + //! impl HrTimerCallback for BoxIntrusiveHrTimer { 131 + //! type Pointer<'a> = Pin<KBox<Self>>; 132 + //! 133 + //! fn run(this: Pin<&mut Self>, _ctx: HrTimerCallbackContext<'_, Self>) -> HrTimerRestart { 134 + //! pr_info!("Timer called\n"); 135 + //! 136 + //! let flag = this.shared.flag.fetch_add(1, ordering::Full); 137 + //! this.shared.cond.complete_all(); 138 + //! 139 + //! if flag == 4 { 140 + //! HrTimerRestart::NoRestart 141 + //! } else { 142 + //! HrTimerRestart::Restart 143 + //! } 144 + //! } 145 + //! } 146 + //! 147 + //! impl_has_hr_timer! { 148 + //! impl HasHrTimer<Self> for BoxIntrusiveHrTimer { 149 + //! mode: RelativeMode<Monotonic>, field: self.timer 150 + //! } 151 + //! } 152 + //! 153 + //! let has_timer = Box::pin_init(BoxIntrusiveHrTimer::new(), GFP_KERNEL)?; 154 + //! let shared = has_timer.shared.clone(); 155 + //! let _handle = has_timer.start(Delta::from_micros(200)); 156 + //! 157 + //! while shared.flag.load(ordering::Relaxed) != 5 { 158 + //! shared.cond.wait_for_completion(); 159 + //! } 160 + //! 161 + //! pr_info!("Counted to 5\n"); 162 + //! # Ok::<(), kernel::error::Error>(()) 163 + //! ``` 164 + //! 165 + //! ## Using an intrusive timer in an [`Arc`] 166 + //! 167 + //! ``` 168 + //! # use kernel::{ 169 + //! # alloc::flags, 170 + //! # impl_has_hr_timer, 171 + //! # prelude::*, 172 + //! # sync::{ 173 + //! # atomic::{ordering, Atomic}, 174 + //! # completion::Completion, 175 + //! # Arc, ArcBorrow, 176 + //! # }, 177 + //! # time::{ 178 + //! # hrtimer::{ 179 + //! # RelativeMode, HrTimer, HrTimerCallback, HrTimerPointer, HrTimerRestart, 180 + //! # HasHrTimer, HrTimerCallbackContext 181 + //! # }, 182 + //! # Delta, Monotonic, 183 + //! # }, 184 + //! # }; 185 + //! 186 + //! #[pin_data] 187 + //! struct ArcIntrusiveHrTimer { 188 + //! #[pin] 189 + //! timer: HrTimer<Self>, 190 + //! #[pin] 191 + //! flag: Atomic<u64>, 192 + //! #[pin] 193 + //! cond: Completion, 194 + //! } 195 + //! 196 + //! impl ArcIntrusiveHrTimer { 197 + //! fn new() -> impl PinInit<Self> { 198 + //! pin_init!(Self { 199 + //! timer <- HrTimer::new(), 200 + //! flag <- Atomic::new(0), 201 + //! cond <- Completion::new(), 202 + //! }) 203 + //! } 204 + //! } 205 + //! 206 + //! impl HrTimerCallback for ArcIntrusiveHrTimer { 207 + //! type Pointer<'a> = Arc<Self>; 208 + //! 209 + //! fn run( 210 + //! this: ArcBorrow<'_, Self>, 211 + //! _ctx: HrTimerCallbackContext<'_, Self>, 212 + //! ) -> HrTimerRestart { 213 + //! pr_info!("Timer called\n"); 214 + //! 215 + //! let flag = this.flag.fetch_add(1, ordering::Full); 216 + //! this.cond.complete_all(); 217 + //! 218 + //! if flag == 4 { 219 + //! HrTimerRestart::NoRestart 220 + //! } else { 221 + //! HrTimerRestart::Restart 222 + //! } 223 + //! } 224 + //! } 225 + //! 226 + //! impl_has_hr_timer! { 227 + //! impl HasHrTimer<Self> for ArcIntrusiveHrTimer { 228 + //! mode: RelativeMode<Monotonic>, field: self.timer 229 + //! } 230 + //! } 231 + //! 232 + //! let has_timer = Arc::pin_init(ArcIntrusiveHrTimer::new(), GFP_KERNEL)?; 233 + //! let _handle = has_timer.clone().start(Delta::from_micros(200)); 234 + //! 235 + //! while has_timer.flag.load(ordering::Relaxed) != 5 { 236 + //! has_timer.cond.wait_for_completion(); 237 + //! } 238 + //! 239 + //! pr_info!("Counted to 5\n"); 240 + //! # Ok::<(), kernel::error::Error>(()) 241 + //! ``` 242 + //! 243 + //! ## Using a stack-based timer 244 + //! 245 + //! ``` 246 + //! # use kernel::{ 247 + //! # impl_has_hr_timer, 248 + //! # prelude::*, 249 + //! # sync::{ 250 + //! # atomic::{ordering, Atomic}, 251 + //! # completion::Completion, 252 + //! # }, 253 + //! # time::{ 254 + //! # hrtimer::{ 255 + //! # ScopedHrTimerPointer, HrTimer, HrTimerCallback, HrTimerPointer, HrTimerRestart, 256 + //! # HasHrTimer, RelativeMode, HrTimerCallbackContext 257 + //! # }, 258 + //! # Delta, Monotonic, 259 + //! # }, 260 + //! # }; 261 + //! # use pin_init::stack_pin_init; 262 + //! 263 + //! #[pin_data] 264 + //! struct IntrusiveHrTimer { 265 + //! #[pin] 266 + //! timer: HrTimer<Self>, 267 + //! #[pin] 268 + //! flag: Atomic<u64>, 269 + //! #[pin] 270 + //! cond: Completion, 271 + //! } 272 + //! 273 + //! impl IntrusiveHrTimer { 274 + //! fn new() -> impl PinInit<Self> { 275 + //! pin_init!(Self { 276 + //! timer <- HrTimer::new(), 277 + //! flag <- Atomic::new(0), 278 + //! cond <- Completion::new(), 279 + //! }) 280 + //! } 281 + //! } 282 + //! 283 + //! impl HrTimerCallback for IntrusiveHrTimer { 284 + //! type Pointer<'a> = Pin<&'a Self>; 285 + //! 286 + //! fn run(this: Pin<&Self>, _ctx: HrTimerCallbackContext<'_, Self>) -> HrTimerRestart { 287 + //! pr_info!("Timer called\n"); 288 + //! 289 + //! this.flag.store(1, ordering::Release); 290 + //! this.cond.complete_all(); 291 + //! 292 + //! HrTimerRestart::NoRestart 293 + //! } 294 + //! } 295 + //! 296 + //! impl_has_hr_timer! { 297 + //! impl HasHrTimer<Self> for IntrusiveHrTimer { 298 + //! mode: RelativeMode<Monotonic>, field: self.timer 299 + //! } 300 + //! } 301 + //! 302 + //! stack_pin_init!( let has_timer = IntrusiveHrTimer::new() ); 303 + //! has_timer.as_ref().start_scoped(Delta::from_micros(200), || { 304 + //! while has_timer.flag.load(ordering::Relaxed) != 1 { 305 + //! has_timer.cond.wait_for_completion(); 306 + //! } 307 + //! }); 308 + //! 309 + //! pr_info!("Flag raised\n"); 310 + //! # Ok::<(), kernel::error::Error>(()) 311 + //! ``` 312 + //! 313 + //! ## Using a mutable stack-based timer 314 + //! 315 + //! ``` 316 + //! # use kernel::{ 317 + //! # alloc::flags, 318 + //! # impl_has_hr_timer, 319 + //! # prelude::*, 320 + //! # sync::{ 321 + //! # atomic::{ordering, Atomic}, 322 + //! # completion::Completion, 323 + //! # Arc, 324 + //! # }, 325 + //! # time::{ 326 + //! # hrtimer::{ 327 + //! # ScopedHrTimerPointer, HrTimer, HrTimerCallback, HrTimerPointer, HrTimerRestart, 328 + //! # HasHrTimer, RelativeMode, HrTimerCallbackContext 329 + //! # }, 330 + //! # Delta, Monotonic, 331 + //! # }, 332 + //! # }; 333 + //! # use pin_init::stack_try_pin_init; 334 + //! 335 + //! #[pin_data] 336 + //! struct Shared { 337 + //! #[pin] 338 + //! flag: Atomic<u64>, 339 + //! #[pin] 340 + //! cond: Completion, 341 + //! } 342 + //! 343 + //! impl Shared { 344 + //! fn new() -> impl PinInit<Self> { 345 + //! pin_init!(Self { 346 + //! flag <- Atomic::new(0), 347 + //! cond <- Completion::new(), 348 + //! }) 349 + //! } 350 + //! } 351 + //! 352 + //! #[pin_data] 353 + //! struct IntrusiveHrTimer { 354 + //! #[pin] 355 + //! timer: HrTimer<Self>, 356 + //! shared: Arc<Shared>, 357 + //! } 358 + //! 359 + //! impl IntrusiveHrTimer { 360 + //! fn new() -> impl PinInit<Self, kernel::error::Error> { 361 + //! try_pin_init!(Self { 362 + //! timer <- HrTimer::new(), 363 + //! shared: Arc::pin_init(Shared::new(), flags::GFP_KERNEL)?, 364 + //! }) 365 + //! } 366 + //! } 367 + //! 368 + //! impl HrTimerCallback for IntrusiveHrTimer { 369 + //! type Pointer<'a> = Pin<&'a mut Self>; 370 + //! 371 + //! fn run(this: Pin<&mut Self>, _ctx: HrTimerCallbackContext<'_, Self>) -> HrTimerRestart { 372 + //! pr_info!("Timer called\n"); 373 + //! 374 + //! let flag = this.shared.flag.fetch_add(1, ordering::Full); 375 + //! this.shared.cond.complete_all(); 376 + //! 377 + //! if flag == 4 { 378 + //! HrTimerRestart::NoRestart 379 + //! } else { 380 + //! HrTimerRestart::Restart 381 + //! } 382 + //! } 383 + //! } 384 + //! 385 + //! impl_has_hr_timer! { 386 + //! impl HasHrTimer<Self> for IntrusiveHrTimer { 387 + //! mode: RelativeMode<Monotonic>, field: self.timer 388 + //! } 389 + //! } 390 + //! 391 + //! stack_try_pin_init!( let has_timer =? IntrusiveHrTimer::new() ); 392 + //! let shared = has_timer.shared.clone(); 393 + //! 394 + //! has_timer.as_mut().start_scoped(Delta::from_micros(200), || { 395 + //! while shared.flag.load(ordering::Relaxed) != 5 { 396 + //! shared.cond.wait_for_completion(); 397 + //! } 398 + //! }); 399 + //! 400 + //! pr_info!("Counted to 5\n"); 401 + //! # Ok::<(), kernel::error::Error>(()) 402 + //! ``` 403 + //! 404 + //! [`Arc`]: kernel::sync::Arc 69 405 70 406 use super::{ClockSource, Delta, Instant}; 71 407 use crate::{prelude::*, types::Opaque};
+6 -29
rust/kernel/transmute.rs
··· 49 49 let slice_ptr = bytes.as_ptr().cast::<Self>(); 50 50 let size = size_of::<Self>(); 51 51 52 - #[allow(clippy::incompatible_msrv)] 53 52 if bytes.len() == size && slice_ptr.is_aligned() { 54 53 // SAFETY: Size and alignment were just checked. 55 54 unsafe { Some(&*slice_ptr) } ··· 66 67 where 67 68 Self: Sized, 68 69 { 69 - if bytes.len() < size_of::<Self>() { 70 - None 71 - } else { 72 - // PANIC: We checked that `bytes.len() >= size_of::<Self>`, thus `split_at` cannot 73 - // panic. 74 - // TODO: replace with `split_at_checked` once the MSRV is >= 1.80. 75 - let (prefix, remainder) = bytes.split_at(size_of::<Self>()); 70 + let (prefix, remainder) = bytes.split_at_checked(size_of::<Self>())?; 76 71 77 - Self::from_bytes(prefix).map(|s| (s, remainder)) 78 - } 72 + Self::from_bytes(prefix).map(|s| (s, remainder)) 79 73 } 80 74 81 75 /// Converts a mutable slice of bytes to a reference to `Self`. ··· 84 92 let slice_ptr = bytes.as_mut_ptr().cast::<Self>(); 85 93 let size = size_of::<Self>(); 86 94 87 - #[allow(clippy::incompatible_msrv)] 88 95 if bytes.len() == size && slice_ptr.is_aligned() { 89 96 // SAFETY: Size and alignment were just checked. 90 97 unsafe { Some(&mut *slice_ptr) } ··· 101 110 where 102 111 Self: AsBytes + Sized, 103 112 { 104 - if bytes.len() < size_of::<Self>() { 105 - None 106 - } else { 107 - // PANIC: We checked that `bytes.len() >= size_of::<Self>`, thus `split_at_mut` cannot 108 - // panic. 109 - // TODO: replace with `split_at_mut_checked` once the MSRV is >= 1.80. 110 - let (prefix, remainder) = bytes.split_at_mut(size_of::<Self>()); 113 + let (prefix, remainder) = bytes.split_at_mut_checked(size_of::<Self>())?; 111 114 112 - Self::from_bytes_mut(prefix).map(|s| (s, remainder)) 113 - } 115 + Self::from_bytes_mut(prefix).map(|s| (s, remainder)) 114 116 } 115 117 116 118 /// Creates an owned instance of `Self` by copying `bytes`. ··· 133 149 where 134 150 Self: Sized, 135 151 { 136 - if bytes.len() < size_of::<Self>() { 137 - None 138 - } else { 139 - // PANIC: We checked that `bytes.len() >= size_of::<Self>`, thus `split_at` cannot 140 - // panic. 141 - // TODO: replace with `split_at_checked` once the MSRV is >= 1.80. 142 - let (prefix, remainder) = bytes.split_at(size_of::<Self>()); 152 + let (prefix, remainder) = bytes.split_at_checked(size_of::<Self>())?; 143 153 144 - Self::from_bytes_copy(prefix).map(|s| (s, remainder)) 145 - } 154 + Self::from_bytes_copy(prefix).map(|s| (s, remainder)) 146 155 } 147 156 } 148 157
-2
rust/kernel/types.rs
··· 11 11 }; 12 12 use pin_init::{PinInit, Wrapper, Zeroable}; 13 13 14 - pub use crate::sync::aref::{ARef, AlwaysRefCounted}; 15 - 16 14 /// Used to transfer ownership to and from foreign (non-Rust) languages. 17 15 /// 18 16 /// Ownership is transferred from Rust to a foreign language by calling [`Self::into_foreign`] and
+2 -4
rust/kernel/usb.rs
··· 18 18 to_result, // 19 19 }, 20 20 prelude::*, 21 - types::{ 22 - AlwaysRefCounted, 23 - Opaque, // 24 - }, 21 + sync::aref::AlwaysRefCounted, 22 + types::Opaque, 25 23 ThisModule, // 26 24 }; 27 25 use core::{
+1
rust/kernel/xarray.rs
··· 172 172 } 173 173 174 174 impl<T> From<StoreError<T>> for Error { 175 + #[inline] 175 176 fn from(value: StoreError<T>) -> Self { 176 177 value.error 177 178 }
-1
rust/macros/helpers.rs
··· 49 49 } 50 50 51 51 #[cfg(CONFIG_RUSTC_HAS_SPAN_FILE)] 52 - #[allow(clippy::incompatible_msrv)] 53 52 { 54 53 proc_macro::Span::call_site().file() 55 54 }
+5 -4
rust/macros/kunit.rs
··· 87 87 continue; 88 88 }; 89 89 90 - // TODO: Replace below with `extract_if` when MSRV is bumped above 1.85. 91 - let before_len = f.attrs.len(); 92 - f.attrs.retain(|attr| !attr.path().is_ident("test")); 93 - if f.attrs.len() == before_len { 90 + if f.attrs 91 + .extract_if(.., |attr| attr.path().is_ident("test")) 92 + .count() 93 + == 0 94 + { 94 95 processed_items.push(Item::Fn(f)); 95 96 continue; 96 97 }
+3
rust/macros/lib.rs
··· 6 6 // and thus add a dependency on `include/config/RUSTC_VERSION_TEXT`, which is 7 7 // touched by Kconfig when the version string from the compiler changes. 8 8 9 + // Stable since Rust 1.87.0. 10 + #![feature(extract_if)] 11 + // 9 12 // Stable since Rust 1.88.0 under a different name, `proc_macro_span_file`, 10 13 // which was added in Rust 1.88.0. This is why `cfg_attr` is used here, i.e. 11 14 // to avoid depending on the full `proc_macro_span` on Rust >= 1.88.0.
+2 -7
rust/macros/module.rs
··· 52 52 fn emit_base(&mut self, field: &str, content: &str, builtin: bool, param: bool) { 53 53 let string = if builtin { 54 54 // Built-in modules prefix their modinfo strings by `module.`. 55 - format!( 56 - "{module}.{field}={content}\0", 57 - module = self.module, 58 - field = field, 59 - content = content 60 - ) 55 + format!("{module}.{field}={content}\0", module = self.module) 61 56 } else { 62 57 // Loadable modules' modinfo strings go as-is. 63 58 format!("{field}={content}\0") ··· 104 109 } 105 110 106 111 fn emit_param(&mut self, field: &str, param: &str, content: &str) { 107 - let content = format!("{param}:{content}", param = param, content = content); 112 + let content = format!("{param}:{content}"); 108 113 self.emit_internal(field, &content, true); 109 114 } 110 115
+1 -2
rust/pin-init/README.md
··· 160 160 ```rust 161 161 use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure}; 162 162 use core::{ 163 - ptr::addr_of_mut, 164 163 marker::PhantomPinned, 165 164 cell::UnsafeCell, 166 165 pin::Pin, ··· 198 199 unsafe { 199 200 pin_init_from_closure(move |slot: *mut Self| { 200 201 // `slot` contains uninit memory, avoid creating a reference. 201 - let foo = addr_of_mut!((*slot).foo); 202 + let foo = &raw mut (*slot).foo; 202 203 let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>(); 203 204 204 205 // Initialize the `foo`
+3
rust/pin-init/examples/big_struct_in_place.rs
··· 1 1 // SPDX-License-Identifier: Apache-2.0 OR MIT 2 2 3 + #![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))] 4 + #![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))] 5 + 3 6 use pin_init::*; 4 7 5 8 // Struct with size over 1GiB
+2 -1
rust/pin-init/examples/linked_list.rs
··· 2 2 3 3 #![allow(clippy::undocumented_unsafe_blocks)] 4 4 #![cfg_attr(feature = "alloc", feature(allocator_api))] 5 - #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))] 5 + #![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))] 6 + #![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))] 6 7 7 8 use core::{ 8 9 cell::Cell,
+2 -1
rust/pin-init/examples/mutex.rs
··· 2 2 3 3 #![allow(clippy::undocumented_unsafe_blocks)] 4 4 #![cfg_attr(feature = "alloc", feature(allocator_api))] 5 - #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))] 5 + #![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))] 6 + #![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))] 6 7 #![allow(clippy::missing_safety_doc)] 7 8 8 9 use core::{
+2 -1
rust/pin-init/examples/pthread_mutex.rs
··· 3 3 // inspired by <https://github.com/nbdd0121/pin-init/blob/trunk/examples/pthread_mutex.rs> 4 4 #![allow(clippy::undocumented_unsafe_blocks)] 5 5 #![cfg_attr(feature = "alloc", feature(allocator_api))] 6 - #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))] 6 + #![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))] 7 + #![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))] 7 8 8 9 #[cfg(not(windows))] 9 10 mod pthread_mtx {
+2 -1
rust/pin-init/examples/static_init.rs
··· 2 2 3 3 #![allow(clippy::undocumented_unsafe_blocks)] 4 4 #![cfg_attr(feature = "alloc", feature(allocator_api))] 5 - #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))] 5 + #![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))] 6 + #![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))] 6 7 #![allow(unused_imports)] 7 8 8 9 use core::{
+10 -4
rust/pin-init/internal/src/init.rs
··· 173 173 }; 174 174 // SAFETY: TODO 175 175 let init = unsafe { ::pin_init::#init_from_closure::<_, #error>(init) }; 176 + // FIXME: this let binding is required to avoid a compiler error (cycle when computing the 177 + // opaque type returned by this function) before Rust 1.81. Remove after MSRV bump. 178 + #[allow( 179 + clippy::let_and_return, 180 + reason = "some clippy versions warn about the let binding" 181 + )] 176 182 init 177 183 }}) 178 184 } ··· 270 264 { 271 265 #value_prep 272 266 // SAFETY: TODO 273 - unsafe { #write(::core::ptr::addr_of_mut!((*#slot).#ident), #value_ident) }; 267 + unsafe { #write(&raw mut (*#slot).#ident, #value_ident) }; 274 268 } 275 269 #(#cfgs)* 276 270 #[allow(unused_variables)] ··· 293 287 // return when an error/panic occurs. 294 288 // - We also use `#data` to require the correct trait (`Init` or `PinInit`) 295 289 // for `#ident`. 296 - unsafe { #data.#ident(::core::ptr::addr_of_mut!((*#slot).#ident), #init)? }; 290 + unsafe { #data.#ident(&raw mut (*#slot).#ident, #init)? }; 297 291 }, 298 292 quote! { 299 293 // SAFETY: TODO ··· 308 302 unsafe { 309 303 ::pin_init::Init::__init( 310 304 #init, 311 - ::core::ptr::addr_of_mut!((*#slot).#ident), 305 + &raw mut (*#slot).#ident, 312 306 )? 313 307 }; 314 308 }, ··· 348 342 // SAFETY: We forget the guard later when initialization has succeeded. 349 343 let #guard = unsafe { 350 344 ::pin_init::__internal::DropGuard::new( 351 - ::core::ptr::addr_of_mut!((*slot).#ident) 345 + &raw mut (*slot).#ident 352 346 ) 353 347 }; 354 348 });
+1 -1
rust/pin-init/internal/src/lib.rs
··· 6 6 7 7 //! `pin-init` proc macros. 8 8 9 - #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))] 9 + #![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))] 10 10 // Documentation is done in the pin-init crate instead. 11 11 #![allow(missing_docs)] 12 12
+50 -23
rust/pin-init/src/lib.rs
··· 172 172 //! # #![feature(extern_types)] 173 173 //! use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure}; 174 174 //! use core::{ 175 - //! ptr::addr_of_mut, 176 175 //! marker::PhantomPinned, 177 176 //! cell::UnsafeCell, 178 177 //! pin::Pin, ··· 210 211 //! unsafe { 211 212 //! pin_init_from_closure(move |slot: *mut Self| { 212 213 //! // `slot` contains uninit memory, avoid creating a reference. 213 - //! let foo = addr_of_mut!((*slot).foo); 214 + //! let foo = &raw mut (*slot).foo; 214 215 //! let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>(); 215 216 //! 216 217 //! // Initialize the `foo` ··· 263 264 //! [`impl Init<T, E>`]: crate::Init 264 265 //! [Rust-for-Linux]: https://rust-for-linux.com/ 265 266 266 - #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))] 267 + #![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))] 268 + #![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))] 267 269 #![cfg_attr( 268 - all( 269 - any(feature = "alloc", feature = "std"), 270 - not(RUSTC_NEW_UNINIT_IS_STABLE) 271 - ), 270 + all(any(feature = "alloc", feature = "std"), USE_RUSTC_FEATURES), 272 271 feature(new_uninit) 273 272 )] 274 273 #![forbid(missing_docs, unsafe_op_in_unsafe_fn)] ··· 276 279 all(feature = "unsafe-pinned", CONFIG_RUSTC_HAS_UNSAFE_PINNED), 277 280 feature(unsafe_pinned) 278 281 )] 282 + #![cfg_attr(all(USE_RUSTC_FEATURES, doc), allow(internal_features))] 283 + #![cfg_attr(all(USE_RUSTC_FEATURES, doc), feature(rustdoc_internals))] 279 284 280 285 use core::{ 281 286 cell::UnsafeCell, ··· 754 755 /// 755 756 /// ```rust 756 757 /// # use pin_init::*; 757 - /// # use core::{ptr::addr_of_mut, marker::PhantomPinned}; 758 + /// # use core::marker::PhantomPinned; 758 759 /// #[pin_data] 759 760 /// #[derive(Zeroable)] 760 761 /// struct Buf { ··· 768 769 /// let init = pin_init!(&this in Buf { 769 770 /// buf: [0; 64], 770 771 /// // SAFETY: TODO. 771 - /// ptr: unsafe { addr_of_mut!((*this.as_ptr()).buf).cast() }, 772 + /// ptr: unsafe { (&raw mut (*this.as_ptr()).buf).cast() }, 772 773 /// pin: PhantomPinned, 773 774 /// }); 774 775 /// let init = pin_init!(Buf { ··· 1146 1147 // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety 1147 1148 // requirements. 1148 1149 let res = unsafe { pin_init_from_closure(|ptr: *mut U| init.__pinned_init(ptr.cast::<T>())) }; 1149 - // FIXME: remove the let statement once the nightly-MSRV allows it (1.78 otherwise encounters a 1150 - // cycle when computing the type returned by this function) 1151 - #[allow(clippy::let_and_return)] 1150 + // FIXME: this let binding is required to avoid a compiler error (cycle when computing the opaque 1151 + // type returned by this function) before Rust 1.81. Remove after MSRV bump. 1152 + #[allow( 1153 + clippy::let_and_return, 1154 + reason = "some clippy versions warn about the let binding" 1155 + )] 1152 1156 res 1153 1157 } 1154 1158 ··· 1165 1163 // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety 1166 1164 // requirements. 1167 1165 let res = unsafe { init_from_closure(|ptr: *mut U| init.__init(ptr.cast::<T>())) }; 1168 - // FIXME: remove the let statement once the nightly-MSRV allows it (1.78 otherwise encounters a 1169 - // cycle when computing the type returned by this function) 1170 - #[allow(clippy::let_and_return)] 1166 + // FIXME: this let binding is required to avoid a compiler error (cycle when computing the opaque 1167 + // type returned by this function) before Rust 1.81. Remove after MSRV bump. 1168 + #[allow( 1169 + clippy::let_and_return, 1170 + reason = "some clippy versions warn about the let binding" 1171 + )] 1171 1172 res 1172 1173 } 1173 1174 ··· 1615 1610 // SAFETY: `T: Zeroable` and `UnsafeCell` is `repr(transparent)`. 1616 1611 {<T: ?Sized + Zeroable>} UnsafeCell<T>, 1617 1612 1618 - // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee: 1619 - // <https://doc.rust-lang.org/stable/std/option/index.html#representation>). 1620 - Option<NonZeroU8>, Option<NonZeroU16>, Option<NonZeroU32>, Option<NonZeroU64>, 1621 - Option<NonZeroU128>, Option<NonZeroUsize>, 1622 - Option<NonZeroI8>, Option<NonZeroI16>, Option<NonZeroI32>, Option<NonZeroI64>, 1623 - Option<NonZeroI128>, Option<NonZeroIsize>, 1624 - 1625 1613 // SAFETY: `null` pointer is valid. 1626 1614 // 1627 1615 // We cannot use `T: ?Sized`, since the VTABLE pointer part of fat pointers is not allowed to be ··· 1633 1635 } 1634 1636 1635 1637 macro_rules! impl_tuple_zeroable { 1636 - ($(,)?) => {}; 1638 + ($first:ident, $(,)?) => { 1639 + #[cfg_attr(all(USE_RUSTC_FEATURES, doc), doc(fake_variadic))] 1640 + /// Implemented for tuples up to 10 items long. 1641 + // SAFETY: All elements are zeroable and padding can be zero. 1642 + unsafe impl<$first: Zeroable> Zeroable for ($first,) {} 1643 + }; 1637 1644 ($first:ident, $($t:ident),* $(,)?) => { 1645 + #[cfg_attr(doc, doc(hidden))] 1638 1646 // SAFETY: All elements are zeroable and padding can be zero. 1639 1647 unsafe impl<$first: Zeroable, $($t: Zeroable),*> Zeroable for ($first, $($t),*) {} 1640 1648 impl_tuple_zeroable!($($t),* ,); ··· 1655 1651 $(impl_fn_zeroable_option!({unsafe extern $abi} $args);)* 1656 1652 }; 1657 1653 ({$($prefix:tt)*} {$(,)?}) => {}; 1654 + ({$($prefix:tt)*} {$ret:ident, $arg:ident $(,)?}) => { 1655 + #[cfg_attr(all(USE_RUSTC_FEATURES, doc), doc(fake_variadic))] 1656 + /// Implemented for function pointers with up to 20 arity. 1657 + // SAFETY: function pointers are part of the option layout optimization: 1658 + // <https://doc.rust-lang.org/stable/std/option/index.html#representation>. 1659 + unsafe impl<$ret, $arg> ZeroableOption for $($prefix)* fn($arg) -> $ret {} 1660 + impl_fn_zeroable_option!({$($prefix)*} {$arg,}); 1661 + }; 1658 1662 ({$($prefix:tt)*} {$ret:ident, $($rest:ident),* $(,)?}) => { 1663 + #[cfg_attr(doc, doc(hidden))] 1659 1664 // SAFETY: function pointers are part of the option layout optimization: 1660 1665 // <https://doc.rust-lang.org/stable/std/option/index.html#representation>. 1661 1666 unsafe impl<$ret, $($rest),*> ZeroableOption for $($prefix)* fn($($rest),*) -> $ret {} ··· 1673 1660 } 1674 1661 1675 1662 impl_fn_zeroable_option!(["Rust", "C"] { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U }); 1663 + 1664 + macro_rules! impl_non_zero_int_zeroable_option { 1665 + ($($int:ty),* $(,)?) => { 1666 + // SAFETY: Safety comment written in the macro invocation. 1667 + $(unsafe impl ZeroableOption for $int {})* 1668 + }; 1669 + } 1670 + 1671 + impl_non_zero_int_zeroable_option! { 1672 + // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee: 1673 + // <https://doc.rust-lang.org/stable/std/option/index.html#representation>). 1674 + NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize, 1675 + NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize, 1676 + } 1676 1677 1677 1678 /// This trait allows creating an instance of `Self` which contains exactly one 1678 1679 /// [structurally pinned value](https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning).
+1 -4
rust/uapi/lib.rs
··· 8 8 //! userspace APIs. 9 9 10 10 #![no_std] 11 - // See <https://github.com/rust-lang/rust-bindgen/issues/1651>. 12 - #![cfg_attr(test, allow(deref_nullptr))] 13 - #![cfg_attr(test, allow(unaligned_references))] 14 - #![cfg_attr(test, allow(unsafe_op_in_unsafe_fn))] 15 11 #![allow( 16 12 clippy::all, 17 13 clippy::cast_lossless, ··· 24 28 unsafe_op_in_unsafe_fn 25 29 )] 26 30 #![cfg_attr(CONFIG_RUSTC_HAS_UNNECESSARY_TRANSMUTES, allow(unnecessary_transmutes))] 31 + #![feature(cfi_encoding)] 27 32 28 33 // Manual definition of blocklisted types. 29 34 type __kernel_size_t = usize;
+7 -8
scripts/Makefile.build
··· 310 310 311 311 # The features in this list are the ones allowed for non-`rust/` code. 312 312 # 313 - # - Stable since Rust 1.79.0: `feature(slice_ptr_len)`. 314 - # - Stable since Rust 1.81.0: `feature(lint_reasons)`. 315 - # - Stable since Rust 1.82.0: `feature(asm_const)`, 316 - # `feature(offset_of_nested)`, `feature(raw_ref_op)`. 317 - # - Stable since Rust 1.84.0: `feature(strict_provenance)`. 318 313 # - Stable since Rust 1.87.0: `feature(asm_goto)`. 319 314 # - Expected to become stable: `feature(arbitrary_self_types)`. 320 315 # - To be determined: `feature(used_with_arg)`. 321 316 # 322 317 # Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on 323 318 # the unstable features in use. 324 - rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,lint_reasons,offset_of_nested,raw_ref_op,slice_ptr_len,strict_provenance,used_with_arg 319 + rust_allowed_features := arbitrary_self_types,asm_goto,used_with_arg 325 320 326 321 # `--out-dir` is required to avoid temporaries being created by `rustc` in the 327 322 # current working directory, which may be not accessible in the out-of-tree ··· 329 334 -Zcrate-attr='feature($(rust_allowed_features))' \ 330 335 -Zunstable-options --extern pin_init --extern kernel \ 331 336 --crate-type rlib -L $(objtree)/rust/ \ 332 - --crate-name $(basename $(notdir $@)) \ 333 337 --sysroot=/dev/null \ 334 338 --out-dir $(dir $@) --emit=dep-info=$(depfile) 335 339 ··· 341 347 # would not match each other. 342 348 343 349 quiet_cmd_rustc_o_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@ 344 - cmd_rustc_o_rs = $(rust_common_cmd) --emit=obj=$@ $< $(cmd_objtool) 350 + cmd_rustc_o_rs = $(rust_common_cmd) --emit=$(if $(CONFIG_RUST_INLINE_HELPERS),llvm-bc=$(patsubst %.o,%.bc,$@),obj=$@) $< \ 351 + $(if $(CONFIG_RUST_INLINE_HELPERS),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \ 352 + $(objtree)/rust/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \ 353 + $(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \ 354 + $(cmd_ld_single)) \ 355 + $(cmd_objtool) 345 356 346 357 define rule_rustc_o_rs 347 358 $(call cmd_and_fixdep,rustc_o_rs)
+216 -82
scripts/generate_rust_analyzer.py
··· 10 10 import pathlib 11 11 import subprocess 12 12 import sys 13 + from typing import Dict, Iterable, List, Literal, Optional, TypedDict 13 14 14 - def args_crates_cfgs(cfgs): 15 + def invoke_rustc(args: List[str]) -> str: 16 + return subprocess.check_output( 17 + [os.environ["RUSTC"]] + args, 18 + stdin=subprocess.DEVNULL, 19 + ).decode('utf-8').strip() 20 + 21 + def args_crates_cfgs(cfgs: List[str]) -> Dict[str, List[str]]: 15 22 crates_cfgs = {} 16 23 for cfg in cfgs: 17 24 crate, vals = cfg.split("=", 1) ··· 26 19 27 20 return crates_cfgs 28 21 29 - def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edition): 22 + class Dependency(TypedDict): 23 + crate: int 24 + name: str 25 + 26 + 27 + class Source(TypedDict): 28 + include_dirs: List[str] 29 + exclude_dirs: List[str] 30 + 31 + 32 + class Crate(TypedDict): 33 + display_name: str 34 + root_module: str 35 + is_workspace_member: bool 36 + deps: List[Dependency] 37 + cfg: List[str] 38 + edition: str 39 + env: Dict[str, str] 40 + 41 + 42 + class ProcMacroCrate(Crate): 43 + is_proc_macro: Literal[True] 44 + proc_macro_dylib_path: str # `pathlib.Path` is not JSON serializable. 45 + 46 + 47 + class CrateWithGenerated(Crate): 48 + source: Source 49 + 50 + 51 + def generate_crates( 52 + srctree: pathlib.Path, 53 + objtree: pathlib.Path, 54 + sysroot_src: pathlib.Path, 55 + external_src: Optional[pathlib.Path], 56 + cfgs: List[str], 57 + core_edition: str, 58 + ) -> List[Crate]: 30 59 # Generate the configuration list. 31 - cfg = [] 60 + generated_cfg = [] 32 61 with open(objtree / "include" / "generated" / "rustc_cfg") as fd: 33 62 for line in fd: 34 63 line = line.replace("--cfg=", "") 35 64 line = line.replace("\n", "") 36 - cfg.append(line) 65 + generated_cfg.append(line) 37 66 38 - # Now fill the crates list -- dependencies need to come first. 39 - # 40 - # Avoid O(n^2) iterations by keeping a map of indexes. 41 - crates = [] 42 - crates_indexes = {} 67 + # Now fill the crates list. 68 + crates: List[Crate] = [] 43 69 crates_cfgs = args_crates_cfgs(cfgs) 44 70 45 - def append_crate(display_name, root_module, deps, cfg=[], is_workspace_member=True, is_proc_macro=False, edition="2021"): 46 - crate = { 71 + def get_crate_name(path: pathlib.Path) -> str: 72 + return invoke_rustc(["--print", "crate-name", str(path)]) 73 + 74 + def build_crate( 75 + display_name: str, 76 + root_module: pathlib.Path, 77 + deps: List[Dependency], 78 + *, 79 + cfg: Optional[List[str]], 80 + is_workspace_member: Optional[bool], 81 + edition: Optional[str], 82 + ) -> Crate: 83 + cfg = cfg if cfg is not None else crates_cfgs.get(display_name, []) 84 + is_workspace_member = ( 85 + is_workspace_member if is_workspace_member is not None else True 86 + ) 87 + edition = edition if edition is not None else "2021" 88 + return { 47 89 "display_name": display_name, 48 90 "root_module": str(root_module), 49 91 "is_workspace_member": is_workspace_member, 50 - "is_proc_macro": is_proc_macro, 51 - "deps": [{"crate": crates_indexes[dep], "name": dep} for dep in deps], 92 + "deps": deps, 52 93 "cfg": cfg, 53 94 "edition": edition, 54 95 "env": { 55 96 "RUST_MODFILE": "This is only for rust-analyzer" 56 97 } 57 98 } 58 - if is_proc_macro: 59 - proc_macro_dylib_name = subprocess.check_output( 60 - [os.environ["RUSTC"], "--print", "file-names", "--crate-name", display_name, "--crate-type", "proc-macro", "-"], 61 - stdin=subprocess.DEVNULL, 62 - ).decode('utf-8').strip() 63 - crate["proc_macro_dylib_path"] = f"{objtree}/rust/{proc_macro_dylib_name}" 64 - crates_indexes[display_name] = len(crates) 99 + 100 + def append_proc_macro_crate( 101 + display_name: str, 102 + root_module: pathlib.Path, 103 + deps: List[Dependency], 104 + *, 105 + cfg: Optional[List[str]] = None, 106 + is_workspace_member: Optional[bool] = None, 107 + edition: Optional[str] = None, 108 + ) -> Dependency: 109 + crate = build_crate( 110 + display_name, 111 + root_module, 112 + deps, 113 + cfg=cfg, 114 + is_workspace_member=is_workspace_member, 115 + edition=edition, 116 + ) 117 + proc_macro_dylib_name = invoke_rustc([ 118 + "--print", 119 + "file-names", 120 + "--crate-name", 121 + display_name, 122 + "--crate-type", 123 + "proc-macro", 124 + "-", 125 + ]) 126 + proc_macro_crate: ProcMacroCrate = { 127 + **crate, 128 + "is_proc_macro": True, 129 + "proc_macro_dylib_path": str(objtree / "rust" / proc_macro_dylib_name), 130 + } 131 + return register_crate(proc_macro_crate) 132 + 133 + def register_crate(crate: Crate) -> Dependency: 134 + index = len(crates) 65 135 crates.append(crate) 136 + return {"crate": index, "name": crate["display_name"]} 137 + 138 + def append_crate( 139 + display_name: str, 140 + root_module: pathlib.Path, 141 + deps: List[Dependency], 142 + *, 143 + cfg: Optional[List[str]] = None, 144 + is_workspace_member: Optional[bool] = None, 145 + edition: Optional[str] = None, 146 + ) -> Dependency: 147 + return register_crate( 148 + build_crate( 149 + display_name, 150 + root_module, 151 + deps, 152 + cfg=cfg, 153 + is_workspace_member=is_workspace_member, 154 + edition=edition, 155 + ) 156 + ) 66 157 67 158 def append_sysroot_crate( 68 - display_name, 69 - deps, 70 - cfg=[], 71 - ): 72 - append_crate( 159 + display_name: str, 160 + deps: List[Dependency], 161 + *, 162 + cfg: Optional[List[str]] = None, 163 + ) -> Dependency: 164 + return append_crate( 73 165 display_name, 74 166 sysroot_src / display_name / "src" / "lib.rs", 75 167 deps, 76 - cfg, 168 + cfg=cfg, 77 169 is_workspace_member=False, 78 170 # Miguel Ojeda writes: 79 171 # ··· 204 98 # NB: sysroot crates reexport items from one another so setting up our transitive dependencies 205 99 # here is important for ensuring that rust-analyzer can resolve symbols. The sources of truth 206 100 # for this dependency graph are `(sysroot_src / crate / "Cargo.toml" for crate in crates)`. 207 - append_sysroot_crate("core", [], cfg=crates_cfgs.get("core", [])) 208 - append_sysroot_crate("alloc", ["core"]) 209 - append_sysroot_crate("std", ["alloc", "core"]) 210 - append_sysroot_crate("proc_macro", ["core", "std"]) 101 + core = append_sysroot_crate("core", []) 102 + alloc = append_sysroot_crate("alloc", [core]) 103 + std = append_sysroot_crate("std", [alloc, core]) 104 + proc_macro = append_sysroot_crate("proc_macro", [core, std]) 211 105 212 - append_crate( 106 + compiler_builtins = append_crate( 213 107 "compiler_builtins", 214 108 srctree / "rust" / "compiler_builtins.rs", 215 - ["core"], 109 + [core], 216 110 ) 217 111 218 - append_crate( 112 + proc_macro2 = append_crate( 219 113 "proc_macro2", 220 114 srctree / "rust" / "proc-macro2" / "lib.rs", 221 - ["core", "alloc", "std", "proc_macro"], 222 - cfg=crates_cfgs["proc_macro2"], 115 + [core, alloc, std, proc_macro], 223 116 ) 224 117 225 - append_crate( 118 + quote = append_crate( 226 119 "quote", 227 120 srctree / "rust" / "quote" / "lib.rs", 228 - ["core", "alloc", "std", "proc_macro", "proc_macro2"], 229 - cfg=crates_cfgs["quote"], 121 + [core, alloc, std, proc_macro, proc_macro2], 230 122 edition="2018", 231 123 ) 232 124 233 - append_crate( 125 + syn = append_crate( 234 126 "syn", 235 127 srctree / "rust" / "syn" / "lib.rs", 236 - ["std", "proc_macro", "proc_macro2", "quote"], 237 - cfg=crates_cfgs["syn"], 128 + [std, proc_macro, proc_macro2, quote], 238 129 ) 239 130 240 - append_crate( 131 + macros = append_proc_macro_crate( 241 132 "macros", 242 133 srctree / "rust" / "macros" / "lib.rs", 243 - ["std", "proc_macro", "proc_macro2", "quote", "syn"], 244 - is_proc_macro=True, 134 + [std, proc_macro, proc_macro2, quote, syn], 245 135 ) 246 136 247 - append_crate( 137 + build_error = append_crate( 248 138 "build_error", 249 139 srctree / "rust" / "build_error.rs", 250 - ["core", "compiler_builtins"], 140 + [core, compiler_builtins], 251 141 ) 252 142 253 - append_crate( 143 + pin_init_internal = append_proc_macro_crate( 254 144 "pin_init_internal", 255 145 srctree / "rust" / "pin-init" / "internal" / "src" / "lib.rs", 256 - ["std", "proc_macro", "proc_macro2", "quote", "syn"], 257 - cfg=["kernel"], 258 - is_proc_macro=True, 146 + [std, proc_macro, proc_macro2, quote, syn], 259 147 ) 260 148 261 - append_crate( 149 + pin_init = append_crate( 262 150 "pin_init", 263 151 srctree / "rust" / "pin-init" / "src" / "lib.rs", 264 - ["core", "compiler_builtins", "pin_init_internal", "macros"], 265 - cfg=["kernel"], 152 + [core, compiler_builtins, pin_init_internal, macros], 266 153 ) 267 154 268 - append_crate( 155 + ffi = append_crate( 269 156 "ffi", 270 157 srctree / "rust" / "ffi.rs", 271 - ["core", "compiler_builtins"], 158 + [core, compiler_builtins], 272 159 ) 273 160 274 161 def append_crate_with_generated( 275 - display_name, 276 - deps, 277 - ): 278 - append_crate( 162 + display_name: str, 163 + deps: List[Dependency], 164 + ) -> Dependency: 165 + crate = build_crate( 279 166 display_name, 280 167 srctree / "rust"/ display_name / "lib.rs", 281 168 deps, 282 - cfg=cfg, 169 + cfg=generated_cfg, 170 + is_workspace_member=True, 171 + edition=None, 283 172 ) 284 - crates[-1]["env"]["OBJTREE"] = str(objtree.resolve(True)) 285 - crates[-1]["source"] = { 286 - "include_dirs": [ 287 - str(srctree / "rust" / display_name), 288 - str(objtree / "rust") 289 - ], 290 - "exclude_dirs": [], 173 + crate["env"]["OBJTREE"] = str(objtree.resolve(True)) 174 + crate_with_generated: CrateWithGenerated = { 175 + **crate, 176 + "source": { 177 + "include_dirs": [ 178 + str(srctree / "rust" / display_name), 179 + str(objtree / "rust"), 180 + ], 181 + "exclude_dirs": [], 182 + }, 291 183 } 184 + return register_crate(crate_with_generated) 292 185 293 - append_crate_with_generated("bindings", ["core", "ffi", "pin_init"]) 294 - append_crate_with_generated("uapi", ["core", "ffi", "pin_init"]) 295 - append_crate_with_generated("kernel", ["core", "macros", "build_error", "pin_init", "ffi", "bindings", "uapi"]) 186 + bindings = append_crate_with_generated("bindings", [core, ffi, pin_init]) 187 + uapi = append_crate_with_generated("uapi", [core, ffi, pin_init]) 188 + kernel = append_crate_with_generated( 189 + "kernel", [core, macros, build_error, pin_init, ffi, bindings, uapi] 190 + ) 296 191 297 - def is_root_crate(build_file, target): 192 + scripts = srctree / "scripts" 193 + makefile = (scripts / "Makefile").read_text() 194 + for path in scripts.glob("*.rs"): 195 + name = path.stem 196 + if f"{name}-rust" not in makefile: 197 + continue 198 + append_crate( 199 + name, 200 + path, 201 + [std], 202 + ) 203 + 204 + def is_root_crate(build_file: pathlib.Path, target: str) -> bool: 298 205 try: 299 - return f"{target}.o" in open(build_file).read() 206 + contents = build_file.read_text() 300 207 except FileNotFoundError: 301 208 return False 209 + return f"{target}.o" in contents 302 210 303 211 # Then, the rest outside of `rust/`. 304 212 # 305 213 # We explicitly mention the top-level folders we want to cover. 306 - extra_dirs = map(lambda dir: srctree / dir, ("samples", "drivers")) 214 + extra_dirs: Iterable[pathlib.Path] = ( 215 + srctree / dir for dir in ("samples", "drivers") 216 + ) 307 217 if external_src is not None: 308 218 extra_dirs = [external_src] 309 219 for folder in extra_dirs: 310 220 for path in folder.rglob("*.rs"): 311 221 logging.info("Checking %s", path) 312 - name = path.name.replace(".rs", "") 222 + file_name = path.stem 313 223 314 224 # Skip those that are not crate roots. 315 - if not is_root_crate(path.parent / "Makefile", name) and \ 316 - not is_root_crate(path.parent / "Kbuild", name): 225 + if not is_root_crate(path.parent / "Makefile", file_name) and \ 226 + not is_root_crate(path.parent / "Kbuild", file_name): 317 227 continue 318 228 319 - logging.info("Adding %s", name) 229 + crate_name = get_crate_name(path) 230 + logging.info("Adding %s", crate_name) 320 231 append_crate( 321 - name, 232 + crate_name, 322 233 path, 323 - ["core", "kernel", "pin_init"], 324 - cfg=cfg, 234 + [core, kernel, pin_init], 235 + cfg=generated_cfg, 325 236 ) 326 237 327 238 return crates 328 239 329 - def main(): 240 + def main() -> None: 330 241 parser = argparse.ArgumentParser() 331 242 parser.add_argument('--verbose', '-v', action='store_true') 332 243 parser.add_argument('--cfgs', action='append', default=[]) ··· 353 230 parser.add_argument("sysroot", type=pathlib.Path) 354 231 parser.add_argument("sysroot_src", type=pathlib.Path) 355 232 parser.add_argument("exttree", type=pathlib.Path, nargs="?") 356 - args = parser.parse_args() 233 + 234 + class Args(argparse.Namespace): 235 + verbose: bool 236 + cfgs: List[str] 237 + srctree: pathlib.Path 238 + objtree: pathlib.Path 239 + sysroot: pathlib.Path 240 + sysroot_src: pathlib.Path 241 + exttree: Optional[pathlib.Path] 242 + core_edition: str 243 + 244 + args = parser.parse_args(namespace=Args()) 357 245 358 246 logging.basicConfig( 359 247 format="[%(asctime)s] [%(levelname)s] %(message)s",
+2 -2
scripts/min-tool-version.sh
··· 31 31 fi 32 32 ;; 33 33 rustc) 34 - echo 1.78.0 34 + echo 1.85.0 35 35 ;; 36 36 bindgen) 37 - echo 0.65.1 37 + echo 0.71.1 38 38 ;; 39 39 *) 40 40 echo "$1: unknown tool" >&2
+1 -35
scripts/rust_is_available.sh
··· 121 121 # Check that the Rust bindings generator is suitable. 122 122 # 123 123 # Non-stable and distributions' versions may have a version suffix, e.g. `-dev`. 124 - # 125 - # The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0 126 - # (https://github.com/rust-lang/rust-bindgen/pull/2678) and 0.71.0 127 - # (https://github.com/rust-lang/rust-bindgen/pull/3040). It can be removed when 128 - # the minimum version is upgraded past the latter (0.69.1 and 0.71.1 both fixed 129 - # the issue). 130 124 rust_bindings_generator_output=$( \ 131 - LC_ALL=C "$BINDGEN" --version workaround-for-0.69.0 2>/dev/null 125 + LC_ALL=C "$BINDGEN" --version 2>/dev/null 132 126 ) || rust_bindings_generator_code=$? 133 127 if [ -n "$rust_bindings_generator_code" ]; then 134 128 echo >&2 "***" ··· 156 162 echo >&2 "*** Minimum version: $rust_bindings_generator_min_version" 157 163 echo >&2 "***" 158 164 exit 1 159 - fi 160 - if [ "$rust_bindings_generator_cversion" -eq 6600 ] || 161 - [ "$rust_bindings_generator_cversion" -eq 6601 ]; then 162 - # Distributions may have patched the issue (e.g. Debian did). 163 - if ! "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_0_66.h >/dev/null; then 164 - echo >&2 "***" 165 - echo >&2 "*** Rust bindings generator '$BINDGEN' versions 0.66.0 and 0.66.1 may not" 166 - echo >&2 "*** work due to a bug (https://github.com/rust-lang/rust-bindgen/pull/2567)," 167 - echo >&2 "*** unless patched (like Debian's)." 168 - echo >&2 "*** Your version: $rust_bindings_generator_version" 169 - echo >&2 "***" 170 - warning=1 171 - fi 172 165 fi 173 166 174 167 # Check that the `libclang` used by the Rust bindings generator is suitable. ··· 206 225 echo >&2 "*** Minimum version: $bindgen_libclang_min_version" 207 226 echo >&2 "***" 208 227 exit 1 209 - fi 210 - 211 - if [ "$bindgen_libclang_cversion" -ge 1900100 ] && 212 - [ "$rust_bindings_generator_cversion" -lt 6905 ]; then 213 - # Distributions may have patched the issue (e.g. Debian did). 214 - if ! "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_libclang_concat.h | grep -q foofoo; then 215 - echo >&2 "***" 216 - echo >&2 "*** Rust bindings generator '$BINDGEN' < 0.69.5 together with libclang >= 19.1" 217 - echo >&2 "*** may not work due to a bug (https://github.com/rust-lang/rust-bindgen/pull/2824)," 218 - echo >&2 "*** unless patched (like Debian's)." 219 - echo >&2 "*** Your bindgen version: $rust_bindings_generator_version" 220 - echo >&2 "*** Your libclang version: $bindgen_libclang_version" 221 - echo >&2 "***" 222 - warning=1 223 - fi 224 228 fi 225 229 226 230 # If the C compiler is Clang, then we can also check whether its version
-2
scripts/rust_is_available_bindgen_0_66.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #define A "\0"
-3
scripts/rust_is_available_bindgen_libclang_concat.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #define F(x) int x##x 3 - F(foo);
+3 -55
scripts/rust_is_available_test.py
··· 54 54 """) 55 55 56 56 @classmethod 57 - def generate_bindgen(cls, version_stdout, libclang_stderr, version_0_66_patched=False, libclang_concat_patched=False): 57 + def generate_bindgen(cls, version_stdout, libclang_stderr): 58 58 if libclang_stderr is None: 59 59 libclang_case = f"raise SystemExit({cls.bindgen_default_bindgen_libclang_failure_exit_code})" 60 60 else: 61 61 libclang_case = f"print({repr(libclang_stderr)}, file=sys.stderr)" 62 62 63 - if version_0_66_patched: 64 - version_0_66_case = "pass" 65 - else: 66 - version_0_66_case = "raise SystemExit(1)" 67 - 68 - if libclang_concat_patched: 69 - libclang_concat_case = "print('pub static mut foofoo: ::std::os::raw::c_int;')" 70 - else: 71 - libclang_concat_case = "pass" 72 - 73 63 return cls.generate_executable(f"""#!/usr/bin/env python3 74 64 import sys 75 65 if "rust_is_available_bindgen_libclang.h" in " ".join(sys.argv): 76 66 {libclang_case} 77 - elif "rust_is_available_bindgen_0_66.h" in " ".join(sys.argv): 78 - {version_0_66_case} 79 - elif "rust_is_available_bindgen_libclang_concat.h" in " ".join(sys.argv): 80 - {libclang_concat_case} 81 67 else: 82 68 print({repr(version_stdout)}) 83 69 """) 84 70 85 71 @classmethod 86 - def generate_bindgen_version(cls, stdout, version_0_66_patched=False): 87 - return cls.generate_bindgen(stdout, cls.bindgen_default_bindgen_libclang_stderr, version_0_66_patched) 72 + def generate_bindgen_version(cls, stdout): 73 + return cls.generate_bindgen(stdout, cls.bindgen_default_bindgen_libclang_stderr) 88 74 89 75 @classmethod 90 76 def generate_bindgen_libclang_failure(cls): ··· 231 245 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen }) 232 246 self.assertIn(f"Rust bindings generator '{bindgen}' is too old.", result.stderr) 233 247 234 - def test_bindgen_bad_version_0_66_0_and_0_66_1(self): 235 - for version in ("0.66.0", "0.66.1"): 236 - with self.subTest(version=version): 237 - bindgen = self.generate_bindgen_version(f"bindgen {version}") 238 - result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen }) 239 - self.assertIn(f"Rust bindings generator '{bindgen}' versions 0.66.0 and 0.66.1 may not", result.stderr) 240 - 241 - def test_bindgen_bad_version_0_66_0_and_0_66_1_patched(self): 242 - for version in ("0.66.0", "0.66.1"): 243 - with self.subTest(version=version): 244 - bindgen = self.generate_bindgen_version(f"bindgen {version}", True) 245 - result = self.run_script(self.Expected.SUCCESS, { "BINDGEN": bindgen }) 246 - 247 248 def test_bindgen_libclang_failure(self): 248 249 bindgen = self.generate_bindgen_libclang_failure() 249 250 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen }) ··· 247 274 bindgen = self.generate_bindgen_libclang("scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version 10.0.0 [-W#pragma-messages], err: false") 248 275 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen }) 249 276 self.assertIn(f"libclang (used by the Rust bindings generator '{bindgen}') is too old.", result.stderr) 250 - 251 - def test_bindgen_bad_libclang_concat(self): 252 - for (bindgen_version, libclang_version, expected_not_patched) in ( 253 - ("0.69.4", "18.0.0", self.Expected.SUCCESS), 254 - ("0.69.4", "19.1.0", self.Expected.SUCCESS_WITH_WARNINGS), 255 - ("0.69.4", "19.2.0", self.Expected.SUCCESS_WITH_WARNINGS), 256 - 257 - ("0.69.5", "18.0.0", self.Expected.SUCCESS), 258 - ("0.69.5", "19.1.0", self.Expected.SUCCESS), 259 - ("0.69.5", "19.2.0", self.Expected.SUCCESS), 260 - 261 - ("0.70.0", "18.0.0", self.Expected.SUCCESS), 262 - ("0.70.0", "19.1.0", self.Expected.SUCCESS), 263 - ("0.70.0", "19.2.0", self.Expected.SUCCESS), 264 - ): 265 - with self.subTest(bindgen_version=bindgen_version, libclang_version=libclang_version): 266 - cc = self.generate_clang(f"clang version {libclang_version}") 267 - libclang_stderr = f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {libclang_version} [-W#pragma-messages], err: false" 268 - bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr) 269 - result = self.run_script(expected_not_patched, { "BINDGEN": bindgen, "CC": cc }) 270 - if expected_not_patched == self.Expected.SUCCESS_WITH_WARNINGS: 271 - self.assertIn(f"Rust bindings generator '{bindgen}' < 0.69.5 together with libclang >= 19.1", result.stderr) 272 - 273 - bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr, libclang_concat_patched=True) 274 - result = self.run_script(self.Expected.SUCCESS, { "BINDGEN": bindgen, "CC": cc }) 275 277 276 278 def test_clang_matches_bindgen_libclang_different_bindgen(self): 277 279 bindgen = self.generate_bindgen_libclang("scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version 999.0.0 [-W#pragma-messages], err: false")