Skip to content

Commit 8ede842

Browse files
committed
Pull Rust updates from Miguel Ojeda: "Another routine one in terms of features. We got two version upgrades this time, but in terms of lines, 'alloc' changes are not very large. Toolchain and infrastructure: - Upgrade to Rust 1.76.0 This time around, due to how the kernel and Rust schedules have aligned, there are two upgrades in fact. These allow us to remove two more unstable features ('const_maybe_uninit_zeroed' and 'ptr_metadata') from the list, among other improvements - Mark 'rustc' (and others) invocations as recursive, which fixes a new warning and prepares us for the future in case we eventually take advantage of the Make jobserver 'kernel' crate: - Add the 'container_of!' macro - Stop using the unstable 'ptr_metadata' feature by employing the now stable 'byte_sub' method to implement 'Arc::from_raw()' - Add the 'time' module with a 'msecs_to_jiffies()' conversion function to begin with, to be used by Rust Binder - Add 'notify_sync()' and 'wait_interruptible_timeout()' methods to 'CondVar', to be used by Rust Binder - Update integer types for 'CondVar' - Rename 'wait_list' field to 'wait_queue_head' in 'CondVar' - Implement 'Display' and 'Debug' for 'BStr' - Add the 'try_from_foreign()' method to the 'ForeignOwnable' trait - Add reexports for macros so that they can be used from the right module (in addition to the root) - A series of code documentation improvements, including adding intra-doc links, consistency improvements, typo fixes... 'macros' crate: - Place generated 'init_module()' function in '.init.text' Documentation: - Add documentation on Rust doctests and how they work" * tag 'rust-6.9' of https://github.com/Rust-for-Linux/linux: (29 commits) rust: upgrade to Rust 1.76.0 kbuild: mark `rustc` (and others) invocations as recursive rust: add `container_of!` macro rust: str: implement `Display` and `Debug` for `BStr` rust: module: place generated init_module() function in .init.text rust: types: add `try_from_foreign()` method docs: rust: Add description of Rust documentation test as KUnit ones docs: rust: Move testing to a separate page rust: kernel: stop using ptr_metadata feature rust: kernel: add reexports for macros rust: locked_by: shorten doclink preview rust: kernel: remove unneeded doclink targets rust: kernel: add doclinks rust: kernel: add blank lines in front of code blocks rust: kernel: mark code fragments in docs with backticks rust: kernel: unify spelling of refcount in docs rust: str: move SAFETY comment in front of unsafe block rust: str: use `NUL` instead of 0 in doc comments rust: kernel: add srctree-relative doclinks rust: ioctl: end top-level module docs with full stop ...
2 parents 5a2a15c + 768409c commit 8ede842

35 files changed

+809
-252
lines changed

Documentation/process/changes.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ you probably needn't concern yourself with pcmciautils.
3131
====================== =============== ========================================
3232
GNU C 5.1 gcc --version
3333
Clang/LLVM (optional) 11.0.0 clang --version
34-
Rust (optional) 1.74.1 rustc --version
34+
Rust (optional) 1.76.0 rustc --version
3535
bindgen (optional) 0.65.1 bindgen --version
3636
GNU make 3.82 make --version
3737
bash 4.2 bash --version

Documentation/rust/general-information.rst

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -77,27 +77,3 @@ configuration:
7777
#[cfg(CONFIG_X="y")] // Enabled as a built-in (`y`)
7878
#[cfg(CONFIG_X="m")] // Enabled as a module (`m`)
7979
#[cfg(not(CONFIG_X))] // Disabled
80-
81-
82-
Testing
83-
-------
84-
85-
There are the tests that come from the examples in the Rust documentation
86-
and get transformed into KUnit tests. These can be run via KUnit. For example
87-
via ``kunit_tool`` (``kunit.py``) on the command line::
88-
89-
./tools/testing/kunit/kunit.py run --make_options LLVM=1 --arch x86_64 --kconfig_add CONFIG_RUST=y
90-
91-
Alternatively, KUnit can run them as kernel built-in at boot. Refer to
92-
Documentation/dev-tools/kunit/index.rst for the general KUnit documentation
93-
and Documentation/dev-tools/kunit/architecture.rst for the details of kernel
94-
built-in vs. command line testing.
95-
96-
Additionally, there are the ``#[test]`` tests. These can be run using
97-
the ``rusttest`` Make target::
98-
99-
make LLVM=1 rusttest
100-
101-
This requires the kernel ``.config`` and downloads external repositories.
102-
It runs the ``#[test]`` tests on the host (currently) and thus is fairly
103-
limited in what these tests can test.

Documentation/rust/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ configurations.
4040
general-information
4141
coding-guidelines
4242
arch-support
43+
testing
4344

4445
.. only:: subproject and html
4546

Documentation/rust/testing.rst

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
Testing
4+
=======
5+
6+
This document contains useful information how to test the Rust code in the
7+
kernel.
8+
9+
There are two sorts of tests:
10+
11+
- The KUnit tests.
12+
- The ``#[test]`` tests.
13+
14+
The KUnit tests
15+
---------------
16+
17+
These are the tests that come from the examples in the Rust documentation. They
18+
get transformed into KUnit tests.
19+
20+
Usage
21+
*****
22+
23+
These tests can be run via KUnit. For example via ``kunit_tool`` (``kunit.py``)
24+
on the command line::
25+
26+
./tools/testing/kunit/kunit.py run --make_options LLVM=1 --arch x86_64 --kconfig_add CONFIG_RUST=y
27+
28+
Alternatively, KUnit can run them as kernel built-in at boot. Refer to
29+
Documentation/dev-tools/kunit/index.rst for the general KUnit documentation
30+
and Documentation/dev-tools/kunit/architecture.rst for the details of kernel
31+
built-in vs. command line testing.
32+
33+
To use these KUnit doctests, the following must be enabled::
34+
35+
CONFIG_KUNIT
36+
Kernel hacking -> Kernel Testing and Coverage -> KUnit - Enable support for unit tests
37+
CONFIG_RUST_KERNEL_DOCTESTS
38+
Kernel hacking -> Rust hacking -> Doctests for the `kernel` crate
39+
40+
in the kernel config system.
41+
42+
KUnit tests are documentation tests
43+
***********************************
44+
45+
These documentation tests are typically examples of usage of any item (e.g.
46+
function, struct, module...).
47+
48+
They are very convenient because they are just written alongside the
49+
documentation. For instance:
50+
51+
.. code-block:: rust
52+
53+
/// Sums two numbers.
54+
///
55+
/// ```
56+
/// assert_eq!(mymod::f(10, 20), 30);
57+
/// ```
58+
pub fn f(a: i32, b: i32) -> i32 {
59+
a + b
60+
}
61+
62+
In userspace, the tests are collected and run via ``rustdoc``. Using the tool
63+
as-is would be useful already, since it allows verifying that examples compile
64+
(thus enforcing they are kept in sync with the code they document) and as well
65+
as running those that do not depend on in-kernel APIs.
66+
67+
For the kernel, however, these tests get transformed into KUnit test suites.
68+
This means that doctests get compiled as Rust kernel objects, allowing them to
69+
run against a built kernel.
70+
71+
A benefit of this KUnit integration is that Rust doctests get to reuse existing
72+
testing facilities. For instance, the kernel log would look like::
73+
74+
KTAP version 1
75+
1..1
76+
KTAP version 1
77+
# Subtest: rust_doctests_kernel
78+
1..59
79+
# rust_doctest_kernel_build_assert_rs_0.location: rust/kernel/build_assert.rs:13
80+
ok 1 rust_doctest_kernel_build_assert_rs_0
81+
# rust_doctest_kernel_build_assert_rs_1.location: rust/kernel/build_assert.rs:56
82+
ok 2 rust_doctest_kernel_build_assert_rs_1
83+
# rust_doctest_kernel_init_rs_0.location: rust/kernel/init.rs:122
84+
ok 3 rust_doctest_kernel_init_rs_0
85+
...
86+
# rust_doctest_kernel_types_rs_2.location: rust/kernel/types.rs:150
87+
ok 59 rust_doctest_kernel_types_rs_2
88+
# rust_doctests_kernel: pass:59 fail:0 skip:0 total:59
89+
# Totals: pass:59 fail:0 skip:0 total:59
90+
ok 1 rust_doctests_kernel
91+
92+
Tests using the `? <https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator>`_
93+
operator are also supported as usual, e.g.:
94+
95+
.. code-block:: rust
96+
97+
/// ```
98+
/// # use kernel::{spawn_work_item, workqueue};
99+
/// spawn_work_item!(workqueue::system(), || pr_info!("x"))?;
100+
/// # Ok::<(), Error>(())
101+
/// ```
102+
103+
The tests are also compiled with Clippy under ``CLIPPY=1``, just like normal
104+
code, thus also benefitting from extra linting.
105+
106+
In order for developers to easily see which line of doctest code caused a
107+
failure, a KTAP diagnostic line is printed to the log. This contains the
108+
location (file and line) of the original test (i.e. instead of the location in
109+
the generated Rust file)::
110+
111+
# rust_doctest_kernel_types_rs_2.location: rust/kernel/types.rs:150
112+
113+
Rust tests appear to assert using the usual ``assert!`` and ``assert_eq!``
114+
macros from the Rust standard library (``core``). We provide a custom version
115+
that forwards the call to KUnit instead. Importantly, these macros do not
116+
require passing context, unlike those for KUnit testing (i.e.
117+
``struct kunit *``). This makes them easier to use, and readers of the
118+
documentation do not need to care about which testing framework is used. In
119+
addition, it may allow us to test third-party code more easily in the future.
120+
121+
A current limitation is that KUnit does not support assertions in other tasks.
122+
Thus, we presently simply print an error to the kernel log if an assertion
123+
actually failed. Additionally, doctests are not run for nonpublic functions.
124+
125+
The ``#[test]`` tests
126+
---------------------
127+
128+
Additionally, there are the ``#[test]`` tests. These can be run using the
129+
``rusttest`` Make target::
130+
131+
make LLVM=1 rusttest
132+
133+
This requires the kernel ``.config`` and downloads external repositories. It
134+
runs the ``#[test]`` tests on the host (currently) and thus is fairly limited in
135+
what these tests can test.

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,7 +1201,7 @@ prepare0: archprepare
12011201
# All the preparing..
12021202
prepare: prepare0
12031203
ifdef CONFIG_RUST
1204-
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh
1204+
+$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh
12051205
$(Q)$(MAKE) $(build)=rust
12061206
endif
12071207

