All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Ballance <andrewjballance@gmail.com>
To: jbaron@akamai.com, jim.cromie@gmail.com,
	daniel.almeida@collabora.com, acourbot@nvidia.com,
	ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com,
	gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org,
	a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu,
	dakr@kernel.org, gregkh@linuxfoundation.org, rafael@kernel.org,
	rostedt@goodmis.org, andrewjballance@gmail.com
Cc: viresh.kumar@linaro.org, lina+kernel@asahilina.net,
	tamird@gmail.com, jubalh@iodoru.org,
	rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [RFC PATCH 2/3] rust: device add support for dynamic debug to pr_debug!
Date: Wed, 11 Jun 2025 15:29:51 -0500	[thread overview]
Message-ID: <20250611202952.1670168-3-andrewjballance@gmail.com> (raw)
In-Reply-To: <20250611202952.1670168-1-andrewjballance@gmail.com>

adds support for dynamic debug for the pr_debug macro.

Signed-off-by: Andrew Ballance <andrewjballance@gmail.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() },
+                    },
+                }
+            }
+
+            #[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
+    #[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
+                unsafe {
+                    $crate::print::dynamic_debug::dynamic_pr_debug(
+                        &mut DEBUG_INFO,
+                        format_args!($($f)*)
+                    );
+                }
+            }
+        }};
+    }
+}
-- 
2.49.0


  parent reply	other threads:[~2025-06-11 20:30 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-11 20:29 [RFC PATCH 0/3] rust: add suppord for dynamic debug Andrew Ballance
2025-06-11 20:29 ` [RFC PATCH 1/3] rust: static jump: add support for nested arguments Andrew Ballance
2025-06-11 21:32   ` Alice Ryhl
2025-06-11 20:29 ` Andrew Ballance [this message]
2025-06-11 21:38   ` [RFC PATCH 2/3] rust: device add support for dynamic debug to pr_debug! Alice Ryhl
2025-06-12  4:02     ` Andrew Ballance
2025-06-12  7:17       ` Alice Ryhl
2025-06-11 20:29 ` [RFC PATCH 3/3] rust: device add support for dynamic debug to dev_dbg! Andrew Ballance
2025-06-11 20:36 ` [RFC PATCH 0/3] rust: add suppord for dynamic debug Andrew Ballance

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250611202952.1670168-3-andrewjballance@gmail.com \
    --to=andrewjballance@gmail.com \
    --cc=a.hindborg@kernel.org \
    --cc=acourbot@nvidia.com \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=dakr@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=gary@garyguo.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=jbaron@akamai.com \
    --cc=jim.cromie@gmail.com \
    --cc=jubalh@iodoru.org \
    --cc=lina+kernel@asahilina.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rafael@kernel.org \
    --cc=rostedt@goodmis.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tamird@gmail.com \
    --cc=tmgross@umich.edu \
    --cc=viresh.kumar@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.