From: Zhi Wang <zhiw@nvidia.com>
To: <rust-for-linux@vger.kernel.org>, <linux-kernel@vger.kernel.org>
Cc: <andrewjballance@gmail.com>, <daniel.almeida@collabora.com>,
<dakr@kernel.org>, <aliceryhl@google.com>, <ojeda@kernel.org>,
<boqun@kernel.org>, <gary@garyguo.net>,
<bjorn3_gh@protonmail.com>, <lossin@kernel.org>,
<a.hindborg@kernel.org>, <tmgross@umich.edu>, <cjia@nvidia.com>,
<smitra@nvidia.com>, <ankita@nvidia.com>, <aniketa@nvidia.com>,
<kwankhede@nvidia.com>, <targupta@nvidia.com>, <kjaju@nvidia.com>,
<alkumar@nvidia.com>, <acourbot@nvidia.com>,
<jhubbard@nvidia.com>, <zhiwang@kernel.org>,
Zhi Wang <zhiw@nvidia.com>
Subject: [PATCH v3 5/5] rust: device: add dynamic debug support to dev_dbg!
Date: Thu, 1 Oct 2026 17:59:40 +0300 [thread overview]
Message-ID: <20261001145940.1077801-6-zhiw@nvidia.com> (raw)
In-Reply-To: <20261001145940.1077801-1-zhiw@nvidia.com>
From: Andrew Ballance <andrewjballance@gmail.com>
Use Rust dynamic debug descriptors for dev_dbg! under DYNAMIC_DEBUG, or
DYNAMIC_DEBUG_CORE with a per-crate DYNAMIC_DEBUG_MODULE opt-in. Route
output through __dynamic_dev_dbg to retain device information and the
standard dynamic debug prefix controls.
Evaluate both the device expression and formatting arguments only when
the callsite is enabled. Calls start disabled and are controlled only by
dynamic debug. Without dynamic debug for the crate, type-check the
arguments without evaluating or printing them. Debug assertions no longer
control either path.
Make direct Device::pr_dbg() calls unconditional, like the other level
methods; callers needing callsite control and lazy evaluation use dev_dbg!.
No in-tree direct callers need conversion.
Document configuration, module selection and the explicit function-name
and embedded-NUL limitations.
Link: https://lore.kernel.org/rust-for-linux/20250620210533.400889-5-andrewjballance@gmail.com/
Signed-off-by: Andrew Ballance <andrewjballance@gmail.com>
[Zhi: Rebase onto driver-core-testing; use the revised descriptor and
printing bridge; keep device and argument evaluation conditional in
both dynamic and fallback paths; keep caller expressions outside unsafe
blocks while retaining their temporaries through each printing call.]
Signed-off-by: Zhi Wang <zhiw@nvidia.com>
---
.../admin-guide/dynamic-debug-howto.rst | 41 ++++++++++++++++++
rust/helpers/dynamic_debug.c | 8 ++++
rust/kernel/device.rs | 42 +++++++++++++++----
rust/kernel/print/dynamic_debug.rs | 27 ++++++++++++
4 files changed, 110 insertions(+), 8 deletions(-)
diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
index 9c2f096ed1d8..004312c0e9bc 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -390,3 +390,44 @@ just a shortcut for ``print_hex_dump(KERN_DEBUG)``.
For ``print_hex_dump_debug()``/``print_hex_dump_bytes()``, format string is
its ``prefix_str`` argument, if it is constant string; or ``hexdump``
in case ``prefix_str`` is built dynamically.
+
+Rust printing macros
+====================
+
+Rust ``pr_debug!`` and ``dev_dbg!`` use the same control file and boot or
+module parameters as their C counterparts. With ``CONFIG_DYNAMIC_DEBUG=y``,
+their callsites are initially disabled and can be enabled at runtime or
+through boot and module parameters. Rust's ``debug_assertions`` setting
+does not affect debug logging.
+
+With only ``CONFIG_DYNAMIC_DEBUG_CORE=y``, select the Rust crates to include
+in the catalogue using their Kbuild Rust flags, for example::
+
+ RUSTFLAGS_my_driver.o += --cfg DYNAMIC_DEBUG_MODULE
+
+Without dynamic debug for a crate, its ``pr_debug!`` and ``dev_dbg!`` calls
+stay disabled. Disabled calls do not evaluate their formatting arguments
+or device expressions, but their arguments are still checked at compile
+time. Keep required work and error handling outside those expressions.
+
+Rust callsites support the ``module``, ``file``, ``line`` and ``format``
+selectors. The module is the name supplied by Kbuild, including for callsites
+in nested Rust modules. Hyphens in this name become underscores, just as for C
+callsites. This name is independent of the prefix printed by ``pr_debug!``,
+which continues to use the name declared in ``module!``. The format is the
+original Rust format string, with ``{}`` placeholders, rather than the C
+``%pA`` formatting bridge.
+An embedded NUL ends the catalogue's copy of the format string; Rust
+formatting still uses the full string.
+
+Automatic Rust function names are not provided. The function field contains
+``<unknown>``, which is also what the ``f`` prefix flag displays. Use the
+other selectors to select Rust callsites; ``func`` cannot distinguish Rust
+functions. Rust callsites use the default, unclassified debug class.
+
+For example, to control a module named ``my_driver`` at load time or while
+it is running::
+
+ modprobe my_driver dyndbg=+p
+ echo 'module my_driver -p' > /proc/dynamic_debug/control
+ echo 'module my_driver +p' > /proc/dynamic_debug/control
diff --git a/rust/helpers/dynamic_debug.c b/rust/helpers/dynamic_debug.c
index 0ede4ee2eb79..fd2cfc57a3e6 100644
--- a/rust/helpers/dynamic_debug.c
+++ b/rust/helpers/dynamic_debug.c
@@ -22,4 +22,12 @@ __rust_helper void rust_helper_ddebug_print(struct _ddebug *descriptor,
dump_stack();
}
+__rust_helper void rust_helper_ddebug_dev_print(struct _ddebug *descriptor,
+ const struct device *dev,
+ const void *args)
+{
+ __dynamic_dev_dbg(descriptor, dev, "%pA", args);
+ if (descriptor->flags & _DPRINTK_FLAGS_INCL_STACK)
+ dump_stack();
+}
#endif
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index 2291d85b6849..968ac16ebb91 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -370,14 +370,13 @@ pub fn pr_info(&self, args: fmt::Arguments<'_>) {
/// Prints a debug-level message (level 7) prefixed with device information.
///
- /// More details are available from [`dev_dbg`].
+ /// This method prints unconditionally. Use [`dev_dbg!`] for dynamic debug callsites and lazy
+ /// evaluation of the device and formatting arguments.
///
- /// [`dev_dbg`]: crate::dev_dbg
+ /// [`dev_dbg!`]: crate::dev_dbg
pub fn pr_dbg(&self, args: fmt::Arguments<'_>) {
- if cfg!(debug_assertions) {
- // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
- unsafe { self.printk(bindings::KERN_DEBUG, args) };
- }
+ // SAFETY: `KERN_DEBUG` is a null-terminated kernel log-level constant.
+ unsafe { self.printk(bindings::KERN_DEBUG, args) };
}
/// Prints the provided message to the console.
@@ -929,13 +928,19 @@ macro_rules! dev_info {
///
/// This level should be used for debug messages.
///
-/// Equivalent to the kernel's `dev_dbg` macro, except that it doesn't support dynamic debug yet.
+/// Equivalent to the kernel's `dev_dbg` macro.
+///
+/// Supports [dynamic debug] with the same configuration and callsite selection as [`pr_debug!`].
+/// The function name is recorded as `<unknown>`. When a message is disabled, neither the device
+/// expression nor the formatting arguments are evaluated.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
/// [`core::fmt`] and [`std::format!`].
///
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
/// [`std::format!`]: https://doc.rust-lang.org/std/macro.format.html
+/// [dynamic debug]: https://docs.kernel.org/admin-guide/dynamic-debug-howto.html
+/// [`pr_debug!`]: crate::pr_debug!
///
/// # Examples
///
@@ -948,5 +953,26 @@ macro_rules! dev_info {
/// ```
#[macro_export]
macro_rules! dev_dbg {
- ($($f:tt)*) => { $crate::dev_printk!(pr_dbg, $($f)*) }
+ ($dev:expr, $($f:tt)*) => {{
+ #[cfg(any(CONFIG_DYNAMIC_DEBUG, all(CONFIG_DYNAMIC_DEBUG_CORE, DYNAMIC_DEBUG_MODULE)))]
+ {
+ $crate::dynamic_debug!(__descriptor, ($($f)*), {
+ match ($dev.as_ref(), $crate::prelude::fmt!($($f)*)) {
+ // SAFETY: `dynamic_debug!` supplies a live, initialized static descriptor.
+ // Its mutable fields are accessed only by the C dynamic debug code.
+ (dev, args) => unsafe {
+ $crate::print::dynamic_debug::Descriptor::dev_print(__descriptor, dev, args)
+ },
+ }
+ });
+ }
+
+ #[cfg(not(any(CONFIG_DYNAMIC_DEBUG, all(CONFIG_DYNAMIC_DEBUG_CORE, DYNAMIC_DEBUG_MODULE))))]
+ {
+ // Keep checking arguments even when dynamic debug is unavailable.
+ if false {
+ $crate::dev_printk!(pr_dbg, $dev, $($f)*);
+ }
+ }
+ }};
}
diff --git a/rust/kernel/print/dynamic_debug.rs b/rust/kernel/print/dynamic_debug.rs
index da4c40ed8fcc..e7250013998f 100644
--- a/rust/kernel/print/dynamic_debug.rs
+++ b/rust/kernel/print/dynamic_debug.rs
@@ -8,6 +8,10 @@
//! discovers them at boot or module load and removes them before the module is freed.
use crate::{
+ device::{
+ Device,
+ DeviceContext, //
+ },
fmt,
prelude::*,
str::as_char_ptr_in_const_context, //
@@ -90,6 +94,29 @@ pub unsafe fn print(descriptor: *mut Self, prefix: &CStr, args: fmt::Arguments<'
)
};
}
+
+ /// Prints arguments with device information and the dynamic debug prefixes.
+ ///
+ /// # Safety
+ ///
+ /// `descriptor` must point to an initialized descriptor valid for this call, whose string
+ /// pointers refer to valid NUL-terminated C strings. Concurrent access must follow the C
+ /// dynamic debug and jump label synchronization rules, without conflicting Rust accesses.
+ pub unsafe fn dev_print<Ctx: DeviceContext>(
+ descriptor: *mut Self,
+ dev: &Device<Ctx>,
+ args: fmt::Arguments<'_>,
+ ) {
+ // SAFETY: The descriptor is valid by the caller's guarantee and `dev` is alive for this
+ // call. The helper consumes the `%pA` arguments synchronously without retaining them.
+ unsafe {
+ bindings::ddebug_dev_print(
+ &raw mut (*descriptor).inner,
+ dev.as_raw(),
+ core::ptr::from_ref(&args).cast(),
+ )
+ };
+ }
}
/// Extracts only the format string for the callsite catalogue.
--
2.53.0
prev parent reply other threads:[~2026-10-01 15:00 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-01 14:59 [PATCH v3 0/5] Rust dynamic debug support for pr_debug! and dev_dbg! Zhi Wang
2026-10-01 14:59 ` [PATCH v3 1/5] gpu: nova-core: validate firmware versions before debug logging Zhi Wang
2026-10-01 14:59 ` [PATCH v3 2/5] rust: jump label: add support for nested arguments Zhi Wang
2026-10-01 14:59 ` [PATCH v3 3/5] dynamic_debug: expose printing declarations with the core enabled Zhi Wang
2026-10-01 14:59 ` [PATCH v3 4/5] rust: print: add dynamic debug support to pr_debug! Zhi Wang
2026-10-01 14:59 ` Zhi Wang [this message]
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=20261001145940.1077801-6-zhiw@nvidia.com \
--to=zhiw@nvidia.com \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=aliceryhl@google.com \
--cc=alkumar@nvidia.com \
--cc=andrewjballance@gmail.com \
--cc=aniketa@nvidia.com \
--cc=ankita@nvidia.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=cjia@nvidia.com \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=gary@garyguo.net \
--cc=jhubbard@nvidia.com \
--cc=kjaju@nvidia.com \
--cc=kwankhede@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=smitra@nvidia.com \
--cc=targupta@nvidia.com \
--cc=tmgross@umich.edu \
--cc=zhiwang@kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®