projects/linux·blob v7.2 · refs

132 lines · 4.3 KiB

1// SPDX-License-Identifier: GPL-2.0
2
3// Copyright (C) 2024, 2025 FUJITA Tomonori <[email protected]>
4
5//! Support for BUG and WARN functionality.
6//!
7//! C header: [`include/asm-generic/bug.h`](srctree/include/asm-generic/bug.h)
8
9#[macro_export]
10#[doc(hidden)]
11#[cfg(all(CONFIG_BUG, not(CONFIG_UML), not(CONFIG_LOONGARCH), not(CONFIG_ARM)))]
12#[cfg(CONFIG_DEBUG_BUGVERBOSE)]
13macro_rules! warn_flags {
14 ($file:expr, $flags:expr) => {
15 const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;
16 const _FILE: &[u8] = $file.as_bytes();
17 // Plus one for null-terminator.
18 static FILE: [u8; _FILE.len() + 1] = {
19 let mut bytes = [0; _FILE.len() + 1];
20 let mut i = 0;
21 while i < _FILE.len() {
22 bytes[i] = _FILE[i];
23 i += 1;
24 }
25 bytes
26 };
27
28 // SAFETY:
29 // - `file`, `line`, `flags`, and `size` are all compile-time constants or
30 // symbols, preventing any invalid memory access.
31 // - The asm block has no side effects and does not modify any registers
32 // or memory. It is purely for embedding metadata into the ELF section.
33 unsafe {
34 $crate::asm!(
35 concat!(
36 "/* {size} */",
37 include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
38 include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
39 file = sym FILE,
40 line = const line!(),
41 flags = const FLAGS,
42 size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),
43 );
44 }
45 }
46}
47
48#[macro_export]
49#[doc(hidden)]
50#[cfg(all(CONFIG_BUG, not(CONFIG_UML), not(CONFIG_LOONGARCH), not(CONFIG_ARM)))]
51#[cfg(not(CONFIG_DEBUG_BUGVERBOSE))]
52macro_rules! warn_flags {
53 ($file:expr, $flags:expr) => {
54 const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;
55
56 // SAFETY:
57 // - `flags` and `size` are all compile-time constants, preventing
58 // any invalid memory access.
59 // - The asm block has no side effects and does not modify any registers
60 // or memory. It is purely for embedding metadata into the ELF section.
61 unsafe {
62 $crate::asm!(
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")));
67 flags = const FLAGS,
68 size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),
69 );
70 }
71 }
72}
73
74#[macro_export]
75#[doc(hidden)]
76#[cfg(all(CONFIG_BUG, CONFIG_UML))]
77macro_rules! warn_flags {
78 ($file:expr, $flags:expr) => {
79 // SAFETY: It is always safe to call `warn_slowpath_fmt()`
80 // with a valid null-terminated string.
81 unsafe {
82 $crate::bindings::warn_slowpath_fmt(
83 $crate::c_str!(::core::file!()).as_char_ptr(),
84 line!() as $crate::ffi::c_int,
85 $flags as $crate::ffi::c_uint,
86 ::core::ptr::null(),
87 );
88 }
89 };
90}
91
92#[macro_export]
93#[doc(hidden)]
94#[cfg(all(CONFIG_BUG, any(CONFIG_LOONGARCH, CONFIG_ARM)))]
95macro_rules! warn_flags {
96 ($file:expr, $flags:expr) => {
97 // SAFETY: It is always safe to call `WARN_ON()`.
98 unsafe { $crate::bindings::WARN_ON(true) }
99 };
100}
101
102#[macro_export]
103#[doc(hidden)]
104#[cfg(not(CONFIG_BUG))]
105macro_rules! warn_flags {
106 ($file:expr, $flags:expr) => {};
107}
108
109#[doc(hidden)]
110pub const fn bugflag_taint(value: u32) -> u32 {
111 value << 8
112}
113
114/// Report a warning if `cond` is true and return the condition's evaluation result.
115#[macro_export]
116macro_rules! warn_on {
117 ($cond:expr) => {{
118 let cond = $cond;
119
120 #[cfg(CONFIG_DEBUG_BUGVERBOSE_DETAILED)]
121 const _COND_STR: &str = concat!("[", stringify!($cond), "] ", file!());
122 #[cfg(not(CONFIG_DEBUG_BUGVERBOSE_DETAILED))]
123 const _COND_STR: &str = file!();
124
125 if cond {
126 const WARN_ON_FLAGS: u32 = $crate::bug::bugflag_taint($crate::bindings::TAINT_WARN);
127
128 $crate::warn_flags!(_COND_STR, WARN_ON_FLAGS);
129 }
130 cond
131 }};
132}