Skip to contentSkip to conversation

Rust fixes for the upcoming 1.89 release

PATCH Applied Miguel Ojeda 4 participants 8 messages Jul 12, 2025 – Jul 14, 2025

Subsystems (7)
lore
Share & tools
lore

Miguel Ojeda

author maintainer
#0 lore raw

cover Rust fixes for the upcoming 1.89 release

A couple fixes for the upcoming 1.89.0 release, currently in beta.

With this, current nightly (1.90) gets also clean.

Miguel Ojeda (2):
objtool/rust: add one more noreturn Rust function for Rust 1.89.0
rust: use #[used(compiler)] to fix build and modpost with Rust >=

    1.89.0
 rust/Makefile           |  1 +
 rust/kernel/firmware.rs |  2 +-
 rust/kernel/kunit.rs    |  2 +-
 rust/kernel/lib.rs      |  3 +++
 rust/macros/module.rs   | 10 +++++-----
 scripts/Makefile.build  |  3 ++-
 tools/objtool/check.c   |  1 +
 7 files changed, 14 insertions(+), 8 deletions(-)

base-commit: fe49aae0fcb348b656bbde2eb1d1c75d8a1a5c3c --
2.50.1

author maintainer
#1 lore raw

PATCH 1/2 objtool/rust: add one more `noreturn` Rust function for Rust 1.89.0

Starting with Rust 1.89.0 (expected 2025-08-07), under CONFIG_RUST_DEBUG_ASSERTIONS=y, objtool may report:

rust/kernel.o: warning: objtool: _R..._6kernel4pageNtB5_4Page8read_raw() falls through to next function _R..._6kernel4pageNtB5_4Page9write_raw()

(and many others) due to calls to the noreturn symbol:

core::panicking::panic_nounwind_fmt

Thus add the mangled one to the list so that objtool knows it is actually noreturn.

See commit 56d680dd23c3 ("objtool/rust: list noreturn Rust functions") for more details.

Cc [email protected] # Needed in 6.12.y and later (Rust is pinned in older LTSs).
Cc Josh Poimboeuf <[email protected]>
Cc Peter Zijlstra <[email protected]>
---
 tools/objtool/check.c | 1 +
 1 file changed, 1 insertion(+)
tools/objtool/check.c +1 -0
index f23bdda737aa..3257eefc41ed 100644
@@ -224,6 +224,7 @@ static bool is_rust_noreturn(const struct symbol *func)
 	       str_ends_with(func->name, "_4core9panicking14panic_explicit")				||
 	       str_ends_with(func->name, "_4core9panicking14panic_nounwind")				||
 	       str_ends_with(func->name, "_4core9panicking18panic_bounds_check")			||
+	       str_ends_with(func->name, "_4core9panicking18panic_nounwind_fmt")			||
 	       str_ends_with(func->name, "_4core9panicking19assert_failed_inner")			||
 	       str_ends_with(func->name, "_4core9panicking30panic_null_pointer_dereference")		||
 	       str_ends_with(func->name, "_4core9panicking36panic_misaligned_pointer_dereference")	||
Signature · 1 line
2.50.1
maintainer Acked-by on v1 1/2
#2 lore raw

Re: [PATCH 1/2] objtool/rust: add one more `noreturn` Rust function for Rust 1.89.0

Quoted 13 lines · Miguel Ojeda

Starting with Rust 1.89.0 (expected 2025-08-07), under CONFIG_RUST_DEBUG_ASSERTIONS=y, objtool may report:

rust/kernel.o: warning: objtool: _R..._6kernel4pageNtB5_4Page8read_raw() falls through to next function _R..._6kernel4pageNtB5_4Page9write_raw()

(and many others) due to calls to the noreturn symbol:

core::panicking::panic_nounwind_fmt

Thus add the mangled one to the list so that objtool knows it is actually noreturn.

Quoted 7 lines

See commit 56d680dd23c3 ("objtool/rust: list noreturn Rust functions") for more details.

Cc [email protected] # Needed in 6.12.y and later (Rust is pinned in older LTSs).
Cc Josh Poimboeuf <[email protected]>
Cc Peter Zijlstra <[email protected]>
Quoted 9 lines
---
 tools/objtool/check.c | 1 +
 1 file changed, 1 insertion(+)
tools/objtool/check.c +0 -0
index f23bdda737aa..3257eefc41ed 100644

tools/objtool/check.c static bool is_rust_noreturn(const struct symbol *func) · line 230

