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 @@
1# SPDX-License-Identifier: GPL-2.01# SPDX-License-Identifier: GPL-2.0
2 2
3msrv = "1.78.0"3msrv = "1.85.0"
4 4
5check-private-items = true5check-private-items = true
6 6
@@ -9,3 +9,13 @@ disallowed-macros = [ · 2 unmodified lines
9 # it here, see: https://github.com/rust-lang/rust-clippy/issues/11303.9 # it here, see: https://github.com/rust-lang/rust-clippy/issues/11303.
10 { path = "kernel::dbg", reason = "the `dbg!` macro is intended as a debugging tool", allow-invalid = true },10 { path = "kernel::dbg", reason = "the `dbg!` macro is intended as a debugging tool", allow-invalid = true },
11]11]
12
13[[disallowed-methods]]
14path = "core::ffi::CStr::as_ptr"
15replacement = "kernel::prelude::CStrExt::as_char_ptr"
16reason = "kernel's `char` is always unsigned, use `as_char_ptr` instead"
17
18[[disallowed-methods]]
19path = "core::ffi::CStr::from_ptr"
20replacement = "kernel::prelude::CStrExt::from_char_ptr"
21reason = "kernel's `char` is always unsigned, use `from_char_ptr` instead"
.gitignore+4−0
@@ -13,6 +13,7 @@ · 12 unmodified lines
13.*13.*
14*.a14*.a
15*.asn1.[ch]15*.asn1.[ch]
16*.bc
16*.bin17*.bin
17*.bz218*.bz2
18*.c.[012]*.*19*.c.[012]*.*
@@ -184,3 +185,6 @@ sphinx_*/ · 165 unmodified lines
184 185
185# Rust analyzer configuration186# Rust analyzer configuration
186/rust-project.json187/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
31====================== =============== ========================================31====================== =============== ========================================
32GNU C 8.1 gcc --version32GNU C 8.1 gcc --version
33Clang/LLVM (optional) 15.0.0 clang --version33Clang/LLVM (optional) 15.0.0 clang --version
34Rust (optional) 1.78.0 rustc --version34Rust (optional) 1.85.0 rustc --version
35bindgen (optional) 0.65.1 bindgen --version35bindgen (optional) 0.71.1 bindgen --version
36GNU make 4.0 make --version36GNU make 4.0 make --version
37bash 4.2 bash --version37bash 4.2 bash --version
38binutils 2.30 ld -v38binutils 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
157 157
158.. code-block:: kconfig158.. code-block:: kconfig
159 159
160 config RUSTC_VERSION_MIN_107900160 config RUSTC_HAS_SPAN_FILE
161 def_bool y if RUSTC_VERSION >= 107900161 def_bool RUSTC_VERSION >= 108800
Documentation/rust/quick-start.rst+20−32
@@ -57,8 +57,8 @@ of the box, e.g.:: · 56 unmodified lines
57Gentoo Linux57Gentoo Linux
58************58************
59 59
60Gentoo Linux (and especially the testing branch) provides recent Rust releases60Gentoo Linux provides recent Rust releases and thus it should generally work out
61and thus it should generally work out of the box, e.g.::61of the box, e.g.::
62 62
63 USE='rust-src rustfmt clippy' emerge dev-lang/rust dev-util/bindgen63 USE='rust-src rustfmt clippy' emerge dev-lang/rust dev-util/bindgen
64 64
@@ -68,8 +68,8 @@ and thus it should generally work out of the box, e.g.:: · 3 unmodified lines
68Nix68Nix
69***69***
70 70
71Nix (unstable channel) provides recent Rust releases and thus it should71Nix provides recent Rust releases and thus it should generally work out of the
72generally work out of the box, e.g.::72box, e.g.::
73 73
74 { pkgs ? import <nixpkgs> {} }:74 { pkgs ? import <nixpkgs> {} }:
75 pkgs.mkShell {75 pkgs.mkShell {
@@ -84,16 +84,13 @@ openSUSE · 8 unmodified lines
84openSUSE Slowroll and openSUSE Tumbleweed provide recent Rust releases and thus84openSUSE Slowroll and openSUSE Tumbleweed provide recent Rust releases and thus
85they should generally work out of the box, e.g.::85they should generally work out of the box, e.g.::
86 86
87 zypper install rust rust1.79-src rust-bindgen clang87 zypper install rust rust-src rust-bindgen clang
88 88
89 89
90Ubuntu90Ubuntu
91******91******
92 92
9325.0493Ubuntu 25.10 and 26.04 LTS provide recent Rust releases and thus they should
94~~~~~
95
96The latest Ubuntu releases provide recent Rust releases and thus they should
97generally work out of the box, e.g.::94generally work out of the box, e.g.::
98 95
99 apt install rustc rust-src bindgen rustfmt rust-clippy96 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
112releases, they require some additional configuration to be set, using109releases, they require some additional configuration to be set, using
113the versioned packages, e.g.::110the versioned packages, e.g.::
114 111
115 apt install rustc-1.80 rust-1.80-src bindgen-0.65 rustfmt-1.80 \112 apt install rustc-1.85 rust-1.85-src bindgen-0.71 rustfmt-1.85 \
116 rust-1.80-clippy113 rust-1.85-clippy
117 ln -s /usr/lib/rust-1.80/bin/rustfmt /usr/bin/rustfmt-1.80114 ln -s /usr/lib/rust-1.85/bin/rustfmt /usr/bin/rustfmt-1.85
118 ln -s /usr/lib/rust-1.80/bin/clippy-driver /usr/bin/clippy-driver-1.80115 ln -s /usr/lib/rust-1.85/bin/clippy-driver /usr/bin/clippy-driver-1.85
119 116
120None of these packages set their tools as defaults; therefore they should be117None of these packages set their tools as defaults; therefore they should be
121specified explicitly, e.g.::118specified explicitly, e.g.::
122 119
123 make LLVM=1 RUSTC=rustc-1.80 RUSTDOC=rustdoc-1.80 RUSTFMT=rustfmt-1.80 \120 make LLVM=1 RUSTC=rustc-1.85 RUSTDOC=rustdoc-1.85 RUSTFMT=rustfmt-1.85 \
124 CLIPPY_DRIVER=clippy-driver-1.80 BINDGEN=bindgen-0.65121 CLIPPY_DRIVER=clippy-driver-1.85 BINDGEN=bindgen-0.71
125 122
126Alternatively, modify the ``PATH`` variable to place the Rust 1.80 binaries123Alternatively, modify the ``PATH`` variable to place the Rust 1.85 binaries
127first and set ``bindgen`` as the default, e.g.::124first and set ``bindgen`` as the default, e.g.::
128 125
129 PATH=/usr/lib/rust-1.80/bin:$PATH126 PATH=/usr/lib/rust-1.85/bin:$PATH
130 update-alternatives --install /usr/bin/bindgen bindgen \127 update-alternatives --install /usr/bin/bindgen bindgen \
131 /usr/bin/bindgen-0.65 100128 /usr/bin/bindgen-0.71 100
132 update-alternatives --set bindgen /usr/bin/bindgen-0.65129 update-alternatives --set bindgen /usr/bin/bindgen-0.71
133 130
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.::
135 132
136 RUST_LIB_SRC=/usr/src/rustc-$(rustc-1.80 --version | cut -d' ' -f2)/library133 RUST_LIB_SRC=/usr/src/rustc-$(rustc-1.85 --version | cut -d' ' -f2)/library
137 134
138For convenience, ``RUST_LIB_SRC`` can be exported to the global environment.135For convenience, ``RUST_LIB_SRC`` can be exported to the global environment.
139 136
140In addition, ``bindgen-0.65`` is available in newer releases (24.04 LTS and137In addition, ``bindgen-0.71`` is available in newer releases (24.04 LTS),
14124.10), but it may not be available in older ones (20.04 LTS and 22.04 LTS),138but it may not be available in older ones (20.04 LTS and 22.04 LTS),
142thus ``bindgen`` may need to be built manually (please see below).139thus ``bindgen`` may need to be built manually (please see below).
143 140
144 141
@@ -355,12 +352,3 @@ Hacking · 210 unmodified lines
355To dive deeper, take a look at the source code of the samples352To dive deeper, take a look at the source code of the samples
356at ``samples/rust/``, the Rust support code under ``rust/`` and353at ``samples/rust/``, the Rust support code under ``rust/`` and
357the ``Rust hacking`` menu under ``Kernel hacking``.354the ``Rust hacking`` menu under ``Kernel hacking``.
358
359If GDB/Binutils is used and Rust symbols are not getting demangled, the reason
360is the toolchain does not support Rust's new v0 mangling scheme yet.
361There 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
23166P: https://rust-for-linux.com/contributing23166P: https://rust-for-linux.com/contributing
23167T: git https://github.com/Rust-for-Linux/linux.git rust-next23167T: git https://github.com/Rust-for-Linux/linux.git rust-next
23168F: .clippy.toml23168F: .clippy.toml
23169F: .rustfmt.toml
23169F: Documentation/rust/23170F: Documentation/rust/
23170F: include/trace/events/rust_sample.h23171F: include/trace/events/rust_sample.h
23171F: rust/23172F: rust/
Makefile+19−2
@@ -487,6 +487,7 @@ export rust_common_flags := --edition=2021 \ · 486 unmodified lines
487 -Wclippy::as_underscore \487 -Wclippy::as_underscore \
488 -Wclippy::cast_lossless \488 -Wclippy::cast_lossless \
489 -Wclippy::ignored_unit_patterns \489 -Wclippy::ignored_unit_patterns \
490 -Aclippy::incompatible_msrv \
490 -Wclippy::mut_mut \491 -Wclippy::mut_mut \
491 -Wclippy::needless_bitwise_bool \492 -Wclippy::needless_bitwise_bool \
492 -Aclippy::needless_lifetimes \493 -Aclippy::needless_lifetimes \
@@ -495,6 +496,7 @@ export rust_common_flags := --edition=2021 \ · 2 unmodified lines
495 -Wclippy::ptr_cast_constness \496 -Wclippy::ptr_cast_constness \
496 -Wclippy::ref_as_ptr \497 -Wclippy::ref_as_ptr \
497 -Wclippy::undocumented_unsafe_blocks \498 -Wclippy::undocumented_unsafe_blocks \
499 -Aclippy::uninlined_format_args \
498 -Wclippy::unnecessary_safety_comment \500 -Wclippy::unnecessary_safety_comment \
499 -Wclippy::unnecessary_safety_doc \501 -Wclippy::unnecessary_safety_doc \
500 -Wrustdoc::missing_crate_level_docs \502 -Wrustdoc::missing_crate_level_docs \
@@ -505,7 +507,7 @@ KBUILD_HOSTCFLAGS := $(KBUILD_USERHOSTCFLAGS) $(HOST_LFS_CFLAGS) \ · 4 unmodified lines
505KBUILD_HOSTCXXFLAGS := -Wall -O2 $(HOST_LFS_CFLAGS) $(HOSTCXXFLAGS) \507KBUILD_HOSTCXXFLAGS := -Wall -O2 $(HOST_LFS_CFLAGS) $(HOSTCXXFLAGS) \
506 -I $(srctree)/scripts/include508 -I $(srctree)/scripts/include
507KBUILD_HOSTRUSTFLAGS := $(rust_common_flags) -O -Cstrip=debuginfo \509KBUILD_HOSTRUSTFLAGS := $(rust_common_flags) -O -Cstrip=debuginfo \
508 -Zallow-features= $(HOSTRUSTFLAGS)510 -Zallow-features=
509KBUILD_HOSTLDFLAGS := $(HOST_LFS_LDFLAGS) $(HOSTLDFLAGS)511KBUILD_HOSTLDFLAGS := $(HOST_LFS_LDFLAGS) $(HOSTLDFLAGS)
510KBUILD_HOSTLDLIBS := $(HOST_LFS_LIBS) $(HOSTLDLIBS)512KBUILD_HOSTLDLIBS := $(HOST_LFS_LIBS) $(HOSTLDLIBS)
511KBUILD_PROCMACROLDFLAGS := $(or $(PROCMACROLDFLAGS),$(KBUILD_HOSTLDFLAGS))513KBUILD_PROCMACROLDFLAGS := $(or $(PROCMACROLDFLAGS),$(KBUILD_HOSTLDFLAGS))
@@ -516,6 +518,7 @@ ifneq ($(LLVM),) · 4 unmodified lines
516CC = $(LLVM_PREFIX)clang$(LLVM_SUFFIX)518CC = $(LLVM_PREFIX)clang$(LLVM_SUFFIX)
517LD = $(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX)519LD = $(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX)
518AR = $(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX)520AR = $(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX)
521LLVM_LINK = $(LLVM_PREFIX)llvm-link$(LLVM_SUFFIX)
519NM = $(LLVM_PREFIX)llvm-nm$(LLVM_SUFFIX)522NM = $(LLVM_PREFIX)llvm-nm$(LLVM_SUFFIX)
520OBJCOPY = $(LLVM_PREFIX)llvm-objcopy$(LLVM_SUFFIX)523OBJCOPY = $(LLVM_PREFIX)llvm-objcopy$(LLVM_SUFFIX)
521OBJDUMP = $(LLVM_PREFIX)llvm-objdump$(LLVM_SUFFIX)524OBJDUMP = $(LLVM_PREFIX)llvm-objdump$(LLVM_SUFFIX)
@@ -629,7 +632,7 @@ export RUSTC_BOOTSTRAP := 1 · 107 unmodified lines
629export CLIPPY_CONF_DIR := $(srctree)632export CLIPPY_CONF_DIR := $(srctree)
630 633
631export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC HOSTPKG_CONFIG634export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC HOSTPKG_CONFIG
632export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN635export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN LLVM_LINK
633export HOSTRUSTC KBUILD_HOSTRUSTFLAGS636export HOSTRUSTC KBUILD_HOSTRUSTFLAGS
634export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL637export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL
635export PERL PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX638export PERL PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
@@ -834,6 +837,20 @@ endif # CONFIG_TRACEPOINTS · 198 unmodified lines
834 837
835export WARN_ON_UNUSED_TRACEPOINTS838export WARN_ON_UNUSED_TRACEPOINTS
836 839
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.
847rust_common_flags_per_version := \
848 $(if $(call rustc-min-version,108600),,-Aclippy::precedence)
849
850rust_common_flags += $(rust_common_flags_per_version)
851KBUILD_HOSTRUSTFLAGS += $(rust_common_flags_per_version) $(HOSTRUSTFLAGS)
852KBUILD_RUSTFLAGS += $(rust_common_flags_per_version)
853
837include $(srctree)/arch/$(SRCARCH)/Makefile854include $(srctree)/arch/$(SRCARCH)/Makefile
838 855
839ifdef need-config856ifdef need-config
arch/Kconfig+1−2
@@ -968,10 +968,9 @@ config HAVE_CFI_ICALL_NORMALIZE_INTEGERS · 967 unmodified lines
968config HAVE_CFI_ICALL_NORMALIZE_INTEGERS_RUSTC968config HAVE_CFI_ICALL_NORMALIZE_INTEGERS_RUSTC
969 def_bool y969 def_bool y
970 depends on HAVE_CFI_ICALL_NORMALIZE_INTEGERS970 depends on HAVE_CFI_ICALL_NORMALIZE_INTEGERS
971 depends on RUSTC_VERSION >= 107900
972 depends on ARM64 || X86_64971 depends on ARM64 || X86_64
973 # With GCOV/KASAN we need this fix: https://github.com/rust-lang/rust/pull/129373972 # With GCOV/KASAN we need this fix: https://github.com/rust-lang/rust/pull/129373
974 depends on (RUSTC_LLVM_VERSION >= 190103 && RUSTC_VERSION >= 108200) || \973 depends on RUSTC_LLVM_VERSION >= 190103 || \
975 (!GCOV_KERNEL && !KASAN_GENERIC && !KASAN_SW_TAGS)974 (!GCOV_KERNEL && !KASAN_GENERIC && !KASAN_SW_TAGS)
976 975
977config CFI_PERMISSIVE976config CFI_PERMISSIVE
arch/arm64/Kconfig+0−8
@@ -292,14 +292,6 @@ config ARM64 · 291 unmodified lines
292config RUSTC_SUPPORTS_ARM64292config RUSTC_SUPPORTS_ARM64
293 def_bool y293 def_bool y
294 depends on CPU_LITTLE_ENDIAN294 depends on CPU_LITTLE_ENDIAN
295 # Shadow call stack is only supported on certain rustc versions.
296 #
297 # When using the UNWIND_PATCH_PAC_INTO_SCS option, rustc version 1.80+ is
298 # required due to use of the -Zfixed-x18 flag.
299 #
300 # Otherwise, rustc version 1.82+ is required due to use of the
301 # -Zsanitizer=shadow-call-stack flag.
302 depends on !SHADOW_CALL_STACK || RUSTC_VERSION >= 108200 || RUSTC_VERSION >= 108000 && UNWIND_PATCH_PAC_INTO_SCS
303 295
304config CLANG_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS296config CLANG_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS
305 def_bool CC_IS_CLANG297 def_bool CC_IS_CLANG
arch/riscv/Kconfig+0−3
@@ -232,9 +232,6 @@ config RISCV · 231 unmodified lines
232config RUSTC_SUPPORTS_RISCV232config RUSTC_SUPPORTS_RISCV
233 def_bool y233 def_bool y
234 depends on 64BIT234 depends on 64BIT
235 # Shadow call stack requires rustc version 1.82+ due to use of the
236 # -Zsanitizer=shadow-call-stack flag.
237 depends on !SHADOW_CALL_STACK || RUSTC_VERSION >= 108200
238 235
239config CLANG_SUPPORTS_DYNAMIC_FTRACE236config CLANG_SUPPORTS_DYNAMIC_FTRACE
240 def_bool CC_IS_CLANG237 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
5rust_binder-y := \5rust_binder-y := \
6 rust_binder_main.o \6 rust_binder_main.o \
7 rust_binderfs.o \7 rust_binderfs.o \
8 rust_binder_events.o \8 rust_binder_events.o
9 page_range_helper.o
drivers/android/binder/page_range.rs+3−3
@@ -683,15 +683,15 @@ unsafe extern "C" fn rust_shrink_scan( · 682 unmodified lines
683 unsafe {683 unsafe {
684 bindings::list_lru_walk(684 bindings::list_lru_walk(
685 list_lru,685 list_lru,
686 Some(bindings::rust_shrink_free_page_wrap),686 Some(rust_shrink_free_page),
687 ptr::null_mut(),687 ptr::null_mut(),
688 nr_to_scan,688 nr_to_scan,
689 )689 )
690 }690 }
691}691}
692 692
693const LRU_SKIP: bindings::lru_status = bindings::lru_status_LRU_SKIP;693const LRU_SKIP: bindings::lru_status = bindings::lru_status::LRU_SKIP;
694const LRU_REMOVED_ENTRY: bindings::lru_status = bindings::lru_status_LRU_REMOVED_RETRY;694const LRU_REMOVED_ENTRY: bindings::lru_status = bindings::lru_status::LRU_REMOVED_RETRY;
695 695
696/// # Safety696/// # Safety
697/// Called by the shrinker.697/// 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
15unsigned int rust_shrink_free_page(struct list_head *item,
16 struct list_lru_one *list,
17 void *cb_arg);
18
19enum lru_status
20rust_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
11enum lru_status
12rust_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
3// Copyright (C) 2025 Google LLC.3// Copyright (C) 2025 Google LLC.
4 4
5//! Binder -- the Android IPC mechanism.5//! Binder -- the Android IPC mechanism.
6
7#![crate_name = "rust_binder"]
6#![recursion_limit = "256"]8#![recursion_limit = "256"]
7#![allow(9#![allow(
8 clippy::as_underscore,10 clippy::as_underscore,
drivers/gpu/drm/tyr/driver.rs+0−12
@@ -53,18 +53,6 @@ pub(crate) struct TyrData { · 52 unmodified lines
53 pub(crate) gpu_info: GpuInfo,53 pub(crate) gpu_info: GpuInfo,
54}54}
55 55
56// Both `Clk` and `Regulator` do not implement `Send` or `Sync`, but they
57// should. There are patches on the mailing list to address this, but they have
58// not landed yet.
59//
60// For now, add this workaround so that this patch compiles with the promise
61// that it will be removed in a future patch.
62//
63// SAFETY: This will be removed in a future patch.
64unsafe impl Send for TyrData {}
65// SAFETY: This will be removed in a future patch.
66unsafe impl Sync for TyrData {}
67
68fn issue_soft_reset(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result {56fn issue_soft_reset(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result {
69 regs::GPU_CMD.write(dev, iomem, regs::GPU_CMD_SOFT_RESET)?;57 regs::GPU_CMD.write(dev, iomem, regs::GPU_CMD_SOFT_RESET)?;
70 58
drivers/gpu/nova-core/gsp/cmdq.rs+1−5
@@ -293,7 +293,6 @@ impl DmaGspMem { · 292 unmodified lines
293 let (slice_1, slice_2) = {293 let (slice_1, slice_2) = {
294 let (slice_1, slice_2) = self.driver_write_area();294 let (slice_1, slice_2) = self.driver_write_area();
295 295
296 #[allow(clippy::incompatible_msrv)]
297 (slice_1.as_flattened_mut(), slice_2.as_flattened_mut())296 (slice_1.as_flattened_mut(), slice_2.as_flattened_mut())
298 };297 };
299 298
@@ -545,10 +544,7 @@ impl Cmdq { · 245 unmodified lines
545 Delta::from_millis(1),544 Delta::from_millis(1),
546 timeout,545 timeout,
547 )546 )
548 .map(|(slice_1, slice_2)| {547 .map(|(slice_1, slice_2)| (slice_1.as_flattened(), slice_2.as_flattened()))?;
549 #[allow(clippy::incompatible_msrv)]
550 (slice_1.as_flattened(), slice_2.as_flattened())
551 })?;
552 548
553 // Extract the `GspMsgElement`.549 // Extract the `GspMsgElement`.
554 let (header, slice_1) = GspMsgElement::from_bytes_prefix(slice_1).ok_or(EIO)?;550 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
7//! This module may not be directly used. Please abstract or re-export the needed symbols in the7//! This module may not be directly used. Please abstract or re-export the needed symbols in the
8//! parent module instead.8//! parent module instead.
9 9
10#![cfg_attr(test, allow(deref_nullptr))]
11#![cfg_attr(test, allow(unaligned_references))]
12#![cfg_attr(test, allow(unsafe_op_in_unsafe_fn))]
13#![allow(10#![allow(
14 dead_code,11 dead_code,
15 clippy::all,12 clippy::all,
drivers/pwm/pwm_th1520.rs+0−15
@@ -99,21 +99,6 @@ struct Th1520PwmDriverData { · 98 unmodified lines
99 clk: Clk,99 clk: Clk,
100}100}
101 101
102// This `unsafe` implementation is a temporary necessity because the underlying `kernel::clk::Clk`
103// type does not yet expose `Send` and `Sync` implementations. This block should be removed
104// as soon as the clock abstraction provides these guarantees directly.
105// TODO: Remove those unsafe impl's when Clk will support them itself.
106
107// SAFETY: The `devres` framework requires the driver's private data to be `Send` and `Sync`.
108// We can guarantee this because the PWM core synchronizes all callbacks, preventing concurrent
109// access to the contained `iomem` and `clk` resources.
110unsafe 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.
115unsafe impl Sync for Th1520PwmDriverData {}
116
117impl pwm::PwmOps for Th1520PwmDriverData {102impl pwm::PwmOps for Th1520PwmDriverData {
118 type WfHw = Th1520WfHw;103 type WfHw = Th1520WfHw;
119 104
init/Kconfig+16−14
@@ -82,6 +82,21 @@ config RUSTC_LLVM_VERSION · 81 unmodified lines
82 int82 int
83 default $(rustc-llvm-version)83 default $(rustc-llvm-version)
84 84
85config RUSTC_LLVM_MAJOR_VERSION
86 int
87 default $(shell,expr $(rustc-llvm-version) / 10000)
88
89config 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
85config ARCH_HAS_CC_CAN_LINK100config ARCH_HAS_CC_CAN_LINK
86 bool101 bool
87 102
@@ -163,12 +178,6 @@ config LD_CAN_USE_KEEP_IN_OVERLAY · 75 unmodified lines
163 # https://github.com/llvm/llvm-project/pull/130661178 # https://github.com/llvm/llvm-project/pull/130661
164 def_bool LD_IS_BFD || LLD_VERSION >= 210000179 def_bool LD_IS_BFD || LLD_VERSION >= 210000
165 180
166config RUSTC_HAS_SLICE_AS_FLATTENED
167 def_bool RUSTC_VERSION >= 108000
168
169config RUSTC_HAS_COERCE_POINTEE
170 def_bool RUSTC_VERSION >= 108400
171
172config RUSTC_HAS_SPAN_FILE181config RUSTC_HAS_SPAN_FILE
173 def_bool RUSTC_VERSION >= 108800182 def_bool RUSTC_VERSION >= 108800
174 183
@@ -2178,9 +2187,7 @@ config RUST · 2003 unmodified lines
2178 depends on !DEBUG_INFO_BTF || (PAHOLE_HAS_LANG_EXCLUDE && !LTO)2187 depends on !DEBUG_INFO_BTF || (PAHOLE_HAS_LANG_EXCLUDE && !LTO)
2179 depends on !CFI || HAVE_CFI_ICALL_NORMALIZE_INTEGERS_RUSTC2188 depends on !CFI || HAVE_CFI_ICALL_NORMALIZE_INTEGERS_RUSTC
2180 select CFI_ICALL_NORMALIZE_INTEGERS if CFI2189 select CFI_ICALL_NORMALIZE_INTEGERS if CFI
2181 depends on !CALL_PADDING || RUSTC_VERSION >= 108100
2182 depends on !KASAN_SW_TAGS2190 depends on !KASAN_SW_TAGS
2183 depends on !(MITIGATION_RETHUNK && KASAN) || RUSTC_VERSION >= 108300
2184 help2191 help
2185 Enables Rust support in the kernel.2192 Enables Rust support in the kernel.
2186 2193
@@ -2204,12 +2211,7 @@ config RUSTC_VERSION_TEXT · 17 unmodified lines
2204config BINDGEN_VERSION_TEXT2211config BINDGEN_VERSION_TEXT
2205 string2212 string
2206 depends on RUST2213 depends on RUST
2207 # The dummy parameter `workaround-for-0.69.0` is required to support 0.69.02214 default "$(shell,$(BINDGEN) --version 2>/dev/null)"
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)"
2213 2215
2214#2216#
2215# Place an empty function call at each tracepoint site. Can be2217# 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
3577 3577
3578 If unsure, say N.3578 If unsure, say N.
3579 3579
3580config 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
3580endmenu # "Rust"3597endmenu # "Rust"
3581 3598
3582endmenu # Kernel hacking3599endmenu # Kernel hacking
rust/Makefile+36−33
@@ -6,15 +6,19 @@ rustdoc_output := $(objtree)/Documentation/output/rust/rustdoc · 5 unmodified lines
6obj-$(CONFIG_RUST) += core.o compiler_builtins.o ffi.o6obj-$(CONFIG_RUST) += core.o compiler_builtins.o ffi.o
7always-$(CONFIG_RUST) += exports_core_generated.h7always-$(CONFIG_RUST) += exports_core_generated.h
8 8
9ifdef CONFIG_RUST_INLINE_HELPERS
10always-$(CONFIG_RUST) += helpers/helpers.bc helpers/helpers_module.bc
11else
12obj-$(CONFIG_RUST) += helpers/helpers.o
13always-$(CONFIG_RUST) += exports_helpers_generated.h
14endif
9# Missing prototypes are expected in the helpers since these are exported15# Missing prototypes are expected in the helpers since these are exported
10# for Rust only, thus there is no header nor prototypes.16# for Rust only, thus there is no header nor prototypes.
11obj-$(CONFIG_RUST) += helpers/helpers.o
12CFLAGS_REMOVE_helpers/helpers.o = -Wmissing-prototypes -Wmissing-declarations17CFLAGS_REMOVE_helpers/helpers.o = -Wmissing-prototypes -Wmissing-declarations
13 18
14always-$(CONFIG_RUST) += bindings/bindings_generated.rs bindings/bindings_helpers_generated.rs19always-$(CONFIG_RUST) += bindings/bindings_generated.rs bindings/bindings_helpers_generated.rs
15obj-$(CONFIG_RUST) += bindings.o pin_init.o kernel.o20obj-$(CONFIG_RUST) += bindings.o pin_init.o kernel.o
16always-$(CONFIG_RUST) += exports_helpers_generated.h \21always-$(CONFIG_RUST) += exports_bindings_generated.h exports_kernel_generated.h
17 exports_bindings_generated.h exports_kernel_generated.h
18 22
19always-$(CONFIG_RUST) += uapi/uapi_generated.rs23always-$(CONFIG_RUST) += uapi/uapi_generated.rs
20obj-$(CONFIG_RUST) += uapi.o24obj-$(CONFIG_RUST) += uapi.o
@@ -71,8 +75,7 @@ core-edition := $(if $(call rustc-min-version,108700),2024,2021) · 50 unmodified lines
71 75
72core-skip_flags := \76core-skip_flags := \
73 --edition=2021 \77 --edition=2021 \
74 -Wunreachable_pub \78 -Wunreachable_pub
75 -Wrustdoc::unescaped_backticks
76 79
77core-flags := \80core-flags := \
78 --edition=$(core-edition) \81 --edition=$(core-edition) \
@@ -83,10 +86,8 @@ proc_macro2-cfgs := \ · 4 unmodified lines
83 wrap_proc_macro \86 wrap_proc_macro \
84 $(if $(call rustc-min-version,108800),proc_macro_span_file proc_macro_span_location)87 $(if $(call rustc-min-version,108800),proc_macro_span_file proc_macro_span_location)
85 88
86# Stable since Rust 1.79.0: `feature(proc_macro_byte_character,proc_macro_c_str_literals)`.
87proc_macro2-flags := \89proc_macro2-flags := \
88 --cap-lints=allow \90 --cap-lints=allow \
89 -Zcrate-attr='feature(proc_macro_byte_character,proc_macro_c_str_literals)' \
90 $(call cfgs-to-flags,$(proc_macro2-cfgs))91 $(call cfgs-to-flags,$(proc_macro2-cfgs))
91 92
92quote-cfgs := \93quote-cfgs := \
@@ -118,7 +119,7 @@ syn-flags := \ · 25 unmodified lines
118 $(call cfgs-to-flags,$(syn-cfgs))119 $(call cfgs-to-flags,$(syn-cfgs))
119 120
120pin_init_internal-cfgs := \121pin_init_internal-cfgs := \
121 kernel122 kernel USE_RUSTC_FEATURES
122 123
123pin_init_internal-flags := \124pin_init_internal-flags := \
124 --extern proc_macro2 \125 --extern proc_macro2 \
@@ -127,7 +128,7 @@ pin_init_internal-flags := \ · 2 unmodified lines
127 $(call cfgs-to-flags,$(pin_init_internal-cfgs))128 $(call cfgs-to-flags,$(pin_init_internal-cfgs))
128 129
129pin_init-cfgs := \130pin_init-cfgs := \
130 kernel131 kernel USE_RUSTC_FEATURES
131 132
132pin_init-flags := \133pin_init-flags := \
133 --extern pin_init_internal \134 --extern pin_init_internal \
@@ -141,15 +142,10 @@ rustdoc_modifiers_workaround := $(if $(call rustc-min-version,108800),-Cunsafe-a · 7 unmodified lines
141# Similarly, for doctests (https://github.com/rust-lang/rust/issues/146465).142# Similarly, for doctests (https://github.com/rust-lang/rust/issues/146465).
142doctests_modifiers_workaround := $(rustdoc_modifiers_workaround)$(if $(call rustc-min-version,109100),$(comma)sanitizer)143doctests_modifiers_workaround := $(rustdoc_modifiers_workaround)$(if $(call rustc-min-version,109100),$(comma)sanitizer)
143 144
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`.
148quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $<145quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $<
149 cmd_rustdoc = \146 cmd_rustdoc = \
150 OBJTREE=$(abspath $(objtree)) \147 OBJTREE=$(abspath $(objtree)) \
151 $(RUSTDOC) $(filter-out $(skip_flags) --remap-path-prefix=% --remap-path-scope=%, \148 $(RUSTDOC) $(filter-out $(skip_flags) --remap-path-scope=%,$(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \
152 $(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \
153 $(rustc_target_flags) -L$(objtree)/$(obj) \149 $(rustc_target_flags) -L$(objtree)/$(obj) \
154 -Zunstable-options --generate-link-to-definition \150 -Zunstable-options --generate-link-to-definition \
155 --output $(rustdoc_output) \151 --output $(rustdoc_output) \
@@ -210,8 +206,6 @@ rustdoc-macros: $(src)/macros/lib.rs rustdoc-clean rustdoc-proc_macro2 \ · 54 unmodified lines
210 rustdoc-quote rustdoc-syn FORCE206 rustdoc-quote rustdoc-syn FORCE
211 +$(call if_changed,rustdoc)207 +$(call if_changed,rustdoc)
212 208
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.
215rustdoc-core: private skip_flags = $(core-skip_flags)209rustdoc-core: private skip_flags = $(core-skip_flags)
216rustdoc-core: private rustc_target_flags = $(core-flags)210rustdoc-core: private rustc_target_flags = $(core-flags)
217rustdoc-core: $(RUST_LIB_SRC)/core/src/lib.rs rustdoc-clean FORCE211rustdoc-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
335 rm -rf $(objtree)/$(obj)/test/doctests/kernel; \329 rm -rf $(objtree)/$(obj)/test/doctests/kernel; \
336 mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \330 mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \
337 OBJTREE=$(abspath $(objtree)) \331 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)) \
339 -L$(objtree)/$(obj) --extern ffi --extern pin_init \333 -L$(objtree)/$(obj) --extern ffi --extern pin_init \
340 --extern kernel --extern build_error --extern macros \334 --extern kernel --extern build_error --extern macros \
341 --extern bindings --extern uapi \335 --extern bindings --extern uapi \
@@ -447,22 +441,10 @@ endif · 105 unmodified lines
447# architecture instead of generating `usize`.441# architecture instead of generating `usize`.
448bindgen_c_flags_final = $(bindgen_c_flags_lto) -fno-builtin -D__BINDGEN__442bindgen_c_flags_final = $(bindgen_c_flags_lto) -fno-builtin -D__BINDGEN__
449 443
450# Each `bindgen` release may upgrade the list of Rust target versions. By444# `--rust-target` points to our minimum supported Rust version.
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.
463quiet_cmd_bindgen = BINDGEN $@445quiet_cmd_bindgen = BINDGEN $@
464 cmd_bindgen = \446 cmd_bindgen = \
465 $(BINDGEN) $< $(bindgen_target_flags) --rust-target 1.68 \447 $(BINDGEN) $< $(bindgen_target_flags) --rust-target 1.85 \
466 --use-core --with-derive-default --ctypes-prefix ffi --no-layout-tests \448 --use-core --with-derive-default --ctypes-prefix ffi --no-layout-tests \
467 --no-debug '.*' --enable-function-attribute-detection \449 --no-debug '.*' --enable-function-attribute-detection \
468 -o $@ -- $(bindgen_c_flags_final) -DMODULE \450 -o $@ -- $(bindgen_c_flags_final) -DMODULE \
@@ -496,6 +478,16 @@ $(obj)/bindings/bindings_helpers_generated.rs: private bindgen_target_extra = ; · 27 unmodified lines
496$(obj)/bindings/bindings_helpers_generated.rs: $(src)/helpers/helpers.c FORCE478$(obj)/bindings/bindings_helpers_generated.rs: $(src)/helpers/helpers.c FORCE
497 $(call if_changed_dep,bindgen)479 $(call if_changed_dep,bindgen)
498 480
481quiet_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
499rust_exports = $(NM) -p --defined-only $(1) | awk '$$2~/(T|R|D|B)/ && $$3!~/__(pfx|cfi|odr_asan)/ { printf $(2),$$3 }'491rust_exports = $(NM) -p --defined-only $(1) | awk '$$2~/(T|R|D|B)/ && $$3!~/__(pfx|cfi|odr_asan)/ { printf $(2),$$3 }'
500 492
501quiet_cmd_exports = EXPORTS $@493quiet_cmd_exports = EXPORTS $@
@@ -576,12 +568,16 @@ quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L · 74 unmodified lines
576 OBJTREE=$(abspath $(objtree)) \568 OBJTREE=$(abspath $(objtree)) \
577 $(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \569 $(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \
578 $(filter-out $(skip_flags),$(rust_flags)) $(rustc_target_flags) \570 $(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=$@) \
580 --emit=metadata=$(dir $@)$(patsubst %.o,lib%.rmeta,$(notdir $@)) \572 --emit=metadata=$(dir $@)$(patsubst %.o,lib%.rmeta,$(notdir $@)) \
581 --crate-type rlib -L$(objtree)/$(obj) \573 --crate-type rlib -L$(objtree)/$(obj) \
582 --crate-name $(patsubst %.o,%,$(notdir $@)) $< \574 --crate-name $(patsubst %.o,%,$(notdir $@)) $< \
583 --sysroot=/dev/null \575 --sysroot=/dev/null \
584 -Zunstable-options \576 -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)) \
585 $(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@) \581 $(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@) \
586 $(cmd_objtool)582 $(cmd_objtool)
587 583
@@ -591,6 +587,8 @@ rust-analyzer: · 3 unmodified lines
591 --cfgs='proc_macro2=$(proc_macro2-cfgs)' \587 --cfgs='proc_macro2=$(proc_macro2-cfgs)' \
592 --cfgs='quote=$(quote-cfgs)' \588 --cfgs='quote=$(quote-cfgs)' \
593 --cfgs='syn=$(syn-cfgs)' \589 --cfgs='syn=$(syn-cfgs)' \
590 --cfgs='pin_init_internal=$(pin_init_internal-cfgs)' \
591 --cfgs='pin_init=$(pin_init-cfgs)' \
594 $(realpath $(srctree)) $(realpath $(objtree)) \592 $(realpath $(srctree)) $(realpath $(objtree)) \
595 $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \593 $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \
596 > rust-project.json594 > rust-project.json
@@ -711,4 +709,9 @@ $(obj)/kernel.o: $(obj)/kernel/generated_arch_warn_asm.rs $(obj)/kernel/generate · 114 unmodified lines
711endif709endif
712endif710endif
713 711
712ifdef CONFIG_RUST_INLINE_HELPERS
713$(obj)/kernel.o: private link_helper = 1
714$(obj)/kernel.o: $(obj)/helpers/helpers.bc
715endif
716
714endif # CONFIG_RUST717endif # CONFIG_RUST
rust/bindgen_parameters+4−4
@@ -15,14 +15,14 @@ · 14 unmodified lines
15--opaque-type x86_msi_data15--opaque-type x86_msi_data
16--opaque-type x86_msi_addr_lo16--opaque-type x86_msi_addr_lo
17 17
18# `try` is a reserved keyword since Rust 2018; solved in `bindgen` v0.59.2,
19# commit 2aed6b021680 ("context: Escape the try keyword properly").
20--opaque-type kunit_try_catch
21
22# If SMP is disabled, `arch_spinlock_t` is defined as a ZST which triggers a Rust18# If SMP is disabled, `arch_spinlock_t` is defined as a ZST which triggers a Rust
23# warning. We don't need to peek into it anyway.19# warning. We don't need to peek into it anyway.
24--opaque-type spinlock20--opaque-type spinlock
25 21
22# enums that appear in indirect function calls should specify a cfi type
23--newtype-enum lru_status
24--with-attribute-custom-enum=lru_status='#[cfi_encoding="10lru_status"]'
25
26# `seccomp`'s comment gets understood as a doctest26# `seccomp`'s comment gets understood as a doctest
27--no-doc-comments27--no-doc-comments
28 28
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
149#if IS_ENABLED(CONFIG_ANDROID_BINDER_IPC_RUST)149#if IS_ENABLED(CONFIG_ANDROID_BINDER_IPC_RUST)
150#include "../../drivers/android/binder/rust_binder.h"150#include "../../drivers/android/binder/rust_binder.h"
151#include "../../drivers/android/binder/rust_binder_events.h"151#include "../../drivers/android/binder/rust_binder_events.h"
152#include "../../drivers/android/binder/page_range_helper.h"
153#endif152#endif
rust/bindings/lib.rs+1−4
@@ -9,10 +9,6 @@ · 8 unmodified lines
9//! using this crate.9//! using this crate.
10 10
11#![no_std]11#![no_std]
12// See <https://github.com/rust-lang/rust-bindgen/issues/1651>.
13#![cfg_attr(test, allow(deref_nullptr))]
14#![cfg_attr(test, allow(unaligned_references))]
15#![cfg_attr(test, allow(unsafe_op_in_unsafe_fn))]
16#![allow(12#![allow(
17 clippy::all,13 clippy::all,
18 missing_docs,14 missing_docs,
@@ -23,6 +19,7 @@ · 4 unmodified lines
23 unreachable_pub,19 unreachable_pub,
24 unsafe_op_in_unsafe_fn20 unsafe_op_in_unsafe_fn
25)]21)]
22#![feature(cfi_encoding)]
26 23
27#[allow(dead_code)]24#[allow(dead_code)]
28#[allow(clippy::cast_lossless)]25#[allow(clippy::cast_lossless)]
rust/exports.c+4−1
@@ -16,10 +16,13 @@ · 15 unmodified lines
16#define EXPORT_SYMBOL_RUST_GPL(sym) extern int sym; EXPORT_SYMBOL_GPL(sym)16#define EXPORT_SYMBOL_RUST_GPL(sym) extern int sym; EXPORT_SYMBOL_GPL(sym)
17 17
18#include "exports_core_generated.h"18#include "exports_core_generated.h"
19#include "exports_helpers_generated.h"
20#include "exports_bindings_generated.h"19#include "exports_bindings_generated.h"
21#include "exports_kernel_generated.h"20#include "exports_kernel_generated.h"
22 21
22#ifndef CONFIG_RUST_INLINE_HELPERS
23#include "exports_helpers_generated.h"
24#endif
25
23// For modules using `rust/build_error.rs`.26// For modules using `rust/build_error.rs`.
24#ifdef CONFIG_RUST_BUILD_ASSERT_ALLOW27#ifdef CONFIG_RUST_BUILD_ASSERT_ALLOW
25EXPORT_SYMBOL_RUST_GPL(rust_build_error);28EXPORT_SYMBOL_RUST_GPL(rust_build_error);
rust/helpers/clk.c+13−11
@@ -7,60 +7,62 @@ · 6 unmodified lines
7 * CONFIG_HAVE_CLK or CONFIG_HAVE_CLK_PREPARE aren't set.7 * CONFIG_HAVE_CLK or CONFIG_HAVE_CLK_PREPARE aren't set.
8 */8 */
9#ifndef CONFIG_HAVE_CLK9#ifndef CONFIG_HAVE_CLK
10struct clk *rust_helper_clk_get(struct device *dev, const char *id)10__rust_helper struct clk *rust_helper_clk_get(struct device *dev,
11 const char *id)
11{12{
12 return clk_get(dev, id);13 return clk_get(dev, id);
13}14}
14 15
15void rust_helper_clk_put(struct clk *clk)16__rust_helper void rust_helper_clk_put(struct clk *clk)
16{17{
17 clk_put(clk);18 clk_put(clk);
18}19}
19 20
20int rust_helper_clk_enable(struct clk *clk)21__rust_helper int rust_helper_clk_enable(struct clk *clk)
21{22{
22 return clk_enable(clk);23 return clk_enable(clk);
23}24}
24 25
25void rust_helper_clk_disable(struct clk *clk)26__rust_helper void rust_helper_clk_disable(struct clk *clk)
26{27{
27 clk_disable(clk);28 clk_disable(clk);
28}29}
29 30
30unsigned long rust_helper_clk_get_rate(struct clk *clk)31__rust_helper unsigned long rust_helper_clk_get_rate(struct clk *clk)
31{32{
32 return clk_get_rate(clk);33 return clk_get_rate(clk);
33}34}
34 35
35int rust_helper_clk_set_rate(struct clk *clk, unsigned long rate)36__rust_helper int rust_helper_clk_set_rate(struct clk *clk, unsigned long rate)
36{37{
37 return clk_set_rate(clk, rate);38 return clk_set_rate(clk, rate);
38}39}
39#endif40#endif
40 41
41#ifndef CONFIG_HAVE_CLK_PREPARE42#ifndef CONFIG_HAVE_CLK_PREPARE
42int rust_helper_clk_prepare(struct clk *clk)43__rust_helper int rust_helper_clk_prepare(struct clk *clk)
43{44{
44 return clk_prepare(clk);45 return clk_prepare(clk);
45}46}
46 47
47void rust_helper_clk_unprepare(struct clk *clk)48__rust_helper void rust_helper_clk_unprepare(struct clk *clk)
48{49{
49 clk_unprepare(clk);50 clk_unprepare(clk);
50}51}
51#endif52#endif
52 53
53struct clk *rust_helper_clk_get_optional(struct device *dev, const char *id)54__rust_helper struct clk *rust_helper_clk_get_optional(struct device *dev,
55 const char *id)
54{56{
55 return clk_get_optional(dev, id);57 return clk_get_optional(dev, id);
56}58}
57 59
58int rust_helper_clk_prepare_enable(struct clk *clk)60__rust_helper int rust_helper_clk_prepare_enable(struct clk *clk)
59{61{
60 return clk_prepare_enable(clk);62 return clk_prepare_enable(clk);
61}63}
62 64
63void rust_helper_clk_disable_unprepare(struct clk *clk)65__rust_helper void rust_helper_clk_disable_unprepare(struct clk *clk)
64{66{
65 clk_disable_unprepare(clk);67 clk_disable_unprepare(clk);
66}68}
rust/helpers/helpers.c+29−0
@@ -7,7 +7,36 @@ · 6 unmodified lines
7 * Sorted alphabetically.7 * Sorted alphabetically.
8 */8 */
9 9
10#include <linux/compiler_types.h>
11
12#ifdef __BINDGEN__
13// Omit `inline` for bindgen as it ignores inline functions.
10#define __rust_helper14#define __rust_helper
15#else
16// The helper functions are all inline functions.
17//
18// We use `__always_inline` here to bypass LLVM inlining checks, in case the
19// helpers are inlined directly into Rust CGUs.
20//
21// The LLVM inlining checks are false positives:
22// * LLVM doesn't want to inline functions compiled with
23// `-fno-delete-null-pointer-checks` with code compiled without.
24// The C CGUs all have this enabled and Rust CGUs don't. Inlining is okay
25// since this is one of the hardening features that does not change the ABI,
26// and we shouldn't have null pointer dereferences in these helpers.
27// * LLVM doesn't want to inline functions with different list of builtins. C
28// side has `-fno-builtin-wcslen`; `wcslen` is not a Rust builtin, so they
29// should be compatible, but LLVM does not perform inlining due to attributes
30// mismatch.
31// * clang and Rust doesn't have the exact target string. Clang generates
32// `+cmov,+cx8,+fxsr` but Rust doesn't enable them (in fact, Rust will
33// complain if `-Ctarget-feature=+cmov,+cx8,+fxsr` is used). x86-64 always
34// enable these features, so they are in fact the same target string, but
35// LLVM doesn't understand this and so inlining is inhibited. This can be
36// bypassed with `--ignore-tti-inline-compatible`, but this is a hidden
37// option.
38#define __rust_helper __always_inline
39#endif
11 40
12#include "atomic.c"41#include "atomic.c"
13#include "atomic_ext.c"42#include "atomic_ext.c"
rust/helpers/jump_label.c+1−1
@@ -7,7 +7,7 @@ · 6 unmodified lines
7#include <linux/jump_label.h>7#include <linux/jump_label.h>
8 8
9#ifndef CONFIG_JUMP_LABEL9#ifndef CONFIG_JUMP_LABEL
10int rust_helper_static_key_count(struct static_key *key)10__rust_helper int rust_helper_static_key_count(struct static_key *key)
11{11{
12 return static_key_count(key);12 return static_key_count(key);
13}13}
rust/kernel/alloc/allocator/iter.rs+1−7
@@ -42,15 +42,9 @@ impl<'a> Iterator for VmallocPageIter<'a> { · 41 unmodified lines
42 return None;42 return None;
43 }43 }
44 44
45 // TODO: Use `NonNull::add()` instead, once the minimum supported compiler version is
46 // bumped to 1.80 or later.
47 //
48 // SAFETY: `offset` is in the interval `[0, (self.page_count() - 1) * page::PAGE_SIZE]`,45 // SAFETY: `offset` is in the interval `[0, (self.page_count() - 1) * page::PAGE_SIZE]`,
49 // hence the resulting pointer is guaranteed to be within the same allocation.46 // hence the resulting pointer is guaranteed to be within the same allocation.
50 let ptr = unsafe { self.buf.as_ptr().add(offset) };47 let ptr = unsafe { self.buf.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) };
54 48
55 // SAFETY:49 // SAFETY:
56 // - `ptr` is a valid pointer to a `Vmalloc` allocation.50 // - `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
77/// `self.0` is always properly aligned and either points to memory allocated with `A` or, for77/// `self.0` is always properly aligned and either points to memory allocated with `A` or, for
78/// zero-sized types, is a dangling, well aligned pointer.78/// zero-sized types, is a dangling, well aligned pointer.
79#[repr(transparent)]79#[repr(transparent)]
80#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))]80#[derive(core::marker::CoercePointee)]
81pub struct Box<#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, pointee)] T: ?Sized, A: Allocator>(81pub struct Box<#[pointee] T: ?Sized, A: Allocator>(NonNull<T>, PhantomData<A>);
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))]
89impl<T, U, A> core::ops::CoerceUnsized<Box<U, A>> for Box<T, A>
90where
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))]
100impl<T, U, A> core::ops::DispatchFromDyn<Box<U, A>> for Box<T, A>
101where
102 T: ?Sized + core::marker::Unsize<U>,
103 U: ?Sized,
104 A: Allocator,
105{
106}
107 82
108/// Type alias for [`Box`] with a [`Kmalloc`] allocator.83/// Type alias for [`Box`] with a [`Kmalloc`] allocator.
109///84///
rust/kernel/alloc/kvec/errors.rs+3−0
@@ -15,6 +15,7 @@ impl<T> fmt::Debug for PushError<T> { · 14 unmodified lines
15}15}
16 16
17impl<T> From<PushError<T>> for Error {17impl<T> From<PushError<T>> for Error {
18 #[inline]
18 fn from(_: PushError<T>) -> Error {19 fn from(_: PushError<T>) -> Error {
19 // Returning ENOMEM isn't appropriate because the system is not out of memory. The vector20 // Returning ENOMEM isn't appropriate because the system is not out of memory. The vector
20 // is just full and we are refusing to resize it.21 // is just full and we are refusing to resize it.
@@ -32,6 +33,7 @@ impl fmt::Debug for RemoveError { · 11 unmodified lines
32}33}
33 34
34impl From<RemoveError> for Error {35impl From<RemoveError> for Error {
36 #[inline]
35 fn from(_: RemoveError) -> Error {37 fn from(_: RemoveError) -> Error {
36 EINVAL38 EINVAL
37 }39 }
@@ -55,6 +57,7 @@ impl<T> fmt::Debug for InsertError<T> { · 17 unmodified lines
55}57}
56 58
57impl<T> From<InsertError<T>> for Error {59impl<T> From<InsertError<T>> for Error {
60 #[inline]
58 fn from(_: InsertError<T>) -> Error {61 fn from(_: InsertError<T>) -> Error {
59 EINVAL62 EINVAL
60 }63 }
rust/kernel/block/mq/gen_disk.rs+1−3
@@ -140,9 +140,7 @@ impl GenDiskBuilder { · 139 unmodified lines
140 devnode: None,140 devnode: None,
141 alternative_gpt_sector: None,141 alternative_gpt_sector: None,
142 get_unique_id: None,142 get_unique_id: None,
143 // TODO: Set to THIS_MODULE. Waiting for const_refs_to_static feature to143 // TODO: Set to `THIS_MODULE`.
144 // be merged (unstable in rustc 1.78 which is staged for linux 6.10)
145 // <https://github.com/rust-lang/rust/issues/119618>
146 owner: core::ptr::null_mut(),144 owner: core::ptr::null_mut(),
147 pr_ops: core::ptr::null_mut(),145 pr_ops: core::ptr::null_mut(),
148 free_disk: None,146 free_disk: None,
rust/kernel/build_assert.rs+153−30
@@ -1,10 +1,144 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2 2
3//! Build-time assert.3//! Various assertions that happen during build-time.
4//!
5//! There are three types of build-time assertions that you can use:
6//! - [`static_assert!`]
7//! - [`const_assert!`]
8//! - [`build_assert!`]
9//!
10//! The ones towards the bottom of the list are more expressive, while the ones towards the top of
11//! the list are more robust and trigger earlier in the compilation pipeline. Therefore, you should
12//! prefer the ones towards the top of the list wherever possible.
13//!
14//! # Choosing the correct assertion
15//!
16//! If you're asserting outside any bodies (e.g. initializers or function bodies), you should use
17//! [`static_assert!`] as it is the only assertion that can be used in that context.
18//!
19//! Inside bodies, if your assertion condition does not depend on any variable or generics, you
20//! should use [`static_assert!`]. If the condition depends on generics, but not variables
21//! (including function arguments), you should use [`const_assert!`]. Otherwise, use
22//! [`build_assert!`]. The same is true regardless if the function is `const fn`.
23//!
24//! ```
25//! // Outside any bodies.
26//! static_assert!(core::mem::size_of::<u8>() == 1);
27//! // `const_assert!` and `build_assert!` cannot be used here, they will fail to compile.
28//!
29//! #[inline(always)]
30//! fn foo<const N: usize>(v: usize) {
31//! static_assert!(core::mem::size_of::<u8>() == 1); // Preferred.
32//! const_assert!(core::mem::size_of::<u8>() == 1); // Discouraged.
33//! build_assert!(core::mem::size_of::<u8>() == 1); // Discouraged.
34//!
35//! // `static_assert!(N > 1);` is not allowed.
36//! const_assert!(N > 1); // Preferred.
37//! build_assert!(N > 1); // Discouraged.
38//!
39//! // `static_assert!(v > 1);` is not allowed.
40//! // `const_assert!(v > 1);` is not allowed.
41//! build_assert!(v > 1); // Works.
42//! }
43//! ```
44//!
45//! # Detailed behavior
46//!
47//! `static_assert!()` is equivalent to `static_assert` in C. It requires `expr` to be a constant
48//! expression. This expression cannot refer to any generics. A `static_assert!(expr)` in a program
49//! is always evaluated, regardless if the function it appears in is used or not. This is also the
50//! only usable assertion outside a body.
51//!
52//! `const_assert!()` has no direct C equivalence. It is a more powerful version of
53//! `static_assert!()`, where it may refer to generics in a function. Note that due to the ability
54//! to refer to generics, the assertion is tied to a specific instance of a function. So if it is
55//! used in a generic function that is not instantiated, the assertion will not be checked. For this
56//! reason, `static_assert!()` is preferred wherever possible.
57//!
58//! `build_assert!()` is equivalent to `BUILD_BUG_ON`. It is even more powerful than
59//! `const_assert!()` because it can be used to check tautologies that depend on runtime value (this
60//! is the same as `BUILD_BUG_ON`). However, the assertion failure mechanism can possibly be
61//! undefined symbols and linker errors, it is not developer friendly to debug, so it is recommended
62//! to avoid it and prefer other two assertions where possible.
63
64pub use crate::{
65 build_assert,
66 build_error,
67 const_assert,
68 static_assert, //
69};
4 70
5#[doc(hidden)]71#[doc(hidden)]
6pub use build_error::build_error;72pub use build_error::build_error;
7 73
74/// Static assert (i.e. compile-time assert).
75///
76/// Similar to C11 [`_Static_assert`] and C++11 [`static_assert`].
77///
78/// An optional panic message can be supplied after the expression.
79/// Currently only a string literal without formatting is supported
80/// due to constness limitations of the [`assert!`] macro.
81///
82/// The feature may be added to Rust in the future: see [RFC 2790].
83///
84/// You cannot refer to generics or variables with [`static_assert!`]. If you need to refer to
85/// generics, use [`const_assert!`]; if you need to refer to variables, use [`build_assert!`]. See
86/// the [module documentation](self).
87///
88/// [`_Static_assert`]: https://en.cppreference.com/w/c/language/_Static_assert
89/// [`static_assert`]: https://en.cppreference.com/w/cpp/language/static_assert
90/// [RFC 2790]: https://github.com/rust-lang/rfcs/issues/2790
91///
92/// # Examples
93///
94/// ```
95/// static_assert!(42 > 24);
96/// static_assert!(core::mem::size_of::<u8>() == 1);
97///
98/// const X: &[u8] = b"bar";
99/// static_assert!(X[1] == b'a');
100///
101/// const fn f(x: i32) -> i32 {
102/// x + 2
103/// }
104/// static_assert!(f(40) == 42);
105/// static_assert!(f(40) == 42, "f(x) must add 2 to the given input.");
106/// ```
107#[macro_export]
108macro_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]
136macro_rules! const_assert {
137 ($condition:expr $(,$arg:literal)?) => {
138 const { ::core::assert!($condition $(,$arg)?) };
139 };
140}
141
8/// Fails the build if the code path calling `build_error!` can possibly be executed.142/// Fails the build if the code path calling `build_error!` can possibly be executed.
9///143///
10/// If the macro is executed in const context, `build_error!` will panic.144/// If the macro is executed in const context, `build_error!` will panic.
@@ -38,44 +172,33 @@ macro_rules! build_error { · 27 unmodified lines
38/// will panic. If the compiler or optimizer cannot guarantee the condition will172/// will panic. If the compiler or optimizer cannot guarantee the condition will
39/// be evaluated to `true`, a build error will be triggered.173/// be evaluated to `true`, a build error will be triggered.
40///174///
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).
42///182///
43/// # Examples183/// # Examples
44///184///
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/// }
54/// ```185/// ```
186/// #[inline(always)] // Important.
187/// fn bar(n: usize) {
188/// build_assert!(n > 1);
189/// }
55///190///
56/// When the condition refers to generic parameters or parameters of an inline function,191/// fn foo() {
57/// [`static_assert!`] cannot be used. Use `build_assert!` in this scenario.192/// bar(2);
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
63/// }193/// }
64/// ```
65///194///
66/// When a condition depends on a function argument, the function must be annotated with195/// #[inline(always)] // Important.
67/// `#[inline(always)]`. Without this attribute, the compiler may choose to not inline the196/// const fn const_bar(n: usize) {
68/// function, preventing it from optimizing out the error path.197/// build_assert!(n > 1);
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
75/// }198/// }
76/// ```
77///199///
78/// [`static_assert!`]: crate::static_assert!200/// const _: () = const_bar(2);
201/// ```
79#[macro_export]202#[macro_export]
80macro_rules! build_assert {203macro_rules! build_assert {
81 ($cond:expr $(,)?) => {{204 ($cond:expr $(,)?) => {{
rust/kernel/clk.rs+7−0
@@ -128,6 +128,13 @@ mod common_clk { · 127 unmodified lines
128 #[repr(transparent)]128 #[repr(transparent)]
129 pub struct Clk(*mut bindings::clk);129 pub struct Clk(*mut bindings::clk);
130 130
131 // SAFETY: It is safe to call `clk_put` on another thread than where `clk_get` was called.
132 unsafe impl Send for Clk {}
133
134 // SAFETY: It is safe to call any combination of the `&self` methods in parallel, as the
135 // methods are synchronized internally.
136 unsafe impl Sync for Clk {}
137
131 impl Clk {138 impl Clk {
132 /// Gets [`Clk`] corresponding to a [`Device`] and a connection id.139 /// Gets [`Clk`] corresponding to a [`Device`] and a connection id.
133 ///140 ///
rust/kernel/error.rs+37−0
@@ -216,36 +216,42 @@ impl fmt::Debug for Error { · 215 unmodified lines
216}216}
217 217
218impl From<AllocError> for Error {218impl From<AllocError> for Error {
219 #[inline]
219 fn from(_: AllocError) -> Error {220 fn from(_: AllocError) -> Error {
220 code::ENOMEM221 code::ENOMEM
221 }222 }
222}223}
223 224
224impl From<TryFromIntError> for Error {225impl From<TryFromIntError> for Error {
226 #[inline]
225 fn from(_: TryFromIntError) -> Error {227 fn from(_: TryFromIntError) -> Error {
226 code::EINVAL228 code::EINVAL
227 }229 }
228}230}
229 231
230impl From<Utf8Error> for Error {232impl From<Utf8Error> for Error {
233 #[inline]
231 fn from(_: Utf8Error) -> Error {234 fn from(_: Utf8Error) -> Error {
232 code::EINVAL235 code::EINVAL
233 }236 }
234}237}
235 238
236impl From<LayoutError> for Error {239impl From<LayoutError> for Error {
240 #[inline]
237 fn from(_: LayoutError) -> Error {241 fn from(_: LayoutError) -> Error {
238 code::ENOMEM242 code::ENOMEM
239 }243 }
240}244}
241 245
242impl From<fmt::Error> for Error {246impl From<fmt::Error> for Error {
247 #[inline]
243 fn from(_: fmt::Error) -> Error {248 fn from(_: fmt::Error) -> Error {
244 code::EINVAL249 code::EINVAL
245 }250 }
246}251}
247 252
248impl From<core::convert::Infallible> for Error {253impl From<core::convert::Infallible> for Error {
254 #[inline]
249 fn from(e: core::convert::Infallible) -> Error {255 fn from(e: core::convert::Infallible) -> Error {
250 match e {}256 match e {}
251 }257 }
@@ -446,6 +452,9 @@ pub fn to_result(err: crate::ffi::c_int) -> Result { · 194 unmodified lines
446/// for errors. This function performs the check and converts the "error pointer"452/// for errors. This function performs the check and converts the "error pointer"
447/// to a normal pointer in an idiomatic fashion.453/// to a normal pointer in an idiomatic fashion.
448///454///
455/// Note that a `NULL` pointer is not considered an error pointer, and is returned
456/// as-is, wrapped in [`Ok`].
457///
449/// # Examples458/// # Examples
450///459///
451/// ```ignore460/// ```ignore
@@ -460,6 +469,34 @@ pub fn to_result(err: crate::ffi::c_int) -> Result { · 8 unmodified lines
460/// from_err_ptr(unsafe { bindings::devm_platform_ioremap_resource(pdev.to_ptr(), index) })469/// from_err_ptr(unsafe { bindings::devm_platform_ioremap_resource(pdev.to_ptr(), index) })
461/// }470/// }
462/// ```471/// ```
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/// ```
463pub fn from_err_ptr<T>(ptr: *mut T) -> Result<*mut T> {500pub fn from_err_ptr<T>(ptr: *mut T) -> Result<*mut T> {
464 // CAST: Casting a pointer to `*const crate::ffi::c_void` is always valid.501 // CAST: Casting a pointer to `*const crate::ffi::c_void` is always valid.
465 let const_ptr: *const crate::ffi::c_void = ptr.cast();502 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
16 error::*,16 error::*,
17 of,17 of,
18 prelude::*,18 prelude::*,
19 types::{19 sync::aref::{
20 AlwaysRefCounted,20 ARef,
21 Opaque, //21 AlwaysRefCounted, //
22 }, //22 },
23 types::Opaque, //
23};24};
24 25
25use core::{26use core::{
@@ -31,8 +32,6 @@ use core::{ · 5 unmodified lines
31 }, //32 }, //
32};33};
33 34
34use kernel::types::ARef;
35
36/// An I2C device id table.35/// An I2C device id table.
37#[repr(transparent)]36#[repr(transparent)]
38#[derive(Clone, Copy)]37#[derive(Clone, Copy)]
@@ -416,7 +415,7 @@ kernel::impl_device_context_deref!(unsafe { I2cAdapter }); · 377 unmodified lines
416kernel::impl_device_context_into_aref!(I2cAdapter);415kernel::impl_device_context_into_aref!(I2cAdapter);
417 416
418// SAFETY: Instances of `I2cAdapter` are always reference-counted.417// SAFETY: Instances of `I2cAdapter` are always reference-counted.
419unsafe impl crate::types::AlwaysRefCounted for I2cAdapter {418unsafe impl AlwaysRefCounted for I2cAdapter {
420 fn inc_ref(&self) {419 fn inc_ref(&self) {
421 // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.420 // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
422 unsafe { bindings::i2c_get_adapter(self.index()) };421 unsafe { bindings::i2c_get_adapter(self.index()) };
rust/kernel/lib.rs+2−36
@@ -16,45 +16,14 @@ · 15 unmodified lines
16// Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on16// Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on
17// the unstable features in use.17// the unstable features in use.
18//18//
19// Stable since Rust 1.79.0.
20#![feature(generic_nonzero)]
21#![feature(inline_const)]
22#![feature(pointer_is_aligned)]
23#![feature(slice_ptr_len)]
24//
25// Stable since Rust 1.80.0.
26#![feature(slice_flatten)]
27//
28// Stable since Rust 1.81.0.
29#![feature(lint_reasons)]
30//
31// Stable since Rust 1.82.0.
32#![feature(raw_ref_op)]
33//
34// Stable since Rust 1.83.0.
35#![feature(const_maybe_uninit_as_mut_ptr)]
36#![feature(const_mut_refs)]
37#![feature(const_option)]
38#![feature(const_ptr_write)]
39#![feature(const_refs_to_cell)]
40//
41// Stable since Rust 1.84.0.
42#![feature(strict_provenance)]
43//
44// Expected to become stable.19// Expected to become stable.
45#![feature(arbitrary_self_types)]20#![feature(arbitrary_self_types)]
21#![feature(derive_coerce_pointee)]
46//22//
47// To be determined.23// To be determined.
48#![feature(used_with_arg)]24#![feature(used_with_arg)]
49//25//
50// `feature(derive_coerce_pointee)` is expected to become stable. Before Rust26// `feature(file_with_nul)` is stable since Rust 1.92.0. Before Rust 1.89.0, it did not exist, so
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
58// enable it conditionally.27// enable it conditionally.
59#![cfg_attr(CONFIG_RUSTC_HAS_FILE_WITH_NUL, feature(file_with_nul))]28#![cfg_attr(CONFIG_RUSTC_HAS_FILE_WITH_NUL, feature(file_with_nul))]
60 29
@@ -77,7 +46,6 @@ pub mod bits; · 16 unmodified lines
77#[cfg(CONFIG_BLOCK)]46#[cfg(CONFIG_BLOCK)]
78pub mod block;47pub mod block;
79pub mod bug;48pub mod bug;
80#[doc(hidden)]
81pub mod build_assert;49pub mod build_assert;
82pub mod clk;50pub mod clk;
83#[cfg(CONFIG_CONFIGFS_FS)]51#[cfg(CONFIG_CONFIGFS_FS)]
@@ -145,10 +113,8 @@ pub mod scatterlist; · 61 unmodified lines
145pub mod security;113pub mod security;
146pub mod seq_file;114pub mod seq_file;
147pub mod sizes;115pub mod sizes;
148pub mod slice;
149#[cfg(CONFIG_SOC_BUS)]116#[cfg(CONFIG_SOC_BUS)]
150pub mod soc;117pub mod soc;
151mod static_assert;
152#[doc(hidden)]118#[doc(hidden)]
153pub mod std_vendor;119pub mod std_vendor;
154pub mod str;120pub mod str;
rust/kernel/list.rs+19−3
@@ -12,15 +12,31 @@ use core::ptr; · 11 unmodified lines
12use pin_init::PinInit;12use pin_init::PinInit;
13 13
14mod impl_list_item_mod;14mod impl_list_item_mod;
15#[doc(inline)]
15pub use self::impl_list_item_mod::{16pub use self::impl_list_item_mod::{
16 impl_has_list_links, impl_has_list_links_self_ptr, impl_list_item, HasListLinks, HasSelfPtr,17 impl_has_list_links,
18 impl_has_list_links_self_ptr,
19 impl_list_item,
20 HasListLinks,
21 HasSelfPtr, //
17};22};
18 23
19mod arc;24mod arc;
20pub use self::arc::{impl_list_arc_safe, AtomicTracker, ListArc, ListArcSafe, TryNewListArc};25#[doc(inline)]
26pub use self::arc::{
27 impl_list_arc_safe,
28 AtomicTracker,
29 ListArc,
30 ListArcSafe,
31 TryNewListArc, //
32};
21 33
22mod arc_field;34mod arc_field;
23pub use self::arc_field::{define_list_arc_field_getter, ListArcField};35#[doc(inline)]
36pub use self::arc_field::{
37 define_list_arc_field_getter,
38 ListArcField, //
39};
24 40
25/// A linked list.41/// A linked list.
26///42///
rust/kernel/list/arc.rs+2−21
@@ -82,6 +82,7 @@ pub unsafe trait TryNewListArc<const ID: u64 = 0>: ListArcSafe<ID> { · 81 unmodified lines
82/// [`AtomicTracker`]. However, it is also possible to defer the tracking to another struct82/// [`AtomicTracker`]. However, it is also possible to defer the tracking to another struct
83/// using also using this macro.83/// using also using this macro.
84#[macro_export]84#[macro_export]
85#[doc(hidden)]
85macro_rules! impl_list_arc_safe {86macro_rules! impl_list_arc_safe {
86 (impl$({$($generics:tt)*})? ListArcSafe<$num:tt> for $t:ty { untracked; } $($rest:tt)*) => {87 (impl$({$($generics:tt)*})? ListArcSafe<$num:tt> for $t:ty { untracked; } $($rest:tt)*) => {
87 impl$(<$($generics)*>)? $crate::list::ListArcSafe<$num> for $t {88 impl$(<$($generics)*>)? $crate::list::ListArcSafe<$num> for $t {
@@ -159,7 +160,7 @@ pub use impl_list_arc_safe; · 71 unmodified lines
159///160///
160/// [`List`]: crate::list::List161/// [`List`]: crate::list::List
161#[repr(transparent)]162#[repr(transparent)]
162#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))]163#[derive(core::marker::CoercePointee)]
163pub struct ListArc<T, const ID: u64 = 0>164pub struct ListArc<T, const ID: u64 = 0>
164where165where
165 T: ListArcSafe<ID> + ?Sized,166 T: ListArcSafe<ID> + ?Sized,
@@ -442,26 +443,6 @@ where · 276 unmodified lines
442 }443 }
443}444}
444 445
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))]
448impl<T, U, const ID: u64> core::ops::CoerceUnsized<ListArc<U, ID>> for ListArc<T, ID>
449where
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))]
458impl<T, U, const ID: u64> core::ops::DispatchFromDyn<ListArc<U, ID>> for ListArc<T, ID>
459where
460 T: ListArcSafe<ID> + core::marker::Unsize<U> + ?Sized,
461 U: ListArcSafe<ID> + ?Sized,
462{
463}
464
465/// A utility for tracking whether a [`ListArc`] exists using an atomic.446/// A utility for tracking whether a [`ListArc`] exists using an atomic.
466///447///
467/// # Invariants448/// # Invariants
rust/kernel/list/arc_field.rs+1−0
@@ -66,6 +66,7 @@ impl<T, const ID: u64> ListArcField<T, ID> { · 65 unmodified lines
66 66
67/// Defines getters for a [`ListArcField`].67/// Defines getters for a [`ListArcField`].
68#[macro_export]68#[macro_export]
69#[doc(hidden)]
69macro_rules! define_list_arc_field_getter {70macro_rules! define_list_arc_field_getter {
70 ($pub:vis fn $name:ident(&self $(<$id:tt>)?) -> &$typ:ty { $field:ident }71 ($pub:vis fn $name:ident(&self $(<$id:tt>)?) -> &$typ:ty { $field:ident }
71 $($rest:tt)*72 $($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
29 29
30/// Implements the [`HasListLinks`] trait for the given type.30/// Implements the [`HasListLinks`] trait for the given type.
31#[macro_export]31#[macro_export]
32#[doc(hidden)]
32macro_rules! impl_has_list_links {33macro_rules! impl_has_list_links {
33 ($(impl$({$($generics:tt)*})?34 ($(impl$({$($generics:tt)*})?
34 HasListLinks$(<$id:tt>)?35 HasListLinks$(<$id:tt>)?
@@ -74,6 +75,7 @@ where · 39 unmodified lines
74 75
75/// Implements the [`HasListLinks`] and [`HasSelfPtr`] traits for the given type.76/// Implements the [`HasListLinks`] and [`HasSelfPtr`] traits for the given type.
76#[macro_export]77#[macro_export]
78#[doc(hidden)]
77macro_rules! impl_has_list_links_self_ptr {79macro_rules! impl_has_list_links_self_ptr {
78 ($(impl$({$($generics:tt)*})?80 ($(impl$({$($generics:tt)*})?
79 HasSelfPtr<$item_type:ty $(, $id:tt)?>81 HasSelfPtr<$item_type:ty $(, $id:tt)?>
@@ -181,6 +183,7 @@ pub use impl_has_list_links_self_ptr; · 101 unmodified lines
181/// }183/// }
182/// ```184/// ```
183#[macro_export]185#[macro_export]
186#[doc(hidden)]
184macro_rules! impl_list_item {187macro_rules! impl_list_item {
185 (188 (
186 $(impl$({$($generics:tt)*})? ListItem<$num:tt> for $self:ty {189 $(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
255 /// ```255 /// ```
256 pub const fn new<const VALUE: $type>() -> Self {256 pub const fn new<const VALUE: $type>() -> Self {
257 // Statically assert that `VALUE` fits within the set number of bits.257 // Statically assert that `VALUE` fits within the set number of bits.
258 const {258 const_assert!(fits_within!(VALUE, $type, N));
259 assert!(fits_within!(VALUE, $type, N));
260 }
261 259
262 // SAFETY: `fits_within` confirmed that `VALUE` can be represented within260 // SAFETY: `fits_within` confirmed that `VALUE` can be represented within
263 // `N` bits.261 // `N` bits.
@@ -287,12 +285,10 @@ where · 23 unmodified lines
287 /// The caller must ensure that `value` can be represented within `N` bits.285 /// The caller must ensure that `value` can be represented within `N` bits.
288 const unsafe fn __new(value: T) -> Self {286 const unsafe fn __new(value: T) -> Self {
289 // Enforce the type invariants.287 // Enforce the type invariants.
290 const {288 // `N` cannot be zero.
291 // `N` cannot be zero.289 const_assert!(N != 0);
292 assert!(N != 0);290 // The backing type is at least as large as `N` bits.
293 // The backing type is at least as large as `N` bits.291 const_assert!(N <= T::BITS);
294 assert!(N <= T::BITS);
295 }
296 292
297 // INVARIANT: The caller ensures `value` fits within `N` bits.293 // INVARIANT: The caller ensures `value` fits within `N` bits.
298 Self(value)294 Self(value)
@@ -406,12 +402,10 @@ where · 107 unmodified lines
406 /// assert_eq!(larger_v, v);402 /// assert_eq!(larger_v, v);
407 /// ```403 /// ```
408 pub const fn extend<const M: u32>(self) -> Bounded<T, M> {404 pub const fn extend<const M: u32>(self) -> Bounded<T, M> {
409 const {405 const_assert!(
410 assert!(406 M >= N,
411 M >= N,407 "Requested number of bits is less than the current representation."
412 "Requested number of bits is less than the current representation."408 );
413 );
414 }
415 409
416 // SAFETY: The value did fit within `N` bits, so it will all the more fit within410 // SAFETY: The value did fit within `N` bits, so it will all the more fit within
417 // the larger `M` bits.411 // the larger `M` bits.
rust/kernel/prelude.rs+82−28
@@ -13,43 +13,97 @@ · 12 unmodified lines
13 13
14#[doc(no_inline)]14#[doc(no_inline)]
15pub use core::{15pub use core::{
16 mem::{align_of, align_of_val, size_of, size_of_val},16 mem::{
17 pin::Pin,17 align_of,
18 align_of_val,
19 size_of,
20 size_of_val, //
21 },
22 pin::Pin, //
18};23};
19 24
20pub use ::ffi::{25pub use ::ffi::{
21 c_char, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, c_ulong, c_ulonglong,26 c_char,
22 c_ushort, c_void, CStr,27 c_int,
28 c_long,
29 c_longlong,
30 c_schar,
31 c_short,
32 c_uchar,
33 c_uint,
34 c_ulong,
35 c_ulonglong,
36 c_ushort,
37 c_void,
38 CStr, //
23};39};
24 40
25pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec, VBox, VVec, Vec};
26
27#[doc(no_inline)]41#[doc(no_inline)]
28pub use macros::{export, fmt, kunit_tests, module, vtable};42pub use macros::{
43 export,
44 fmt,
45 kunit_tests,
46 module,
47 vtable, //
48};
29 49
30pub use pin_init::{init, pin_data, pin_init, pinned_drop, InPlaceWrite, Init, PinInit, Zeroable};50pub use pin_init::{
51 init,
52 pin_data,
53 pin_init,
54 pinned_drop,
55 InPlaceWrite,
56 Init,
57 PinInit,
58 Zeroable, //
59};
31 60
32pub use super::{build_assert, build_error};61pub use super::{
62 alloc::{
63 flags::*,
64 Box,
65 KBox,
66 KVBox,
67 KVVec,
68 KVec,
69 VBox,
70 VVec,
71 Vec, //
72 },
73 build_assert,
74 build_error,
75 const_assert,
76 current,
77 dev_alert,
78 dev_crit,
79 dev_dbg,
80 dev_emerg,
81 dev_err,
82 dev_info,
83 dev_notice,
84 dev_warn,
85 error::{
86 code::*,
87 Error,
88 Result, //
89 },
90 init::InPlaceInit,
91 pr_alert,
92 pr_crit,
93 pr_debug,
94 pr_emerg,
95 pr_err,
96 pr_info,
97 pr_notice,
98 pr_warn,
99 static_assert,
100 str::CStrExt as _,
101 try_init,
102 try_pin_init,
103 uaccess::UserPtr,
104 ThisModule, //
105};
33 106
34// `super::std_vendor` is hidden, which makes the macro inline for some reason.107// `super::std_vendor` is hidden, which makes the macro inline for some reason.
35#[doc(no_inline)]108#[doc(no_inline)]
36pub use super::dbg;109pub use super::dbg;
37pub use super::{dev_alert, dev_crit, dev_dbg, dev_emerg, dev_err, dev_info, dev_notice, dev_warn};
38pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
39
40pub use super::{try_init, try_pin_init};
41
42pub use super::static_assert;
43
44pub use super::error::{code::*, Error, Result};
45
46pub use super::{str::CStrExt as _, ThisModule};
47
48pub use super::init::InPlaceInit;
49
50pub use super::current;
51
52pub use super::uaccess::UserPtr;
53
54#[cfg(not(CONFIG_RUSTC_HAS_SLICE_AS_FLATTENED))]
55pub use super::slice::AsFlattened;
rust/kernel/ptr.rs+35−7
@@ -11,6 +11,8 @@ use core::mem::{ · 10 unmodified lines
11};11};
12use core::num::NonZero;12use core::num::NonZero;
13 13
14use crate::const_assert;
15
14/// Type representing an alignment, which is always a power of two.16/// Type representing an alignment, which is always a power of two.
15///17///
16/// It is used to validate that a given value is a valid alignment, and to perform masking and18/// 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
44 /// ```46 /// ```
45 #[inline(always)]47 #[inline(always)]
46 pub const fn new<const ALIGN: usize>() -> Self {48 pub const fn new<const ALIGN: usize>() -> Self {
47 const {49 const_assert!(
48 assert!(50 ALIGN.is_power_of_two(),
49 ALIGN.is_power_of_two(),51 "Provided alignment is not a power of two."
50 "Provided alignment is not a power of two."52 );
51 );
52 }
53 53
54 // INVARIANT: `align` is a power of two.54 // INVARIANT: `align` is a power of two.
55 // SAFETY: `align` is a power of two, and thus non-zero.55 // SAFETY: `align` is a power of two, and thus non-zero.
@@ -87,7 +87,6 @@ impl Alignment { · 31 unmodified lines
87 /// This is equivalent to [`align_of`], but with the return value provided as an [`Alignment`].87 /// This is equivalent to [`align_of`], but with the return value provided as an [`Alignment`].
88 #[inline(always)]88 #[inline(always)]
89 pub const fn of<T>() -> Self {89 pub const fn of<T>() -> Self {
90 #![allow(clippy::incompatible_msrv)]
91 // This cannot panic since alignments are always powers of two.90 // This cannot panic since alignments are always powers of two.
92 //91 //
93 // We unfortunately cannot use `new` as it would require the `generic_const_exprs` feature.92 // 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
253 p.len() * size_of::<T>()252 p.len() * size_of::<T>()
254 }253 }
255}254}
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)]
278pub 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
3//! Commonly used sizes.3//! Commonly used sizes.
4//!4//!
5//! C headers: [`include/linux/sizes.h`](srctree/include/linux/sizes.h).5//! C headers: [`include/linux/sizes.h`](srctree/include/linux/sizes.h).
6//!
7//! The top-level `SZ_*` constants are [`usize`]-typed, for use in kernel page
8//! arithmetic and similar CPU-side work.
9//!
10//! The [`SizeConstants`] trait provides the same constants as associated constants
11//! on [`u32`], [`u64`], and [`usize`], for use in device address spaces where
12//! the address width depends on the hardware. Device drivers frequently need
13//! these constants as [`u64`] (or [`u32`]) rather than [`usize`], because
14//! device address spaces are sized independently of the CPU pointer width.
15//!
16//! # Examples
17//!
18//! ```
19//! use kernel::{
20//! page::PAGE_SIZE,
21//! sizes::{
22//! SizeConstants,
23//! SZ_1M, //
24//! }, //
25//! };
26//!
27//! // Module-level constants continue to work without a type qualifier.
28//! let num_pages_in_1m = SZ_1M / PAGE_SIZE;
29//!
30//! // Trait associated constants require a type qualifier.
31//! let heap_size = 14 * u64::SZ_1M;
32//! let small = u32::SZ_4K;
33//! ```
34
35macro_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}
6 133
7/// 0x00000400134define_sizes!(u32, u64, usize);
8pub const SZ_1K: usize = bindings::SZ_1K as usize;
9/// 0x00000800
10pub const SZ_2K: usize = bindings::SZ_2K as usize;
11/// 0x00001000
12pub const SZ_4K: usize = bindings::SZ_4K as usize;
13/// 0x00002000
14pub const SZ_8K: usize = bindings::SZ_8K as usize;
15/// 0x00004000
16pub const SZ_16K: usize = bindings::SZ_16K as usize;
17/// 0x00008000
18pub const SZ_32K: usize = bindings::SZ_32K as usize;
19/// 0x00010000
20pub const SZ_64K: usize = bindings::SZ_64K as usize;
21/// 0x00020000
22pub const SZ_128K: usize = bindings::SZ_128K as usize;
23/// 0x00040000
24pub const SZ_256K: usize = bindings::SZ_256K as usize;
25/// 0x00080000
26pub const SZ_512K: usize = bindings::SZ_512K as usize;
27/// 0x00100000
28pub const SZ_1M: usize = bindings::SZ_1M as usize;
29/// 0x00200000
30pub const SZ_2M: usize = bindings::SZ_2M as usize;
31/// 0x00400000
32pub const SZ_4M: usize = bindings::SZ_4M as usize;
33/// 0x00800000
34pub const SZ_8M: usize = bindings::SZ_8M as usize;
35/// 0x01000000
36pub const SZ_16M: usize = bindings::SZ_16M as usize;
37/// 0x02000000
38pub const SZ_32M: usize = bindings::SZ_32M as usize;
39/// 0x04000000
40pub const SZ_64M: usize = bindings::SZ_64M as usize;
41/// 0x08000000
42pub const SZ_128M: usize = bindings::SZ_128M as usize;
43/// 0x10000000
44pub const SZ_256M: usize = bindings::SZ_256M as usize;
45/// 0x20000000
46pub const SZ_512M: usize = bindings::SZ_512M as usize;
47/// 0x40000000
48pub const SZ_1G: usize = bindings::SZ_1G as usize;
49/// 0x80000000
50pub const SZ_2G: usize = bindings::SZ_2G as 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))]
22pub 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))]
39impl<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]
35macro_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
189//189//
190// - error[E0379]: functions in trait impls cannot be declared const190// - error[E0379]: functions in trait impls cannot be declared const
191#[inline]191#[inline]
192#[expect(clippy::disallowed_methods, reason = "internal implementation")]
192pub const fn as_char_ptr_in_const_context(c_str: &CStr) -> *const c_char {193pub const fn as_char_ptr_in_const_context(c_str: &CStr) -> *const c_char {
193 c_str.as_ptr().cast()194 c_str.as_ptr().cast()
194}195}
@@ -319,6 +320,7 @@ unsafe fn to_bytes_mut(s: &mut CStr) -> &mut [u8] { · 124 unmodified lines
319 320
320impl CStrExt for CStr {321impl CStrExt for CStr {
321 #[inline]322 #[inline]
323 #[expect(clippy::disallowed_methods, reason = "internal implementation")]
322 unsafe fn from_char_ptr<'a>(ptr: *const c_char) -> &'a Self {324 unsafe fn from_char_ptr<'a>(ptr: *const c_char) -> &'a Self {
323 // SAFETY: The safety preconditions are the same as for `CStr::from_ptr`.325 // SAFETY: The safety preconditions are the same as for `CStr::from_ptr`.
324 unsafe { CStr::from_ptr(ptr.cast()) }326 unsafe { CStr::from_ptr(ptr.cast()) }
@@ -334,6 +336,7 @@ impl CStrExt for CStr { · 9 unmodified lines
334 }336 }
335 337
336 #[inline]338 #[inline]
339 #[expect(clippy::disallowed_methods, reason = "internal implementation")]
337 fn as_char_ptr(&self) -> *const c_char {340 fn as_char_ptr(&self) -> *const c_char {
338 self.as_ptr().cast()341 self.as_ptr().cast()
339 }342 }
@@ -376,19 +379,32 @@ impl AsRef<BStr> for CStr { · 36 unmodified lines
376 }379 }
377}380}
378 381
379/// Creates a new [`CStr`] from a string literal.382/// Creates a new [`CStr`] at compile time.
380///383///
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.
382///391///
383/// # Examples392/// # Examples
384///393///
385/// ```394/// ```
386/// # use kernel::c_str;395/// # use kernel::c_str;
387/// # use kernel::str::CStr;396/// # 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!"));
389/// ```402/// ```
390#[macro_export]403#[macro_export]
391macro_rules! c_str {404macro_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.
392 ($str:expr) => {{408 ($str:expr) => {{
393 const S: &str = concat!($str, "\0");409 const S: &str = concat!($str, "\0");
394 const C: &$crate::str::CStr = match $crate::str::CStr::from_bytes_with_nul(S.as_bytes()) {410 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
828 f.write_str("\0")?;844 f.write_str("\0")?;
829 845
830 // SAFETY: The number of bytes that can be written to `f` is bounded by `size`, which is846 // 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`.
832 unsafe { buf.inc_len(f.bytes_written()) };851 unsafe { buf.inc_len(f.bytes_written()) };
833 852
834 // Check that there are no `NUL` bytes before the end.853 // 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
128/// # Ok::<(), Error>(())128/// # Ok::<(), Error>(())
129/// ```129/// ```
130#[repr(transparent)]130#[repr(transparent)]
131#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))]131#[derive(core::marker::CoercePointee)]
132pub struct Arc<T: ?Sized> {132pub struct Arc<T: ?Sized> {
133 ptr: NonNull<ArcInner<T>>,133 ptr: NonNull<ArcInner<T>>,
134 // NB: this informs dropck that objects of type `ArcInner<T>` may be used in `<Arc<T> as134 // 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
182 }182 }
183}183}
184 184
185// This is to allow coercion from `Arc<T>` to `Arc<U>` if `T` can be converted to the
186// dynamically-sized type (DST) `U`.
187#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
188impl<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))]
192impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Arc<T> {}
193
194// SAFETY: It is safe to send `Arc<T>` to another thread when the underlying `T` is `Sync` because185// SAFETY: It is safe to send `Arc<T>` to another thread when the underlying `T` is `Sync` because
195// it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs186// it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs
196// `T` to be `Send` because any thread that has an `Arc<T>` may ultimately access `T` using a187// `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
547/// # Ok::<(), Error>(())538/// # Ok::<(), Error>(())
548/// ```539/// ```
549#[repr(transparent)]540#[repr(transparent)]
550#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))]541#[derive(core::marker::CoercePointee)]
551pub struct ArcBorrow<'a, T: ?Sized + 'a> {542pub struct ArcBorrow<'a, T: ?Sized + 'a> {
552 inner: NonNull<ArcInner<T>>,543 inner: NonNull<ArcInner<T>>,
553 _p: PhantomData<&'a ()>,544 _p: PhantomData<&'a ()>,
554}545}
555 546
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))]
559impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>>
560 for ArcBorrow<'_, T>
561{
562}
563
564impl<T: ?Sized> Clone for ArcBorrow<'_, T> {547impl<T: ?Sized> Clone for ArcBorrow<'_, T> {
565 fn clone(&self) -> Self {548 fn clone(&self) -> Self {
566 *self549 *self
rust/kernel/task.rs+3−4
@@ -6,16 +6,15 @@ · 5 unmodified lines
6 6
7use crate::{7use crate::{
8 bindings,8 bindings,
9 ffi::{c_int, c_long, c_uint},
10 mm::MmWithUser,9 mm::MmWithUser,
11 pid_namespace::PidNamespace,10 pid_namespace::PidNamespace,
11 prelude::*,
12 sync::aref::ARef,12 sync::aref::ARef,
13 types::{NotThreadSafe, Opaque},13 types::{NotThreadSafe, Opaque},
14};14};
15use core::{15use core::{
16 cmp::{Eq, PartialEq},
17 ops::Deref,16 ops::Deref,
18 ptr,17 ptr, //
19};18};
20 19
21/// A sentinel value used for infinite timeouts.20/// A sentinel value used for infinite timeouts.
@@ -419,7 +418,7 @@ pub fn might_sleep() { · 397 unmodified lines
419 let file = kernel::file_from_location(loc);418 let file = kernel::file_from_location(loc);
420 419
421 // SAFETY: `file.as_ptr()` is valid for reading and guaranteed to be nul-terminated.420 // 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) }
423 }422 }
424 423
425 // SAFETY: Always safe to call.424 // 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
60/// cases the user of the clock has to decide which clock is best suited for the60/// cases the user of the clock has to decide which clock is best suited for the
61/// purpose. In most scenarios clock [`Monotonic`] is the best choice as it61/// purpose. In most scenarios clock [`Monotonic`] is the best choice as it
62/// provides a accurate monotonic notion of time (leap second smearing ignored).62/// provides a accurate monotonic notion of time (leap second smearing ignored).
63pub 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`).
69pub unsafe trait ClockSource {
64 /// The kernel clock ID associated with this clock source.70 /// The kernel clock ID associated with this clock source.
65 ///71 ///
66 /// This constant corresponds to the C side `clockid_t` value.72 /// This constant corresponds to the C side `clockid_t` value.
@@ -68,7 +74,7 @@ pub trait ClockSource { · 1 unmodified line
68 74
69 /// Get the current time from the clock source.75 /// Get the current time from the clock source.
70 ///76 ///
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`.
72 fn ktime_get() -> bindings::ktime_t;78 fn ktime_get() -> bindings::ktime_t;
73}79}
74 80
@@ -85,7 +91,9 @@ pub trait ClockSource { · 10 unmodified lines
85/// count time that the system is suspended.91/// count time that the system is suspended.
86pub struct Monotonic;92pub struct Monotonic;
87 93
88impl ClockSource for Monotonic {94// SAFETY: The kernel's `ktime_get()` is guaranteed to return a value
95// in `0..=KTIME_MAX`.
96unsafe impl ClockSource for Monotonic {
89 const ID: bindings::clockid_t = bindings::CLOCK_MONOTONIC as bindings::clockid_t;97 const ID: bindings::clockid_t = bindings::CLOCK_MONOTONIC as bindings::clockid_t;
90 98
91 fn ktime_get() -> bindings::ktime_t {99 fn ktime_get() -> bindings::ktime_t {
@@ -110,7 +118,9 @@ impl ClockSource for Monotonic { · 18 unmodified lines
110/// the clock will experience discontinuity around leap second adjustment.118/// the clock will experience discontinuity around leap second adjustment.
111pub struct RealTime;119pub struct RealTime;
112 120
113impl ClockSource for RealTime {121// SAFETY: The kernel's `ktime_get_real()` is guaranteed to return a value
122// in `0..=KTIME_MAX`.
123unsafe impl ClockSource for RealTime {
114 const ID: bindings::clockid_t = bindings::CLOCK_REALTIME as bindings::clockid_t;124 const ID: bindings::clockid_t = bindings::CLOCK_REALTIME as bindings::clockid_t;
115 125
116 fn ktime_get() -> bindings::ktime_t {126 fn ktime_get() -> bindings::ktime_t {
@@ -128,7 +138,9 @@ impl ClockSource for RealTime { · 11 unmodified lines
128/// discontinuities if the time is changed using settimeofday(2) or similar.138/// discontinuities if the time is changed using settimeofday(2) or similar.
129pub struct BootTime;139pub struct BootTime;
130 140
131impl ClockSource for BootTime {141// SAFETY: The kernel's `ktime_get_boottime()` is guaranteed to return a value
142// in `0..=KTIME_MAX`.
143unsafe impl ClockSource for BootTime {
132 const ID: bindings::clockid_t = bindings::CLOCK_BOOTTIME as bindings::clockid_t;144 const ID: bindings::clockid_t = bindings::CLOCK_BOOTTIME as bindings::clockid_t;
133 145
134 fn ktime_get() -> bindings::ktime_t {146 fn ktime_get() -> bindings::ktime_t {
@@ -150,7 +162,9 @@ impl ClockSource for BootTime { · 15 unmodified lines
150/// The acronym TAI refers to International Atomic Time.162/// The acronym TAI refers to International Atomic Time.
151pub struct Tai;163pub struct Tai;
152 164
153impl ClockSource for Tai {165// SAFETY: The kernel's `ktime_get_clocktai()` is guaranteed to return a value
166// in `0..=KTIME_MAX`.
167unsafe impl ClockSource for Tai {
154 const ID: bindings::clockid_t = bindings::CLOCK_TAI as bindings::clockid_t;168 const ID: bindings::clockid_t = bindings::CLOCK_TAI as bindings::clockid_t;
155 169
156 fn ktime_get() -> bindings::ktime_t {170 fn ktime_get() -> bindings::ktime_t {
@@ -363,6 +377,12 @@ impl Delta { · 206 unmodified lines
363 /// A span of time equal to zero.377 /// A span of time equal to zero.
364 pub const ZERO: Self = Self { nanos: 0 };378 pub const ZERO: Self = Self { nanos: 0 };
365 379
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
366 /// Create a new [`Delta`] from a number of microseconds.386 /// Create a new [`Delta`] from a number of microseconds.
367 ///387 ///
368 /// The `micros` can range from -9_223_372_036_854_775 to 9_223_372_036_854_775.388 /// 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
66//!66//!
67//! A `restart` operation on a timer in the **stopped** state is equivalent to a67//! A `restart` operation on a timer in the **stopped** state is equivalent to a
68//! `start` operation.68//! `start` operation.
69//!
70//! When a type implements both `HrTimerPointer` and `Clone`, it is possible to
71//! issue the `start` operation while the timer is in the **started** state. In
72//! this case the `start` operation is equivalent to the `restart` operation.
73//!
74//! # Examples
75//!
76//! ## Using an intrusive timer living in a [`Box`]
77//!
78//! ```
79//! # use kernel::{
80//! # alloc::flags,
81//! # impl_has_hr_timer,
82//! # prelude::*,
83//! # sync::{
84//! # atomic::{ordering, Atomic},
85//! # completion::Completion,
86//! # Arc,
87//! # },
88//! # time::{
89//! # hrtimer::{
90//! # RelativeMode, HrTimer, HrTimerCallback, HrTimerPointer,
91//! # HrTimerRestart, HrTimerCallbackContext
92//! # },
93//! # Delta, Monotonic,
94//! # },
95//! # };
96//!
97//! #[pin_data]
98//! struct Shared {
99//! #[pin]
100//! flag: Atomic<u64>,
101//! #[pin]
102//! cond: Completion,
103//! }
104//!
105//! impl Shared {
106//! fn new() -> impl PinInit<Self> {
107//! pin_init!(Self {
108//! flag <- Atomic::new(0),
109//! cond <- Completion::new(),
110//! })
111//! }
112//! }
113//!
114//! #[pin_data]
115//! struct BoxIntrusiveHrTimer {
116//! #[pin]
117//! timer: HrTimer<Self>,
118//! shared: Arc<Shared>,
119//! }
120//!
121//! impl BoxIntrusiveHrTimer {
122//! fn new() -> impl PinInit<Self, kernel::error::Error> {
123//! try_pin_init!(Self {
124//! timer <- HrTimer::new(),
125//! shared: Arc::pin_init(Shared::new(), flags::GFP_KERNEL)?,
126//! })
127//! }
128//! }
129//!
130//! impl HrTimerCallback for BoxIntrusiveHrTimer {
131//! type Pointer<'a> = Pin<KBox<Self>>;
132//!
133//! fn run(this: Pin<&mut Self>, _ctx: HrTimerCallbackContext<'_, Self>) -> HrTimerRestart {
134//! pr_info!("Timer called\n");
135//!
136//! let flag = this.shared.flag.fetch_add(1, ordering::Full);
137//! this.shared.cond.complete_all();
138//!
139//! if flag == 4 {
140//! HrTimerRestart::NoRestart
141//! } else {
142//! HrTimerRestart::Restart
143//! }
144//! }
145//! }
146//!
147//! impl_has_hr_timer! {
148//! impl HasHrTimer<Self> for BoxIntrusiveHrTimer {
149//! mode: RelativeMode<Monotonic>, field: self.timer
150//! }
151//! }
152//!
153//! let has_timer = Box::pin_init(BoxIntrusiveHrTimer::new(), GFP_KERNEL)?;
154//! let shared = has_timer.shared.clone();
155//! let _handle = has_timer.start(Delta::from_micros(200));
156//!
157//! while shared.flag.load(ordering::Relaxed) != 5 {
158//! shared.cond.wait_for_completion();
159//! }
160//!
161//! pr_info!("Counted to 5\n");
162//! # Ok::<(), kernel::error::Error>(())
163//! ```
164//!
165//! ## Using an intrusive timer in an [`Arc`]
166//!
167//! ```
168//! # use kernel::{
169//! # alloc::flags,
170//! # impl_has_hr_timer,
171//! # prelude::*,
172//! # sync::{
173//! # atomic::{ordering, Atomic},
174//! # completion::Completion,
175//! # Arc, ArcBorrow,
176//! # },
177//! # time::{
178//! # hrtimer::{
179//! # RelativeMode, HrTimer, HrTimerCallback, HrTimerPointer, HrTimerRestart,
180//! # HasHrTimer, HrTimerCallbackContext
181//! # },
182//! # Delta, Monotonic,
183//! # },
184//! # };
185//!
186//! #[pin_data]
187//! struct ArcIntrusiveHrTimer {
188//! #[pin]
189//! timer: HrTimer<Self>,
190//! #[pin]
191//! flag: Atomic<u64>,
192//! #[pin]
193//! cond: Completion,
194//! }
195//!
196//! impl ArcIntrusiveHrTimer {
197//! fn new() -> impl PinInit<Self> {
198//! pin_init!(Self {
199//! timer <- HrTimer::new(),
200//! flag <- Atomic::new(0),
201//! cond <- Completion::new(),
202//! })
203//! }
204//! }
205//!
206//! impl HrTimerCallback for ArcIntrusiveHrTimer {
207//! type Pointer<'a> = Arc<Self>;
208//!
209//! fn run(
210//! this: ArcBorrow<'_, Self>,
211//! _ctx: HrTimerCallbackContext<'_, Self>,
212//! ) -> HrTimerRestart {
213//! pr_info!("Timer called\n");
214//!
215//! let flag = this.flag.fetch_add(1, ordering::Full);
216//! this.cond.complete_all();
217//!
218//! if flag == 4 {
219//! HrTimerRestart::NoRestart
220//! } else {
221//! HrTimerRestart::Restart
222//! }
223//! }
224//! }
225//!
226//! impl_has_hr_timer! {
227//! impl HasHrTimer<Self> for ArcIntrusiveHrTimer {
228//! mode: RelativeMode<Monotonic>, field: self.timer
229//! }
230//! }
231//!
232//! let has_timer = Arc::pin_init(ArcIntrusiveHrTimer::new(), GFP_KERNEL)?;
233//! let _handle = has_timer.clone().start(Delta::from_micros(200));
234//!
235//! while has_timer.flag.load(ordering::Relaxed) != 5 {
236//! has_timer.cond.wait_for_completion();
237//! }
238//!
239//! pr_info!("Counted to 5\n");
240//! # Ok::<(), kernel::error::Error>(())
241//! ```
242//!
243//! ## Using a stack-based timer
244//!
245//! ```
246//! # use kernel::{
247//! # impl_has_hr_timer,
248//! # prelude::*,
249//! # sync::{
250//! # atomic::{ordering, Atomic},
251//! # completion::Completion,
252//! # },
253//! # time::{
254//! # hrtimer::{
255//! # ScopedHrTimerPointer, HrTimer, HrTimerCallback, HrTimerPointer, HrTimerRestart,
256//! # HasHrTimer, RelativeMode, HrTimerCallbackContext
257//! # },
258//! # Delta, Monotonic,
259//! # },
260//! # };
261//! # use pin_init::stack_pin_init;
262//!
263//! #[pin_data]
264//! struct IntrusiveHrTimer {
265//! #[pin]
266//! timer: HrTimer<Self>,
267//! #[pin]
268//! flag: Atomic<u64>,
269//! #[pin]
270//! cond: Completion,
271//! }
272//!
273//! impl IntrusiveHrTimer {
274//! fn new() -> impl PinInit<Self> {
275//! pin_init!(Self {
276//! timer <- HrTimer::new(),
277//! flag <- Atomic::new(0),
278//! cond <- Completion::new(),
279//! })
280//! }
281//! }
282//!
283//! impl HrTimerCallback for IntrusiveHrTimer {
284//! type Pointer<'a> = Pin<&'a Self>;
285//!
286//! fn run(this: Pin<&Self>, _ctx: HrTimerCallbackContext<'_, Self>) -> HrTimerRestart {
287//! pr_info!("Timer called\n");
288//!
289//! this.flag.store(1, ordering::Release);
290//! this.cond.complete_all();
291//!
292//! HrTimerRestart::NoRestart
293//! }
294//! }
295//!
296//! impl_has_hr_timer! {
297//! impl HasHrTimer<Self> for IntrusiveHrTimer {
298//! mode: RelativeMode<Monotonic>, field: self.timer
299//! }
300//! }
301//!
302//! stack_pin_init!( let has_timer = IntrusiveHrTimer::new() );
303//! has_timer.as_ref().start_scoped(Delta::from_micros(200), || {
304//! while has_timer.flag.load(ordering::Relaxed) != 1 {
305//! has_timer.cond.wait_for_completion();
306//! }
307//! });
308//!
309//! pr_info!("Flag raised\n");
310//! # Ok::<(), kernel::error::Error>(())
311//! ```
312//!
313//! ## Using a mutable stack-based timer
314//!
315//! ```
316//! # use kernel::{
317//! # alloc::flags,
318//! # impl_has_hr_timer,
319//! # prelude::*,
320//! # sync::{
321//! # atomic::{ordering, Atomic},
322//! # completion::Completion,
323//! # Arc,
324//! # },
325//! # time::{
326//! # hrtimer::{
327//! # ScopedHrTimerPointer, HrTimer, HrTimerCallback, HrTimerPointer, HrTimerRestart,
328//! # HasHrTimer, RelativeMode, HrTimerCallbackContext
329//! # },
330//! # Delta, Monotonic,
331//! # },
332//! # };
333//! # use pin_init::stack_try_pin_init;
334//!
335//! #[pin_data]
336//! struct Shared {
337//! #[pin]
338//! flag: Atomic<u64>,
339//! #[pin]
340//! cond: Completion,
341//! }
342//!
343//! impl Shared {
344//! fn new() -> impl PinInit<Self> {
345//! pin_init!(Self {
346//! flag <- Atomic::new(0),
347//! cond <- Completion::new(),
348//! })
349//! }
350//! }
351//!
352//! #[pin_data]
353//! struct IntrusiveHrTimer {
354//! #[pin]
355//! timer: HrTimer<Self>,
356//! shared: Arc<Shared>,
357//! }
358//!
359//! impl IntrusiveHrTimer {
360//! fn new() -> impl PinInit<Self, kernel::error::Error> {
361//! try_pin_init!(Self {
362//! timer <- HrTimer::new(),
363//! shared: Arc::pin_init(Shared::new(), flags::GFP_KERNEL)?,
364//! })
365//! }
366//! }
367//!
368//! impl HrTimerCallback for IntrusiveHrTimer {
369//! type Pointer<'a> = Pin<&'a mut Self>;
370//!
371//! fn run(this: Pin<&mut Self>, _ctx: HrTimerCallbackContext<'_, Self>) -> HrTimerRestart {
372//! pr_info!("Timer called\n");
373//!
374//! let flag = this.shared.flag.fetch_add(1, ordering::Full);
375//! this.shared.cond.complete_all();
376//!
377//! if flag == 4 {
378//! HrTimerRestart::NoRestart
379//! } else {
380//! HrTimerRestart::Restart
381//! }
382//! }
383//! }
384//!
385//! impl_has_hr_timer! {
386//! impl HasHrTimer<Self> for IntrusiveHrTimer {
387//! mode: RelativeMode<Monotonic>, field: self.timer
388//! }
389//! }
390//!
391//! stack_try_pin_init!( let has_timer =? IntrusiveHrTimer::new() );
392//! let shared = has_timer.shared.clone();
393//!
394//! has_timer.as_mut().start_scoped(Delta::from_micros(200), || {
395//! while shared.flag.load(ordering::Relaxed) != 5 {
396//! shared.cond.wait_for_completion();
397//! }
398//! });
399//!
400//! pr_info!("Counted to 5\n");
401//! # Ok::<(), kernel::error::Error>(())
402//! ```
403//!
404//! [`Arc`]: kernel::sync::Arc
69 405
70use super::{ClockSource, Delta, Instant};406use super::{ClockSource, Delta, Instant};
71use crate::{prelude::*, types::Opaque};407use crate::{prelude::*, types::Opaque};
rust/kernel/transmute.rs+6−29
@@ -49,7 +49,6 @@ pub unsafe trait FromBytes { · 48 unmodified lines
49 let slice_ptr = bytes.as_ptr().cast::<Self>();49 let slice_ptr = bytes.as_ptr().cast::<Self>();
50 let size = size_of::<Self>();50 let size = size_of::<Self>();
51 51
52 #[allow(clippy::incompatible_msrv)]
53 if bytes.len() == size && slice_ptr.is_aligned() {52 if bytes.len() == size && slice_ptr.is_aligned() {
54 // SAFETY: Size and alignment were just checked.53 // SAFETY: Size and alignment were just checked.
55 unsafe { Some(&*slice_ptr) }54 unsafe { Some(&*slice_ptr) }
@@ -67,16 +66,9 @@ pub unsafe trait FromBytes { · 11 unmodified lines
67 where66 where
68 Self: Sized,67 Self: Sized,
69 {68 {
70 if bytes.len() < size_of::<Self>() {69 let (prefix, remainder) = bytes.split_at_checked(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>());
77 70
78 Self::from_bytes(prefix).map(|s| (s, remainder))71 Self::from_bytes(prefix).map(|s| (s, remainder))
79 }
80 }72 }
81 73
82 /// Converts a mutable slice of bytes to a reference to `Self`.74 /// Converts a mutable slice of bytes to a reference to `Self`.
@@ -92,7 +84,6 @@ pub unsafe trait FromBytes { · 9 unmodified lines
92 let slice_ptr = bytes.as_mut_ptr().cast::<Self>();84 let slice_ptr = bytes.as_mut_ptr().cast::<Self>();
93 let size = size_of::<Self>();85 let size = size_of::<Self>();
94 86
95 #[allow(clippy::incompatible_msrv)]
96 if bytes.len() == size && slice_ptr.is_aligned() {87 if bytes.len() == size && slice_ptr.is_aligned() {
97 // SAFETY: Size and alignment were just checked.88 // SAFETY: Size and alignment were just checked.
98 unsafe { Some(&mut *slice_ptr) }89 unsafe { Some(&mut *slice_ptr) }
@@ -110,16 +101,9 @@ pub unsafe trait FromBytes { · 11 unmodified lines
110 where101 where
111 Self: AsBytes + Sized,102 Self: AsBytes + Sized,
112 {103 {
113 if bytes.len() < size_of::<Self>() {104 let (prefix, remainder) = bytes.split_at_mut_checked(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>());
120 105
121 Self::from_bytes_mut(prefix).map(|s| (s, remainder))106 Self::from_bytes_mut(prefix).map(|s| (s, remainder))
122 }
123 }107 }
124 108
125 /// Creates an owned instance of `Self` by copying `bytes`.109 /// Creates an owned instance of `Self` by copying `bytes`.
@@ -149,16 +133,9 @@ pub unsafe trait FromBytes { · 23 unmodified lines
149 where133 where
150 Self: Sized,134 Self: Sized,
151 {135 {
152 if bytes.len() < size_of::<Self>() {136 let (prefix, remainder) = bytes.split_at_checked(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>());
159 137
160 Self::from_bytes_copy(prefix).map(|s| (s, remainder))138 Self::from_bytes_copy(prefix).map(|s| (s, remainder))
161 }
162 }139 }
163}140}
164 141
rust/kernel/types.rs+0−2
@@ -11,8 +11,6 @@ use core::{ · 10 unmodified lines
11};11};
12use pin_init::{PinInit, Wrapper, Zeroable};12use pin_init::{PinInit, Wrapper, Zeroable};
13 13
14pub use crate::sync::aref::{ARef, AlwaysRefCounted};
15
16/// Used to transfer ownership to and from foreign (non-Rust) languages.14/// Used to transfer ownership to and from foreign (non-Rust) languages.
17///15///
18/// Ownership is transferred from Rust to a foreign language by calling [`Self::into_foreign`] and16/// 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
18 to_result, //18 to_result, //
19 },19 },
20 prelude::*,20 prelude::*,
21 types::{21 sync::aref::AlwaysRefCounted,
22 AlwaysRefCounted,22 types::Opaque,
23 Opaque, //
24 },
25 ThisModule, //23 ThisModule, //
26};24};
27use core::{25use core::{
rust/kernel/xarray.rs+1−0
@@ -172,6 +172,7 @@ pub struct StoreError<T> { · 171 unmodified lines
172}172}
173 173
174impl<T> From<StoreError<T>> for Error {174impl<T> From<StoreError<T>> for Error {
175 #[inline]
175 fn from(value: StoreError<T>) -> Self {176 fn from(value: StoreError<T>) -> Self {
176 value.error177 value.error
177 }178 }
rust/macros/helpers.rs+0−1
@@ -49,7 +49,6 @@ pub(crate) fn file() -> String { · 48 unmodified lines
49 }49 }
50 50
51 #[cfg(CONFIG_RUSTC_HAS_SPAN_FILE)]51 #[cfg(CONFIG_RUSTC_HAS_SPAN_FILE)]
52 #[allow(clippy::incompatible_msrv)]
53 {52 {
54 proc_macro::Span::call_site().file()53 proc_macro::Span::call_site().file()
55 }54 }
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
87 continue;87 continue;
88 };88 };
89 89
90 // TODO: Replace below with `extract_if` when MSRV is bumped above 1.85.90 if f.attrs
91 let before_len = f.attrs.len();91 .extract_if(.., |attr| attr.path().is_ident("test"))
92 f.attrs.retain(|attr| !attr.path().is_ident("test"));92 .count()
93 if f.attrs.len() == before_len {93 == 0
94 {
94 processed_items.push(Item::Fn(f));95 processed_items.push(Item::Fn(f));
95 continue;96 continue;
96 }97 }
rust/macros/lib.rs+3−0
@@ -6,6 +6,9 @@ · 5 unmodified lines
6// and thus add a dependency on `include/config/RUSTC_VERSION_TEXT`, which is6// and thus add a dependency on `include/config/RUSTC_VERSION_TEXT`, which is
7// touched by Kconfig when the version string from the compiler changes.7// touched by Kconfig when the version string from the compiler changes.
8 8
9// Stable since Rust 1.87.0.
10#![feature(extract_if)]
11//
9// Stable since Rust 1.88.0 under a different name, `proc_macro_span_file`,12// Stable since Rust 1.88.0 under a different name, `proc_macro_span_file`,
10// which was added in Rust 1.88.0. This is why `cfg_attr` is used here, i.e.13// which was added in Rust 1.88.0. This is why `cfg_attr` is used here, i.e.
11// to avoid depending on the full `proc_macro_span` on Rust >= 1.88.0.14// 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
52 fn emit_base(&mut self, field: &str, content: &str, builtin: bool, param: bool) {52 fn emit_base(&mut self, field: &str, content: &str, builtin: bool, param: bool) {
53 let string = if builtin {53 let string = if builtin {
54 // Built-in modules prefix their modinfo strings by `module.`.54 // Built-in modules prefix their modinfo strings by `module.`.
55 format!(55 format!("{module}.{field}={content}\0", module = self.module)
56 "{module}.{field}={content}\0",
57 module = self.module,
58 field = field,
59 content = content
60 )
61 } else {56 } else {
62 // Loadable modules' modinfo strings go as-is.57 // Loadable modules' modinfo strings go as-is.
63 format!("{field}={content}\0")58 format!("{field}={content}\0")
@@ -109,7 +104,7 @@ impl<'a> ModInfoBuilder<'a> { · 45 unmodified lines
109 }104 }
110 105
111 fn emit_param(&mut self, field: &str, param: &str, content: &str) {106 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}");
113 self.emit_internal(field, &content, true);108 self.emit_internal(field, &content, true);
114 }109 }
115 110
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
160```rust160```rust
161use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure};161use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure};
162use core::{162use core::{
163 ptr::addr_of_mut,
164 marker::PhantomPinned,163 marker::PhantomPinned,
165 cell::UnsafeCell,164 cell::UnsafeCell,
166 pin::Pin,165 pin::Pin,
@@ -199,7 +198,7 @@ impl RawFoo { · 32 unmodified lines
199 unsafe {198 unsafe {
200 pin_init_from_closure(move |slot: *mut Self| {199 pin_init_from_closure(move |slot: *mut Self| {
201 // `slot` contains uninit memory, avoid creating a reference.200 // `slot` contains uninit memory, avoid creating a reference.
202 let foo = addr_of_mut!((*slot).foo);201 let foo = &raw mut (*slot).foo;
203 let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>();202 let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>();
204 203
205 // Initialize the `foo`204 // Initialize the `foo`
rust/pin-init/examples/big_struct_in_place.rs+3−0
@@ -1,5 +1,8 @@
1// SPDX-License-Identifier: Apache-2.0 OR MIT1// SPDX-License-Identifier: Apache-2.0 OR MIT
2 2
3#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
4#![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))]
5
3use pin_init::*;6use pin_init::*;
4 7
5// Struct with size over 1GiB8// Struct with size over 1GiB
rust/pin-init/examples/linked_list.rs+2−1
@@ -2,7 +2,8 @@ · 1 unmodified line
2 2
3#![allow(clippy::undocumented_unsafe_blocks)]3#![allow(clippy::undocumented_unsafe_blocks)]
4#![cfg_attr(feature = "alloc", feature(allocator_api))]4#![cfg_attr(feature = "alloc", feature(allocator_api))]
5#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]5#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
6#![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))]
6 7
7use core::{8use core::{
8 cell::Cell,9 cell::Cell,
rust/pin-init/examples/mutex.rs+2−1
@@ -2,7 +2,8 @@ · 1 unmodified line
2 2
3#![allow(clippy::undocumented_unsafe_blocks)]3#![allow(clippy::undocumented_unsafe_blocks)]
4#![cfg_attr(feature = "alloc", feature(allocator_api))]4#![cfg_attr(feature = "alloc", feature(allocator_api))]
5#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]5#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
6#![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))]
6#![allow(clippy::missing_safety_doc)]7#![allow(clippy::missing_safety_doc)]
7 8
8use core::{9use core::{
rust/pin-init/examples/pthread_mutex.rs+2−1
@@ -3,7 +3,8 @@ · 2 unmodified lines
3// inspired by <https://github.com/nbdd0121/pin-init/blob/trunk/examples/pthread_mutex.rs>3// inspired by <https://github.com/nbdd0121/pin-init/blob/trunk/examples/pthread_mutex.rs>
4#![allow(clippy::undocumented_unsafe_blocks)]4#![allow(clippy::undocumented_unsafe_blocks)]
5#![cfg_attr(feature = "alloc", feature(allocator_api))]5#![cfg_attr(feature = "alloc", feature(allocator_api))]
6#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]6#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
7#![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))]
7 8
8#[cfg(not(windows))]9#[cfg(not(windows))]
9mod pthread_mtx {10mod pthread_mtx {
rust/pin-init/examples/static_init.rs+2−1
@@ -2,7 +2,8 @@ · 1 unmodified line
2 2
3#![allow(clippy::undocumented_unsafe_blocks)]3#![allow(clippy::undocumented_unsafe_blocks)]
4#![cfg_attr(feature = "alloc", feature(allocator_api))]4#![cfg_attr(feature = "alloc", feature(allocator_api))]
5#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]5#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
6#![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))]
6#![allow(unused_imports)]7#![allow(unused_imports)]
7 8
8use core::{9use core::{
rust/pin-init/internal/src/init.rs+10−4
@@ -173,6 +173,12 @@ pub(crate) fn expand( · 172 unmodified lines
173 };173 };
174 // SAFETY: TODO174 // SAFETY: TODO
175 let init = unsafe { ::pin_init::#init_from_closure::<_, #error>(init) };175 let init = unsafe { ::pin_init::#init_from_closure::<_, #error>(init) };
176 // FIXME: this let binding is required to avoid a compiler error (cycle when computing the
177 // opaque type returned by this function) before Rust 1.81. Remove after MSRV bump.
178 #[allow(
179 clippy::let_and_return,
180 reason = "some clippy versions warn about the let binding"
181 )]
176 init182 init
177 }})183 }})
178}184}
@@ -264,7 +270,7 @@ fn init_fields( · 85 unmodified lines
264 {270 {
265 #value_prep271 #value_prep
266 // SAFETY: TODO272 // SAFETY: TODO
267 unsafe { #write(::core::ptr::addr_of_mut!((*#slot).#ident), #value_ident) };273 unsafe { #write(&raw mut (*#slot).#ident, #value_ident) };
268 }274 }
269 #(#cfgs)*275 #(#cfgs)*
270 #[allow(unused_variables)]276 #[allow(unused_variables)]
@@ -287,7 +293,7 @@ fn init_fields( · 16 unmodified lines
287 // return when an error/panic occurs.293 // return when an error/panic occurs.
288 // - We also use `#data` to require the correct trait (`Init` or `PinInit`)294 // - We also use `#data` to require the correct trait (`Init` or `PinInit`)
289 // for `#ident`.295 // for `#ident`.
290 unsafe { #data.#ident(::core::ptr::addr_of_mut!((*#slot).#ident), #init)? };296 unsafe { #data.#ident(&raw mut (*#slot).#ident, #init)? };
291 },297 },
292 quote! {298 quote! {
293 // SAFETY: TODO299 // SAFETY: TODO
@@ -302,7 +308,7 @@ fn init_fields( · 8 unmodified lines
302 unsafe {308 unsafe {
303 ::pin_init::Init::__init(309 ::pin_init::Init::__init(
304 #init,310 #init,
305 ::core::ptr::addr_of_mut!((*#slot).#ident),311 &raw mut (*#slot).#ident,
306 )?312 )?
307 };313 };
308 },314 },
@@ -342,7 +348,7 @@ fn init_fields( · 33 unmodified lines
342 // SAFETY: We forget the guard later when initialization has succeeded.348 // SAFETY: We forget the guard later when initialization has succeeded.
343 let #guard = unsafe {349 let #guard = unsafe {
344 ::pin_init::__internal::DropGuard::new(350 ::pin_init::__internal::DropGuard::new(
345 ::core::ptr::addr_of_mut!((*slot).#ident)351 &raw mut (*slot).#ident
346 )352 )
347 };353 };
348 });354 });
rust/pin-init/internal/src/lib.rs+1−1
@@ -6,7 +6,7 @@ · 5 unmodified lines
6 6
7//! `pin-init` proc macros.7//! `pin-init` proc macros.
8 8
9#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]9#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
10// Documentation is done in the pin-init crate instead.10// Documentation is done in the pin-init crate instead.
11#![allow(missing_docs)]11#![allow(missing_docs)]
12 12
rust/pin-init/src/lib.rs+50−23
@@ -172,7 +172,6 @@ · 171 unmodified lines
172//! # #![feature(extern_types)]172//! # #![feature(extern_types)]
173//! use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure};173//! use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure};
174//! use core::{174//! use core::{
175//! ptr::addr_of_mut,
176//! marker::PhantomPinned,175//! marker::PhantomPinned,
177//! cell::UnsafeCell,176//! cell::UnsafeCell,
178//! pin::Pin,177//! pin::Pin,
@@ -211,7 +210,7 @@ · 32 unmodified lines
211//! unsafe {210//! unsafe {
212//! pin_init_from_closure(move |slot: *mut Self| {211//! pin_init_from_closure(move |slot: *mut Self| {
213//! // `slot` contains uninit memory, avoid creating a reference.212//! // `slot` contains uninit memory, avoid creating a reference.
214//! let foo = addr_of_mut!((*slot).foo);213//! let foo = &raw mut (*slot).foo;
215//! let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>();214//! let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>();
216//!215//!
217//! // Initialize the `foo`216//! // Initialize the `foo`
@@ -264,12 +263,10 @@ · 46 unmodified lines
264//! [`impl Init<T, E>`]: crate::Init263//! [`impl Init<T, E>`]: crate::Init
265//! [Rust-for-Linux]: https://rust-for-linux.com/264//! [Rust-for-Linux]: https://rust-for-linux.com/
266 265
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))]
268#![cfg_attr(268#![cfg_attr(
269 all(269 all(any(feature = "alloc", feature = "std"), USE_RUSTC_FEATURES),
270 any(feature = "alloc", feature = "std"),
271 not(RUSTC_NEW_UNINIT_IS_STABLE)
272 ),
273 feature(new_uninit)270 feature(new_uninit)
274)]271)]
275#![forbid(missing_docs, unsafe_op_in_unsafe_fn)]272#![forbid(missing_docs, unsafe_op_in_unsafe_fn)]
@@ -279,6 +276,8 @@ · 3 unmodified lines
279 all(feature = "unsafe-pinned", CONFIG_RUSTC_HAS_UNSAFE_PINNED),276 all(feature = "unsafe-pinned", CONFIG_RUSTC_HAS_UNSAFE_PINNED),
280 feature(unsafe_pinned)277 feature(unsafe_pinned)
281)]278)]
279#![cfg_attr(all(USE_RUSTC_FEATURES, doc), allow(internal_features))]
280#![cfg_attr(all(USE_RUSTC_FEATURES, doc), feature(rustdoc_internals))]
282 281
283use core::{282use core::{
284 cell::UnsafeCell,283 cell::UnsafeCell,
@@ -755,7 +754,7 @@ macro_rules! stack_try_pin_init { · 470 unmodified lines
755///754///
756/// ```rust755/// ```rust
757/// # use pin_init::*;756/// # use pin_init::*;
758/// # use core::{ptr::addr_of_mut, marker::PhantomPinned};757/// # use core::marker::PhantomPinned;
759/// #[pin_data]758/// #[pin_data]
760/// #[derive(Zeroable)]759/// #[derive(Zeroable)]
761/// struct Buf {760/// struct Buf {
@@ -769,7 +768,7 @@ macro_rules! stack_try_pin_init { · 7 unmodified lines
769/// let init = pin_init!(&this in Buf {768/// let init = pin_init!(&this in Buf {
770/// buf: [0; 64],769/// buf: [0; 64],
771/// // SAFETY: TODO.770/// // SAFETY: TODO.
772/// ptr: unsafe { addr_of_mut!((*this.as_ptr()).buf).cast() },771/// ptr: unsafe { (&raw mut (*this.as_ptr()).buf).cast() },
773/// pin: PhantomPinned,772/// pin: PhantomPinned,
774/// });773/// });
775/// let init = pin_init!(Buf {774/// 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
1147 // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety1146 // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety
1148 // requirements.1147 // requirements.
1149 let res = unsafe { pin_init_from_closure(|ptr: *mut U| init.__pinned_init(ptr.cast::<T>())) };1148 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 a1149 // FIXME: this let binding is required to avoid a compiler error (cycle when computing the opaque
1151 // cycle when computing the type returned by this function)1150 // type returned by this function) before Rust 1.81. Remove after MSRV bump.
1152 #[allow(clippy::let_and_return)]1151 #[allow(
1152 clippy::let_and_return,
1153 reason = "some clippy versions warn about the let binding"
1154 )]
1153 res1155 res
1154}1156}
1155 1157
@@ -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
1163 // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety1165 // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety
1164 // requirements.1166 // requirements.
1165 let res = unsafe { init_from_closure(|ptr: *mut U| init.__init(ptr.cast::<T>())) };1167 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 a1168 // FIXME: this let binding is required to avoid a compiler error (cycle when computing the opaque
1167 // cycle when computing the type returned by this function)1169 // type returned by this function) before Rust 1.81. Remove after MSRV bump.
1168 #[allow(clippy::let_and_return)]1170 #[allow(
1171 clippy::let_and_return,
1172 reason = "some clippy versions warn about the let binding"
1173 )]
1169 res1174 res
1170}1175}
1171 1176
@@ -1610,13 +1615,6 @@ impl_zeroable! { · 438 unmodified lines
1610 // SAFETY: `T: Zeroable` and `UnsafeCell` is `repr(transparent)`.1615 // SAFETY: `T: Zeroable` and `UnsafeCell` is `repr(transparent)`.
1611 {<T: ?Sized + Zeroable>} UnsafeCell<T>,1616 {<T: ?Sized + Zeroable>} UnsafeCell<T>,
1612 1617
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
1620 // SAFETY: `null` pointer is valid.1618 // SAFETY: `null` pointer is valid.
1621 //1619 //
1622 // We cannot use `T: ?Sized`, since the VTABLE pointer part of fat pointers is not allowed to be1620 // 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
1635}1633}
1636 1634
1637macro_rules! impl_tuple_zeroable {1635macro_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 };
1639 ($first:ident, $($t:ident),* $(,)?) => {1642 ($first:ident, $($t:ident),* $(,)?) => {
1643 #[cfg_attr(doc, doc(hidden))]
1640 // SAFETY: All elements are zeroable and padding can be zero.1644 // SAFETY: All elements are zeroable and padding can be zero.
1641 unsafe impl<$first: Zeroable, $($t: Zeroable),*> Zeroable for ($first, $($t),*) {}1645 unsafe impl<$first: Zeroable, $($t: Zeroable),*> Zeroable for ($first, $($t),*) {}
1642 impl_tuple_zeroable!($($t),* ,);1646 impl_tuple_zeroable!($($t),* ,);
@@ -1651,7 +1655,16 @@ macro_rules! impl_fn_zeroable_option { · 8 unmodified lines
1651 $(impl_fn_zeroable_option!({unsafe extern $abi} $args);)*1655 $(impl_fn_zeroable_option!({unsafe extern $abi} $args);)*
1652 };1656 };
1653 ({$($prefix:tt)*} {$(,)?}) => {};1657 ({$($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 };
1654 ({$($prefix:tt)*} {$ret:ident, $($rest:ident),* $(,)?}) => {1666 ({$($prefix:tt)*} {$ret:ident, $($rest:ident),* $(,)?}) => {
1667 #[cfg_attr(doc, doc(hidden))]
1655 // SAFETY: function pointers are part of the option layout optimization:1668 // SAFETY: function pointers are part of the option layout optimization:
1656 // <https://doc.rust-lang.org/stable/std/option/index.html#representation>.1669 // <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
1657 unsafe impl<$ret, $($rest),*> ZeroableOption for $($prefix)* fn($($rest),*) -> $ret {}1670 unsafe impl<$ret, $($rest),*> ZeroableOption for $($prefix)* fn($($rest),*) -> $ret {}
@@ -1661,6 +1674,20 @@ macro_rules! impl_fn_zeroable_option { · 3 unmodified lines
1661 1674
1662impl_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 });1675impl_fn_zeroable_option!(["Rust", "C"] { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U });
1663 1676
1677macro_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
1684impl_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
1664/// This trait allows creating an instance of `Self` which contains exactly one1691/// This trait allows creating an instance of `Self` which contains exactly one
1665/// [structurally pinned value](https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning).1692/// [structurally pinned value](https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning).
1666///1693///
rust/uapi/lib.rs+1−4
@@ -8,10 +8,6 @@ · 7 unmodified lines
8//! userspace APIs.8//! userspace APIs.
9 9
10#![no_std]10#![no_std]
11// See <https://github.com/rust-lang/rust-bindgen/issues/1651>.
12#![cfg_attr(test, allow(deref_nullptr))]
13#![cfg_attr(test, allow(unaligned_references))]
14#![cfg_attr(test, allow(unsafe_op_in_unsafe_fn))]
15#![allow(11#![allow(
16 clippy::all,12 clippy::all,
17 clippy::cast_lossless,13 clippy::cast_lossless,
@@ -28,6 +24,7 @@ · 10 unmodified lines
28 unsafe_op_in_unsafe_fn24 unsafe_op_in_unsafe_fn
29)]25)]
30#![cfg_attr(CONFIG_RUSTC_HAS_UNNECESSARY_TRANSMUTES, allow(unnecessary_transmutes))]26#![cfg_attr(CONFIG_RUSTC_HAS_UNNECESSARY_TRANSMUTES, allow(unnecessary_transmutes))]
27#![feature(cfi_encoding)]
31 28
32// Manual definition of blocklisted types.29// Manual definition of blocklisted types.
33type __kernel_size_t = usize;30type __kernel_size_t = usize;
scripts/Makefile.build+7−8
@@ -310,18 +310,13 @@ $(obj)/%.lst: $(obj)/%.c FORCE · 309 unmodified lines
310 310
311# The features in this list are the ones allowed for non-`rust/` code.311# The features in this list are the ones allowed for non-`rust/` code.
312#312#
313# - Stable since Rust 1.79.0: `feature(slice_ptr_len)`.
314# - Stable since Rust 1.81.0: `feature(lint_reasons)`.
315# - Stable since Rust 1.82.0: `feature(asm_const)`,
316# `feature(offset_of_nested)`, `feature(raw_ref_op)`.
317# - Stable since Rust 1.84.0: `feature(strict_provenance)`.
318# - Stable since Rust 1.87.0: `feature(asm_goto)`.313# - Stable since Rust 1.87.0: `feature(asm_goto)`.
319# - Expected to become stable: `feature(arbitrary_self_types)`.314# - Expected to become stable: `feature(arbitrary_self_types)`.
320# - To be determined: `feature(used_with_arg)`.315# - To be determined: `feature(used_with_arg)`.
321#316#
322# Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on317# Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on
323# the unstable features in use.318# the unstable features in use.
324rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,lint_reasons,offset_of_nested,raw_ref_op,slice_ptr_len,strict_provenance,used_with_arg319rust_allowed_features := arbitrary_self_types,asm_goto,used_with_arg
325 320
326# `--out-dir` is required to avoid temporaries being created by `rustc` in the321# `--out-dir` is required to avoid temporaries being created by `rustc` in the
327# current working directory, which may be not accessible in the out-of-tree322# current working directory, which may be not accessible in the out-of-tree
@@ -334,7 +329,6 @@ rust_common_cmd = \ · 6 unmodified lines
334 -Zcrate-attr='feature($(rust_allowed_features))' \329 -Zcrate-attr='feature($(rust_allowed_features))' \
335 -Zunstable-options --extern pin_init --extern kernel \330 -Zunstable-options --extern pin_init --extern kernel \
336 --crate-type rlib -L $(objtree)/rust/ \331 --crate-type rlib -L $(objtree)/rust/ \
337 --crate-name $(basename $(notdir $@)) \
338 --sysroot=/dev/null \332 --sysroot=/dev/null \
339 --out-dir $(dir $@) --emit=dep-info=$(depfile)333 --out-dir $(dir $@) --emit=dep-info=$(depfile)
340 334
@@ -347,7 +341,12 @@ rust_common_cmd = \ · 6 unmodified lines
347# would not match each other.341# would not match each other.
348 342
349quiet_cmd_rustc_o_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@343quiet_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)
351 350
352define rule_rustc_o_rs351define rule_rustc_o_rs
353 $(call cmd_and_fixdep,rustc_o_rs)352 $(call cmd_and_fixdep,rustc_o_rs)
scripts/generate_rust_analyzer.py+216−82
@@ -10,8 +10,15 @@ import os · 9 unmodified lines
10import pathlib10import pathlib
11import subprocess11import subprocess
12import sys12import sys
13from typing import Dict, Iterable, List, Literal, Optional, TypedDict
13 14
14def args_crates_cfgs(cfgs):15def 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
21def args_crates_cfgs(cfgs: List[str]) -> Dict[str, List[str]]:
15 crates_cfgs = {}22 crates_cfgs = {}
16 for cfg in cfgs:23 for cfg in cfgs:
17 crate, vals = cfg.split("=", 1)24 crate, vals = cfg.split("=", 1)
@@ -19,54 +26,153 @@ def args_crates_cfgs(cfgs): · 1 unmodified line
19 26
20 return crates_cfgs27 return crates_cfgs
21 28
22def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edition):29class Dependency(TypedDict):
30 crate: int
31 name: str
32
33
34class Source(TypedDict):
35 include_dirs: List[str]
36 exclude_dirs: List[str]
37
38
39class 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
49class ProcMacroCrate(Crate):
50 is_proc_macro: Literal[True]
51 proc_macro_dylib_path: str # `pathlib.Path` is not JSON serializable.
52
53
54class CrateWithGenerated(Crate):
55 source: Source
56
57
58def 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]:
23 # Generate the configuration list.66 # Generate the configuration list.
24 cfg = []67 generated_cfg = []
25 with open(objtree / "include" / "generated" / "rustc_cfg") as fd:68 with open(objtree / "include" / "generated" / "rustc_cfg") as fd:
26 for line in fd:69 for line in fd:
27 line = line.replace("--cfg=", "")70 line = line.replace("--cfg=", "")
28 line = line.replace("\n", "")71 line = line.replace("\n", "")
29 cfg.append(line)72 generated_cfg.append(line)
30 73
31 # Now fill the crates list -- dependencies need to come first.74 # Now fill the crates list.
32 #75 crates: List[Crate] = []
33 # Avoid O(n^2) iterations by keeping a map of indexes.
34 crates = []
35 crates_indexes = {}
36 crates_cfgs = args_crates_cfgs(cfgs)76 crates_cfgs = args_crates_cfgs(cfgs)
37 77
38 def append_crate(display_name, root_module, deps, cfg=[], is_workspace_member=True, is_proc_macro=False, edition="2021"):78 def get_crate_name(path: pathlib.Path) -> str:
39 crate = {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 {
40 "display_name": display_name,96 "display_name": display_name,
41 "root_module": str(root_module),97 "root_module": str(root_module),
42 "is_workspace_member": is_workspace_member,98 "is_workspace_member": is_workspace_member,
43 "is_proc_macro": is_proc_macro,99 "deps": deps,
44 "deps": [{"crate": crates_indexes[dep], "name": dep} for dep in deps],
45 "cfg": cfg,100 "cfg": cfg,
46 "edition": edition,101 "edition": edition,
47 "env": {102 "env": {
48 "RUST_MODFILE": "This is only for rust-analyzer"103 "RUST_MODFILE": "This is only for rust-analyzer"
49 }104 }
50 }105 }
51 if is_proc_macro:106
52 proc_macro_dylib_name = subprocess.check_output(107 def append_proc_macro_crate(
53 [os.environ["RUSTC"], "--print", "file-names", "--crate-name", display_name, "--crate-type", "proc-macro", "-"],108 display_name: str,
54 stdin=subprocess.DEVNULL,109 root_module: pathlib.Path,
55 ).decode('utf-8').strip()110 deps: List[Dependency],
56 crate["proc_macro_dylib_path"] = f"{objtree}/rust/{proc_macro_dylib_name}"111 *,
57 crates_indexes[display_name] = len(crates)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)
58 crates.append(crate)142 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 )
59 164
60 def append_sysroot_crate(165 def append_sysroot_crate(
61 display_name,166 display_name: str,
62 deps,167 deps: List[Dependency],
63 cfg=[],168 *,
64 ):169 cfg: Optional[List[str]] = None,
65 append_crate(170 ) -> Dependency:
171 return append_crate(
66 display_name,172 display_name,
67 sysroot_src / display_name / "src" / "lib.rs",173 sysroot_src / display_name / "src" / "lib.rs",
68 deps,174 deps,
69 cfg,175 cfg=cfg,
70 is_workspace_member=False,176 is_workspace_member=False,
71 # Miguel Ojeda writes:177 # Miguel Ojeda writes:
72 #178 #
@@ -98,129 +204,146 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit · 25 unmodified lines
98 # NB: sysroot crates reexport items from one another so setting up our transitive dependencies204 # NB: sysroot crates reexport items from one another so setting up our transitive dependencies
99 # here is important for ensuring that rust-analyzer can resolve symbols. The sources of truth205 # here is important for ensuring that rust-analyzer can resolve symbols. The sources of truth
100 # for this dependency graph are `(sysroot_src / crate / "Cargo.toml" for crate in crates)`.206 # for this dependency graph are `(sysroot_src / crate / "Cargo.toml" for crate in crates)`.
101 append_sysroot_crate("core", [], cfg=crates_cfgs.get("core", []))207 core = append_sysroot_crate("core", [])
102 append_sysroot_crate("alloc", ["core"])208 alloc = append_sysroot_crate("alloc", [core])
103 append_sysroot_crate("std", ["alloc", "core"])209 std = append_sysroot_crate("std", [alloc, core])
104 append_sysroot_crate("proc_macro", ["core", "std"])210 proc_macro = append_sysroot_crate("proc_macro", [core, std])
105 211
106 append_crate(212 compiler_builtins = append_crate(
107 "compiler_builtins",213 "compiler_builtins",
108 srctree / "rust" / "compiler_builtins.rs",214 srctree / "rust" / "compiler_builtins.rs",
109 ["core"],215 [core],
110 )216 )
111 217
112 append_crate(218 proc_macro2 = append_crate(
113 "proc_macro2",219 "proc_macro2",
114 srctree / "rust" / "proc-macro2" / "lib.rs",220 srctree / "rust" / "proc-macro2" / "lib.rs",
115 ["core", "alloc", "std", "proc_macro"],221 [core, alloc, std, proc_macro],
116 cfg=crates_cfgs["proc_macro2"],
117 )222 )
118 223
119 append_crate(224 quote = append_crate(
120 "quote",225 "quote",
121 srctree / "rust" / "quote" / "lib.rs",226 srctree / "rust" / "quote" / "lib.rs",
122 ["core", "alloc", "std", "proc_macro", "proc_macro2"],227 [core, alloc, std, proc_macro, proc_macro2],
123 cfg=crates_cfgs["quote"],
124 edition="2018",228 edition="2018",
125 )229 )
126 230
127 append_crate(231 syn = append_crate(
128 "syn",232 "syn",
129 srctree / "rust" / "syn" / "lib.rs",233 srctree / "rust" / "syn" / "lib.rs",
130 ["std", "proc_macro", "proc_macro2", "quote"],234 [std, proc_macro, proc_macro2, quote],
131 cfg=crates_cfgs["syn"],
132 )235 )
133 236
134 append_crate(237 macros = append_proc_macro_crate(
135 "macros",238 "macros",
136 srctree / "rust" / "macros" / "lib.rs",239 srctree / "rust" / "macros" / "lib.rs",
137 ["std", "proc_macro", "proc_macro2", "quote", "syn"],240 [std, proc_macro, proc_macro2, quote, syn],
138 is_proc_macro=True,
139 )241 )
140 242
141 append_crate(243 build_error = append_crate(
142 "build_error",244 "build_error",
143 srctree / "rust" / "build_error.rs",245 srctree / "rust" / "build_error.rs",
144 ["core", "compiler_builtins"],246 [core, compiler_builtins],
145 )247 )
146 248
147 append_crate(249 pin_init_internal = append_proc_macro_crate(
148 "pin_init_internal",250 "pin_init_internal",
149 srctree / "rust" / "pin-init" / "internal" / "src" / "lib.rs",251 srctree / "rust" / "pin-init" / "internal" / "src" / "lib.rs",
150 ["std", "proc_macro", "proc_macro2", "quote", "syn"],252 [std, proc_macro, proc_macro2, quote, syn],
151 cfg=["kernel"],
152 is_proc_macro=True,
153 )253 )
154 254
155 append_crate(255 pin_init = append_crate(
156 "pin_init",256 "pin_init",
157 srctree / "rust" / "pin-init" / "src" / "lib.rs",257 srctree / "rust" / "pin-init" / "src" / "lib.rs",
158 ["core", "compiler_builtins", "pin_init_internal", "macros"],258 [core, compiler_builtins, pin_init_internal, macros],
159 cfg=["kernel"],
160 )259 )
161 260
162 append_crate(261 ffi = append_crate(
163 "ffi",262 "ffi",
164 srctree / "rust" / "ffi.rs",263 srctree / "rust" / "ffi.rs",
165 ["core", "compiler_builtins"],264 [core, compiler_builtins],
166 )265 )
167 266
168 def append_crate_with_generated(267 def append_crate_with_generated(
169 display_name,268 display_name: str,
170 deps,269 deps: List[Dependency],
171 ):270 ) -> Dependency:
172 append_crate(271 crate = build_crate(
173 display_name,272 display_name,
174 srctree / "rust"/ display_name / "lib.rs",273 srctree / "rust"/ display_name / "lib.rs",
175 deps,274 deps,
176 cfg=cfg,275 cfg=generated_cfg,
276 is_workspace_member=True,
277 edition=None,
177 )278 )
178 crates[-1]["env"]["OBJTREE"] = str(objtree.resolve(True))279 crate["env"]["OBJTREE"] = str(objtree.resolve(True))
179 crates[-1]["source"] = {280 crate_with_generated: CrateWithGenerated = {
180 "include_dirs": [281 **crate,
181 str(srctree / "rust" / display_name),282 "source": {
182 str(objtree / "rust")283 "include_dirs": [
183 ],284 str(srctree / "rust" / display_name),
184 "exclude_dirs": [],285 str(objtree / "rust"),
286 ],
287 "exclude_dirs": [],
288 },
185 }289 }
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 )
186 297
187 append_crate_with_generated("bindings", ["core", "ffi", "pin_init"])298 scripts = srctree / "scripts"
188 append_crate_with_generated("uapi", ["core", "ffi", "pin_init"])299 makefile = (scripts / "Makefile").read_text()
189 append_crate_with_generated("kernel", ["core", "macros", "build_error", "pin_init", "ffi", "bindings", "uapi"])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 )
190 309
191 def is_root_crate(build_file, target):310 def is_root_crate(build_file: pathlib.Path, target: str) -> bool:
192 try:311 try:
193 return f"{target}.o" in open(build_file).read()312 contents = build_file.read_text()
194 except FileNotFoundError:313 except FileNotFoundError:
195 return False314 return False
315 return f"{target}.o" in contents
196 316
197 # Then, the rest outside of `rust/`.317 # Then, the rest outside of `rust/`.
198 #318 #
199 # We explicitly mention the top-level folders we want to cover.319 # 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 )
201 if external_src is not None:323 if external_src is not None:
202 extra_dirs = [external_src]324 extra_dirs = [external_src]
203 for folder in extra_dirs:325 for folder in extra_dirs:
204 for path in folder.rglob("*.rs"):326 for path in folder.rglob("*.rs"):
205 logging.info("Checking %s", path)327 logging.info("Checking %s", path)
206 name = path.name.replace(".rs", "")328 file_name = path.stem
207 329
208 # Skip those that are not crate roots.330 # Skip those that are not crate roots.
209 if not is_root_crate(path.parent / "Makefile", name) and \331 if not is_root_crate(path.parent / "Makefile", file_name) and \
210 not is_root_crate(path.parent / "Kbuild", name):332 not is_root_crate(path.parent / "Kbuild", file_name):
211 continue333 continue
212 334
213 logging.info("Adding %s", name)335 crate_name = get_crate_name(path)
336 logging.info("Adding %s", crate_name)
214 append_crate(337 append_crate(
215 name,338 crate_name,
216 path,339 path,
217 ["core", "kernel", "pin_init"],340 [core, kernel, pin_init],
218 cfg=cfg,341 cfg=generated_cfg,
219 )342 )
220 343
221 return crates344 return crates
222 345
223def main():346def main() -> None:
224 parser = argparse.ArgumentParser()347 parser = argparse.ArgumentParser()
225 parser.add_argument('--verbose', '-v', action='store_true')348 parser.add_argument('--verbose', '-v', action='store_true')
226 parser.add_argument('--cfgs', action='append', default=[])349 parser.add_argument('--cfgs', action='append', default=[])
@@ -230,7 +353,18 @@ def main(): · 3 unmodified lines
230 parser.add_argument("sysroot", type=pathlib.Path)353 parser.add_argument("sysroot", type=pathlib.Path)
231 parser.add_argument("sysroot_src", type=pathlib.Path)354 parser.add_argument("sysroot_src", type=pathlib.Path)
232 parser.add_argument("exttree", type=pathlib.Path, nargs="?")355 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())
234 368
235 logging.basicConfig(369 logging.basicConfig(
236 format="[%(asctime)s] [%(levelname)s] %(message)s",370 format="[%(asctime)s] [%(levelname)s] %(message)s",
scripts/min-tool-version.sh+2−2
@@ -31,10 +31,10 @@ llvm) · 30 unmodified lines
31 fi31 fi
32 ;;32 ;;
33rustc)33rustc)
34 echo 1.78.034 echo 1.85.0
35 ;;35 ;;
36bindgen)36bindgen)
37 echo 0.65.137 echo 0.71.1
38 ;;38 ;;
39*)39*)
40 echo "$1: unknown tool" >&240 echo "$1: unknown tool" >&2
scripts/rust_is_available.sh+1−35
@@ -121,14 +121,8 @@ fi · 120 unmodified lines
121# Check that the Rust bindings generator is suitable.121# Check that the Rust bindings generator is suitable.
122#122#
123# Non-stable and distributions' versions may have a version suffix, e.g. `-dev`.123# Non-stable and distributions' versions may have a version suffix, e.g. `-dev`.
124#
125# The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0
126# (https://github.com/rust-lang/rust-bindgen/pull/2678) and 0.71.0
127# (https://github.com/rust-lang/rust-bindgen/pull/3040). It can be removed when
128# the minimum version is upgraded past the latter (0.69.1 and 0.71.1 both fixed
129# the issue).
130rust_bindings_generator_output=$( \124rust_bindings_generator_output=$( \
131 LC_ALL=C "$BINDGEN" --version workaround-for-0.69.0 2>/dev/null125 LC_ALL=C "$BINDGEN" --version 2>/dev/null
132) || rust_bindings_generator_code=$?126) || rust_bindings_generator_code=$?
133if [ -n "$rust_bindings_generator_code" ]; then127if [ -n "$rust_bindings_generator_code" ]; then
134 echo >&2 "***"128 echo >&2 "***"
@@ -163,19 +157,6 @@ if [ "$rust_bindings_generator_cversion" -lt "$rust_bindings_generator_min_cvers · 28 unmodified lines
163 echo >&2 "***"157 echo >&2 "***"
164 exit 1158 exit 1
165fi159fi
166if [ "$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
178fi
179 160
180# Check that the `libclang` used by the Rust bindings generator is suitable.161# Check that the `libclang` used by the Rust bindings generator is suitable.
181#162#
@@ -227,21 +208,6 @@ if [ "$bindgen_libclang_cversion" -lt "$bindgen_libclang_min_cversion" ]; then · 45 unmodified lines
227 exit 1208 exit 1
228fi209fi
229 210
230if [ "$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
243fi
244
245# If the C compiler is Clang, then we can also check whether its version211# If the C compiler is Clang, then we can also check whether its version
246# matches the `libclang` version used by the Rust bindings generator.212# matches the `libclang` version used by the Rust bindings generator.
247#213#
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
3F(foo);
scripts/rust_is_available_test.py+3−55
@@ -54,37 +54,23 @@ else: · 53 unmodified lines
54""")54""")
55 55
56 @classmethod56 @classmethod
57 def generate_bindgen(cls, version_stdout, libclang_stderr, version_0_66_patched=False, libclang_concat_patched=False):57 def generate_bindgen(cls, version_stdout, libclang_stderr):
58 if libclang_stderr is None:58 if libclang_stderr is None:
59 libclang_case = f"raise SystemExit({cls.bindgen_default_bindgen_libclang_failure_exit_code})"59 libclang_case = f"raise SystemExit({cls.bindgen_default_bindgen_libclang_failure_exit_code})"
60 else:60 else:
61 libclang_case = f"print({repr(libclang_stderr)}, file=sys.stderr)"61 libclang_case = f"print({repr(libclang_stderr)}, file=sys.stderr)"
62 62
63 if version_0_66_patched:
64 version_0_66_case = "pass"
65 else:
66 version_0_66_case = "raise SystemExit(1)"
67
68 if libclang_concat_patched:
69 libclang_concat_case = "print('pub static mut foofoo: ::std::os::raw::c_int;')"
70 else:
71 libclang_concat_case = "pass"
72
73 return cls.generate_executable(f"""#!/usr/bin/env python363 return cls.generate_executable(f"""#!/usr/bin/env python3
74import sys64import sys
75if "rust_is_available_bindgen_libclang.h" in " ".join(sys.argv):65if "rust_is_available_bindgen_libclang.h" in " ".join(sys.argv):
76 {libclang_case}66 {libclang_case}
77elif "rust_is_available_bindgen_0_66.h" in " ".join(sys.argv):
78 {version_0_66_case}
79elif "rust_is_available_bindgen_libclang_concat.h" in " ".join(sys.argv):
80 {libclang_concat_case}
81else:67else:
82 print({repr(version_stdout)})68 print({repr(version_stdout)})
83""")69""")
84 70
85 @classmethod71 @classmethod
86 def generate_bindgen_version(cls, stdout, version_0_66_patched=False):72 def generate_bindgen_version(cls, stdout):
87 return cls.generate_bindgen(stdout, cls.bindgen_default_bindgen_libclang_stderr, version_0_66_patched)73 return cls.generate_bindgen(stdout, cls.bindgen_default_bindgen_libclang_stderr)
88 74
89 @classmethod75 @classmethod
90 def generate_bindgen_libclang_failure(cls):76 def generate_bindgen_libclang_failure(cls):
@@ -245,19 +231,6 @@ else: · 154 unmodified lines
245 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })231 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })
246 self.assertIn(f"Rust bindings generator '{bindgen}' is too old.", result.stderr)232 self.assertIn(f"Rust bindings generator '{bindgen}' is too old.", result.stderr)
247 233
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
261 def test_bindgen_libclang_failure(self):234 def test_bindgen_libclang_failure(self):
262 bindgen = self.generate_bindgen_libclang_failure()235 bindgen = self.generate_bindgen_libclang_failure()
263 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })236 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })
@@ -275,31 +248,6 @@ else: · 11 unmodified lines
275 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })248 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })
276 self.assertIn(f"libclang (used by the Rust bindings generator '{bindgen}') is too old.", result.stderr)249 self.assertIn(f"libclang (used by the Rust bindings generator '{bindgen}') is too old.", result.stderr)
277 250
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
303 def test_clang_matches_bindgen_libclang_different_bindgen(self):251 def test_clang_matches_bindgen_libclang_different_bindgen(self):
304 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")252 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")
305 result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen })253 result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen })