summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile13
-rw-r--r--rust/Makefile6
-rw-r--r--rust/kernel/jump_label.rs12
-rw-r--r--rust/kernel/list.rs2
-rw-r--r--rust/kernel/num/bounded.rs30
-rw-r--r--scripts/Makefile.build3
-rw-r--r--tools/objtool/check.c1
7 files changed, 53 insertions, 14 deletions
diff --git a/Makefile b/Makefile
index 50d918840686..7860ce1fe501 100644
--- a/Makefile
+++ b/Makefile
@@ -1083,6 +1083,16 @@ endif
export CC_FLAGS_SCS
endif
+ifdef CONFIG_RUST_INLINE_HELPERS
+# `rustc` normally emits traps for unreachable paths during code generation.
+# With inline helpers, Clang performs code generation from the linked bitcode
+# instead, so request the same behavior explicitly. Otherwise `objtool` may
+# follow an impossible Rust path into the next function.
+CC_FLAGS_RUST_INLINE_HELPERS := -mllvm -trap-unreachable \
+ -mllvm -no-trap-after-noreturn
+export CC_FLAGS_RUST_INLINE_HELPERS
+endif
+
ifdef CONFIG_LTO_CLANG
ifdef CONFIG_LTO_CLANG_FULL
CC_FLAGS_LTO := -flto
@@ -1118,7 +1128,8 @@ endif
ifdef CONFIG_RUST
# Always pass -Zsanitizer-cfi-normalize-integers as CONFIG_RUST selects
# CONFIG_CFI_ICALL_NORMALIZE_INTEGERS.
- RUSTC_FLAGS_CFI := -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers
+ # Disable function merging as LLVM incorrectly merges functions with different KCFI types.
+ RUSTC_FLAGS_CFI := -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers -Zmerge-functions=disabled
KBUILD_RUSTFLAGS += $(RUSTC_FLAGS_CFI)
export RUSTC_FLAGS_CFI
endif
diff --git a/rust/Makefile b/rust/Makefile
index 48adcd9b7851..da1a7409d984 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -354,7 +354,8 @@ rusttestlib-pin_init: $(src)/pin-init/src/lib.rs rusttestlib-macros \
rusttestlib-kernel: private rustc_target_flags = --extern ffi \
--extern build_error --extern macros --extern pin_init \
--extern bindings --extern uapi \
- --extern zerocopy=$(objtree)/$(obj)/test/libzerocopy.rlib --extern zerocopy_derive
+ --extern zerocopy=$(objtree)/$(obj)/test/libzerocopy.rlib \
+ --extern zerocopy_derive=$(objtree)/$(obj)/test/$(libzerocopy_derive_name)
rusttestlib-kernel: $(src)/kernel/lib.rs rusttestlib-bindings rusttestlib-uapi \
rusttestlib-build_error rusttestlib-pin_init $(obj)/$(libmacros_name) \
$(obj)/bindings.o rusttestlib-zerocopy rusttestlib-zerocopy_derive FORCE
@@ -656,7 +657,8 @@ quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L
-Zunstable-options \
$(if $(link_helper),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \
$(obj)/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \
- $(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
+ $(CC) $(CLANG_FLAGS) $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS)) \
+ $(CC_FLAGS_RUST_INLINE_HELPERS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
$(cmd_ld_single)) \
$(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@) \
$(cmd_objtool)
diff --git a/rust/kernel/jump_label.rs b/rust/kernel/jump_label.rs
index 4e974c768dbd..f54cedcb6fd5 100644
--- a/rust/kernel/jump_label.rs
+++ b/rust/kernel/jump_label.rs
@@ -44,6 +44,7 @@ const _: &str = include!(concat!(
#[macro_export]
#[doc(hidden)]
+#[cfg(not(testlib))]
#[cfg(CONFIG_JUMP_LABEL)]
macro_rules! arch_static_branch {
($key:path, $keytyp:ty, $field:ident, $branch:expr) => {'my_label: {
@@ -61,6 +62,17 @@ macro_rules! arch_static_branch {
}};
}
+#[macro_export]
+#[doc(hidden)]
+#[cfg(testlib)]
+#[cfg(CONFIG_JUMP_LABEL)]
+macro_rules! arch_static_branch {
+ ($key:path, $keytyp:ty, $field:ident, $branch:expr) => {
+ // The asm falls through until patched, which never happens on the host.
+ false
+ };
+}
+
#[cfg(CONFIG_JUMP_LABEL)]
pub use arch_static_branch;
diff --git a/rust/kernel/list.rs b/rust/kernel/list.rs
index 406e3a028c55..0f367264ee2e 100644
--- a/rust/kernel/list.rs
+++ b/rust/kernel/list.rs
@@ -249,7 +249,7 @@ pub use self::arc_field::{
/// assert_eq!(list.iter().count(), 3);
/// }
///
-/// // Pop the items from the list using `pop_front()` and verify the content.
+/// // Pop the items from the list using `pop_back()` and verify the content.
/// {
/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 15));
/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 32));
diff --git a/rust/kernel/num/bounded.rs b/rust/kernel/num/bounded.rs
index d192610a687d..2a2b0a4bca5e 100644
--- a/rust/kernel/num/bounded.rs
+++ b/rust/kernel/num/bounded.rs
@@ -13,7 +13,10 @@ use core::{
};
use kernel::{
- num::Integer,
+ num::{
+ Integer,
+ Unsigned, //
+ },
prelude::*, //
};
@@ -174,13 +177,16 @@ fn fits_within<T: Integer>(value: T, num_bits: u32) -> bool {
/// // `u8` (regardless of the passed value).
/// // let _ = Bounded::<u32, 6>::from(10u8);
///
-/// // Booleans can be converted into single-bit `Bounded`s.
+/// // Booleans can be converted into unsigned `Bounded`s.
///
/// let v = Bounded::<u64, 1>::from(false);
/// assert_eq!(v.get(), 0);
///
/// let v = Bounded::<u64, 1>::from(true);
/// assert_eq!(v.get(), 1);
+///
+/// // This does not build because `i8` is signed.
+/// // let _ = Bounded::<i8, 2>::from(true);
/// ```
///
/// Infallible conversions from a [`Bounded`] to a primitive integer are also supported, and
@@ -203,12 +209,16 @@ fn fits_within<T: Integer>(value: T, num_bits: u32) -> bool {
/// let _v = Bounded::<u32, 10>::new::<10>();
/// // assert_eq!(u8::from(_v), 10);
///
-/// // Single-bit `Bounded`s can be converted into a boolean.
+/// // Unsigned single-bit `Bounded`s can be converted into a boolean.
/// let v = Bounded::<u8, 1>::new::<1>();
/// assert_eq!(bool::from(v), true);
///
/// let v = Bounded::<u8, 1>::new::<0>();
/// assert_eq!(bool::from(v), false);
+///
+/// // This does not build because `i8` is signed.
+/// // let v = Bounded::<i8, 1>::new::<-1>();
+/// // let _ = bool::from(v);
/// ```
///
/// Fallible conversions from any primitive integer to any [`Bounded`] are also supported using the
@@ -1109,31 +1119,33 @@ impl_into_primitive!(
i8 i16 i32 i64 isize
);
-// Single-bit `Bounded`s can be converted from/to a boolean.
+// Unsigned single-bit `Bounded`s can be converted to a boolean.
impl<T> From<Bounded<T, 1>> for bool
where
- T: Integer + Zeroable,
+ T: Integer<Signedness = Unsigned> + Zeroable,
{
fn from(value: Bounded<T, 1>) -> Self {
value.get() != Zeroable::zeroed()
}
}
+// Booleans can be converted to unsigned `Bounded`s.
+
impl<T, const N: u32> From<bool> for Bounded<T, N>
where
- T: Integer + From<bool>,
+ T: Integer<Signedness = Unsigned> + From<bool>,
{
fn from(value: bool) -> Self {
- // SAFETY: A boolean can be represented using a single bit, and thus fits within any
- // integer type for any `N` > 0.
+ // SAFETY: A boolean is represented by `0` or `1`, so it fits within any valid unsigned
+ // `Bounded` width.
unsafe { Self::__new(T::from(value)) }
}
}
impl<T> Bounded<T, 1>
where
- T: Integer + Zeroable,
+ T: Integer<Signedness = Unsigned> + Zeroable,
{
/// Converts this [`Bounded`] into a [`bool`].
///
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index a48209591dee..4349108e75e1 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -347,7 +347,8 @@ quiet_cmd_rustc_o_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@
cmd_rustc_o_rs = $(rust_common_cmd) --emit=$(if $(CONFIG_RUST_INLINE_HELPERS),llvm-bc=$(patsubst %.o,%.bc,$@),obj=$@) $< \
$(if $(CONFIG_RUST_INLINE_HELPERS),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \
$(objtree)/rust/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \
- $(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
+ $(CC) $(CLANG_FLAGS) $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS)) \
+ $(CC_FLAGS_RUST_INLINE_HELPERS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
$(cmd_ld_single)) \
$(cmd_objtool)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index df04e6be2f66..464f6c9d9ff0 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -196,6 +196,7 @@ static bool is_rust_noreturn(const struct symbol *func)
return str_ends_with(func->name, "_4core3num20from_str_radix_panic") ||
str_ends_with(func->name, "_4core3num22from_ascii_radix_panic") ||
str_ends_with(func->name, "_4core3num28from_ascii_bytes_radix_panic") ||
+ str_ends_with(func->name, "_4core3str16slice_error_fail") ||
str_ends_with(func->name, "_4core5sliceSp15copy_from_slice17len_mismatch_fail") ||
str_ends_with(func->name, "_4core6option13expect_failed") ||
str_ends_with(func->name, "_4core6option13unwrap_failed") ||