Quoted 7 lines
tools/objtool/check.c +1 -0
@@ -224,6 +224,7 @@ static bool is_rust_noreturn(const struct symbol *func)
 	       str_ends_with(func->name, "_4core9panicking14panic_explicit")				||
 	       str_ends_with(func->name, "_4core9panicking14panic_nounwind")				||
 	       str_ends_with(func->name, "_4core9panicking18panic_bounds_check")			||
+	       str_ends_with(func->name, "_4core9panicking18panic_nounwind_fmt")			||
 	       str_ends_with(func->name, "_4core9panicking19assert_failed_inner")			||
 	       str_ends_with(func->name, "_4core9panicking30panic_null_pointer_dereference")		||
 	       str_ends_with(func->name, "_4core9panicking36panic_misaligned_pointer_dereference")	||

Just having "_4core9panicking" substring is not sufficient?

reviewer
#3 lore raw

Re: [PATCH 1/2] objtool/rust: add one more `noreturn` Rust function for Rust 1.89.0

Quoted 29 lines · Peter Zijlstra
Quoted 13 lines · Miguel Ojeda

Starting with Rust 1.89.0 (expected 2025-08-07), under CONFIG_RUST_DEBUG_ASSERTIONS=y, objtool may report:

rust/kernel.o: warning: objtool: _R..._6kernel4pageNtB5_4Page8read_raw() falls through to next function _R..._6kernel4pageNtB5_4Page9write_raw()

(and many others) due to calls to the noreturn symbol:

core::panicking::panic_nounwind_fmt

Thus add the mangled one to the list so that objtool knows it is actually noreturn.

Quoted 7 lines

See commit 56d680dd23c3 ("objtool/rust: list noreturn Rust functions") for more details.

Cc [email protected] # Needed in 6.12.y and later (Rust is pinned in older LTSs).
Cc Josh Poimboeuf <[email protected]>
Cc Peter Zijlstra <[email protected]>
Quoted 4 lines
---
 tools/objtool/check.c | 1 +
 1 file changed, 1 insertion(+)
Quoted 14 lines

tools/objtool/check.c static bool is_rust_noreturn(const struct symbol *func) · line 230

Quoted 12 lines
tools/objtool/check.c +1 -0
index f23bdda737aa..3257eefc41ed 100644
@@ -224,6 +224,7 @@ static bool is_rust_noreturn(const struct symbol *func)
             str_ends_with(func->name, "_4core9panicking14panic_explicit")                            ||
             str_ends_with(func->name, "_4core9panicking14panic_nounwind")                            ||
             str_ends_with(func->name, "_4core9panicking18panic_bounds_check")                        ||
+            str_ends_with(func->name, "_4core9panicking18panic_nounwind_fmt")                        ||
             str_ends_with(func->name, "_4core9panicking19assert_failed_inner")                       ||
             str_ends_with(func->name, "_4core9panicking30panic_null_pointer_dereference")            ||
             str_ends_with(func->name, "_4core9panicking36panic_misaligned_pointer_dereference")      ||

Just having "_4core9panicking" substring is not sufficient?

That prefix just means it is defined in the panicking.rs file, which also has a few functions that are not noreturn.

Alice

maintainer
#4 lore raw

Re: [PATCH 1/2] objtool/rust: add one more `noreturn` Rust function for Rust 1.89.0

Quoted 18 lines · Alice Ryhl
Quoted 17 lines
Quoted 8 lines
 tools/objtool/check.c | 1 +
 1 file changed, 1 insertion(+)
tools/objtool/check.c +0 -0
index f23bdda737aa..3257eefc41ed 100644

tools/objtool/check.c static bool is_rust_noreturn(const struct symbol *func) · line 230

Quoted 7 lines
tools/objtool/check.c +1 -0
@@ -224,6 +224,7 @@ static bool is_rust_noreturn(const struct symbol *func)
             str_ends_with(func->name, "_4core9panicking14panic_explicit")                            ||
             str_ends_with(func->name, "_4core9panicking14panic_nounwind")                            ||
             str_ends_with(func->name, "_4core9panicking18panic_bounds_check")                        ||
+            str_ends_with(func->name, "_4core9panicking18panic_nounwind_fmt")                        ||
             str_ends_with(func->name, "_4core9panicking19assert_failed_inner")                       ||
             str_ends_with(func->name, "_4core9panicking30panic_null_pointer_dereference")            ||
             str_ends_with(func->name, "_4core9panicking36panic_misaligned_pointer_dereference")      ||

Just having "_4core9panicking" substring is not sufficient?

Quoted 2 lines

That prefix just means it is defined in the panicking.rs file, which also has a few functions that are not noreturn.

