[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAH5fLggTL9Ej8rcakd-gDz+h0dZhA1PRzxf+76EjxotOBJW7fg@mail.gmail.com>
Date: Wed, 11 Jun 2025 23:38:22 +0200
From: Alice Ryhl <aliceryhl@...gle.com>
To: Andrew Ballance <andrewjballance@...il.com>
Cc: jbaron@...mai.com, jim.cromie@...il.com, daniel.almeida@...labora.com,
acourbot@...dia.com, ojeda@...nel.org, alex.gaynor@...il.com,
boqun.feng@...il.com, gary@...yguo.net, bjorn3_gh@...tonmail.com,
lossin@...nel.org, a.hindborg@...nel.org, tmgross@...ch.edu, dakr@...nel.org,
gregkh@...uxfoundation.org, rafael@...nel.org, rostedt@...dmis.org,
viresh.kumar@...aro.org, lina+kernel@...hilina.net, tamird@...il.com,
jubalh@...oru.org, rust-for-linux@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: Re: [RFC PATCH 2/3] rust: device add support for dynamic debug to pr_debug!
On Wed, Jun 11, 2025 at 10:30 PM Andrew Ballance
<andrewjballance@...il.com> wrote:
>
> adds support for dynamic debug for the pr_debug macro.
>
> Signed-off-by: Andrew Ballance <andrewjballance@...il.com>
> ---
> rust/bindings/bindings_helper.h | 1 +
> rust/kernel/print.rs | 167 +++++++++++++++++++++++++++++++-
> 2 files changed, 164 insertions(+), 4 deletions(-)
>
> diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
> index bc494745f67b..e05e9ce5d887 100644
> --- a/rust/bindings/bindings_helper.h
> +++ b/rust/bindings/bindings_helper.h
> @@ -46,6 +46,7 @@
> #include <linux/cred.h>
> #include <linux/device/faux.h>
> #include <linux/dma-mapping.h>
> +#include <linux/dynamic_debug.h>
> #include <linux/errname.h>
> #include <linux/ethtool.h>
> #include <linux/file.h>
> diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs
> index 9783d960a97a..4f0d79804d23 100644
> --- a/rust/kernel/print.rs
> +++ b/rust/kernel/print.rs
> @@ -371,13 +371,15 @@ macro_rules! pr_info (
> ///
> /// Use this level for debug messages.
> ///
> -/// Equivalent to the kernel's [`pr_debug`] macro, except that it doesn't support dynamic debug
> -/// yet.
> +/// Equivalent to the kernel's [`pr_debug`] macro.
> +///
> +/// This has support for [`dynamic debug`].
> ///
> /// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
> /// [`std::format!`] for information about the formatting syntax.
> ///
> /// [`pr_debug`]: https://docs.kernel.org/core-api/printk-basics.html#c.pr_debug
> +/// [`dynamic debug`]: https://docs.kernel.org/admin-guide/dynamic-debug-howto.html
> /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
> /// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
> ///
> @@ -390,8 +392,18 @@ macro_rules! pr_info (
> #[doc(alias = "print")]
> macro_rules! pr_debug (
> ($($arg:tt)*) => (
> - if cfg!(debug_assertions) {
> - $crate::print_macro!($crate::print::format_strings::DEBUG, false, $($arg)*)
> + #[cfg(any(DYNAMIC_DEBUG_MODULE, CONFIG_DYNAMIC_DEBUG))]
> + {
> + if cfg!(debug_assertions) {
> + $crate::dynamic_pr_debug_unlikely!($($arg)*);
> + }
> + }
> +
> + #[cfg(not(any(DYNAMIC_DEBUG_MODULE, CONFIG_DYNAMIC_DEBUG)))]
> + {
> + if cfg!(debug_assertions) {
> + $crate::print_macro!($crate::print::format_strings::DEBUG, false, $($arg)*)
> + }
> }
> )
> );
> @@ -423,3 +435,150 @@ macro_rules! pr_cont (
> $crate::print_macro!($crate::print::format_strings::CONT, true, $($arg)*)
> )
> );
> +
> +/// all of the code that is used for dynamic debug for pr_debug!
> +/// this is public but hidden. This code should only be called
> +/// by the `pr_debug!` or `dev_dbg!` macros.
> +#[cfg(CONFIG_DYNAMIC_DEBUG_CORE)]
> +#[doc(hidden)]
> +pub mod dynamic_debug {
> +
> + pub use bindings::_ddebug;
> +
> + use crate::c_str;
> + use core::fmt;
> + use kernel::str::CStr;
> +
> + /// a wrapper around the C `struct _ddebug`.
> + /// this is public but hidden.
> + ///
> + /// # Invariants
> + /// - this is always static mut.
> + /// - this is always located in the "__dyndbg" section.
> + /// - this has the same layout as `_ddebug`.
> + #[repr(transparent)]
> + pub struct _Ddebug {
> + pub inner: bindings::_ddebug,
> + }
> +
> + impl _Ddebug {
> + pub const fn new_unlikely(
> + modname: &'static CStr,
> + function: &'static CStr,
> + filename: &'static CStr,
> + format: &'static CStr,
> + line_num: u32,
> + ) -> Self {
> + // rust does not have support for c like bit fields. so
> + // do some bit fiddling to set the line, class and flags varibles
> + let class: u32 = bindings::_DPRINTK_CLASS_DFLT << 18;
> + let flags: u32 = bindings::_DPRINTK_FLAGS_NONE << 24;
> + let bit_fields: u32 = line_num | class | flags;
> +
> + let arr: [u8; 4] = bit_fields.to_ne_bytes();
> + let bits = bindings::__BindgenBitfieldUnit::new(arr);
> +
> + #[cfg(CONFIG_JUMP_LABEL)]
> + {
> + Self {
> + inner: bindings::_ddebug {
> + modname: modname.as_char_ptr(),
> + function: function.as_char_ptr(),
> + filename: filename.as_char_ptr(),
> + format: format.as_char_ptr(),
> + _bitfield_align_1: [],
> + _bitfield_1: bits,
> + // SAFETY: STATIC_KEY_INIT_FALSE is initialized as zero
> + key: unsafe { core::mem::zeroed() },
Please define a STATIC_KEY_INIT_FALSE constant in
rust/kernel/jump_label.rs and refer to it. You can use mem::zeroed()
in the definition of the constant.
> + },
> + }
> + }
> +
> + #[cfg(not(CONFIG_JUMP_LABEL))]
> + {
> + Self {
> + inner: bindings::_ddebug {
> + modname: modname.as_char_ptr(),
> + function: function.as_char_ptr(),
> + filename: filename.as_char_ptr(),
> + format: format.as_char_ptr(),
> + _bitfield_align_1: [],
> + _bitfield_1: bits,
> + __bindgen_padding_0: 0,
> + },
> + }
> + }
> + }
> + }
> +
> + /// a wrapper function around the c function `__dynamic_pr_debug`.
> + /// # Safety
> + /// - descriptor must be a valid reference to a `static mut` _Ddebug
> + pub unsafe fn dynamic_pr_debug(descriptor: &mut _Ddebug, args: fmt::Arguments<'_>) {
> + // SAFETY:
> + // - "%pA" is null terminated and is the format for rust printing
> + // - descriptor.inner is a valid _ddebug
> + unsafe {
> + bindings::__dynamic_pr_debug(
> + &raw mut descriptor.inner,
> + c_str!("%pA").as_char_ptr(),
> + (&raw const args).cast::<ffi::c_void>(),
> + );
> + }
> + }
> +
> + /// macro for dynamic debug equilant to the C `pr_debug` macro
typo
> + #[doc(hidden)]
> + #[macro_export]
> + macro_rules! dynamic_pr_debug_unlikely {
> + ($($f:tt)*) => {{
> + use $crate::c_str;
> + use $crate::str::CStr;
> + use $crate::print::dynamic_debug::{_ddebug, _Ddebug};
> +
> + const MOD_NAME: &CStr = c_str!(module_path!());
> + // right now rust does not have a function! macro. so, hard code this to be
> + // the name of the macro that is printing
> + // TODO:
> + // replace this once either a function! macro exists
> + // or core::any::type_name becomes const
> + const FN_NAME: &CStr = c_str!("pr_debug!");
> + const FILE_NAME: &CStr = c_str!(file!());
> + const MESSAGE: &CStr = c_str!(stringify!($($f)*));
> + const LINE: u32 = line!();
> +
> + #[link_section = "__dyndbg"]
> + static mut DEBUG_INFO: _Ddebug =
> + _Ddebug::new_unlikely(MOD_NAME, FN_NAME, FILE_NAME, MESSAGE, LINE);
> +
> + // SAFETY:
> + // - this is reading from a `static mut` variable
> + // - key.dd_key_false is a valid static key
> + let should_print: bool = unsafe {
> + #[cfg(CONFIG_JUMP_LABEL)]
> + {
> + $crate::jump_label::static_branch_unlikely!(
> + DEBUG_INFO,
> + _Ddebug,
> + inner.key.dd_key_false
> + )
> + }
> + #[cfg(not(CONFIG_JUMP_LABEL))]
> + {
> + // gets the _DPRINTK_FLAGS_PRINT bit
> + DEBUG_INFO.inner.flags() & 1 != 0
> + }
> + };
> +
> + if should_print {
> + // SAFETY: `&mut DEBUG_INFO` is a valid reference to a static mut _Ddebug
No, we can't use mutable references like this. In Rust, the real
meaning of &mut is exclusive, not mutable. (And the real meaning of &
is shared.) We don't have exclusive access to the DEBUG_INFO static
here - the access is shared, so we must use &_ references instead of
&mut _ references here.
Note that by using Opaque, it's possible to mutate the value even if
it's behind a &_ reference.
#[repr(transparent)]
pub struct _Ddebug {
pub inner: Opaque<bindings::_ddebug>,
}
and then you can do DEBUG_INFO.inner.get() to obtain a mutable raw
pointer to the contents.
> + unsafe {
> + $crate::print::dynamic_debug::dynamic_pr_debug(
> + &mut DEBUG_INFO,
> + format_args!($($f)*)
> + );
> + }
> + }
> + }};
> + }
> +}
> --
> 2.49.0
>
Powered by blists - more mailing lists