@@ -1711,7 +1711,7 @@ $(DOC_TARGETS):
17111711
# "Is Rust available?" target
17121712
PHONY += rustavailable
17131713
rustavailable:
1714-
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh && echo "Rust is available!"
1714+
+$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh && echo "Rust is available!"
17151715

17161716
# Documentation target
17171717
#

rust/Makefile

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.o
4040
ifdef CONFIG_RUST
4141

4242
# `$(rust_flags)` is passed in case the user added `--sysroot`.
43-
rustc_sysroot := $(shell $(RUSTC) $(rust_flags) --print sysroot)
43+
rustc_sysroot := $(shell MAKEFLAGS= $(RUSTC) $(rust_flags) --print sysroot)
4444
rustc_host_target := $(shell $(RUSTC) --version --verbose | grep -F 'host: ' | cut -d' ' -f2)
4545
RUST_LIB_SRC ?= $(rustc_sysroot)/lib/rustlib/src/rust/library
4646

@@ -108,14 +108,14 @@ rustdoc-macros: private rustdoc_host = yes
108108
rustdoc-macros: private rustc_target_flags = --crate-type proc-macro \
109109
--extern proc_macro
110110
rustdoc-macros: $(src)/macros/lib.rs FORCE
111-
$(call if_changed,rustdoc)
111+
+$(call if_changed,rustdoc)
112112

113113
rustdoc-core: private rustc_target_flags = $(core-cfgs)
114114
rustdoc-core: $(RUST_LIB_SRC)/core/src/lib.rs FORCE
115-
$(call if_changed,rustdoc)
115+
+$(call if_changed,rustdoc)
116116