Oh well, I figured it was too good to be true anyway. Its just that there was a lot of that around and I had to ask :-)

author maintainer
#5 lore raw

PATCH 2/2 rust: use `#[used(compiler)]` to fix build and `modpost` with Rust >= 1.89.0

In reply to Miguel Ojeda

Starting with Rust 1.89.0 (expected 2025-08-07), the Rust compiler fails to build the rusttest target due to undefined references such as:

    kernel...-cgu.0:(.text....+0x116): undefined reference to
    `rust_helper_kunit_get_current_test'

Moreover, tooling like modpost gets confused:

WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/nova/nova.o
ERROR: modpost: missing MODULE_LICENSE() in drivers/gpu/nova-core/nova_core.o

The reason behind both issues is that the Rust compiler will now [1] treat #[used] as #[used(linker)] instead of #[used(compiler)] for our targets. This means that the retain section flag (R, SHF_GNU_RETAIN) will be used and that they will be marked as unique too, with different IDs. In turn, that means we end up with undefined references that did not get discarded in rusttest and that multiple .modinfo sections are generated, which confuse tooling like modpost because they only expect one.

Thus start using #[used(compiler)] to keep the previous behavior and to be explicit about what we want. Sadly, it is an unstable feature (used_with_arg) [2] -- we will talk to upstream Rust about it. The good news is that it has been available for a long time (Rust >= 1.60) [3].

The changes should also be fine for previous Rust versions, since they behave the same way as before [4].

Alternatively, we could use #[no_mangle] or #[export_name = ...] since those still behave like #[used(compiler)], but of course it is not really what we want to express, and it requires other changes to avoid symbol conflicts.

---
 rust/Makefile           |  1 +
 rust/kernel/firmware.rs |  2 +-
 rust/kernel/kunit.rs    |  2 +-
 rust/kernel/lib.rs      |  3 +++
 rust/macros/module.rs   | 10 +++++-----
 scripts/Makefile.build  |  3 ++-
 6 files changed, 13 insertions(+), 8 deletions(-)
rust/Makefile +1 -0
index 27dec7904c3a..115b63b7d1e3 100644
@@ -194,6 +194,7 @@ quiet_cmd_rustdoc_test = RUSTDOC T $<
 	RUST_MODFILE=test.rs \
 	OBJTREE=$(abspath $(objtree)) \
 	$(RUSTDOC) --test $(rust_common_flags) \
+		-Zcrate-attr='feature(used_with_arg)' \
 		@$(objtree)/include/generated/rustc_cfg \
 		$(rustc_target_flags) $(rustdoc_test_target_flags) \
 		$(rustdoc_test_quiet) \
rust/kernel/firmware.rs +1 -1
index 2494c96e105f..4fe621f35716 100644
@@ -202,7 +202,7 @@ macro_rules! module_firmware {
             };
 
             #[link_section = ".modinfo"]
-            #[used]
+            #[used(compiler)]
             static __MODULE_FIRMWARE: [u8; $($builder)*::create(__MODULE_FIRMWARE_PREFIX)
                 .build_length()] = $($builder)*::create(__MODULE_FIRMWARE_PREFIX).build();
         };
rust/kernel/kunit.rs +1 -1
index 4b8cdcb21e77..b9e65905e121 100644
@@ -302,7 +302,7 @@ macro_rules! kunit_unsafe_test_suite {
                     is_init: false,
                 };
 
-            #[used]
+            #[used(compiler)]
             #[allow(unused_unsafe)]
             #[cfg_attr(not(target_os = "macos"), link_section = ".kunit_test_suites")]
             static mut KUNIT_TEST_SUITE_ENTRY: *const ::kernel::bindings::kunit_suite =
rust/kernel/lib.rs +3 -0
index 6b4774b2b1c3..e13d6ed88fa6 100644
@@ -34,6 +34,9 @@
 // Expected to become stable.
 #![feature(arbitrary_self_types)]
 //
+// To be determined.
+#![feature(used_with_arg)]
+//
 // `feature(derive_coerce_pointee)` is expected to become stable. Before Rust
 // 1.84.0, it did not exist, so enable the predecessor features.
 #![cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, feature(derive_coerce_pointee))]
rust/macros/module.rs +5 -5
index 2ddd2eeb2852..75efc6eeeafc 100644
@@ -57,7 +57,7 @@ fn emit_base(&mut self, field: &str, content: &str, builtin: bool) {
                 {cfg}
                 #[doc(hidden)]
                 #[cfg_attr(not(target_os = \"macos\"), link_section = \".modinfo\")]
-                #[used]
+                #[used(compiler)]
                 pub static __{module}_{counter}: [u8; {length}] = *{string};
             ",
             cfg = if builtin {
@@ -249,7 +249,7 @@ mod __module_init {{
                     // key or a new section. For the moment, keep it simple.
                     #[cfg(MODULE)]
                     #[doc(hidden)]
-                    #[used]
+                    #[used(compiler)]
                     static __IS_RUST_MODULE: () = ();
 
                     static mut __MOD: ::core::mem::MaybeUninit<{type_}> =
@@ -273,7 +273,7 @@ mod __module_init {{
 
                     #[cfg(MODULE)]
                     #[doc(hidden)]
-                    #[used]
+                    #[used(compiler)]
                     #[link_section = \".init.data\"]
                     static __UNIQUE_ID___addressable_init_module: unsafe extern \"C\" fn() -> i32 = init_module;
 
@@ -293,7 +293,7 @@ mod __module_init {{
 
                     #[cfg(MODULE)]
                     #[doc(hidden)]
-                    #[used]
+                    #[used(compiler)]
                     #[link_section = \".exit.data\"]
                     static __UNIQUE_ID___addressable_cleanup_module: extern \"C\" fn() = cleanup_module;
 
@@ -303,7 +303,7 @@ mod __module_init {{
                     #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))]
                     #[doc(hidden)]
                     #[link_section = \"{initcall_section}\"]
-                    #[used]
+                    #[used(compiler)]
                     pub static __{ident}_initcall: extern \"C\" fn() ->
                         ::kernel::ffi::c_int = __{ident}_init;
 
scripts/Makefile.build +2 -1
index a6461ea411f7..ba71b27aa363 100644
@@ -312,10 +312,11 @@ $(obj)/%.lst: $(obj)/%.c FORCE
 #   - Stable since Rust 1.82.0: `feature(asm_const)`, `feature(raw_ref_op)`.
 #   - Stable since Rust 1.87.0: `feature(asm_goto)`.
 #   - Expected to become stable: `feature(arbitrary_self_types)`.
+#   - To be determined: `feature(used_with_arg)`.
 #
 # Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on
 # the unstable features in use.
-rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,lint_reasons,raw_ref_op
+rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,lint_reasons,raw_ref_op,used_with_arg
 
 # `--out-dir` is required to avoid temporaries being created by `rustc` in the
 # current working directory, which may be not accessible in the out-of-tree
Signature · 1 line
2.50.1
reviewer Reviewed-by on v1 2/2
#6 lore raw

Re: [PATCH 2/2] rust: use `#[used(compiler)]` to fix build and `modpost` with Rust >= 1.89.0

