mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-28 07:33:45 -04:00
Running `make rusttest` with `ARCH=` set to an architecture other than
the host's fails, e.g. `ARCH=arm64` on an x86_64 host:
error: invalid instruction mnemonic 'brk'
--> rust/kernel/bug.rs:63:17
|
63 | / concat!(
64 | | "/* {size} */",
65 | | include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
66 | | include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
| |_______________________________________________________________________________________________________^
|
note: instantiated into assembly here
--> <inline asm>:1:115
|
1 | /* 8 */.pushsection __bug_table,"aw"; .align 2; 14470: .long 14471f - .;.short 2305;.align 2; .popsection; 14471:brk 0x800
| ^^^
The reason is that `rusttest` builds the `kernel` crate as a host
library: it passes the `CONFIG_*` cfgs of the configured architecture,
but not `--target`, so code generation happens for the
host. `warn_flags!` then selects the arch-specific inline asm arm
based on `CONFIG_*`, and the host assembler rejects it.
This does not happen with the current `master` because `warn_on!` has
no user inside the `kernel` crate itself yet, but it will as soon as
one is added.
Reported-by: Miguel Ojeda <ojeda@kernel.org>
Closes: https://lore.kernel.org/all/CANiq72n4=fz=JNKY0Jdm8BnLa=RmHB2B7s0bO47YTJ7hygqBZg@mail.gmail.com/
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
Cc: stable@vger.kernel.org
Fixes: dff64b0727 ("rust: Add warn_on macro")
Link: https://patch.msgid.link/20260808022608.1125174-1-tomo@flapping.org
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
155 lines
4.6 KiB
Rust
155 lines
4.6 KiB
Rust
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
// Copyright (C) 2024, 2025 FUJITA Tomonori <fujita.tomonori@gmail.com>
|
|
|
|
//! Support for BUG and WARN functionality.
|
|
//!
|
|
//! C header: [`include/asm-generic/bug.h`](srctree/include/asm-generic/bug.h)
|
|
|
|
#[macro_export]
|
|
#[doc(hidden)]
|
|
#[cfg(not(testlib))]
|
|
#[cfg(all(CONFIG_BUG, not(CONFIG_UML), not(CONFIG_LOONGARCH), not(CONFIG_ARM)))]
|
|
#[cfg(CONFIG_DEBUG_BUGVERBOSE)]
|
|
macro_rules! warn_flags {
|
|
($file:expr, $flags:expr) => {
|
|
const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;
|
|
const _FILE: &[u8] = $file.as_bytes();
|
|
// Plus one for null-terminator.
|
|
static FILE: [u8; _FILE.len() + 1] = {
|
|
let mut bytes = [0; _FILE.len() + 1];
|
|
let mut i = 0;
|
|
while i < _FILE.len() {
|
|
bytes[i] = _FILE[i];
|
|
i += 1;
|
|
}
|
|
bytes
|
|
};
|
|
|
|
// SAFETY:
|
|
// - `file`, `line`, `flags`, and `size` are all compile-time constants or
|
|
// symbols, preventing any invalid memory access.
|
|
// - The asm block has no side effects and does not modify any registers
|
|
// or memory. It is purely for embedding metadata into the ELF section.
|
|
unsafe {
|
|
$crate::asm!(
|
|
concat!(
|
|
"/* {size} */",
|
|
include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
|
|
include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
|
|
file = sym FILE,
|
|
line = const line!(),
|
|
flags = const FLAGS,
|
|
size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
#[doc(hidden)]
|
|
#[cfg(not(testlib))]
|
|
#[cfg(all(CONFIG_BUG, not(CONFIG_UML), not(CONFIG_LOONGARCH), not(CONFIG_ARM)))]
|
|
#[cfg(not(CONFIG_DEBUG_BUGVERBOSE))]
|
|
macro_rules! warn_flags {
|
|
($file:expr, $flags:expr) => {
|
|
const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;
|
|
|
|
if false {
|
|
_ = $file;
|
|
}
|
|
|
|
// SAFETY:
|
|
// - `flags` and `size` are all compile-time constants, preventing
|
|
// any invalid memory access.
|
|
// - The asm block has no side effects and does not modify any registers
|
|
// or memory. It is purely for embedding metadata into the ELF section.
|
|
unsafe {
|
|
$crate::asm!(
|
|
concat!(
|
|
"/* {size} */",
|
|
include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
|
|
include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
|
|
flags = const FLAGS,
|
|
size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
#[doc(hidden)]
|
|
#[cfg(not(testlib))]
|
|
#[cfg(all(CONFIG_BUG, CONFIG_UML))]
|
|
macro_rules! warn_flags {
|
|
($file:expr, $flags:expr) => {
|
|
if false {
|
|
_ = $file;
|
|
}
|
|
|
|
// SAFETY: It is always safe to call `warn_slowpath_fmt()`
|
|
// with a valid null-terminated string.
|
|
unsafe {
|
|
$crate::bindings::warn_slowpath_fmt(
|
|
$crate::c_str!(::core::file!()).as_char_ptr(),
|
|
line!() as $crate::ffi::c_int,
|
|
$flags as $crate::ffi::c_uint,
|
|
::core::ptr::null(),
|
|
);
|
|
}
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
#[doc(hidden)]
|
|
#[cfg(not(testlib))]
|
|
#[cfg(all(CONFIG_BUG, any(CONFIG_LOONGARCH, CONFIG_ARM)))]
|
|
macro_rules! warn_flags {
|
|
($file:expr, $flags:expr) => {
|
|
if false {
|
|
_ = $file;
|
|
_ = $flags;
|
|
}
|
|
|
|
// SAFETY: It is always safe to call `WARN_ON()`.
|
|
unsafe { $crate::bindings::WARN_ON(true) }
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
#[doc(hidden)]
|
|
#[cfg(any(testlib, not(CONFIG_BUG)))]
|
|
macro_rules! warn_flags {
|
|
($file:expr, $flags:expr) => {
|
|
if false {
|
|
_ = $file;
|
|
_ = $flags;
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
pub const fn bugflag_taint(value: u32) -> u32 {
|
|
value << 8
|
|
}
|
|
|
|
/// Report a warning if `cond` is true and return the condition's evaluation result.
|
|
#[macro_export]
|
|
macro_rules! warn_on {
|
|
($cond:expr) => {{
|
|
let cond = $cond;
|
|
|
|
#[cfg(CONFIG_DEBUG_BUGVERBOSE_DETAILED)]
|
|
const COND_STR: &str = concat!("[", stringify!($cond), "] ", file!());
|
|
#[cfg(not(CONFIG_DEBUG_BUGVERBOSE_DETAILED))]
|
|
const COND_STR: &str = file!();
|
|
|
|
if cond {
|
|
const WARN_ON_FLAGS: u32 = $crate::bug::bugflag_taint($crate::bindings::TAINT_WARN);
|
|
|
|
$crate::warn_flags!(COND_STR, WARN_ON_FLAGS);
|
|
}
|
|
cond
|
|
}};
|
|
}
|