1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
// 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(all(CONFIG_BUG, not(CONFIG_UML), not(CONFIG_LOONGARCH), not(CONFIG_ARM)))]
#[cfg(CONFIG_DEBUG_BUGVERBOSE)]
macro_rules! warn_flags {
($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(all(CONFIG_BUG, not(CONFIG_UML), not(CONFIG_LOONGARCH), not(CONFIG_ARM)))]
#[cfg(not(CONFIG_DEBUG_BUGVERBOSE))]
macro_rules! warn_flags {
($flags:expr) => {
const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;
// 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(all(CONFIG_BUG, CONFIG_UML))]
macro_rules! warn_flags {
($flags:expr) => {
// 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(all(CONFIG_BUG, any(CONFIG_LOONGARCH, CONFIG_ARM)))]
macro_rules! warn_flags {
($flags:expr) => {
// SAFETY: It is always safe to call `WARN_ON()`.
unsafe { $crate::bindings::WARN_ON(true) }
};
}
#[macro_export]
#[doc(hidden)]
#[cfg(not(CONFIG_BUG))]
macro_rules! warn_flags {
($flags:expr) => {};
}
#[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;
if cond {
const WARN_ON_FLAGS: u32 = $crate::bug::bugflag_taint($crate::bindings::TAINT_WARN);
$crate::warn_flags!(WARN_ON_FLAGS);
}
cond
}};
}
|