History

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 ...

Linus Torvalds committed 7 months ago

Commit 26ff9692 parents 2848320 8a2305178 files · +1391 −821Browse files

Unified · Split

78 files
  1. .clippy.toml +11 −1
  2. .gitignore +4 −0
  3. Documentation/process/changes.rst +2 −2
  4. Documentation/rust/general-information.rst +2 −2
  5. Documentation/rust/quick-start.rst +20 −32
  6. MAINTAINERS +1 −0
  7. Makefile +19 −2
  8. arch/Kconfig +1 −2
  9. arch/arm64/Kconfig +0 −8
  10. arch/riscv/Kconfig +0 −3
  11. drivers/android/binder/Makefile +1 −2
  12. drivers/android/binder/page_range.rs +3 −3
  13. drivers/android/binder/page_range_helper.c +0 −24
  14. drivers/android/binder/page_range_helper.h +0 −15
  15. drivers/android/binder/rust_binder_main.rs +2 −0
  16. drivers/gpu/drm/tyr/driver.rs +0 −12
  17. drivers/gpu/nova-core/gsp/cmdq.rs +1 −5
  18. drivers/gpu/nova-core/gsp/fw/r570_144.rs +0 −3
  19. drivers/pwm/pwm_th1520.rs +0 −15
  20. init/Kconfig +16 −14
  21. lib/Kconfig.debug +17 −0
  22. rust/Makefile +36 −33
  23. rust/bindgen_parameters +4 −4
  24. rust/bindings/bindings_helper.h +0 −1
  25. rust/bindings/lib.rs +1 −4
  26. rust/exports.c +4 −1
  27. rust/helpers/clk.c +13 −11
  28. rust/helpers/helpers.c +29 −0
  29. rust/helpers/jump_label.c +1 −1
  30. rust/kernel/alloc/allocator/iter.rs +1 −7
  31. rust/kernel/alloc/kbox.rs +2 −27
  32. rust/kernel/alloc/kvec/errors.rs +3 −0
  33. rust/kernel/block/mq/gen_disk.rs +1 −3
  34. rust/kernel/build_assert.rs +153 −30
  35. rust/kernel/clk.rs +7 −0
  36. rust/kernel/error.rs +37 −0
  37. rust/kernel/i2c.rs +6 −7
  38. rust/kernel/lib.rs +2 −36
  39. rust/kernel/list.rs +19 −3
  40. rust/kernel/list/arc.rs +2 −21
  41. rust/kernel/list/arc_field.rs +1 −0
  42. rust/kernel/list/impl_list_item_mod.rs +3 −0
  43. rust/kernel/num/bounded.rs +9 −15
  44. rust/kernel/prelude.rs +82 −28
  45. rust/kernel/ptr.rs +35 −7
  46. rust/kernel/sizes.rs +128 −44
  47. rust/kernel/slice.rs +0 −49
  48. rust/kernel/static_assert.rs +0 −39
  49. rust/kernel/str.rs +23 −4
  50. rust/kernel/sync/arc.rs +2 −19
  51. rust/kernel/task.rs +3 −4
  52. rust/kernel/time.rs +26 −6
  53. rust/kernel/time/hrtimer.rs +336 −0
  54. rust/kernel/transmute.rs +6 −29
  55. rust/kernel/types.rs +0 −2
  56. rust/kernel/usb.rs +2 −4
  57. rust/kernel/xarray.rs +1 −0
  58. rust/macros/helpers.rs +0 −1
  59. rust/macros/kunit.rs +5 −4
  60. rust/macros/lib.rs +3 −0
  61. rust/macros/module.rs +2 −7
  62. rust/pin-init/README.md +1 −2
  63. rust/pin-init/examples/big_struct_in_place.rs +3 −0
  64. rust/pin-init/examples/linked_list.rs +2 −1
  65. rust/pin-init/examples/mutex.rs +2 −1
  66. rust/pin-init/examples/pthread_mutex.rs +2 −1
  67. rust/pin-init/examples/static_init.rs +2 −1
  68. rust/pin-init/internal/src/init.rs +10 −4
  69. rust/pin-init/internal/src/lib.rs +1 −1
  70. rust/pin-init/src/lib.rs +50 −23
  71. rust/uapi/lib.rs +1 −4
  72. scripts/Makefile.build +7 −8
  73. scripts/generate_rust_analyzer.py +216 −82
  74. scripts/min-tool-version.sh +2 −2
  75. scripts/rust_is_available.sh +1 −35
  76. scripts/rust_is_available_bindgen_0_66.h +0 −2
  77. scripts/rust_is_available_bindgen_libclang_concat.h +0 −3
  78. scripts/rust_is_available_test.py +3 −55