117117
rustdoc-compiler_builtins: $(src)/compiler_builtins.rs rustdoc-core FORCE
118-
$(call if_changed,rustdoc)
118+
+$(call if_changed,rustdoc)
119119

120120
# We need to allow `rustdoc::broken_intra_doc_links` because some
121121
# `no_global_oom_handling` functions refer to non-`no_global_oom_handling`
@@ -124,15 +124,15 @@ rustdoc-compiler_builtins: $(src)/compiler_builtins.rs rustdoc-core FORCE
124124
rustdoc-alloc: private rustc_target_flags = $(alloc-cfgs) \
125125
-Arustdoc::broken_intra_doc_links
126126
rustdoc-alloc: $(src)/alloc/lib.rs rustdoc-core rustdoc-compiler_builtins FORCE
127-
$(call if_changed,rustdoc)
127+
+$(call if_changed,rustdoc)
128128

129129
rustdoc-kernel: private rustc_target_flags = --extern alloc \
130130
--extern build_error --extern macros=$(objtree)/$(obj)/libmacros.so \
131131
--extern bindings --extern uapi
132132
rustdoc-kernel: $(src)/kernel/lib.rs rustdoc-core rustdoc-macros \
133133
rustdoc-compiler_builtins rustdoc-alloc $(obj)/libmacros.so \
134134
$(obj)/bindings.o FORCE
135-
$(call if_changed,rustdoc)
135+
+$(call if_changed,rustdoc)
136136

137137
quiet_cmd_rustc_test_library = RUSTC TL $<
138138
cmd_rustc_test_library = \
@@ -146,18 +146,18 @@ quiet_cmd_rustc_test_library = RUSTC TL $<
146146
--crate-name $(subst rusttest-,,$(subst rusttestlib-,,$@)) $<
147147

148148
rusttestlib-build_error: $(src)/build_error.rs rusttest-prepare FORCE
149-
$(call if_changed,rustc_test_library)
149+
+$(call if_changed,rustc_test_library)
150150

151151
rusttestlib-macros: private rustc_target_flags = --extern proc_macro
152152
rusttestlib-macros: private rustc_test_library_proc = yes
153153
rusttestlib-macros: $(src)/macros/lib.rs rusttest-prepare FORCE
154-
$(call if_changed,rustc_test_library)
154+
+$(call if_changed,rustc_test_library)
155155

156156
rusttestlib-bindings: $(src)/bindings/lib.rs rusttest-prepare FORCE
157-
$(call if_changed,rustc_test_library)
157+
+$(call if_changed,rustc_test_library)
158158

159159
rusttestlib-uapi: $(src)/uapi/lib.rs rusttest-prepare FORCE
160-
$(call if_changed,rustc_test_library)
160+
+$(call if_changed,rustc_test_library)
161161

162162
quiet_cmd_rustdoc_test = RUSTDOC T $<
163163
cmd_rustdoc_test = \
@@ -189,7 +189,7 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
189189
$(src)/kernel/lib.rs $(obj)/kernel.o \
190190
$(objtree)/scripts/rustdoc_test_builder \
191191
$(objtree)/scripts/rustdoc_test_gen FORCE
192-
$(call if_changed,rustdoc_test_kernel)
192+
+$(call if_changed,rustdoc_test_kernel)
193193

194194
# We cannot use `-Zpanic-abort-tests` because some tests are dynamic,
195195
# so for the moment we skip `-Cpanic=abort`.
@@ -254,21 +254,21 @@ quiet_cmd_rustsysroot = RUSTSYSROOT
254254
$(objtree)/$(obj)/test/sysroot/lib/rustlib/$(rustc_host_target)/lib
255255

256256
rusttest-prepare: FORCE
257-
$(call if_changed,rustsysroot)
257+
+$(call if_changed,rustsysroot)
258258

259259
rusttest-macros: private rustc_target_flags = --extern proc_macro
260260
rusttest-macros: private rustdoc_test_target_flags = --crate-type proc-macro
261261
rusttest-macros: $(src)/macros/lib.rs rusttest-prepare FORCE
262-
$(call if_changed,rustc_test)
263-
$(call if_changed,rustdoc_test)
262+
+$(call if_changed,rustc_test)
263+
+$(call if_changed,rustdoc_test)
264264

