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