.clippy.toml+11−1
@@ -1,6 +1,6 @@
11 # SPDX-License-Identifier: GPL-2.0
22
3−msrv = "1.78.0"
3+msrv = "1.85.0"
44
55 check-private-items = true
66
@@ -9,3 +9,13 @@ disallowed-macros = [ · 2 unmodified lines
99 # it here, see: https://github.com/rust-lang/rust-clippy/issues/11303.
1010 { path = "kernel::dbg", reason = "the `dbg!` macro is intended as a debugging tool", allow-invalid = true },
1111 ]
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"
.gitignore+4−0
@@ -13,6 +13,7 @@ · 12 unmodified lines
1313 .*
1414 *.a
1515 *.asn1.[ch]
16+*.bc
1617 *.bin
1718 *.bz2
1819 *.c.[012]*.*
@@ -184,3 +185,6 @@ sphinx_*/ · 165 unmodified lines
184185
185186 # Rust analyzer configuration
186187 /rust-project.json
188+
189+# bc language scripts (not LLVM bitcode)
190+!kernel/time/timeconst.bc
Documentation/process/changes.rst+2−2
@@ -31,8 +31,8 @@ you probably needn't concern yourself with pcmciautils. · 30 unmodified lines
3131 ====================== =============== ========================================
3232 GNU C 8.1 gcc --version
3333 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
3636 GNU make 4.0 make --version
3737 bash 4.2 bash --version
3838 binutils 2.30 ld -v
Documentation/rust/general-information.rst+2−2
@@ -157,5 +157,5 @@ numerical comparisons, one may define a new Kconfig symbol: · 156 unmodified lines
157157
158158 .. code-block:: kconfig
159159
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
Documentation/rust/quick-start.rst+20−32
@@ -57,8 +57,8 @@ of the box, e.g.:: · 56 unmodified lines
5757 Gentoo Linux
5858 ************
5959
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.::
6262
6363 USE='rust-src rustfmt clippy' emerge dev-lang/rust dev-util/bindgen
6464
@@ -68,8 +68,8 @@ and thus it should generally work out of the box, e.g.:: · 3 unmodified lines
6868 Nix
6969 ***
7070
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.::
7373
7474 { pkgs ? import <nixpkgs> {} }:
7575 pkgs.mkShell {
@@ -84,16 +84,13 @@ openSUSE · 8 unmodified lines
8484 openSUSE Slowroll and openSUSE Tumbleweed provide recent Rust releases and thus
8585 they should generally work out of the box, e.g.::
8686
87− zypper install rust rust1.79-src rust-bindgen clang
87+ zypper install rust rust-src rust-bindgen clang
8888
8989
9090 Ubuntu
9191 ******
9292
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
9794 generally work out of the box, e.g.::
9895
9996 apt install rustc rust-src bindgen rustfmt rust-clippy
@@ -112,33 +109,33 @@ Though Ubuntu 24.04 LTS and older versions still provide recent Rust · 12 unmodified lines
112109 releases, they require some additional configuration to be set, using
113110 the versioned packages, e.g.::
114111
115− apt install rustc-1.80 rust-1.80-src bindgen-0.65 rustfmt-1.80 \
116− rust-1.80-clippy
117− ln -s /usr/lib/rust-1.80/bin/rustfmt /usr/bin/rustfmt-1.80
118− ln -s /usr/lib/rust-1.80/bin/clippy-driver /usr/bin/clippy-driver-1.80
112+ apt install rustc-1.85 rust-1.85-src bindgen-0.71 rustfmt-1.85 \
113+ rust-1.85-clippy
114+ ln -s /usr/lib/rust-1.85/bin/rustfmt /usr/bin/rustfmt-1.85
115+ ln -s /usr/lib/rust-1.85/bin/clippy-driver /usr/bin/clippy-driver-1.85
119116
120117 None of these packages set their tools as defaults; therefore they should be
121118 specified explicitly, e.g.::
122119
123− make LLVM=1 RUSTC=rustc-1.80 RUSTDOC=rustdoc-1.80 RUSTFMT=rustfmt-1.80 \
124− CLIPPY_DRIVER=clippy-driver-1.80 BINDGEN=bindgen-0.65
120+ make LLVM=1 RUSTC=rustc-1.85 RUSTDOC=rustdoc-1.85 RUSTFMT=rustfmt-1.85 \
121+ CLIPPY_DRIVER=clippy-driver-1.85 BINDGEN=bindgen-0.71
125122
126−Alternatively, modify the ``PATH`` variable to place the Rust 1.80 binaries
123+Alternatively, modify the ``PATH`` variable to place the Rust 1.85 binaries
127124 first and set ``bindgen`` as the default, e.g.::
128125
129− PATH=/usr/lib/rust-1.80/bin:$PATH
126+ PATH=/usr/lib/rust-1.85/bin:$PATH
130127 update-alternatives --install /usr/bin/bindgen bindgen \
131− /usr/bin/bindgen-0.65 100
132− update-alternatives --set bindgen /usr/bin/bindgen-0.65
128+ /usr/bin/bindgen-0.71 100
129+ update-alternatives --set bindgen /usr/bin/bindgen-0.71
133130
134−``RUST_LIB_SRC`` needs to be set when using the versioned packages, e.g.::
131+``RUST_LIB_SRC`` may need to be set when using the versioned packages, e.g.::
135132
136− RUST_LIB_SRC=/usr/src/rustc-$(rustc-1.80 --version | cut -d' ' -f2)/library
133+ RUST_LIB_SRC=/usr/src/rustc-$(rustc-1.85 --version | cut -d' ' -f2)/library
137134
138135 For convenience, ``RUST_LIB_SRC`` can be exported to the global environment.
139136
140−In addition, ``bindgen-0.65`` is available in newer releases (24.04 LTS and
141−24.10), but it may not be available in older ones (20.04 LTS and 22.04 LTS),
137+In addition, ``bindgen-0.71`` is available in newer releases (24.04 LTS),
138+but it may not be available in older ones (20.04 LTS and 22.04 LTS),
142139 thus ``bindgen`` may need to be built manually (please see below).
143140
144141
@@ -355,12 +352,3 @@ Hacking · 210 unmodified lines
355352 To dive deeper, take a look at the source code of the samples
356353 at ``samples/rust/``, the Rust support code under ``rust/`` and
357354 the ``Rust hacking`` menu under ``Kernel hacking``.
358−
359−If GDB/Binutils is used and Rust symbols are not getting demangled, the reason
360−is the toolchain does not support Rust's new v0 mangling scheme yet.
361−There are a few ways out:
362−
363−- Install a newer release (GDB >= 10.2, Binutils >= 2.36).
364−
365−- Some versions of GDB (e.g. vanilla GDB 10.1) are able to use
366− the pre-demangled names embedded in the debug info (``CONFIG_DEBUG_INFO``).
MAINTAINERS+1−0
@@ -23166,6 +23166,7 @@ C: zulip://rust-for-linux.zulipchat.com · 23165 unmodified lines
2316623166 P: https://rust-for-linux.com/contributing
2316723167 T: git https://github.com/Rust-for-Linux/linux.git rust-next
2316823168 F: .clippy.toml
23169+F: .rustfmt.toml
2316923170 F: Documentation/rust/
2317023171 F: include/trace/events/rust_sample.h
2317123172 F: rust/
Makefile+19−2
@@ -487,6 +487,7 @@ export rust_common_flags := --edition=2021 \ · 486 unmodified lines
487487 -Wclippy::as_underscore \
488488 -Wclippy::cast_lossless \
489489 -Wclippy::ignored_unit_patterns \
490+ -Aclippy::incompatible_msrv \
490491 -Wclippy::mut_mut \
491492 -Wclippy::needless_bitwise_bool \
492493 -Aclippy::needless_lifetimes \
@@ -495,6 +496,7 @@ export rust_common_flags := --edition=2021 \ · 2 unmodified lines
495496 -Wclippy::ptr_cast_constness \
496497 -Wclippy::ref_as_ptr \
497498 -Wclippy::undocumented_unsafe_blocks \
499+ -Aclippy::uninlined_format_args \
498500 -Wclippy::unnecessary_safety_comment \
499501 -Wclippy::unnecessary_safety_doc \
500502 -Wrustdoc::missing_crate_level_docs \
@@ -505,7 +507,7 @@ KBUILD_HOSTCFLAGS := $(KBUILD_USERHOSTCFLAGS) $(HOST_LFS_CFLAGS) \ · 4 unmodified lines
505507 KBUILD_HOSTCXXFLAGS := -Wall -O2 $(HOST_LFS_CFLAGS) $(HOSTCXXFLAGS) \
506508 -I $(srctree)/scripts/include
507509 KBUILD_HOSTRUSTFLAGS := $(rust_common_flags) -O -Cstrip=debuginfo \
508− -Zallow-features= $(HOSTRUSTFLAGS)
510+ -Zallow-features=
509511 KBUILD_HOSTLDFLAGS := $(HOST_LFS_LDFLAGS) $(HOSTLDFLAGS)
510512 KBUILD_HOSTLDLIBS := $(HOST_LFS_LIBS) $(HOSTLDLIBS)
511513 KBUILD_PROCMACROLDFLAGS := $(or $(PROCMACROLDFLAGS),$(KBUILD_HOSTLDFLAGS))
@@ -516,6 +518,7 @@ ifneq ($(LLVM),) · 4 unmodified lines
516518 CC = $(LLVM_PREFIX)clang$(LLVM_SUFFIX)
517519 LD = $(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX)
518520 AR = $(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX)
521+LLVM_LINK = $(LLVM_PREFIX)llvm-link$(LLVM_SUFFIX)
519522 NM = $(LLVM_PREFIX)llvm-nm$(LLVM_SUFFIX)
520523 OBJCOPY = $(LLVM_PREFIX)llvm-objcopy$(LLVM_SUFFIX)
521524 OBJDUMP = $(LLVM_PREFIX)llvm-objdump$(LLVM_SUFFIX)
@@ -629,7 +632,7 @@ export RUSTC_BOOTSTRAP := 1 · 107 unmodified lines
629632 export CLIPPY_CONF_DIR := $(srctree)
630633
631634 export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC HOSTPKG_CONFIG
632−export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN
635+export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN LLVM_LINK
633636 export HOSTRUSTC KBUILD_HOSTRUSTFLAGS
634637 export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL
635638 export PERL PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
@@ -834,6 +837,20 @@ endif # CONFIG_TRACEPOINTS · 198 unmodified lines
834837
835838 export WARN_ON_UNUSED_TRACEPOINTS
836839
840+# Per-version Rust flags. These are like `rust_common_flags`, but may
841+# depend on the Rust compiler version (e.g. using `rustc-min-version`).
842+#
843+# `-Aclippy::precedence`: the lint was extended in Rust 1.85.0 to
844+# include bitmasking and shift operations. However, because it generated
845+# many hits, in Rust 1.86.0 it was split into a new `precedence_bits`
846+# lint which is not enabled by default.
847+rust_common_flags_per_version := \
848+ $(if $(call rustc-min-version,108600),,-Aclippy::precedence)
849+
850+rust_common_flags += $(rust_common_flags_per_version)
851+KBUILD_HOSTRUSTFLAGS += $(rust_common_flags_per_version) $(HOSTRUSTFLAGS)
852+KBUILD_RUSTFLAGS += $(rust_common_flags_per_version)
853+
837854 include $(srctree)/arch/$(SRCARCH)/Makefile
838855
839856 ifdef need-config
arch/Kconfig+1−2
@@ -968,10 +968,9 @@ config HAVE_CFI_ICALL_NORMALIZE_INTEGERS · 967 unmodified lines
968968 config HAVE_CFI_ICALL_NORMALIZE_INTEGERS_RUSTC
969969 def_bool y
970970 depends on HAVE_CFI_ICALL_NORMALIZE_INTEGERS
971− depends on RUSTC_VERSION >= 107900
972971 depends on ARM64 || X86_64
973972 # 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 || \
975974 (!GCOV_KERNEL && !KASAN_GENERIC && !KASAN_SW_TAGS)
976975
977976 config CFI_PERMISSIVE
arch/arm64/Kconfig+0−8
@@ -292,14 +292,6 @@ config ARM64 · 291 unmodified lines
292292 config RUSTC_SUPPORTS_ARM64
293293 def_bool y
294294 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
303295
304296 config CLANG_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS
305297 def_bool CC_IS_CLANG
arch/riscv/Kconfig+0−3
@@ -232,9 +232,6 @@ config RISCV · 231 unmodified lines
232232 config RUSTC_SUPPORTS_RISCV
233233 def_bool y
234234 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
238235
239236 config CLANG_SUPPORTS_DYNAMIC_FTRACE
240237 def_bool CC_IS_CLANG
drivers/android/binder/Makefile+1−2
@@ -5,5 +5,4 @@ obj-$(CONFIG_ANDROID_BINDER_IPC_RUST) += rust_binder.o · 4 unmodified lines
55 rust_binder-y := \
66 rust_binder_main.o \
77 rust_binderfs.o \
8− rust_binder_events.o \
9− page_range_helper.o
8+ rust_binder_events.o
drivers/android/binder/page_range.rs+3−3
@@ -683,15 +683,15 @@ unsafe extern "C" fn rust_shrink_scan( · 682 unmodified lines
683683 unsafe {
684684 bindings::list_lru_walk(
685685 list_lru,
686− Some(bindings::rust_shrink_free_page_wrap),
686+ Some(rust_shrink_free_page),
687687 ptr::null_mut(),
688688 nr_to_scan,
689689 )
690690 }
691691 }
692692
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;
695695
696696 /// # Safety
697697 /// Called by the shrinker.
drivers/android/binder/page_range_helper.c+0−24
@@ -1,24 +0,0 @@
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−}
drivers/android/binder/page_range_helper.h+0−15
@@ -1,15 +0,0 @@
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 */
drivers/android/binder/rust_binder_main.rs+2−0
@@ -3,6 +3,8 @@ · 2 unmodified lines
33 // Copyright (C) 2025 Google LLC.
44
55 //! Binder -- the Android IPC mechanism.
6+
7+#![crate_name = "rust_binder"]
68 #![recursion_limit = "256"]
79 #![allow(
810 clippy::as_underscore,
drivers/gpu/drm/tyr/driver.rs+0−12
@@ -53,18 +53,6 @@ pub(crate) struct TyrData { · 52 unmodified lines
5353 pub(crate) gpu_info: GpuInfo,
5454 }
5555
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−
6856 fn issue_soft_reset(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result {
6957 regs::GPU_CMD.write(dev, iomem, regs::GPU_CMD_SOFT_RESET)?;
7058
drivers/gpu/nova-core/gsp/cmdq.rs+1−5
@@ -293,7 +293,6 @@ impl DmaGspMem { · 292 unmodified lines
293293 let (slice_1, slice_2) = {
294294 let (slice_1, slice_2) = self.driver_write_area();
295295
296− #[allow(clippy::incompatible_msrv)]
297296 (slice_1.as_flattened_mut(), slice_2.as_flattened_mut())
298297 };
299298
@@ -545,10 +544,7 @@ impl Cmdq { · 245 unmodified lines
545544 Delta::from_millis(1),
546545 timeout,
547546 )
548− .map(|(slice_1, slice_2)| {
549− #[allow(clippy::incompatible_msrv)]
550− (slice_1.as_flattened(), slice_2.as_flattened())
551− })?;
547+ .map(|(slice_1, slice_2)| (slice_1.as_flattened(), slice_2.as_flattened()))?;
552548
553549 // Extract the `GspMsgElement`.
554550 let (header, slice_1) = GspMsgElement::from_bytes_prefix(slice_1).ok_or(EIO)?;
drivers/gpu/nova-core/gsp/fw/r570_144.rs+0−3
@@ -7,9 +7,6 @@ · 6 unmodified lines
77 //! This module may not be directly used. Please abstract or re-export the needed symbols in the
88 //! parent module instead.
99
10−#![cfg_attr(test, allow(deref_nullptr))]
11−#![cfg_attr(test, allow(unaligned_references))]
12−#![cfg_attr(test, allow(unsafe_op_in_unsafe_fn))]
1310 #![allow(
1411 dead_code,
1512 clippy::all,
drivers/pwm/pwm_th1520.rs+0−15
@@ -99,21 +99,6 @@ struct Th1520PwmDriverData { · 98 unmodified lines
9999 clk: Clk,
100100 }
101101
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−
117102 impl pwm::PwmOps for Th1520PwmDriverData {
118103 type WfHw = Th1520WfHw;
119104
init/Kconfig+16−14
@@ -82,6 +82,21 @@ config RUSTC_LLVM_VERSION · 81 unmodified lines
8282 int
8383 default $(rustc-llvm-version)
8484
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+
85100 config ARCH_HAS_CC_CAN_LINK
86101 bool
87102
@@ -163,12 +178,6 @@ config LD_CAN_USE_KEEP_IN_OVERLAY · 75 unmodified lines
163178 # https://github.com/llvm/llvm-project/pull/130661
164179 def_bool LD_IS_BFD || LLD_VERSION >= 210000
165180
166−config RUSTC_HAS_SLICE_AS_FLATTENED
167− def_bool RUSTC_VERSION >= 108000
168−
169−config RUSTC_HAS_COERCE_POINTEE
170− def_bool RUSTC_VERSION >= 108400
171−
172181 config RUSTC_HAS_SPAN_FILE
173182 def_bool RUSTC_VERSION >= 108800
174183
@@ -2178,9 +2187,7 @@ config RUST · 2003 unmodified lines
21782187 depends on !DEBUG_INFO_BTF || (PAHOLE_HAS_LANG_EXCLUDE && !LTO)
21792188 depends on !CFI || HAVE_CFI_ICALL_NORMALIZE_INTEGERS_RUSTC
21802189 select CFI_ICALL_NORMALIZE_INTEGERS if CFI
2181− depends on !CALL_PADDING || RUSTC_VERSION >= 108100
21822190 depends on !KASAN_SW_TAGS
2183− depends on !(MITIGATION_RETHUNK && KASAN) || RUSTC_VERSION >= 108300
21842191 help
21852192 Enables Rust support in the kernel.
21862193
@@ -2204,12 +2211,7 @@ config RUSTC_VERSION_TEXT · 17 unmodified lines
22042211 config BINDGEN_VERSION_TEXT
22052212 string
22062213 depends on RUST
2207− # The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0
2208− # (https://github.com/rust-lang/rust-bindgen/pull/2678) and 0.71.0
2209− # (https://github.com/rust-lang/rust-bindgen/pull/3040). It can be removed
2210− # when the minimum version is upgraded past the latter (0.69.1 and 0.71.1
2211− # both fixed the issue).
2212− default "$(shell,$(BINDGEN) --version workaround-for-0.69.0 2>/dev/null)"
2214+ default "$(shell,$(BINDGEN) --version 2>/dev/null)"
22132215
22142216 #
22152217 # Place an empty function call at each tracepoint site. Can be
lib/Kconfig.debug+17−0
@@ -3577,6 +3577,23 @@ config RUST_KERNEL_DOCTESTS · 3576 unmodified lines
35773577
35783578 If unsure, say N.
35793579
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+
35803597 endmenu # "Rust"
35813598
35823599 endmenu # Kernel hacking
rust/Makefile+36−33
@@ -6,15 +6,19 @@ rustdoc_output := $(objtree)/Documentation/output/rust/rustdoc · 5 unmodified lines
66 obj-$(CONFIG_RUST) += core.o compiler_builtins.o ffi.o
77 always-$(CONFIG_RUST) += exports_core_generated.h
88
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
915 # Missing prototypes are expected in the helpers since these are exported
1016 # for Rust only, thus there is no header nor prototypes.
11−obj-$(CONFIG_RUST) += helpers/helpers.o
1217 CFLAGS_REMOVE_helpers/helpers.o = -Wmissing-prototypes -Wmissing-declarations
1318
1419 always-$(CONFIG_RUST) += bindings/bindings_generated.rs bindings/bindings_helpers_generated.rs
1520 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
1822
1923 always-$(CONFIG_RUST) += uapi/uapi_generated.rs
2024 obj-$(CONFIG_RUST) += uapi.o
@@ -71,8 +75,7 @@ core-edition := $(if $(call rustc-min-version,108700),2024,2021) · 50 unmodified lines
7175
7276 core-skip_flags := \
7377 --edition=2021 \
74− -Wunreachable_pub \
75− -Wrustdoc::unescaped_backticks
78+ -Wunreachable_pub
7679
7780 core-flags := \
7881 --edition=$(core-edition) \
@@ -83,10 +86,8 @@ proc_macro2-cfgs := \ · 4 unmodified lines
8386 wrap_proc_macro \
8487 $(if $(call rustc-min-version,108800),proc_macro_span_file proc_macro_span_location)
8588
86−# Stable since Rust 1.79.0: `feature(proc_macro_byte_character,proc_macro_c_str_literals)`.
8789 proc_macro2-flags := \
8890 --cap-lints=allow \
89− -Zcrate-attr='feature(proc_macro_byte_character,proc_macro_c_str_literals)' \
9091 $(call cfgs-to-flags,$(proc_macro2-cfgs))
9192
9293 quote-cfgs := \
@@ -118,7 +119,7 @@ syn-flags := \ · 25 unmodified lines
118119 $(call cfgs-to-flags,$(syn-cfgs))
119120
120121 pin_init_internal-cfgs := \
121− kernel
122+ kernel USE_RUSTC_FEATURES
122123
123124 pin_init_internal-flags := \
124125 --extern proc_macro2 \
@@ -127,7 +128,7 @@ pin_init_internal-flags := \ · 2 unmodified lines
127128 $(call cfgs-to-flags,$(pin_init_internal-cfgs))
128129
129130 pin_init-cfgs := \
130− kernel
131+ kernel USE_RUSTC_FEATURES
131132
132133 pin_init-flags := \
133134 --extern pin_init_internal \
@@ -141,15 +142,10 @@ rustdoc_modifiers_workaround := $(if $(call rustc-min-version,108800),-Cunsafe-a · 7 unmodified lines
141142 # Similarly, for doctests (https://github.com/rust-lang/rust/issues/146465).
142143 doctests_modifiers_workaround := $(rustdoc_modifiers_workaround)$(if $(call rustc-min-version,109100),$(comma)sanitizer)
143144
144−# `rustc` recognizes `--remap-path-prefix` since 1.26.0, but `rustdoc` only
145−# since Rust 1.81.0. Moreover, `rustdoc` ICEs on out-of-tree builds since Rust
146−# 1.82.0 (https://github.com/rust-lang/rust/issues/138520). Thus workaround both
147−# issues skipping the flag. The former also applies to `RUSTDOC TK`.
148145 quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $<
149146 cmd_rustdoc = \
150147 OBJTREE=$(abspath $(objtree)) \
151− $(RUSTDOC) $(filter-out $(skip_flags) --remap-path-prefix=% --remap-path-scope=%, \
152− $(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \
148+ $(RUSTDOC) $(filter-out $(skip_flags) --remap-path-scope=%,$(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \
153149 $(rustc_target_flags) -L$(objtree)/$(obj) \
154150 -Zunstable-options --generate-link-to-definition \
155151 --output $(rustdoc_output) \
@@ -210,8 +206,6 @@ rustdoc-macros: $(src)/macros/lib.rs rustdoc-clean rustdoc-proc_macro2 \ · 54 unmodified lines
210206 rustdoc-quote rustdoc-syn FORCE
211207 +$(call if_changed,rustdoc)
212208
213−# Starting with Rust 1.82.0, skipping `-Wrustdoc::unescaped_backticks` should
214−# not be needed -- see https://github.com/rust-lang/rust/pull/128307.
215209 rustdoc-core: private skip_flags = $(core-skip_flags)
216210 rustdoc-core: private rustc_target_flags = $(core-flags)
217211 rustdoc-core: $(RUST_LIB_SRC)/core/src/lib.rs rustdoc-clean FORCE
@@ -335,7 +329,7 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $< · 117 unmodified lines
335329 rm -rf $(objtree)/$(obj)/test/doctests/kernel; \
336330 mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \
337331 OBJTREE=$(abspath $(objtree)) \
338− $(RUSTDOC) --test $(filter-out --remap-path-prefix=% --remap-path-scope=%,$(rust_flags)) \
332+ $(RUSTDOC) --test $(filter-out --remap-path-scope=%,$(rust_flags)) \
339333 -L$(objtree)/$(obj) --extern ffi --extern pin_init \
340334 --extern kernel --extern build_error --extern macros \
341335 --extern bindings --extern uapi \
@@ -447,22 +441,10 @@ endif · 105 unmodified lines
447441 # architecture instead of generating `usize`.
448442 bindgen_c_flags_final = $(bindgen_c_flags_lto) -fno-builtin -D__BINDGEN__
449443
450−# Each `bindgen` release may upgrade the list of Rust target versions. By
451−# default, the highest stable release in their list is used. Thus we need to set
452−# a `--rust-target` to avoid future `bindgen` releases emitting code that
453−# `rustc` may not understand. On top of that, `bindgen` does not support passing
454−# an unknown Rust target version.
455−#
456−# Therefore, the Rust target for `bindgen` can be only as high as the minimum
457−# Rust version the kernel supports and only as high as the greatest stable Rust
458−# target supported by the minimum `bindgen` version the kernel supports (that
459−# is, if we do not test the actual `rustc`/`bindgen` versions running).
460−#
461−# Starting with `bindgen` 0.71.0, we will be able to set any future Rust version
462−# instead, i.e. we will be able to set here our minimum supported Rust version.
444+# `--rust-target` points to our minimum supported Rust version.
463445 quiet_cmd_bindgen = BINDGEN $@
464446 cmd_bindgen = \
465− $(BINDGEN) $< $(bindgen_target_flags) --rust-target 1.68 \
447+ $(BINDGEN) $< $(bindgen_target_flags) --rust-target 1.85 \
466448 --use-core --with-derive-default --ctypes-prefix ffi --no-layout-tests \
467449 --no-debug '.*' --enable-function-attribute-detection \
468450 -o $@ -- $(bindgen_c_flags_final) -DMODULE \
@@ -496,6 +478,16 @@ $(obj)/bindings/bindings_helpers_generated.rs: private bindgen_target_extra = ; · 27 unmodified lines
496478 $(obj)/bindings/bindings_helpers_generated.rs: $(src)/helpers/helpers.c FORCE
497479 $(call if_changed_dep,bindgen)
498480
481+quiet_cmd_rust_helper = HELPER $@
482+ cmd_rust_helper = \
483+ $(CC) $(filter-out $(CFLAGS_REMOVE_helpers/helpers.o), $(c_flags)) \
484+ -c -g0 $< -emit-llvm -o $@
485+
486+$(obj)/helpers/helpers.bc: private part-of-builtin := y
487+$(obj)/helpers/helpers_module.bc: private part-of-module := y
488+$(obj)/helpers/helpers.bc $(obj)/helpers/helpers_module.bc: $(src)/helpers/helpers.c FORCE
489+ +$(call if_changed_dep,rust_helper)
490+
499491 rust_exports = $(NM) -p --defined-only $(1) | awk '$$2~/(T|R|D|B)/ && $$3!~/__(pfx|cfi|odr_asan)/ { printf $(2),$$3 }'
500492
501493 quiet_cmd_exports = EXPORTS $@
@@ -576,12 +568,16 @@ quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L · 74 unmodified lines
576568 OBJTREE=$(abspath $(objtree)) \
577569 $(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \
578570 $(filter-out $(skip_flags),$(rust_flags)) $(rustc_target_flags) \
579− --emit=dep-info=$(depfile) --emit=obj=$@ \
571+ --emit=dep-info=$(depfile) --emit=$(if $(link_helper),llvm-bc=$(patsubst %.o,%.bc,$@),obj=$@) \
580572 --emit=metadata=$(dir $@)$(patsubst %.o,lib%.rmeta,$(notdir $@)) \
581573 --crate-type rlib -L$(objtree)/$(obj) \
582574 --crate-name $(patsubst %.o,%,$(notdir $@)) $< \
583575 --sysroot=/dev/null \
584576 -Zunstable-options \
577+ $(if $(link_helper),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \
578+ $(obj)/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \
579+ $(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
580+ $(cmd_ld_single)) \
585581 $(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@) \
586582 $(cmd_objtool)
587583
@@ -591,6 +587,8 @@ rust-analyzer: · 3 unmodified lines
591587 --cfgs='proc_macro2=$(proc_macro2-cfgs)' \
592588 --cfgs='quote=$(quote-cfgs)' \
593589 --cfgs='syn=$(syn-cfgs)' \
590+ --cfgs='pin_init_internal=$(pin_init_internal-cfgs)' \
591+ --cfgs='pin_init=$(pin_init-cfgs)' \
594592 $(realpath $(srctree)) $(realpath $(objtree)) \
595593 $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \
596594 > rust-project.json
@@ -711,4 +709,9 @@ $(obj)/kernel.o: $(obj)/kernel/generated_arch_warn_asm.rs $(obj)/kernel/generate · 114 unmodified lines
711709 endif
712710 endif
713711
712+ifdef CONFIG_RUST_INLINE_HELPERS
713+$(obj)/kernel.o: private link_helper = 1
714+$(obj)/kernel.o: $(obj)/helpers/helpers.bc
715+endif
716+
714717 endif # CONFIG_RUST
rust/bindgen_parameters+4−4
@@ -15,14 +15,14 @@ · 14 unmodified lines
1515 --opaque-type x86_msi_data
1616 --opaque-type x86_msi_addr_lo
1717
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−
2218 # If SMP is disabled, `arch_spinlock_t` is defined as a ZST which triggers a Rust
2319 # warning. We don't need to peek into it anyway.
2420 --opaque-type spinlock
2521
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+
2626 # `seccomp`'s comment gets understood as a doctest
2727 --no-doc-comments
2828
rust/bindings/bindings_helper.h+0−1
@@ -149,5 +149,4 @@ const vm_flags_t RUST_CONST_HELPER_VM_NOHUGEPAGE = VM_NOHUGEPAGE; · 148 unmodified lines
149149 #if IS_ENABLED(CONFIG_ANDROID_BINDER_IPC_RUST)
150150 #include "../../drivers/android/binder/rust_binder.h"
151151 #include "../../drivers/android/binder/rust_binder_events.h"
152−#include "../../drivers/android/binder/page_range_helper.h"
153152 #endif
rust/bindings/lib.rs+1−4
@@ -9,10 +9,6 @@ · 8 unmodified lines
99 //! using this crate.
1010
1111 #![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))]
1612 #![allow(
1713 clippy::all,
1814 missing_docs,
@@ -23,6 +19,7 @@ · 4 unmodified lines
2319 unreachable_pub,
2420 unsafe_op_in_unsafe_fn
2521 )]
22+#![feature(cfi_encoding)]
2623
2724 #[allow(dead_code)]
2825 #[allow(clippy::cast_lossless)]
rust/exports.c+4−1
@@ -16,10 +16,13 @@ · 15 unmodified lines
1616 #define EXPORT_SYMBOL_RUST_GPL(sym) extern int sym; EXPORT_SYMBOL_GPL(sym)
1717
1818 #include "exports_core_generated.h"
19−#include "exports_helpers_generated.h"
2019 #include "exports_bindings_generated.h"
2120 #include "exports_kernel_generated.h"
2221
22+#ifndef CONFIG_RUST_INLINE_HELPERS
23+#include "exports_helpers_generated.h"
24+#endif
25+
2326 // For modules using `rust/build_error.rs`.
2427 #ifdef CONFIG_RUST_BUILD_ASSERT_ALLOW
2528 EXPORT_SYMBOL_RUST_GPL(rust_build_error);
rust/helpers/clk.c+13−11
@@ -7,60 +7,62 @@ · 6 unmodified lines
77 * CONFIG_HAVE_CLK or CONFIG_HAVE_CLK_PREPARE aren't set.
88 */
99 #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)
1112 {
1213 return clk_get(dev, id);
1314 }
1415
15−void rust_helper_clk_put(struct clk *clk)
16+__rust_helper void rust_helper_clk_put(struct clk *clk)
1617 {
1718 clk_put(clk);
1819 }
1920
20−int rust_helper_clk_enable(struct clk *clk)
21+__rust_helper int rust_helper_clk_enable(struct clk *clk)
2122 {
2223 return clk_enable(clk);
2324 }
2425
25−void rust_helper_clk_disable(struct clk *clk)
26+__rust_helper void rust_helper_clk_disable(struct clk *clk)
2627 {
2728 clk_disable(clk);
2829 }
2930
30−unsigned long rust_helper_clk_get_rate(struct clk *clk)
31+__rust_helper unsigned long rust_helper_clk_get_rate(struct clk *clk)
3132 {
3233 return clk_get_rate(clk);
3334 }
3435
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)
3637 {
3738 return clk_set_rate(clk, rate);
3839 }
3940 #endif
4041
4142 #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)
4344 {
4445 return clk_prepare(clk);
4546 }
4647
47−void rust_helper_clk_unprepare(struct clk *clk)
48+__rust_helper void rust_helper_clk_unprepare(struct clk *clk)
4849 {
4950 clk_unprepare(clk);
5051 }
5152 #endif
5253
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)
5456 {
5557 return clk_get_optional(dev, id);
5658 }
5759
58−int rust_helper_clk_prepare_enable(struct clk *clk)
60+__rust_helper int rust_helper_clk_prepare_enable(struct clk *clk)
5961 {
6062 return clk_prepare_enable(clk);
6163 }
6264
63−void rust_helper_clk_disable_unprepare(struct clk *clk)
65+__rust_helper void rust_helper_clk_disable_unprepare(struct clk *clk)
6466 {
6567 clk_disable_unprepare(clk);
6668 }
rust/helpers/helpers.c+29−0
@@ -7,7 +7,36 @@ · 6 unmodified lines
77 * Sorted alphabetically.
88 */
99
10+#include <linux/compiler_types.h>
11+
12+#ifdef __BINDGEN__
13+// Omit `inline` for bindgen as it ignores inline functions.
1014 #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
1140
1241 #include "atomic.c"
1342 #include "atomic_ext.c"
rust/helpers/jump_label.c+1−1
@@ -7,7 +7,7 @@ · 6 unmodified lines
77 #include <linux/jump_label.h>
88
99 #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)
1111 {
1212 return static_key_count(key);
1313 }
rust/kernel/alloc/allocator/iter.rs+1−7
@@ -42,15 +42,9 @@ impl<'a> Iterator for VmallocPageIter<'a> { · 41 unmodified lines
4242 return None;
4343 }
4444
45− // TODO: Use `NonNull::add()` instead, once the minimum supported compiler version is
46− // bumped to 1.80 or later.
47− //
4845 // SAFETY: `offset` is in the interval `[0, (self.page_count() - 1) * page::PAGE_SIZE]`,
4946 // 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) };
5448
5549 // SAFETY:
5650 // - `ptr` is a valid pointer to a `Vmalloc` allocation.
rust/kernel/alloc/kbox.rs+2−27
@@ -77,33 +77,8 @@ use pin_init::{InPlaceWrite, Init, PinInit, ZeroableOption}; · 76 unmodified lines
7777 /// `self.0` is always properly aligned and either points to memory allocated with `A` or, for
7878 /// zero-sized types, is a dangling, well aligned pointer.
7979 #[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>);
10782
10883 /// Type alias for [`Box`] with a [`Kmalloc`] allocator.
10984 ///
rust/kernel/alloc/kvec/errors.rs+3−0
@@ -15,6 +15,7 @@ impl<T> fmt::Debug for PushError<T> { · 14 unmodified lines
1515 }
1616
1717 impl<T> From<PushError<T>> for Error {
18+ #[inline]
1819 fn from(_: PushError<T>) -> Error {
1920 // Returning ENOMEM isn't appropriate because the system is not out of memory. The vector
2021 // is just full and we are refusing to resize it.
@@ -32,6 +33,7 @@ impl fmt::Debug for RemoveError { · 11 unmodified lines
3233 }
3334
3435 impl From<RemoveError> for Error {
36+ #[inline]
3537 fn from(_: RemoveError) -> Error {
3638 EINVAL
3739 }
@@ -55,6 +57,7 @@ impl<T> fmt::Debug for InsertError<T> { · 17 unmodified lines
5557 }
5658
5759 impl<T> From<InsertError<T>> for Error {
60+ #[inline]
5861 fn from(_: InsertError<T>) -> Error {
5962 EINVAL
6063 }
rust/kernel/block/mq/gen_disk.rs+1−3
@@ -140,9 +140,7 @@ impl GenDiskBuilder { · 139 unmodified lines
140140 devnode: None,
141141 alternative_gpt_sector: None,
142142 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`.
146144 owner: core::ptr::null_mut(),
147145 pr_ops: core::ptr::null_mut(),
148146 free_disk: None,
rust/kernel/build_assert.rs+153−30
@@ -1,10 +1,144 @@
11 // SPDX-License-Identifier: GPL-2.0
22
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+};
470
571 #[doc(hidden)]
672 pub use build_error::build_error;
773
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+}
141+
8142 /// Fails the build if the code path calling `build_error!` can possibly be executed.
9143 ///
10144 /// If the macro is executed in const context, `build_error!` will panic.
@@ -38,44 +172,33 @@ macro_rules! build_error { · 27 unmodified lines
38172 /// will panic. If the compiler or optimizer cannot guarantee the condition will
39173 /// be evaluated to `true`, a build error will be triggered.
40174 ///
41−/// [`static_assert!`] should be preferred to `build_assert!` whenever possible.
175+/// When a condition depends on a function argument, the function must be annotated with
176+/// `#[inline(always)]`. Without this attribute, the compiler may choose to not inline the
177+/// function, preventing it from optimizing out the error path.
178+///
179+/// If the assertion condition does not depend on any variables or generics, you should use
180+/// [`static_assert!`]. If the assertion condition does not depend on variables, but does depend on
181+/// generics, you should use [`const_assert!`]. See the [module documentation](self).
42182 ///
43183 /// # Examples
44184 ///
45−/// These examples show that different types of [`assert!`] will trigger errors
46−/// at different stage of compilation. It is preferred to err as early as
47−/// possible, so [`static_assert!`] should be used whenever possible.
48−/// ```ignore
49−/// fn foo() {
50−/// static_assert!(1 > 1); // Compile-time error
51−/// build_assert!(1 > 1); // Build-time error
52−/// assert!(1 > 1); // Run-time error
53−/// }
54185 /// ```
186+/// #[inline(always)] // Important.
187+/// fn bar(n: usize) {
188+/// build_assert!(n > 1);
189+/// }
55190 ///
56−/// When the condition refers to generic parameters or parameters of an inline function,
57−/// [`static_assert!`] cannot be used. Use `build_assert!` in this scenario.
58−/// ```
59−/// fn foo<const N: usize>() {
60−/// // `static_assert!(N > 1);` is not allowed
61−/// build_assert!(N > 1); // Build-time check
62−/// assert!(N > 1); // Run-time check
191+/// fn foo() {
192+/// bar(2);
63193 /// }
64−/// ```
65194 ///
66−/// When a condition depends on a function argument, the function must be annotated with
67−/// `#[inline(always)]`. Without this attribute, the compiler may choose to not inline the
68−/// function, preventing it from optimizing out the error path.
69−/// ```
70−/// #[inline(always)]
71−/// fn bar(n: usize) {
72−/// // `static_assert!(n > 1);` is not allowed
73−/// build_assert!(n > 1); // Build-time check
74−/// assert!(n > 1); // Run-time check
195+/// #[inline(always)] // Important.
196+/// const fn const_bar(n: usize) {
197+/// build_assert!(n > 1);
75198 /// }
76−/// ```
77199 ///
78−/// [`static_assert!`]: crate::static_assert!
200+/// const _: () = const_bar(2);
201+/// ```
79202 #[macro_export]
80203 macro_rules! build_assert {
81204 ($cond:expr $(,)?) => {{
rust/kernel/clk.rs+7−0
@@ -128,6 +128,13 @@ mod common_clk { · 127 unmodified lines
128128 #[repr(transparent)]
129129 pub struct Clk(*mut bindings::clk);
130130
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+
131138 impl Clk {
132139 /// Gets [`Clk`] corresponding to a [`Device`] and a connection id.
133140 ///
rust/kernel/error.rs+37−0
@@ -216,36 +216,42 @@ impl fmt::Debug for Error { · 215 unmodified lines
216216 }
217217
218218 impl From<AllocError> for Error {
219+ #[inline]
219220 fn from(_: AllocError) -> Error {
220221 code::ENOMEM
221222 }
222223 }
223224
224225 impl From<TryFromIntError> for Error {
226+ #[inline]
225227 fn from(_: TryFromIntError) -> Error {
226228 code::EINVAL
227229 }
228230 }
229231
230232 impl From<Utf8Error> for Error {
233+ #[inline]
231234 fn from(_: Utf8Error) -> Error {
232235 code::EINVAL
233236 }
234237 }
235238
236239 impl From<LayoutError> for Error {
240+ #[inline]
237241 fn from(_: LayoutError) -> Error {
238242 code::ENOMEM
239243 }
240244 }
241245
242246 impl From<fmt::Error> for Error {
247+ #[inline]
243248 fn from(_: fmt::Error) -> Error {
244249 code::EINVAL
245250 }
246251 }
247252
248253 impl From<core::convert::Infallible> for Error {
254+ #[inline]
249255 fn from(e: core::convert::Infallible) -> Error {
250256 match e {}
251257 }
@@ -446,6 +452,9 @@ pub fn to_result(err: crate::ffi::c_int) -> Result { · 194 unmodified lines
446452 /// for errors. This function performs the check and converts the "error pointer"
447453 /// to a normal pointer in an idiomatic fashion.
448454 ///
455+/// Note that a `NULL` pointer is not considered an error pointer, and is returned
456+/// as-is, wrapped in [`Ok`].
457+///
449458 /// # Examples
450459 ///
451460 /// ```ignore
@@ -460,6 +469,34 @@ pub fn to_result(err: crate::ffi::c_int) -> Result { · 8 unmodified lines
460469 /// from_err_ptr(unsafe { bindings::devm_platform_ioremap_resource(pdev.to_ptr(), index) })
461470 /// }
462471 /// ```
472+///
473+/// ```
474+/// # use kernel::error::from_err_ptr;
475+/// # mod bindings {
476+/// # #![expect(clippy::missing_safety_doc)]
477+/// # use kernel::prelude::*;
478+/// # pub(super) unsafe fn einval_err_ptr() -> *mut kernel::ffi::c_void {
479+/// # EINVAL.to_ptr()
480+/// # }
481+/// # pub(super) unsafe fn null_ptr() -> *mut kernel::ffi::c_void {
482+/// # core::ptr::null_mut()
483+/// # }
484+/// # pub(super) unsafe fn non_null_ptr() -> *mut kernel::ffi::c_void {
485+/// # 0x1234 as *mut kernel::ffi::c_void
486+/// # }
487+/// # }
488+/// // SAFETY: ...
489+/// let einval_err = from_err_ptr(unsafe { bindings::einval_err_ptr() });
490+/// assert_eq!(einval_err, Err(EINVAL));
491+///
492+/// // SAFETY: ...
493+/// let null_ok = from_err_ptr(unsafe { bindings::null_ptr() });
494+/// assert_eq!(null_ok, Ok(core::ptr::null_mut()));
495+///
496+/// // SAFETY: ...
497+/// let non_null = from_err_ptr(unsafe { bindings::non_null_ptr() }).unwrap();
498+/// assert_ne!(non_null, core::ptr::null_mut());
499+/// ```
463500 pub fn from_err_ptr<T>(ptr: *mut T) -> Result<*mut T> {
464501 // CAST: Casting a pointer to `*const crate::ffi::c_void` is always valid.
465502 let const_ptr: *const crate::ffi::c_void = ptr.cast();
rust/kernel/i2c.rs+6−7
@@ -16,10 +16,11 @@ use crate::{ · 15 unmodified lines
1616 error::*,
1717 of,
1818 prelude::*,
19− types::{
20− AlwaysRefCounted,
21− Opaque, //
22− }, //
19+ sync::aref::{
20+ ARef,
21+ AlwaysRefCounted, //
22+ },
23+ types::Opaque, //
2324 };
2425
2526 use core::{
@@ -31,8 +32,6 @@ use core::{ · 5 unmodified lines
3132 }, //
3233 };
3334
34−use kernel::types::ARef;
35−
3635 /// An I2C device id table.
3736 #[repr(transparent)]
3837 #[derive(Clone, Copy)]
@@ -416,7 +415,7 @@ kernel::impl_device_context_deref!(unsafe { I2cAdapter }); · 377 unmodified lines
416415 kernel::impl_device_context_into_aref!(I2cAdapter);
417416
418417 // SAFETY: Instances of `I2cAdapter` are always reference-counted.
419−unsafe impl crate::types::AlwaysRefCounted for I2cAdapter {
418+unsafe impl AlwaysRefCounted for I2cAdapter {
420419 fn inc_ref(&self) {
421420 // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
422421 unsafe { bindings::i2c_get_adapter(self.index()) };
rust/kernel/lib.rs+2−36
@@ -16,45 +16,14 @@ · 15 unmodified lines
1616 // Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on
1717 // the unstable features in use.
1818 //
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−//
4419 // Expected to become stable.
4520 #![feature(arbitrary_self_types)]
21+#![feature(derive_coerce_pointee)]
4622 //
4723 // To be determined.
4824 #![feature(used_with_arg)]
4925 //
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
5827 // enable it conditionally.
5928 #![cfg_attr(CONFIG_RUSTC_HAS_FILE_WITH_NUL, feature(file_with_nul))]
6029
@@ -77,7 +46,6 @@ pub mod bits; · 16 unmodified lines
7746 #[cfg(CONFIG_BLOCK)]
7847 pub mod block;
7948 pub mod bug;
80−#[doc(hidden)]
8149 pub mod build_assert;
8250 pub mod clk;
8351 #[cfg(CONFIG_CONFIGFS_FS)]
@@ -145,10 +113,8 @@ pub mod scatterlist; · 61 unmodified lines
145113 pub mod security;
146114 pub mod seq_file;
147115 pub mod sizes;
148−pub mod slice;
149116 #[cfg(CONFIG_SOC_BUS)]
150117 pub mod soc;
151−mod static_assert;
152118 #[doc(hidden)]
153119 pub mod std_vendor;
154120 pub mod str;
rust/kernel/list.rs+19−3
@@ -12,15 +12,31 @@ use core::ptr; · 11 unmodified lines
1212 use pin_init::PinInit;
1313
1414 mod impl_list_item_mod;
15+#[doc(inline)]
1516 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, //
1722 };
1823
1924 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+};
2133
2234 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+};
2440
2541 /// A linked list.
2642 ///
rust/kernel/list/arc.rs+2−21
@@ -82,6 +82,7 @@ pub unsafe trait TryNewListArc<const ID: u64 = 0>: ListArcSafe<ID> { · 81 unmodified lines
8282 /// [`AtomicTracker`]. However, it is also possible to defer the tracking to another struct
8383 /// using also using this macro.
8484 #[macro_export]
85+#[doc(hidden)]
8586 macro_rules! impl_list_arc_safe {
8687 (impl$({$($generics:tt)*})? ListArcSafe<$num:tt> for $t:ty { untracked; } $($rest:tt)*) => {
8788 impl$(<$($generics)*>)? $crate::list::ListArcSafe<$num> for $t {
@@ -159,7 +160,7 @@ pub use impl_list_arc_safe; · 71 unmodified lines
159160 ///
160161 /// [`List`]: crate::list::List
161162 #[repr(transparent)]
162−#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))]
163+#[derive(core::marker::CoercePointee)]
163164 pub struct ListArc<T, const ID: u64 = 0>
164165 where
165166 T: ListArcSafe<ID> + ?Sized,
@@ -442,26 +443,6 @@ where · 276 unmodified lines
442443 }
443444 }
444445
445−// This is to allow coercion from `ListArc<T>` to `ListArc<U>` if `T` can be converted to the
446−// dynamically-sized type (DST) `U`.
447−#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
448−impl<T, U, const ID: u64> core::ops::CoerceUnsized<ListArc<U, ID>> for ListArc<T, ID>
449−where
450− T: ListArcSafe<ID> + core::marker::Unsize<U> + ?Sized,
451− U: ListArcSafe<ID> + ?Sized,
452−{
453−}
454−
455−// This is to allow `ListArc<U>` to be dispatched on when `ListArc<T>` can be coerced into
456−// `ListArc<U>`.
457−#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
458−impl<T, U, const ID: u64> core::ops::DispatchFromDyn<ListArc<U, ID>> for ListArc<T, ID>
459−where
460− T: ListArcSafe<ID> + core::marker::Unsize<U> + ?Sized,
461− U: ListArcSafe<ID> + ?Sized,
462−{
463−}
464−
465446 /// A utility for tracking whether a [`ListArc`] exists using an atomic.
466447 ///
467448 /// # Invariants
rust/kernel/list/arc_field.rs+1−0
@@ -66,6 +66,7 @@ impl<T, const ID: u64> ListArcField<T, ID> { · 65 unmodified lines
6666
6767 /// Defines getters for a [`ListArcField`].
6868 #[macro_export]
69+#[doc(hidden)]
6970 macro_rules! define_list_arc_field_getter {
7071 ($pub:vis fn $name:ident(&self $(<$id:tt>)?) -> &$typ:ty { $field:ident }
7172 $($rest:tt)*
rust/kernel/list/impl_list_item_mod.rs+3−0
@@ -29,6 +29,7 @@ pub unsafe trait HasListLinks<const ID: u64 = 0> { · 28 unmodified lines
2929
3030 /// Implements the [`HasListLinks`] trait for the given type.
3131 #[macro_export]
32+#[doc(hidden)]
3233 macro_rules! impl_has_list_links {
3334 ($(impl$({$($generics:tt)*})?
3435 HasListLinks$(<$id:tt>)?
@@ -74,6 +75,7 @@ where · 39 unmodified lines
7475
7576 /// Implements the [`HasListLinks`] and [`HasSelfPtr`] traits for the given type.
7677 #[macro_export]
78+#[doc(hidden)]
7779 macro_rules! impl_has_list_links_self_ptr {
7880 ($(impl$({$($generics:tt)*})?
7981 HasSelfPtr<$item_type:ty $(, $id:tt)?>
@@ -181,6 +183,7 @@ pub use impl_has_list_links_self_ptr; · 101 unmodified lines
181183 /// }
182184 /// ```
183185 #[macro_export]
186+#[doc(hidden)]
184187 macro_rules! impl_list_item {
185188 (
186189 $(impl$({$($generics:tt)*})? ListItem<$num:tt> for $self:ty {
rust/kernel/num/bounded.rs+9−15
@@ -255,9 +255,7 @@ macro_rules! impl_const_new { · 254 unmodified lines
255255 /// ```
256256 pub const fn new<const VALUE: $type>() -> Self {
257257 // 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));
261259
262260 // SAFETY: `fits_within` confirmed that `VALUE` can be represented within
263261 // `N` bits.
@@ -287,12 +285,10 @@ where · 23 unmodified lines
287285 /// The caller must ensure that `value` can be represented within `N` bits.
288286 const unsafe fn __new(value: T) -> Self {
289287 // Enforce the type invariants.
290− const {
291− // `N` cannot be zero.
292− assert!(N != 0);
293− // The backing type is at least as large as `N` bits.
294− assert!(N <= T::BITS);
295− }
288+ // `N` cannot be zero.
289+ const_assert!(N != 0);
290+ // The backing type is at least as large as `N` bits.
291+ const_assert!(N <= T::BITS);
296292
297293 // INVARIANT: The caller ensures `value` fits within `N` bits.
298294 Self(value)
@@ -406,12 +402,10 @@ where · 107 unmodified lines
406402 /// assert_eq!(larger_v, v);
407403 /// ```
408404 pub const fn extend<const M: u32>(self) -> Bounded<T, M> {
409− const {
410− assert!(
411− M >= N,
412− "Requested number of bits is less than the current representation."
413− );
414− }
405+ const_assert!(
406+ M >= N,
407+ "Requested number of bits is less than the current representation."
408+ );
415409
416410 // SAFETY: The value did fit within `N` bits, so it will all the more fit within
417411 // the larger `M` bits.
rust/kernel/prelude.rs+82−28
@@ -13,43 +13,97 @@ · 12 unmodified lines
1313
1414 #[doc(no_inline)]
1515 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, //
1823 };
1924
2025 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, //
2339 };
2440
25−pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec, VBox, VVec, Vec};
26−
2741 #[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+};
2949
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+};
3160
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+};
33106
34107 // `super::std_vendor` is hidden, which makes the macro inline for some reason.
35108 #[doc(no_inline)]
36109 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;
rust/kernel/ptr.rs+35−7
@@ -11,6 +11,8 @@ use core::mem::{ · 10 unmodified lines
1111 };
1212 use core::num::NonZero;
1313
14+use crate::const_assert;
15+
1416 /// Type representing an alignment, which is always a power of two.
1517 ///
1618 /// It is used to validate that a given value is a valid alignment, and to perform masking and
@@ -44,12 +46,10 @@ impl Alignment { · 27 unmodified lines
4446 /// ```
4547 #[inline(always)]
4648 pub const fn new<const ALIGN: usize>() -> Self {
47− const {
48− assert!(
49− ALIGN.is_power_of_two(),
50− "Provided alignment is not a power of two."
51− );
52− }
49+ const_assert!(
50+ ALIGN.is_power_of_two(),
51+ "Provided alignment is not a power of two."
52+ );
5353
5454 // INVARIANT: `align` is a power of two.
5555 // SAFETY: `align` is a power of two, and thus non-zero.
@@ -87,7 +87,6 @@ impl Alignment { · 31 unmodified lines
8787 /// This is equivalent to [`align_of`], but with the return value provided as an [`Alignment`].
8888 #[inline(always)]
8989 pub const fn of<T>() -> Self {
90− #![allow(clippy::incompatible_msrv)]
9190 // This cannot panic since alignments are always powers of two.
9291 //
9392 // We unfortunately cannot use `new` as it would require the `generic_const_exprs` feature.
@@ -253,3 +252,32 @@ impl<T> KnownSize for [T] { · 159 unmodified lines
253252 p.len() * size_of::<T>()
254253 }
255254 }
255+
256+/// Aligns `value` up to `align`.
257+///
258+/// This is the const-compatible equivalent of [`Alignable::align_up`].
259+///
260+/// Returns [`None`] on overflow.
261+///
262+/// # Examples
263+///
264+/// ```
265+/// use kernel::{
266+/// ptr::{
267+/// const_align_up,
268+/// Alignment, //
269+/// },
270+/// sizes::SZ_4K, //
271+/// };
272+///
273+/// assert_eq!(const_align_up(0x4f, Alignment::new::<16>()), Some(0x50));
274+/// assert_eq!(const_align_up(0x40, Alignment::new::<16>()), Some(0x40));
275+/// assert_eq!(const_align_up(1, Alignment::new::<SZ_4K>()), Some(SZ_4K));
276+/// ```
277+#[inline(always)]
278+pub const fn const_align_up(value: usize, align: Alignment) -> Option<usize> {
279+ match value.checked_add(align.as_usize() - 1) {
280+ Some(v) => Some(v & align.mask()),
281+ None => None,
282+ }
283+}
rust/kernel/sizes.rs+128−44
@@ -3,48 +3,132 @@ · 2 unmodified lines
33 //! Commonly used sizes.
44 //!
55 //! 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+//! ```
34+
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+}
6133
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;
134+define_sizes!(u32, u64, usize);
rust/kernel/slice.rs+0−49
@@ -1,49 +0,0 @@
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−}
rust/kernel/static_assert.rs+0−39
@@ -1,39 +0,0 @@
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−}
rust/kernel/str.rs+23−4
@@ -189,6 +189,7 @@ macro_rules! b_str { · 188 unmodified lines
189189 //
190190 // - error[E0379]: functions in trait impls cannot be declared const
191191 #[inline]
192+#[expect(clippy::disallowed_methods, reason = "internal implementation")]
192193 pub const fn as_char_ptr_in_const_context(c_str: &CStr) -> *const c_char {
193194 c_str.as_ptr().cast()
194195 }
@@ -319,6 +320,7 @@ unsafe fn to_bytes_mut(s: &mut CStr) -> &mut [u8] { · 124 unmodified lines
319320
320321 impl CStrExt for CStr {
321322 #[inline]
323+ #[expect(clippy::disallowed_methods, reason = "internal implementation")]
322324 unsafe fn from_char_ptr<'a>(ptr: *const c_char) -> &'a Self {
323325 // SAFETY: The safety preconditions are the same as for `CStr::from_ptr`.
324326 unsafe { CStr::from_ptr(ptr.cast()) }
@@ -334,6 +336,7 @@ impl CStrExt for CStr { · 9 unmodified lines
334336 }
335337
336338 #[inline]
339+ #[expect(clippy::disallowed_methods, reason = "internal implementation")]
337340 fn as_char_ptr(&self) -> *const c_char {
338341 self.as_ptr().cast()
339342 }
@@ -376,19 +379,32 @@ impl AsRef<BStr> for CStr { · 36 unmodified lines
376379 }
377380 }
378381
379−/// Creates a new [`CStr`] from a string literal.
382+/// Creates a new [`CStr`] at compile time.
380383 ///
381−/// The string literal should not contain any `NUL` bytes.
384+/// Rust supports C string literals since Rust 1.77, and they should be used instead of this macro
385+/// where possible. This macro exists to allow static *non-literal* C strings to be created at
386+/// compile time. This is most often used in other macros.
387+///
388+/// # Panics
389+///
390+/// This macro panics if the operand contains an interior `NUL` byte.
382391 ///
383392 /// # Examples
384393 ///
385394 /// ```
386395 /// # use kernel::c_str;
387396 /// # use kernel::str::CStr;
388−/// const MY_CSTR: &CStr = c_str!("My awesome CStr!");
397+/// // This is allowed, but `c"literal"` should be preferred for literals.
398+/// const BAD: &CStr = c_str!("literal");
399+///
400+/// // `c_str!` is still needed for static non-literal C strings.
401+/// const GOOD: &CStr = c_str!(concat!(file!(), ":", line!(), ": My CStr!"));
389402 /// ```
390403 #[macro_export]
391404 macro_rules! c_str {
405+ // NB: We could write `($str:lit) => compile_error!("use a C string literal instead");` here but
406+ // that would trigger when the literal is at the top of several macro expansions. That would be
407+ // too limiting to macro authors.
392408 ($str:expr) => {{
393409 const S: &str = concat!($str, "\0");
394410 const C: &$crate::str::CStr = match $crate::str::CStr::from_bytes_with_nul(S.as_bytes()) {
@@ -828,7 +844,10 @@ impl CString { · 433 unmodified lines
828844 f.write_str("\0")?;
829845
830846 // SAFETY: The number of bytes that can be written to `f` is bounded by `size`, which is
831− // `buf`'s capacity. The contents of the buffer have been initialised by writes to `f`.
847+ // `buf`'s capacity. The `Formatter` is created with `size` as its limit, and the `?`
848+ // operators on `write_fmt` and `write_str` above ensure that if writing exceeds this
849+ // limit, an error is returned early. The contents of the buffer have been initialised
850+ // by writes to `f`.
832851 unsafe { buf.inc_len(f.bytes_written()) };
833852
834853 // Check that there are no `NUL` bytes before the end.
rust/kernel/sync/arc.rs+2−19
@@ -128,7 +128,7 @@ mod std_vendor; · 127 unmodified lines
128128 /// # Ok::<(), Error>(())
129129 /// ```
130130 #[repr(transparent)]
131−#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))]
131+#[derive(core::marker::CoercePointee)]
132132 pub struct Arc<T: ?Sized> {
133133 ptr: NonNull<ArcInner<T>>,
134134 // NB: this informs dropck that objects of type `ArcInner<T>` may be used in `<Arc<T> as
@@ -182,15 +182,6 @@ impl<T: ?Sized> ArcInner<T> { · 47 unmodified lines
182182 }
183183 }
184184
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−
194185 // SAFETY: It is safe to send `Arc<T>` to another thread when the underlying `T` is `Sync` because
195186 // it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs
196187 // `T` to be `Send` because any thread that has an `Arc<T>` may ultimately access `T` using a
@@ -547,20 +538,12 @@ impl<T: ?Sized> From<Pin<UniqueArc<T>>> for Arc<T> { · 350 unmodified lines
547538 /// # Ok::<(), Error>(())
548539 /// ```
549540 #[repr(transparent)]
550−#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))]
541+#[derive(core::marker::CoercePointee)]
551542 pub struct ArcBorrow<'a, T: ?Sized + 'a> {
552543 inner: NonNull<ArcInner<T>>,
553544 _p: PhantomData<&'a ()>,
554545 }
555546
556−// This is to allow `ArcBorrow<U>` to be dispatched on when `ArcBorrow<T>` can be coerced into
557−// `ArcBorrow<U>`.
558−#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
559−impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>>
560− for ArcBorrow<'_, T>
561−{
562−}
563−
564547 impl<T: ?Sized> Clone for ArcBorrow<'_, T> {
565548 fn clone(&self) -> Self {
566549 *self
rust/kernel/task.rs+3−4
@@ -6,16 +6,15 @@ · 5 unmodified lines
66
77 use crate::{
88 bindings,
9− ffi::{c_int, c_long, c_uint},
109 mm::MmWithUser,
1110 pid_namespace::PidNamespace,
11+ prelude::*,
1212 sync::aref::ARef,
1313 types::{NotThreadSafe, Opaque},
1414 };
1515 use core::{
16− cmp::{Eq, PartialEq},
1716 ops::Deref,
18− ptr,
17+ ptr, //
1918 };
2019
2120 /// A sentinel value used for infinite timeouts.
@@ -419,7 +418,7 @@ pub fn might_sleep() { · 397 unmodified lines
419418 let file = kernel::file_from_location(loc);
420419
421420 // SAFETY: `file.as_ptr()` is valid for reading and guaranteed to be nul-terminated.
422− unsafe { crate::bindings::__might_sleep(file.as_ptr().cast(), loc.line() as i32) }
421+ unsafe { crate::bindings::__might_sleep(file.as_char_ptr(), loc.line() as i32) }
423422 }
424423
425424 // SAFETY: Always safe to call.
rust/kernel/time.rs+26−6
@@ -60,7 +60,13 @@ pub fn msecs_to_jiffies(msecs: Msecs) -> Jiffies { · 59 unmodified lines
6060 /// cases the user of the clock has to decide which clock is best suited for the
6161 /// purpose. In most scenarios clock [`Monotonic`] is the best choice as it
6262 /// 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 {
6470 /// The kernel clock ID associated with this clock source.
6571 ///
6672 /// This constant corresponds to the C side `clockid_t` value.
@@ -68,7 +74,7 @@ pub trait ClockSource { · 1 unmodified line
6874
6975 /// Get the current time from the clock source.
7076 ///
71− /// The function must return a value in the range from 0 to `KTIME_MAX`.
77+ /// The function must return a value in the range `0..=KTIME_MAX`.
7278 fn ktime_get() -> bindings::ktime_t;
7379 }
7480
@@ -85,7 +91,9 @@ pub trait ClockSource { · 10 unmodified lines
8591 /// count time that the system is suspended.
8692 pub struct Monotonic;
8793
88−impl ClockSource for Monotonic {
94+// SAFETY: The kernel's `ktime_get()` is guaranteed to return a value
95+// in `0..=KTIME_MAX`.
96+unsafe impl ClockSource for Monotonic {
8997 const ID: bindings::clockid_t = bindings::CLOCK_MONOTONIC as bindings::clockid_t;
9098
9199 fn ktime_get() -> bindings::ktime_t {
@@ -110,7 +118,9 @@ impl ClockSource for Monotonic { · 18 unmodified lines
110118 /// the clock will experience discontinuity around leap second adjustment.
111119 pub struct RealTime;
112120
113−impl ClockSource for RealTime {
121+// SAFETY: The kernel's `ktime_get_real()` is guaranteed to return a value
122+// in `0..=KTIME_MAX`.
123+unsafe impl ClockSource for RealTime {
114124 const ID: bindings::clockid_t = bindings::CLOCK_REALTIME as bindings::clockid_t;
115125
116126 fn ktime_get() -> bindings::ktime_t {
@@ -128,7 +138,9 @@ impl ClockSource for RealTime { · 11 unmodified lines
128138 /// discontinuities if the time is changed using settimeofday(2) or similar.
129139 pub struct BootTime;
130140
131−impl ClockSource for BootTime {
141+// SAFETY: The kernel's `ktime_get_boottime()` is guaranteed to return a value
142+// in `0..=KTIME_MAX`.
143+unsafe impl ClockSource for BootTime {
132144 const ID: bindings::clockid_t = bindings::CLOCK_BOOTTIME as bindings::clockid_t;
133145
134146 fn ktime_get() -> bindings::ktime_t {
@@ -150,7 +162,9 @@ impl ClockSource for BootTime { · 15 unmodified lines
150162 /// The acronym TAI refers to International Atomic Time.
151163 pub struct Tai;
152164
153−impl ClockSource for Tai {
165+// SAFETY: The kernel's `ktime_get_clocktai()` is guaranteed to return a value
166+// in `0..=KTIME_MAX`.
167+unsafe impl ClockSource for Tai {
154168 const ID: bindings::clockid_t = bindings::CLOCK_TAI as bindings::clockid_t;
155169
156170 fn ktime_get() -> bindings::ktime_t {
@@ -363,6 +377,12 @@ impl Delta { · 206 unmodified lines
363377 /// A span of time equal to zero.
364378 pub const ZERO: Self = Self { nanos: 0 };
365379
380+ /// Create a new [`Delta`] from a number of nanoseconds.
381+ #[inline]
382+ pub const fn from_nanos(nanos: i64) -> Self {
383+ Self { nanos }
384+ }
385+
366386 /// Create a new [`Delta`] from a number of microseconds.
367387 ///
368388 /// The `micros` can range from -9_223_372_036_854_775 to 9_223_372_036_854_775.
rust/kernel/time/hrtimer.rs+336−0
@@ -66,6 +66,342 @@ · 65 unmodified lines
6666 //!
6767 //! A `restart` operation on a timer in the **stopped** state is equivalent to a
6868 //! `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
69405
70406 use super::{ClockSource, Delta, Instant};
71407 use crate::{prelude::*, types::Opaque};
rust/kernel/transmute.rs+6−29
@@ -49,7 +49,6 @@ pub unsafe trait FromBytes { · 48 unmodified lines
4949 let slice_ptr = bytes.as_ptr().cast::<Self>();
5050 let size = size_of::<Self>();
5151
52− #[allow(clippy::incompatible_msrv)]
5352 if bytes.len() == size && slice_ptr.is_aligned() {
5453 // SAFETY: Size and alignment were just checked.
5554 unsafe { Some(&*slice_ptr) }
@@ -67,16 +66,9 @@ pub unsafe trait FromBytes { · 11 unmodified lines
6766 where
6867 Self: Sized,
6968 {
70− if bytes.len() < size_of::<Self>() {
71− None
72− } else {
73− // PANIC: We checked that `bytes.len() >= size_of::<Self>`, thus `split_at` cannot
74− // panic.
75− // TODO: replace with `split_at_checked` once the MSRV is >= 1.80.
76− let (prefix, remainder) = bytes.split_at(size_of::<Self>());
69+ let (prefix, remainder) = bytes.split_at_checked(size_of::<Self>())?;
7770
78− Self::from_bytes(prefix).map(|s| (s, remainder))
79− }
71+ Self::from_bytes(prefix).map(|s| (s, remainder))
8072 }
8173
8274 /// Converts a mutable slice of bytes to a reference to `Self`.
@@ -92,7 +84,6 @@ pub unsafe trait FromBytes { · 9 unmodified lines
9284 let slice_ptr = bytes.as_mut_ptr().cast::<Self>();
9385 let size = size_of::<Self>();
9486
95− #[allow(clippy::incompatible_msrv)]
9687 if bytes.len() == size && slice_ptr.is_aligned() {
9788 // SAFETY: Size and alignment were just checked.
9889 unsafe { Some(&mut *slice_ptr) }
@@ -110,16 +101,9 @@ pub unsafe trait FromBytes { · 11 unmodified lines
110101 where
111102 Self: AsBytes + Sized,
112103 {
113− if bytes.len() < size_of::<Self>() {
114− None
115− } else {
116− // PANIC: We checked that `bytes.len() >= size_of::<Self>`, thus `split_at_mut` cannot
117− // panic.
118− // TODO: replace with `split_at_mut_checked` once the MSRV is >= 1.80.
119− let (prefix, remainder) = bytes.split_at_mut(size_of::<Self>());
104+ let (prefix, remainder) = bytes.split_at_mut_checked(size_of::<Self>())?;
120105
121− Self::from_bytes_mut(prefix).map(|s| (s, remainder))
122− }
106+ Self::from_bytes_mut(prefix).map(|s| (s, remainder))
123107 }
124108
125109 /// Creates an owned instance of `Self` by copying `bytes`.
@@ -149,16 +133,9 @@ pub unsafe trait FromBytes { · 23 unmodified lines
149133 where
150134 Self: Sized,
151135 {
152− if bytes.len() < size_of::<Self>() {
153− None
154− } else {
155− // PANIC: We checked that `bytes.len() >= size_of::<Self>`, thus `split_at` cannot
156− // panic.
157− // TODO: replace with `split_at_checked` once the MSRV is >= 1.80.
158− let (prefix, remainder) = bytes.split_at(size_of::<Self>());
136+ let (prefix, remainder) = bytes.split_at_checked(size_of::<Self>())?;
159137
160− Self::from_bytes_copy(prefix).map(|s| (s, remainder))
161− }
138+ Self::from_bytes_copy(prefix).map(|s| (s, remainder))
162139 }
163140 }
164141
rust/kernel/types.rs+0−2
@@ -11,8 +11,6 @@ use core::{ · 10 unmodified lines
1111 };
1212 use pin_init::{PinInit, Wrapper, Zeroable};
1313
14−pub use crate::sync::aref::{ARef, AlwaysRefCounted};
15−
1614 /// Used to transfer ownership to and from foreign (non-Rust) languages.
1715 ///
1816 /// Ownership is transferred from Rust to a foreign language by calling [`Self::into_foreign`] and
rust/kernel/usb.rs+2−4
@@ -18,10 +18,8 @@ use crate::{ · 17 unmodified lines
1818 to_result, //
1919 },
2020 prelude::*,
21− types::{
22− AlwaysRefCounted,
23− Opaque, //
24− },
21+ sync::aref::AlwaysRefCounted,
22+ types::Opaque,
2523 ThisModule, //
2624 };
2725 use core::{
rust/kernel/xarray.rs+1−0
@@ -172,6 +172,7 @@ pub struct StoreError<T> { · 171 unmodified lines
172172 }
173173
174174 impl<T> From<StoreError<T>> for Error {
175+ #[inline]
175176 fn from(value: StoreError<T>) -> Self {
176177 value.error
177178 }
rust/macros/helpers.rs+0−1
@@ -49,7 +49,6 @@ pub(crate) fn file() -> String { · 48 unmodified lines
4949 }
5050
5151 #[cfg(CONFIG_RUSTC_HAS_SPAN_FILE)]
52− #[allow(clippy::incompatible_msrv)]
5352 {
5453 proc_macro::Span::call_site().file()
5554 }
rust/macros/kunit.rs+5−4
@@ -87,10 +87,11 @@ pub(crate) fn kunit_tests(test_suite: Ident, mut module: ItemMod) -> Result<Toke · 86 unmodified lines
8787 continue;
8888 };
8989
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+ {
9495 processed_items.push(Item::Fn(f));
9596 continue;
9697 }
rust/macros/lib.rs+3−0
@@ -6,6 +6,9 @@ · 5 unmodified lines
66 // and thus add a dependency on `include/config/RUSTC_VERSION_TEXT`, which is
77 // touched by Kconfig when the version string from the compiler changes.
88
9+// Stable since Rust 1.87.0.
10+#![feature(extract_if)]
11+//
912 // Stable since Rust 1.88.0 under a different name, `proc_macro_span_file`,
1013 // which was added in Rust 1.88.0. This is why `cfg_attr` is used here, i.e.
1114 // to avoid depending on the full `proc_macro_span` on Rust >= 1.88.0.
rust/macros/module.rs+2−7
@@ -52,12 +52,7 @@ impl<'a> ModInfoBuilder<'a> { · 51 unmodified lines
5252 fn emit_base(&mut self, field: &str, content: &str, builtin: bool, param: bool) {
5353 let string = if builtin {
5454 // 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)
6156 } else {
6257 // Loadable modules' modinfo strings go as-is.
6358 format!("{field}={content}\0")
@@ -109,7 +104,7 @@ impl<'a> ModInfoBuilder<'a> { · 45 unmodified lines
109104 }
110105
111106 fn emit_param(&mut self, field: &str, param: &str, content: &str) {
112− let content = format!("{param}:{content}", param = param, content = content);
107+ let content = format!("{param}:{content}");
113108 self.emit_internal(field, &content, true);
114109 }
115110
rust/pin-init/README.md+1−2
@@ -160,7 +160,6 @@ actually does the initialization in the correct way. Here are the things to look · 159 unmodified lines
160160 ```rust
161161 use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure};
162162 use core::{
163− ptr::addr_of_mut,
164163 marker::PhantomPinned,
165164 cell::UnsafeCell,
166165 pin::Pin,
@@ -199,7 +198,7 @@ impl RawFoo { · 32 unmodified lines
199198 unsafe {
200199 pin_init_from_closure(move |slot: *mut Self| {
201200 // `slot` contains uninit memory, avoid creating a reference.
202− let foo = addr_of_mut!((*slot).foo);
201+ let foo = &raw mut (*slot).foo;
203202 let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>();
204203
205204 // Initialize the `foo`
rust/pin-init/examples/big_struct_in_place.rs+3−0
@@ -1,5 +1,8 @@
11 // SPDX-License-Identifier: Apache-2.0 OR MIT
22
3+#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
4+#![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))]
5+
36 use pin_init::*;
47
58 // Struct with size over 1GiB
rust/pin-init/examples/linked_list.rs+2−1
@@ -2,7 +2,8 @@ · 1 unmodified line
22
33 #![allow(clippy::undocumented_unsafe_blocks)]
44 #![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))]
67
78 use core::{
89 cell::Cell,
rust/pin-init/examples/mutex.rs+2−1
@@ -2,7 +2,8 @@ · 1 unmodified line
22
33 #![allow(clippy::undocumented_unsafe_blocks)]
44 #![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))]
67 #![allow(clippy::missing_safety_doc)]
78
89 use core::{
rust/pin-init/examples/pthread_mutex.rs+2−1
@@ -3,7 +3,8 @@ · 2 unmodified lines
33 // inspired by <https://github.com/nbdd0121/pin-init/blob/trunk/examples/pthread_mutex.rs>
44 #![allow(clippy::undocumented_unsafe_blocks)]
55 #![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))]
78
89 #[cfg(not(windows))]
910 mod pthread_mtx {
rust/pin-init/examples/static_init.rs+2−1
@@ -2,7 +2,8 @@ · 1 unmodified line
22
33 #![allow(clippy::undocumented_unsafe_blocks)]
44 #![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))]
67 #![allow(unused_imports)]
78
89 use core::{
rust/pin-init/internal/src/init.rs+10−4
@@ -173,6 +173,12 @@ pub(crate) fn expand( · 172 unmodified lines
173173 };
174174 // SAFETY: TODO
175175 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+ )]
176182 init
177183 }})
178184 }
@@ -264,7 +270,7 @@ fn init_fields( · 85 unmodified lines
264270 {
265271 #value_prep
266272 // SAFETY: TODO
267− unsafe { #write(::core::ptr::addr_of_mut!((*#slot).#ident), #value_ident) };
273+ unsafe { #write(&raw mut (*#slot).#ident, #value_ident) };
268274 }
269275 #(#cfgs)*
270276 #[allow(unused_variables)]
@@ -287,7 +293,7 @@ fn init_fields( · 16 unmodified lines
287293 // return when an error/panic occurs.
288294 // - We also use `#data` to require the correct trait (`Init` or `PinInit`)
289295 // for `#ident`.
290− unsafe { #data.#ident(::core::ptr::addr_of_mut!((*#slot).#ident), #init)? };
296+ unsafe { #data.#ident(&raw mut (*#slot).#ident, #init)? };
291297 },
292298 quote! {
293299 // SAFETY: TODO
@@ -302,7 +308,7 @@ fn init_fields( · 8 unmodified lines
302308 unsafe {
303309 ::pin_init::Init::__init(
304310 #init,
305− ::core::ptr::addr_of_mut!((*#slot).#ident),
311+ &raw mut (*#slot).#ident,
306312 )?
307313 };
308314 },
@@ -342,7 +348,7 @@ fn init_fields( · 33 unmodified lines
342348 // SAFETY: We forget the guard later when initialization has succeeded.
343349 let #guard = unsafe {
344350 ::pin_init::__internal::DropGuard::new(
345− ::core::ptr::addr_of_mut!((*slot).#ident)
351+ &raw mut (*slot).#ident
346352 )
347353 };
348354 });
rust/pin-init/internal/src/lib.rs+1−1
@@ -6,7 +6,7 @@ · 5 unmodified lines
66
77 //! `pin-init` proc macros.
88
9−#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
9+#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
1010 // Documentation is done in the pin-init crate instead.
1111 #![allow(missing_docs)]
1212
rust/pin-init/src/lib.rs+50−23
@@ -172,7 +172,6 @@ · 171 unmodified lines
172172 //! # #![feature(extern_types)]
173173 //! use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure};
174174 //! use core::{
175−//! ptr::addr_of_mut,
176175 //! marker::PhantomPinned,
177176 //! cell::UnsafeCell,
178177 //! pin::Pin,
@@ -211,7 +210,7 @@ · 32 unmodified lines
211210 //! unsafe {
212211 //! pin_init_from_closure(move |slot: *mut Self| {
213212 //! // `slot` contains uninit memory, avoid creating a reference.
214−//! let foo = addr_of_mut!((*slot).foo);
213+//! let foo = &raw mut (*slot).foo;
215214 //! let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>();
216215 //!
217216 //! // Initialize the `foo`
@@ -264,12 +263,10 @@ · 46 unmodified lines
264263 //! [`impl Init<T, E>`]: crate::Init
265264 //! [Rust-for-Linux]: https://rust-for-linux.com/
266265
267−#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
266+#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
267+#![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))]
268268 #![cfg_attr(
269− all(
270− any(feature = "alloc", feature = "std"),
271− not(RUSTC_NEW_UNINIT_IS_STABLE)
272− ),
269+ all(any(feature = "alloc", feature = "std"), USE_RUSTC_FEATURES),
273270 feature(new_uninit)
274271 )]
275272 #![forbid(missing_docs, unsafe_op_in_unsafe_fn)]
@@ -279,6 +276,8 @@ · 3 unmodified lines
279276 all(feature = "unsafe-pinned", CONFIG_RUSTC_HAS_UNSAFE_PINNED),
280277 feature(unsafe_pinned)
281278 )]
279+#![cfg_attr(all(USE_RUSTC_FEATURES, doc), allow(internal_features))]
280+#![cfg_attr(all(USE_RUSTC_FEATURES, doc), feature(rustdoc_internals))]
282281
283282 use core::{
284283 cell::UnsafeCell,
@@ -755,7 +754,7 @@ macro_rules! stack_try_pin_init { · 470 unmodified lines
755754 ///
756755 /// ```rust
757756 /// # use pin_init::*;
758−/// # use core::{ptr::addr_of_mut, marker::PhantomPinned};
757+/// # use core::marker::PhantomPinned;
759758 /// #[pin_data]
760759 /// #[derive(Zeroable)]
761760 /// struct Buf {
@@ -769,7 +768,7 @@ macro_rules! stack_try_pin_init { · 7 unmodified lines
769768 /// let init = pin_init!(&this in Buf {
770769 /// buf: [0; 64],
771770 /// // SAFETY: TODO.
772−/// ptr: unsafe { addr_of_mut!((*this.as_ptr()).buf).cast() },
771+/// ptr: unsafe { (&raw mut (*this.as_ptr()).buf).cast() },
773772 /// pin: PhantomPinned,
774773 /// });
775774 /// let init = pin_init!(Buf {
@@ -1147,9 +1146,12 @@ pub const unsafe fn cast_pin_init<T, U, E>(init: impl PinInit<T, E>) -> impl Pin · 371 unmodified lines
11471146 // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety
11481147 // requirements.
11491148 let res = unsafe { pin_init_from_closure(|ptr: *mut U| init.__pinned_init(ptr.cast::<T>())) };
1150− // FIXME: remove the let statement once the nightly-MSRV allows it (1.78 otherwise encounters a
1151− // cycle when computing the type returned by this function)
1152− #[allow(clippy::let_and_return)]
1149+ // FIXME: this let binding is required to avoid a compiler error (cycle when computing the opaque
1150+ // type returned by this function) before Rust 1.81. Remove after MSRV bump.
1151+ #[allow(
1152+ clippy::let_and_return,
1153+ reason = "some clippy versions warn about the let binding"
1154+ )]
11531155 res
11541156 }
11551157
@@ -1163,9 +1165,12 @@ pub const unsafe fn cast_init<T, U, E>(init: impl Init<T, E>) -> impl Init<U, E> · 7 unmodified lines
11631165 // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety
11641166 // requirements.
11651167 let res = unsafe { init_from_closure(|ptr: *mut U| init.__init(ptr.cast::<T>())) };
1166− // FIXME: remove the let statement once the nightly-MSRV allows it (1.78 otherwise encounters a
1167− // cycle when computing the type returned by this function)
1168− #[allow(clippy::let_and_return)]
1168+ // FIXME: this let binding is required to avoid a compiler error (cycle when computing the opaque
1169+ // type returned by this function) before Rust 1.81. Remove after MSRV bump.
1170+ #[allow(
1171+ clippy::let_and_return,
1172+ reason = "some clippy versions warn about the let binding"
1173+ )]
11691174 res
11701175 }
11711176
@@ -1610,13 +1615,6 @@ impl_zeroable! { · 438 unmodified lines
16101615 // SAFETY: `T: Zeroable` and `UnsafeCell` is `repr(transparent)`.
16111616 {<T: ?Sized + Zeroable>} UnsafeCell<T>,
16121617
1613− // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee:
1614− // <https://doc.rust-lang.org/stable/std/option/index.html#representation>).
1615− Option<NonZeroU8>, Option<NonZeroU16>, Option<NonZeroU32>, Option<NonZeroU64>,
1616− Option<NonZeroU128>, Option<NonZeroUsize>,
1617− Option<NonZeroI8>, Option<NonZeroI16>, Option<NonZeroI32>, Option<NonZeroI64>,
1618− Option<NonZeroI128>, Option<NonZeroIsize>,
1619−
16201618 // SAFETY: `null` pointer is valid.
16211619 //
16221620 // We cannot use `T: ?Sized`, since the VTABLE pointer part of fat pointers is not allowed to be
@@ -1635,8 +1633,14 @@ impl_zeroable! { · 12 unmodified lines
16351633 }
16361634
16371635 macro_rules! impl_tuple_zeroable {
1638− ($(,)?) => {};
1636+ ($first:ident, $(,)?) => {
1637+ #[cfg_attr(all(USE_RUSTC_FEATURES, doc), doc(fake_variadic))]
1638+ /// Implemented for tuples up to 10 items long.
1639+ // SAFETY: All elements are zeroable and padding can be zero.
1640+ unsafe impl<$first: Zeroable> Zeroable for ($first,) {}
1641+ };
16391642 ($first:ident, $($t:ident),* $(,)?) => {
1643+ #[cfg_attr(doc, doc(hidden))]
16401644 // SAFETY: All elements are zeroable and padding can be zero.
16411645 unsafe impl<$first: Zeroable, $($t: Zeroable),*> Zeroable for ($first, $($t),*) {}
16421646 impl_tuple_zeroable!($($t),* ,);
@@ -1651,7 +1655,16 @@ macro_rules! impl_fn_zeroable_option { · 8 unmodified lines
16511655 $(impl_fn_zeroable_option!({unsafe extern $abi} $args);)*
16521656 };
16531657 ({$($prefix:tt)*} {$(,)?}) => {};
1658+ ({$($prefix:tt)*} {$ret:ident, $arg:ident $(,)?}) => {
1659+ #[cfg_attr(all(USE_RUSTC_FEATURES, doc), doc(fake_variadic))]
1660+ /// Implemented for function pointers with up to 20 arity.
1661+ // SAFETY: function pointers are part of the option layout optimization:
1662+ // <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
1663+ unsafe impl<$ret, $arg> ZeroableOption for $($prefix)* fn($arg) -> $ret {}
1664+ impl_fn_zeroable_option!({$($prefix)*} {$arg,});
1665+ };
16541666 ({$($prefix:tt)*} {$ret:ident, $($rest:ident),* $(,)?}) => {
1667+ #[cfg_attr(doc, doc(hidden))]
16551668 // SAFETY: function pointers are part of the option layout optimization:
16561669 // <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
16571670 unsafe impl<$ret, $($rest),*> ZeroableOption for $($prefix)* fn($($rest),*) -> $ret {}
@@ -1661,6 +1674,20 @@ macro_rules! impl_fn_zeroable_option { · 3 unmodified lines
16611674
16621675 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 });
16631676
1677+macro_rules! impl_non_zero_int_zeroable_option {
1678+ ($($int:ty),* $(,)?) => {
1679+ // SAFETY: Safety comment written in the macro invocation.
1680+ $(unsafe impl ZeroableOption for $int {})*
1681+ };
1682+}
1683+
1684+impl_non_zero_int_zeroable_option! {
1685+ // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee:
1686+ // <https://doc.rust-lang.org/stable/std/option/index.html#representation>).
1687+ NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
1688+ NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize,
1689+}
1690+
16641691 /// This trait allows creating an instance of `Self` which contains exactly one
16651692 /// [structurally pinned value](https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning).
16661693 ///
rust/uapi/lib.rs+1−4
@@ -8,10 +8,6 @@ · 7 unmodified lines
88 //! userspace APIs.
99
1010 #![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))]
1511 #![allow(
1612 clippy::all,
1713 clippy::cast_lossless,
@@ -28,6 +24,7 @@ · 10 unmodified lines
2824 unsafe_op_in_unsafe_fn
2925 )]
3026 #![cfg_attr(CONFIG_RUSTC_HAS_UNNECESSARY_TRANSMUTES, allow(unnecessary_transmutes))]
27+#![feature(cfi_encoding)]
3128
3229 // Manual definition of blocklisted types.
3330 type __kernel_size_t = usize;
scripts/Makefile.build+7−8
@@ -310,18 +310,13 @@ $(obj)/%.lst: $(obj)/%.c FORCE · 309 unmodified lines
310310
311311 # The features in this list are the ones allowed for non-`rust/` code.
312312 #
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)`.
318313 # - Stable since Rust 1.87.0: `feature(asm_goto)`.
319314 # - Expected to become stable: `feature(arbitrary_self_types)`.
320315 # - To be determined: `feature(used_with_arg)`.
321316 #
322317 # Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on
323318 # 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
325320
326321 # `--out-dir` is required to avoid temporaries being created by `rustc` in the
327322 # current working directory, which may be not accessible in the out-of-tree
@@ -334,7 +329,6 @@ rust_common_cmd = \ · 6 unmodified lines
334329 -Zcrate-attr='feature($(rust_allowed_features))' \
335330 -Zunstable-options --extern pin_init --extern kernel \
336331 --crate-type rlib -L $(objtree)/rust/ \
337− --crate-name $(basename $(notdir $@)) \
338332 --sysroot=/dev/null \
339333 --out-dir $(dir $@) --emit=dep-info=$(depfile)
340334
@@ -347,7 +341,12 @@ rust_common_cmd = \ · 6 unmodified lines
347341 # would not match each other.
348342
349343 quiet_cmd_rustc_o_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@
350− cmd_rustc_o_rs = $(rust_common_cmd) --emit=obj=$@ $< $(cmd_objtool)
344+ cmd_rustc_o_rs = $(rust_common_cmd) --emit=$(if $(CONFIG_RUST_INLINE_HELPERS),llvm-bc=$(patsubst %.o,%.bc,$@),obj=$@) $< \
345+ $(if $(CONFIG_RUST_INLINE_HELPERS),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \
346+ $(objtree)/rust/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \
347+ $(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
348+ $(cmd_ld_single)) \
349+ $(cmd_objtool)
351350
352351 define rule_rustc_o_rs
353352 $(call cmd_and_fixdep,rustc_o_rs)
scripts/generate_rust_analyzer.py+216−82
@@ -10,8 +10,15 @@ import os · 9 unmodified lines
1010 import pathlib
1111 import subprocess
1212 import sys
13+from typing import Dict, Iterable, List, Literal, Optional, TypedDict
1314
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]]:
1522 crates_cfgs = {}
1623 for cfg in cfgs:
1724 crate, vals = cfg.split("=", 1)
@@ -19,54 +26,153 @@ def args_crates_cfgs(cfgs): · 1 unmodified line
1926
2027 return crates_cfgs
2128
22−def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edition):
29+class Dependency(TypedDict):
30+ crate: int
31+ name: str
32+
33+
34+class Source(TypedDict):
35+ include_dirs: List[str]
36+ exclude_dirs: List[str]
37+
38+
39+class Crate(TypedDict):
40+ display_name: str
41+ root_module: str
42+ is_workspace_member: bool
43+ deps: List[Dependency]
44+ cfg: List[str]
45+ edition: str
46+ env: Dict[str, str]
47+
48+
49+class ProcMacroCrate(Crate):
50+ is_proc_macro: Literal[True]
51+ proc_macro_dylib_path: str # `pathlib.Path` is not JSON serializable.
52+
53+
54+class CrateWithGenerated(Crate):
55+ source: Source
56+
57+
58+def generate_crates(
59+ srctree: pathlib.Path,
60+ objtree: pathlib.Path,
61+ sysroot_src: pathlib.Path,
62+ external_src: Optional[pathlib.Path],
63+ cfgs: List[str],
64+ core_edition: str,
65+) -> List[Crate]:
2366 # Generate the configuration list.
24− cfg = []
67+ generated_cfg = []
2568 with open(objtree / "include" / "generated" / "rustc_cfg") as fd:
2669 for line in fd:
2770 line = line.replace("--cfg=", "")
2871 line = line.replace("\n", "")
29− cfg.append(line)
72+ generated_cfg.append(line)
3073
31− # Now fill the crates list -- dependencies need to come first.
32− #
33− # Avoid O(n^2) iterations by keeping a map of indexes.
34− crates = []
35− crates_indexes = {}
74+ # Now fill the crates list.
75+ crates: List[Crate] = []
3676 crates_cfgs = args_crates_cfgs(cfgs)
3777
38− def append_crate(display_name, root_module, deps, cfg=[], is_workspace_member=True, is_proc_macro=False, edition="2021"):
39− crate = {
78+ def get_crate_name(path: pathlib.Path) -> str:
79+ return invoke_rustc(["--print", "crate-name", str(path)])
80+
81+ def build_crate(
82+ display_name: str,
83+ root_module: pathlib.Path,
84+ deps: List[Dependency],
85+ *,
86+ cfg: Optional[List[str]],
87+ is_workspace_member: Optional[bool],
88+ edition: Optional[str],
89+ ) -> Crate:
90+ cfg = cfg if cfg is not None else crates_cfgs.get(display_name, [])
91+ is_workspace_member = (
92+ is_workspace_member if is_workspace_member is not None else True
93+ )
94+ edition = edition if edition is not None else "2021"
95+ return {
4096 "display_name": display_name,
4197 "root_module": str(root_module),
4298 "is_workspace_member": is_workspace_member,
43− "is_proc_macro": is_proc_macro,
44− "deps": [{"crate": crates_indexes[dep], "name": dep} for dep in deps],
99+ "deps": deps,
45100 "cfg": cfg,
46101 "edition": edition,
47102 "env": {
48103 "RUST_MODFILE": "This is only for rust-analyzer"
49104 }
50105 }
51− if is_proc_macro:
52− proc_macro_dylib_name = subprocess.check_output(
53− [os.environ["RUSTC"], "--print", "file-names", "--crate-name", display_name, "--crate-type", "proc-macro", "-"],
54− stdin=subprocess.DEVNULL,
55− ).decode('utf-8').strip()
56− crate["proc_macro_dylib_path"] = f"{objtree}/rust/{proc_macro_dylib_name}"
57− crates_indexes[display_name] = len(crates)
106+
107+ def append_proc_macro_crate(
108+ display_name: str,
109+ root_module: pathlib.Path,
110+ deps: List[Dependency],
111+ *,
112+ cfg: Optional[List[str]] = None,
113+ is_workspace_member: Optional[bool] = None,
114+ edition: Optional[str] = None,
115+ ) -> Dependency:
116+ crate = build_crate(
117+ display_name,
118+ root_module,
119+ deps,
120+ cfg=cfg,
121+ is_workspace_member=is_workspace_member,
122+ edition=edition,
123+ )
124+ proc_macro_dylib_name = invoke_rustc([
125+ "--print",
126+ "file-names",
127+ "--crate-name",
128+ display_name,
129+ "--crate-type",
130+ "proc-macro",
131+ "-",
132+ ])
133+ proc_macro_crate: ProcMacroCrate = {
134+ **crate,
135+ "is_proc_macro": True,
136+ "proc_macro_dylib_path": str(objtree / "rust" / proc_macro_dylib_name),
137+ }
138+ return register_crate(proc_macro_crate)
139+
140+ def register_crate(crate: Crate) -> Dependency:
141+ index = len(crates)
58142 crates.append(crate)
143+ return {"crate": index, "name": crate["display_name"]}
144+
145+ def append_crate(
146+ display_name: str,
147+ root_module: pathlib.Path,
148+ deps: List[Dependency],
149+ *,
150+ cfg: Optional[List[str]] = None,
151+ is_workspace_member: Optional[bool] = None,
152+ edition: Optional[str] = None,
153+ ) -> Dependency:
154+ return register_crate(
155+ build_crate(
156+ display_name,
157+ root_module,
158+ deps,
159+ cfg=cfg,
160+ is_workspace_member=is_workspace_member,
161+ edition=edition,
162+ )
163+ )
59164
60165 def append_sysroot_crate(
61− display_name,
62− deps,
63− cfg=[],
64− ):
65− append_crate(
166+ display_name: str,
167+ deps: List[Dependency],
168+ *,
169+ cfg: Optional[List[str]] = None,
170+ ) -> Dependency:
171+ return append_crate(
66172 display_name,
67173 sysroot_src / display_name / "src" / "lib.rs",
68174 deps,
69− cfg,
175+ cfg=cfg,
70176 is_workspace_member=False,
71177 # Miguel Ojeda writes:
72178 #
@@ -98,129 +204,146 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit · 25 unmodified lines
98204 # NB: sysroot crates reexport items from one another so setting up our transitive dependencies
99205 # here is important for ensuring that rust-analyzer can resolve symbols. The sources of truth
100206 # for this dependency graph are `(sysroot_src / crate / "Cargo.toml" for crate in crates)`.
101− append_sysroot_crate("core", [], cfg=crates_cfgs.get("core", []))
102− append_sysroot_crate("alloc", ["core"])
103− append_sysroot_crate("std", ["alloc", "core"])
104− append_sysroot_crate("proc_macro", ["core", "std"])
207+ core = append_sysroot_crate("core", [])
208+ alloc = append_sysroot_crate("alloc", [core])
209+ std = append_sysroot_crate("std", [alloc, core])
210+ proc_macro = append_sysroot_crate("proc_macro", [core, std])
105211
106− append_crate(
212+ compiler_builtins = append_crate(
107213 "compiler_builtins",
108214 srctree / "rust" / "compiler_builtins.rs",
109− ["core"],
215+ [core],
110216 )
111217
112− append_crate(
218+ proc_macro2 = append_crate(
113219 "proc_macro2",
114220 srctree / "rust" / "proc-macro2" / "lib.rs",
115− ["core", "alloc", "std", "proc_macro"],
116− cfg=crates_cfgs["proc_macro2"],
221+ [core, alloc, std, proc_macro],
117222 )
118223
119− append_crate(
224+ quote = append_crate(
120225 "quote",
121226 srctree / "rust" / "quote" / "lib.rs",
122− ["core", "alloc", "std", "proc_macro", "proc_macro2"],
123− cfg=crates_cfgs["quote"],
227+ [core, alloc, std, proc_macro, proc_macro2],
124228 edition="2018",
125229 )
126230
127− append_crate(
231+ syn = append_crate(
128232 "syn",
129233 srctree / "rust" / "syn" / "lib.rs",
130− ["std", "proc_macro", "proc_macro2", "quote"],
131− cfg=crates_cfgs["syn"],
234+ [std, proc_macro, proc_macro2, quote],
132235 )
133236
134− append_crate(
237+ macros = append_proc_macro_crate(
135238 "macros",
136239 srctree / "rust" / "macros" / "lib.rs",
137− ["std", "proc_macro", "proc_macro2", "quote", "syn"],
138− is_proc_macro=True,
240+ [std, proc_macro, proc_macro2, quote, syn],
139241 )
140242
141− append_crate(
243+ build_error = append_crate(
142244 "build_error",
143245 srctree / "rust" / "build_error.rs",
144− ["core", "compiler_builtins"],
246+ [core, compiler_builtins],
145247 )
146248
147− append_crate(
249+ pin_init_internal = append_proc_macro_crate(
148250 "pin_init_internal",
149251 srctree / "rust" / "pin-init" / "internal" / "src" / "lib.rs",
150− ["std", "proc_macro", "proc_macro2", "quote", "syn"],
151− cfg=["kernel"],
152− is_proc_macro=True,
252+ [std, proc_macro, proc_macro2, quote, syn],
153253 )
154254
155− append_crate(
255+ pin_init = append_crate(
156256 "pin_init",
157257 srctree / "rust" / "pin-init" / "src" / "lib.rs",
158− ["core", "compiler_builtins", "pin_init_internal", "macros"],
159− cfg=["kernel"],
258+ [core, compiler_builtins, pin_init_internal, macros],
160259 )
161260
162− append_crate(
261+ ffi = append_crate(
163262 "ffi",
164263 srctree / "rust" / "ffi.rs",
165− ["core", "compiler_builtins"],
264+ [core, compiler_builtins],
166265 )
167266
168267 def append_crate_with_generated(
169− display_name,
170− deps,
171− ):
172− append_crate(
268+ display_name: str,
269+ deps: List[Dependency],
270+ ) -> Dependency:
271+ crate = build_crate(
173272 display_name,
174273 srctree / "rust"/ display_name / "lib.rs",
175274 deps,
176− cfg=cfg,
275+ cfg=generated_cfg,
276+ is_workspace_member=True,
277+ edition=None,
177278 )
178− crates[-1]["env"]["OBJTREE"] = str(objtree.resolve(True))
179− crates[-1]["source"] = {
180− "include_dirs": [
181− str(srctree / "rust" / display_name),
182− str(objtree / "rust")
183− ],
184− "exclude_dirs": [],
279+ crate["env"]["OBJTREE"] = str(objtree.resolve(True))
280+ crate_with_generated: CrateWithGenerated = {
281+ **crate,
282+ "source": {
283+ "include_dirs": [
284+ str(srctree / "rust" / display_name),
285+ str(objtree / "rust"),
286+ ],
287+ "exclude_dirs": [],
288+ },
185289 }
290+ return register_crate(crate_with_generated)
291+
292+ bindings = append_crate_with_generated("bindings", [core, ffi, pin_init])
293+ uapi = append_crate_with_generated("uapi", [core, ffi, pin_init])
294+ kernel = append_crate_with_generated(
295+ "kernel", [core, macros, build_error, pin_init, ffi, bindings, uapi]
296+ )
186297
187− append_crate_with_generated("bindings", ["core", "ffi", "pin_init"])
188− append_crate_with_generated("uapi", ["core", "ffi", "pin_init"])
189− append_crate_with_generated("kernel", ["core", "macros", "build_error", "pin_init", "ffi", "bindings", "uapi"])
298+ scripts = srctree / "scripts"
299+ makefile = (scripts / "Makefile").read_text()
300+ for path in scripts.glob("*.rs"):
301+ name = path.stem
302+ if f"{name}-rust" not in makefile:
303+ continue
304+ append_crate(
305+ name,
306+ path,
307+ [std],
308+ )
190309
191− def is_root_crate(build_file, target):
310+ def is_root_crate(build_file: pathlib.Path, target: str) -> bool:
192311 try:
193− return f"{target}.o" in open(build_file).read()
312+ contents = build_file.read_text()
194313 except FileNotFoundError:
195314 return False
315+ return f"{target}.o" in contents
196316
197317 # Then, the rest outside of `rust/`.
198318 #
199319 # We explicitly mention the top-level folders we want to cover.
200− extra_dirs = map(lambda dir: srctree / dir, ("samples", "drivers"))
320+ extra_dirs: Iterable[pathlib.Path] = (
321+ srctree / dir for dir in ("samples", "drivers")
322+ )
201323 if external_src is not None:
202324 extra_dirs = [external_src]
203325 for folder in extra_dirs:
204326 for path in folder.rglob("*.rs"):
205327 logging.info("Checking %s", path)
206− name = path.name.replace(".rs", "")
328+ file_name = path.stem
207329
208330 # Skip those that are not crate roots.
209− if not is_root_crate(path.parent / "Makefile", name) and \
210− not is_root_crate(path.parent / "Kbuild", name):
331+ if not is_root_crate(path.parent / "Makefile", file_name) and \
332+ not is_root_crate(path.parent / "Kbuild", file_name):
211333 continue
212334
213− logging.info("Adding %s", name)
335+ crate_name = get_crate_name(path)
336+ logging.info("Adding %s", crate_name)
214337 append_crate(
215− name,
338+ crate_name,
216339 path,
217− ["core", "kernel", "pin_init"],
218− cfg=cfg,
340+ [core, kernel, pin_init],
341+ cfg=generated_cfg,
219342 )
220343
221344 return crates
222345
223−def main():
346+def main() -> None:
224347 parser = argparse.ArgumentParser()
225348 parser.add_argument('--verbose', '-v', action='store_true')
226349 parser.add_argument('--cfgs', action='append', default=[])
@@ -230,7 +353,18 @@ def main(): · 3 unmodified lines
230353 parser.add_argument("sysroot", type=pathlib.Path)
231354 parser.add_argument("sysroot_src", type=pathlib.Path)
232355 parser.add_argument("exttree", type=pathlib.Path, nargs="?")
233− args = parser.parse_args()
356+
357+ class Args(argparse.Namespace):
358+ verbose: bool
359+ cfgs: List[str]
360+ srctree: pathlib.Path
361+ objtree: pathlib.Path
362+ sysroot: pathlib.Path
363+ sysroot_src: pathlib.Path
364+ exttree: Optional[pathlib.Path]
365+ core_edition: str
366+
367+ args = parser.parse_args(namespace=Args())
234368
235369 logging.basicConfig(
236370 format="[%(asctime)s] [%(levelname)s] %(message)s",
scripts/min-tool-version.sh+2−2
@@ -31,10 +31,10 @@ llvm) · 30 unmodified lines
3131 fi
3232 ;;
3333 rustc)
34− echo 1.78.0
34+ echo 1.85.0
3535 ;;
3636 bindgen)
37− echo 0.65.1
37+ echo 0.71.1
3838 ;;
3939 *)
4040 echo "$1: unknown tool" >&2
scripts/rust_is_available.sh+1−35
@@ -121,14 +121,8 @@ fi · 120 unmodified lines
121121 # Check that the Rust bindings generator is suitable.
122122 #
123123 # 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).
130124 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
132126 ) || rust_bindings_generator_code=$?
133127 if [ -n "$rust_bindings_generator_code" ]; then
134128 echo >&2 "***"
@@ -163,19 +157,6 @@ if [ "$rust_bindings_generator_cversion" -lt "$rust_bindings_generator_min_cvers · 28 unmodified lines
163157 echo >&2 "***"
164158 exit 1
165159 fi
166−if [ "$rust_bindings_generator_cversion" -eq 6600 ] ||
167− [ "$rust_bindings_generator_cversion" -eq 6601 ]; then
168− # Distributions may have patched the issue (e.g. Debian did).
169− if ! "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_0_66.h >/dev/null; then
170− echo >&2 "***"
171− echo >&2 "*** Rust bindings generator '$BINDGEN' versions 0.66.0 and 0.66.1 may not"
172− echo >&2 "*** work due to a bug (https://github.com/rust-lang/rust-bindgen/pull/2567),"
173− echo >&2 "*** unless patched (like Debian's)."
174− echo >&2 "*** Your version: $rust_bindings_generator_version"
175− echo >&2 "***"
176− warning=1
177− fi
178−fi
179160
180161 # Check that the `libclang` used by the Rust bindings generator is suitable.
181162 #
@@ -227,21 +208,6 @@ if [ "$bindgen_libclang_cversion" -lt "$bindgen_libclang_min_cversion" ]; then · 45 unmodified lines
227208 exit 1
228209 fi
229210
230−if [ "$bindgen_libclang_cversion" -ge 1900100 ] &&
231− [ "$rust_bindings_generator_cversion" -lt 6905 ]; then
232− # Distributions may have patched the issue (e.g. Debian did).
233− if ! "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_libclang_concat.h | grep -q foofoo; then
234− echo >&2 "***"
235− echo >&2 "*** Rust bindings generator '$BINDGEN' < 0.69.5 together with libclang >= 19.1"
236− echo >&2 "*** may not work due to a bug (https://github.com/rust-lang/rust-bindgen/pull/2824),"
237− echo >&2 "*** unless patched (like Debian's)."
238− echo >&2 "*** Your bindgen version: $rust_bindings_generator_version"
239− echo >&2 "*** Your libclang version: $bindgen_libclang_version"
240− echo >&2 "***"
241− warning=1
242− fi
243−fi
244−
245211 # If the C compiler is Clang, then we can also check whether its version
246212 # matches the `libclang` version used by the Rust bindings generator.
247213 #
scripts/rust_is_available_bindgen_0_66.h+0−2
@@ -1,2 +0,0 @@
1−/* SPDX-License-Identifier: GPL-2.0 */
2−#define A "\0"
scripts/rust_is_available_bindgen_libclang_concat.h+0−3
@@ -1,3 +0,0 @@
1−/* SPDX-License-Identifier: GPL-2.0 */
2−#define F(x) int x##x
3−F(foo);
scripts/rust_is_available_test.py+3−55
@@ -54,37 +54,23 @@ else: · 53 unmodified lines
5454 """)
5555
5656 @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):
5858 if libclang_stderr is None:
5959 libclang_case = f"raise SystemExit({cls.bindgen_default_bindgen_libclang_failure_exit_code})"
6060 else:
6161 libclang_case = f"print({repr(libclang_stderr)}, file=sys.stderr)"
6262
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−
7363 return cls.generate_executable(f"""#!/usr/bin/env python3
7464 import sys
7565 if "rust_is_available_bindgen_libclang.h" in " ".join(sys.argv):
7666 {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}
8167 else:
8268 print({repr(version_stdout)})
8369 """)
8470
8571 @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)
8874
8975 @classmethod
9076 def generate_bindgen_libclang_failure(cls):
@@ -245,19 +231,6 @@ else: · 154 unmodified lines
245231 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })
246232 self.assertIn(f"Rust bindings generator '{bindgen}' is too old.", result.stderr)
247233
248− def test_bindgen_bad_version_0_66_0_and_0_66_1(self):
249− for version in ("0.66.0", "0.66.1"):
250− with self.subTest(version=version):
251− bindgen = self.generate_bindgen_version(f"bindgen {version}")
252− result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen })
253− self.assertIn(f"Rust bindings generator '{bindgen}' versions 0.66.0 and 0.66.1 may not", result.stderr)
254−
255− def test_bindgen_bad_version_0_66_0_and_0_66_1_patched(self):
256− for version in ("0.66.0", "0.66.1"):
257− with self.subTest(version=version):
258− bindgen = self.generate_bindgen_version(f"bindgen {version}", True)
259− result = self.run_script(self.Expected.SUCCESS, { "BINDGEN": bindgen })
260−
261234 def test_bindgen_libclang_failure(self):
262235 bindgen = self.generate_bindgen_libclang_failure()
263236 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })
@@ -275,31 +248,6 @@ else: · 11 unmodified lines
275248 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })
276249 self.assertIn(f"libclang (used by the Rust bindings generator '{bindgen}') is too old.", result.stderr)
277250
278− def test_bindgen_bad_libclang_concat(self):
279− for (bindgen_version, libclang_version, expected_not_patched) in (
280− ("0.69.4", "18.0.0", self.Expected.SUCCESS),
281− ("0.69.4", "19.1.0", self.Expected.SUCCESS_WITH_WARNINGS),
282− ("0.69.4", "19.2.0", self.Expected.SUCCESS_WITH_WARNINGS),
283−
284− ("0.69.5", "18.0.0", self.Expected.SUCCESS),
285− ("0.69.5", "19.1.0", self.Expected.SUCCESS),
286− ("0.69.5", "19.2.0", self.Expected.SUCCESS),
287−
288− ("0.70.0", "18.0.0", self.Expected.SUCCESS),
289− ("0.70.0", "19.1.0", self.Expected.SUCCESS),
290− ("0.70.0", "19.2.0", self.Expected.SUCCESS),
291− ):
292− with self.subTest(bindgen_version=bindgen_version, libclang_version=libclang_version):
293− cc = self.generate_clang(f"clang version {libclang_version}")
294− libclang_stderr = f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {libclang_version} [-W#pragma-messages], err: false"
295− bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr)
296− result = self.run_script(expected_not_patched, { "BINDGEN": bindgen, "CC": cc })
297− if expected_not_patched == self.Expected.SUCCESS_WITH_WARNINGS:
298− self.assertIn(f"Rust bindings generator '{bindgen}' < 0.69.5 together with libclang >= 19.1", result.stderr)
299−
300− bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr, libclang_concat_patched=True)
301− result = self.run_script(self.Expected.SUCCESS, { "BINDGEN": bindgen, "CC": cc })
302−
303251 def test_clang_matches_bindgen_libclang_different_bindgen(self):
304252 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")
305253 result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen })