1#[macro_export]
10#[doc(hidden)]
11#[cfg(not(testlib))]
12#[cfg(all(CONFIG_BUG, not(CONFIG_UML), not(CONFIG_LOONGARCH), not(CONFIG_ARM)))]
13#[cfg(CONFIG_DEBUG_BUGVERBOSE)]
14macro_rules! warn_flags {
15 ($file:expr, $flags:expr) => {
16 const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;
17 const _FILE: &[u8] = $file.as_bytes();
18 static FILE: [u8; _FILE.len() + 1] = {
20 let mut bytes = [0; _FILE.len() + 1];
21 let mut i = 0;
22 while i < _FILE.len() {
23 bytes[i] = _FILE[i];
24 i += 1;
25 }
26 bytes
27 };
28
29 unsafe {
35 $crate::asm!(
36 concat!(
37 "/* {size} */",
38 include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
39 include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
40 file = sym FILE,
41 line = const line!(),
42 flags = const FLAGS,
43 size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),
44 );
45 }
46 }
47}
48
49#[macro_export]
50#[doc(hidden)]
51#[cfg(not(testlib))]
52#[cfg(all(CONFIG_BUG, not(CONFIG_UML), not(CONFIG_LOONGARCH), not(CONFIG_ARM)))]
53#[cfg(not(CONFIG_DEBUG_BUGVERBOSE))]
54macro_rules! warn_flags {
55 ($file:expr, $flags:expr) => {
56 const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;
57
58 if false {
59 _ = $file;
60 }
61
62 unsafe {
68 $crate::asm!(
69 concat!(
70 "/* {size} */",
71 include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
72 include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
73 flags = const FLAGS,
74 size = const ::core::mem::size_of::<$crate::bindings::bug_entry>(),
75 );
76 }
77 }
78}
79
80#[macro_export]
81#[doc(hidden)]
82#[cfg(not(testlib))]
83#[cfg(all(CONFIG_BUG, CONFIG_UML))]
84macro_rules! warn_flags {
85 ($file:expr, $flags:expr) => {
86 if false {
87 _ = $file;
88 _ = $flags;
89 }
90
91 unsafe {
96 $crate::bindings::warn_slowpath_fmt(
97 $crate::str::CStrExt::as_char_ptr($crate::c_str!(::core::file!())),
98 line!() as $crate::ffi::c_int,
99 $crate::bindings::TAINT_WARN,
100 ::core::ptr::null(),
101 );
102 }
103 };
104}
105
106#[macro_export]
107#[doc(hidden)]
108#[cfg(not(testlib))]
109#[cfg(all(CONFIG_BUG, any(CONFIG_LOONGARCH, CONFIG_ARM)))]
110macro_rules! warn_flags {
111 ($file:expr, $flags:expr) => {
112 if false {
113 _ = $file;
114 _ = $flags;
115 }
116
117 unsafe { $crate::bindings::WARN_ON(true) }
119 };
120}
121
122#[macro_export]
123#[doc(hidden)]
124#[cfg(any(testlib, not(CONFIG_BUG)))]
125macro_rules! warn_flags {
126 ($file:expr, $flags:expr) => {
127 if false {
128 _ = $file;
129 _ = $flags;
130 }
131 };
132}
133
134#[doc(hidden)]
135pub const fn bugflag_taint(value: u32) -> u32 {
136 value << 8
137}
138
139#[macro_export]
141macro_rules! warn_on {
142 ($cond:expr) => {{
143 let cond = $cond;
144
145 #[cfg(CONFIG_DEBUG_BUGVERBOSE_DETAILED)]
146 const COND_STR: &str = concat!("[", stringify!($cond), "] ", file!());
147 #[cfg(not(CONFIG_DEBUG_BUGVERBOSE_DETAILED))]
148 const COND_STR: &str = file!();
149
150 if cond {
151 const WARN_ON_FLAGS: u32 = $crate::bug::bugflag_taint($crate::bindings::TAINT_WARN);
152
153 $crate::warn_flags!(COND_STR, WARN_ON_FLAGS);
154 }
155 cond
156 }};
157}
158
159#[cfg(CONFIG_RUST_BUG_KUNIT_TEST)]
160#[macros::kunit_tests(rust_kernel_bug)]
161mod tests {
162 #[test]
165 fn test_warn_on() {
166 let test = unsafe { bindings::kunit_get_current_test() };
169
170 let handle = unsafe { bindings::kunit_start_suppress_warning(test) };
173
174 assert!(!warn_on!(false));
175 assert!(warn_on!(true));
176
177 let suppressed_count = unsafe { bindings::kunit_suppressed_warning_count(handle) };
180
181 unsafe { bindings::kunit_end_suppress_warning(test, handle) };
184
185 assert_eq!(suppressed_count, 1);
186 }
187}