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)] 110*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