265265
rusttest-kernel: private rustc_target_flags = --extern alloc \
266266
--extern build_error --extern macros --extern bindings --extern uapi
267267
rusttest-kernel: $(src)/kernel/lib.rs rusttest-prepare \
268268
rusttestlib-build_error rusttestlib-macros rusttestlib-bindings \
269269
rusttestlib-uapi FORCE
270-
$(call if_changed,rustc_test)
271-
$(call if_changed,rustc_test_library)
270+
+$(call if_changed,rustc_test)
271+
+$(call if_changed,rustc_test_library)
272272

273273
ifdef CONFIG_CC_IS_CLANG
274274
bindgen_c_flags = $(c_flags)
@@ -396,7 +396,7 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
396396
# Therefore, to get `libmacros.so` automatically recompiled when the compiler
397397
# version changes, we add `core.o` as a dependency (even if it is not needed).
398398
$(obj)/libmacros.so: $(src)/macros/lib.rs $(obj)/core.o FORCE
399-
$(call if_changed_dep,rustc_procmacro)
399+
+$(call if_changed_dep,rustc_procmacro)
400400

401401
quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L $@
402402
cmd_rustc_library = \
@@ -435,36 +435,36 @@ $(obj)/core.o: private skip_flags = -Dunreachable_pub
435435
$(obj)/core.o: private rustc_objcopy = $(foreach sym,$(redirect-intrinsics),--redefine-sym $(sym)=__rust$(sym))
436436
$(obj)/core.o: private rustc_target_flags = $(core-cfgs)
437437
$(obj)/core.o: $(RUST_LIB_SRC)/core/src/lib.rs scripts/target.json FORCE
438-
$(call if_changed_dep,rustc_library)
438+
+$(call if_changed_dep,rustc_library)
439439

440440
$(obj)/compiler_builtins.o: private rustc_objcopy = -w -W '__*'
441441
$(obj)/compiler_builtins.o: $(src)/compiler_builtins.rs $(obj)/core.o FORCE
442-
$(call if_changed_dep,rustc_library)
442+
+$(call if_changed_dep,rustc_library)
443443

444444
$(obj)/alloc.o: private skip_clippy = 1
445445
$(obj)/alloc.o: private skip_flags = -Dunreachable_pub
446446
$(obj)/alloc.o: private rustc_target_flags = $(alloc-cfgs)
447447
$(obj)/alloc.o: $(src)/alloc/lib.rs $(obj)/compiler_builtins.o FORCE
448-
$(call if_changed_dep,rustc_library)
448+
+$(call if_changed_dep,rustc_library)
449449

450450
$(obj)/build_error.o: $(src)/build_error.rs $(obj)/compiler_builtins.o FORCE
451-
$(call if_changed_dep,rustc_library)
451+
+$(call if_changed_dep,rustc_library)
452452

453453
$(obj)/bindings.o: $(src)/bindings/lib.rs \
454454
$(obj)/compiler_builtins.o \
455455
$(obj)/bindings/bindings_generated.rs \
456456
$(obj)/bindings/bindings_helpers_generated.rs FORCE
457-
$(call if_changed_dep,rustc_library)
457+
+$(call if_changed_dep,rustc_library)
458458

459459
$(obj)/uapi.o: $(src)/uapi/lib.rs \
460460
$(obj)/compiler_builtins.o \
461461
$(obj)/uapi/uapi_generated.rs FORCE
462-
$(call if_changed_dep,rustc_library)
462+
+$(call if_changed_dep,rustc_library)
463463

464464
$(obj)/kernel.o: private rustc_target_flags = --extern alloc \
465465
--extern build_error --extern macros --extern bindings --extern uapi
466466
$(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/alloc.o $(obj)/build_error.o \
467467
$(obj)/libmacros.so $(obj)/bindings.o $(obj)/uapi.o FORCE
468-
$(call if_changed_dep,rustc_library)
468+
+$(call if_changed_dep,rustc_library)
469469

470470
endif # CONFIG_RUST

0 commit comments

Comments
 (0)