Quoted 34 lines · Miguel Ojeda

Starting with Rust 1.89.0 (expected 2025-08-07), the Rust compiler fails to build the rusttest target due to undefined references such as:

    kernel...-cgu.0:(.text....+0x116): undefined reference to
    `rust_helper_kunit_get_current_test'

Moreover, tooling like modpost gets confused:

WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/gpu/drm/nova/nova.o
ERROR: modpost: missing MODULE_LICENSE() in drivers/gpu/nova-core/nova_core.o

The reason behind both issues is that the Rust compiler will now [1] treat #[used] as #[used(linker)] instead of #[used(compiler)] for our targets. This means that the retain section flag (R, SHF_GNU_RETAIN) will be used and that they will be marked as unique too, with different IDs. In turn, that means we end up with undefined references that did not get discarded in rusttest and that multiple .modinfo sections are generated, which confuse tooling like modpost because they only expect one.

Thus start using #[used(compiler)] to keep the previous behavior and to be explicit about what we want. Sadly, it is an unstable feature (used_with_arg) [2] -- we will talk to upstream Rust about it. The good news is that it has been available for a long time (Rust >= 1.60) [3].

The changes should also be fine for previous Rust versions, since they behave the same way as before [4].

Alternatively, we could use #[no_mangle] or #[export_name = ...] since those still behave like #[used(compiler)], but of course it is not really what we want to express, and it requires other changes to avoid symbol conflicts.

Quoted 9 lines
Applied
#7 lore raw
In reply to Miguel Ojeda
Quoted 4 lines · Miguel Ojeda

A couple fixes for the upcoming 1.89.0 release, currently in beta.

With this, current nightly (1.90) gets also clean.

Applied to rust-fixes -- thanks everyone!

I am applying these now so that v6.16 is fine by the time the compiler releases, giving how their release weeks will likely line up.

(Added Acked-by from Björn to the second patch he gave me after discussing it in private -- thanks!)

Cheers,
Miguel