414 lines · rust
1// SPDX-License-Identifier: GPL-2.02 3//! Printing facilities.4//!5//! C header: [`include/linux/printk.h`](srctree/include/linux/printk.h)6//!7//! Reference: <https://docs.kernel.org/core-api/printk-basics.html>8 9use core::{10 ffi::{c_char, c_void},11 fmt,12};13 14use crate::str::RawFormatter;15 16// Called from `vsprintf` with format specifier `%pA`.17#[no_mangle]18unsafe extern "C" fn rust_fmt_argument(19 buf: *mut c_char,20 end: *mut c_char,21 ptr: *const c_void,22) -> *mut c_char {23 use fmt::Write;24 // SAFETY: The C contract guarantees that `buf` is valid if it's less than `end`.25 let mut w = unsafe { RawFormatter::from_ptrs(buf.cast(), end.cast()) };26 let _ = w.write_fmt(unsafe { *(ptr as *const fmt::Arguments<'_>) });27 w.pos().cast()28}29 30/// Format strings.31///32/// Public but hidden since it should only be used from public macros.33#[doc(hidden)]34pub mod format_strings {35 /// The length we copy from the `KERN_*` kernel prefixes.36 const LENGTH_PREFIX: usize = 2;37 38 /// The length of the fixed format strings.39 pub const LENGTH: usize = 10;40 41 /// Generates a fixed format string for the kernel's [`_printk`].42 ///43 /// The format string is always the same for a given level, i.e. for a44 /// given `prefix`, which are the kernel's `KERN_*` constants.45 ///46 /// [`_printk`]: srctree/include/linux/printk.h47 const fn generate(is_cont: bool, prefix: &[u8; 3]) -> [u8; LENGTH] {48 // Ensure the `KERN_*` macros are what we expect.49 assert!(prefix[0] == b'\x01');50 if is_cont {51 assert!(prefix[1] == b'c');52 } else {53 assert!(prefix[1] >= b'0' && prefix[1] <= b'7');54 }55 assert!(prefix[2] == b'\x00');56 57 let suffix: &[u8; LENGTH - LENGTH_PREFIX] = if is_cont {58 b"%pA\0\0\0\0\0"59 } else {60 b"%s: %pA\0"61 };62 63 [64 prefix[0], prefix[1], suffix[0], suffix[1], suffix[2], suffix[3], suffix[4], suffix[5],65 suffix[6], suffix[7],66 ]67 }68 69 // Generate the format strings at compile-time.70 //71 // This avoids the compiler generating the contents on the fly in the stack.72 //73 // Furthermore, `static` instead of `const` is used to share the strings74 // for all the kernel.75 pub static EMERG: [u8; LENGTH] = generate(false, bindings::KERN_EMERG);76 pub static ALERT: [u8; LENGTH] = generate(false, bindings::KERN_ALERT);77 pub static CRIT: [u8; LENGTH] = generate(false, bindings::KERN_CRIT);78 pub static ERR: [u8; LENGTH] = generate(false, bindings::KERN_ERR);79 pub static WARNING: [u8; LENGTH] = generate(false, bindings::KERN_WARNING);80 pub static NOTICE: [u8; LENGTH] = generate(false, bindings::KERN_NOTICE);81 pub static INFO: [u8; LENGTH] = generate(false, bindings::KERN_INFO);82 pub static DEBUG: [u8; LENGTH] = generate(false, bindings::KERN_DEBUG);83 pub static CONT: [u8; LENGTH] = generate(true, bindings::KERN_CONT);84}85 86/// Prints a message via the kernel's [`_printk`].87///88/// Public but hidden since it should only be used from public macros.89///90/// # Safety91///92/// The format string must be one of the ones in [`format_strings`], and93/// the module name must be null-terminated.94///95/// [`_printk`]: srctree/include/linux/_printk.h96#[doc(hidden)]97#[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))]98pub unsafe fn call_printk(99 format_string: &[u8; format_strings::LENGTH],100 module_name: &[u8],101 args: fmt::Arguments<'_>,102) {103 // `_printk` does not seem to fail in any path.104 #[cfg(CONFIG_PRINTK)]105 unsafe {106 bindings::_printk(107 format_string.as_ptr() as _,108 module_name.as_ptr(),109 &args as *const _ as *const c_void,110 );111 }112}113 114/// Prints a message via the kernel's [`_printk`] for the `CONT` level.115///116/// Public but hidden since it should only be used from public macros.117///118/// [`_printk`]: srctree/include/linux/printk.h119#[doc(hidden)]120#[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))]121pub fn call_printk_cont(args: fmt::Arguments<'_>) {122 // `_printk` does not seem to fail in any path.123 //124 // SAFETY: The format string is fixed.125 #[cfg(CONFIG_PRINTK)]126 unsafe {127 bindings::_printk(128 format_strings::CONT.as_ptr() as _,129 &args as *const _ as *const c_void,130 );131 }132}133 134/// Performs formatting and forwards the string to [`call_printk`].135///136/// Public but hidden since it should only be used from public macros.137#[doc(hidden)]138#[cfg(not(testlib))]139#[macro_export]140#[allow(clippy::crate_in_macro_def)]141macro_rules! print_macro (142 // The non-continuation cases (most of them, e.g. `INFO`).143 ($format_string:path, false, $($arg:tt)+) => (144 // To remain sound, `arg`s must be expanded outside the `unsafe` block.145 // Typically one would use a `let` binding for that; however, `format_args!`146 // takes borrows on the arguments, but does not extend the scope of temporaries.147 // Therefore, a `match` expression is used to keep them around, since148 // the scrutinee is kept until the end of the `match`.149 match format_args!($($arg)+) {150 // SAFETY: This hidden macro should only be called by the documented151 // printing macros which ensure the format string is one of the fixed152 // ones. All `__LOG_PREFIX`s are null-terminated as they are generated153 // by the `module!` proc macro or fixed values defined in a kernel154 // crate.155 args => unsafe {156 $crate::print::call_printk(157 &$format_string,158 crate::__LOG_PREFIX,159 args,160 );161 }162 }163 );164 165 // The `CONT` case.166 ($format_string:path, true, $($arg:tt)+) => (167 $crate::print::call_printk_cont(168 format_args!($($arg)+),169 );170 );171);172 173/// Stub for doctests174#[cfg(testlib)]175#[macro_export]176macro_rules! print_macro (177 ($format_string:path, $e:expr, $($arg:tt)+) => (178 ()179 );180);181 182// We could use a macro to generate these macros. However, doing so ends183// up being a bit ugly: it requires the dollar token trick to escape `$` as184// well as playing with the `doc` attribute. Furthermore, they cannot be easily185// imported in the prelude due to [1]. So, for the moment, we just write them186// manually, like in the C side; while keeping most of the logic in another187// macro, i.e. [`print_macro`].188//189// [1]: https://github.com/rust-lang/rust/issues/52234190 191/// Prints an emergency-level message (level 0).192///193/// Use this level if the system is unusable.194///195/// Equivalent to the kernel's [`pr_emerg`] macro.196///197/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and198/// `alloc::format!` for information about the formatting syntax.199///200/// [`pr_emerg`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_emerg201/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html202///203/// # Examples204///205/// ```206/// pr_emerg!("hello {}\n", "there");207/// ```208#[macro_export]209macro_rules! pr_emerg (210 ($($arg:tt)*) => (211 $crate::print_macro!($crate::print::format_strings::EMERG, false, $($arg)*)212 )213);214 215/// Prints an alert-level message (level 1).216///217/// Use this level if action must be taken immediately.218///219/// Equivalent to the kernel's [`pr_alert`] macro.220///221/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and222/// `alloc::format!` for information about the formatting syntax.223///224/// [`pr_alert`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_alert225/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html226///227/// # Examples228///229/// ```230/// pr_alert!("hello {}\n", "there");231/// ```232#[macro_export]233macro_rules! pr_alert (234 ($($arg:tt)*) => (235 $crate::print_macro!($crate::print::format_strings::ALERT, false, $($arg)*)236 )237);238 239/// Prints a critical-level message (level 2).240///241/// Use this level for critical conditions.242///243/// Equivalent to the kernel's [`pr_crit`] macro.244///245/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and246/// `alloc::format!` for information about the formatting syntax.247///248/// [`pr_crit`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_crit249/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html250///251/// # Examples252///253/// ```254/// pr_crit!("hello {}\n", "there");255/// ```256#[macro_export]257macro_rules! pr_crit (258 ($($arg:tt)*) => (259 $crate::print_macro!($crate::print::format_strings::CRIT, false, $($arg)*)260 )261);262 263/// Prints an error-level message (level 3).264///265/// Use this level for error conditions.266///267/// Equivalent to the kernel's [`pr_err`] macro.268///269/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and270/// `alloc::format!` for information about the formatting syntax.271///272/// [`pr_err`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_err273/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html274///275/// # Examples276///277/// ```278/// pr_err!("hello {}\n", "there");279/// ```280#[macro_export]281macro_rules! pr_err (282 ($($arg:tt)*) => (283 $crate::print_macro!($crate::print::format_strings::ERR, false, $($arg)*)284 )285);286 287/// Prints a warning-level message (level 4).288///289/// Use this level for warning conditions.290///291/// Equivalent to the kernel's [`pr_warn`] macro.292///293/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and294/// `alloc::format!` for information about the formatting syntax.295///296/// [`pr_warn`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_warn297/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html298///299/// # Examples300///301/// ```302/// pr_warn!("hello {}\n", "there");303/// ```304#[macro_export]305macro_rules! pr_warn (306 ($($arg:tt)*) => (307 $crate::print_macro!($crate::print::format_strings::WARNING, false, $($arg)*)308 )309);310 311/// Prints a notice-level message (level 5).312///313/// Use this level for normal but significant conditions.314///315/// Equivalent to the kernel's [`pr_notice`] macro.316///317/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and318/// `alloc::format!` for information about the formatting syntax.319///320/// [`pr_notice`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_notice321/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html322///323/// # Examples324///325/// ```326/// pr_notice!("hello {}\n", "there");327/// ```328#[macro_export]329macro_rules! pr_notice (330 ($($arg:tt)*) => (331 $crate::print_macro!($crate::print::format_strings::NOTICE, false, $($arg)*)332 )333);334 335/// Prints an info-level message (level 6).336///337/// Use this level for informational messages.338///339/// Equivalent to the kernel's [`pr_info`] macro.340///341/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and342/// `alloc::format!` for information about the formatting syntax.343///344/// [`pr_info`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_info345/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html346///347/// # Examples348///349/// ```350/// pr_info!("hello {}\n", "there");351/// ```352#[macro_export]353#[doc(alias = "print")]354macro_rules! pr_info (355 ($($arg:tt)*) => (356 $crate::print_macro!($crate::print::format_strings::INFO, false, $($arg)*)357 )358);359 360/// Prints a debug-level message (level 7).361///362/// Use this level for debug messages.363///364/// Equivalent to the kernel's [`pr_debug`] macro, except that it doesn't support dynamic debug365/// yet.366///367/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and368/// `alloc::format!` for information about the formatting syntax.369///370/// [`pr_debug`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_debug371/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html372///373/// # Examples374///375/// ```376/// pr_debug!("hello {}\n", "there");377/// ```378#[macro_export]379#[doc(alias = "print")]380macro_rules! pr_debug (381 ($($arg:tt)*) => (382 if cfg!(debug_assertions) {383 $crate::print_macro!($crate::print::format_strings::DEBUG, false, $($arg)*)384 }385 )386);387 388/// Continues a previous log message in the same line.389///390/// Use only when continuing a previous `pr_*!` macro (e.g. [`pr_info!`]).391///392/// Equivalent to the kernel's [`pr_cont`] macro.393///394/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and395/// `alloc::format!` for information about the formatting syntax.396///397/// [`pr_info!`]: crate::pr_info!398/// [`pr_cont`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_cont399/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html400///401/// # Examples402///403/// ```404/// # use kernel::pr_cont;405/// pr_info!("hello");406/// pr_cont!(" {}\n", "there");407/// ```408#[macro_export]409macro_rules! pr_cont (410 ($($arg:tt)*) => (411 $crate::print_macro!($crate::print::format_strings::CONT, true, $($arg)*)412 )413);414