* [RFC PATCH 0/3] rust: add suppord for dynamic debug
@ 2025-06-11 20:29 Andrew Ballance
2025-06-11 20:29 ` [RFC PATCH 1/3] rust: static jump: add support for nested arguments Andrew Ballance
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Andrew Ballance @ 2025-06-11 20:29 UTC (permalink / raw)
To: jbaron, jim.cromie, daniel.almeida, acourbot, ojeda, alex.gaynor,
boqun.feng, gary, bjorn3_gh, lossin, a.hindborg, aliceryhl,
tmgross, dakr, gregkh, rafael, rostedt, andrewjballance
Cc: viresh.kumar, lina+kernel, tamird, jubalh, rust-for-linux,
linux-kernel
This patch series adds support for dynamic debug to the rust
pr_debug! and dev_dbg! macros.
I have tested it and it and it does work but, there are a few
differences between this and the c version (hence why this is a rfc).
rust does not have an equivlant to the C __func__ macro. so, for the
time being this hard codes the function name to be the name of the
macro e.g. "pr_debug!" and "dev_dbg!".
This uses the module_path! macro to get the module name, which will not
be exactly the same as the c version if a kernel module contains multiple
rust modules. e.g. it might be "kernel_module_name::rust_module_name".
this does give a more accurate description of where the print statement
is located but it exactly what the c version does.
This patch series also had to make a small change to the static_branch!
macro so that it allows keys that are nested multiple structs deep within
a static variable.
Closes: https://github.com/Rust-for-Linux/linux/issues/453
Link: https://rust-for-linux.zulipchat.com/#narrow/channel/291565-Help/topic/Dynamic.20Debug.3F/with/519289668
Andrew Ballance (3):
rust: static jump: add support for nested arguments
rust: device add support for dynamic debug to pr_debug!
rust: device add support for dynamic debug to dev_dbg!
rust/bindings/bindings_helper.h | 1 +
rust/kernel/device.rs | 102 ++++++++++++++++++-
rust/kernel/jump_label.rs | 10 +-
rust/kernel/print.rs | 167 +++++++++++++++++++++++++++++++-
4 files changed, 269 insertions(+), 11 deletions(-)
--
2.49.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH 1/3] rust: static jump: add support for nested arguments
2025-06-11 20:29 [RFC PATCH 0/3] rust: add suppord for dynamic debug Andrew Ballance
@ 2025-06-11 20:29 ` Andrew Ballance
2025-06-11 21:32 ` Alice Ryhl
2025-06-11 20:29 ` [RFC PATCH 2/3] rust: device add support for dynamic debug to pr_debug! Andrew Ballance
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Andrew Ballance @ 2025-06-11 20:29 UTC (permalink / raw)
To: jbaron, jim.cromie, daniel.almeida, acourbot, ojeda, alex.gaynor,
boqun.feng, gary, bjorn3_gh, lossin, a.hindborg, aliceryhl,
tmgross, dakr, gregkh, rafael, rostedt, andrewjballance
Cc: viresh.kumar, lina+kernel, tamird, jubalh, rust-for-linux,
linux-kernel
allows for nested arguments to be used with the static_branch macro.
e.g. `outer.inner.key` can now be accessed by the macro
Signed-off-by: Andrew Ballance <andrewjballance@gmail.com>
---
rust/kernel/jump_label.rs | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/rust/kernel/jump_label.rs b/rust/kernel/jump_label.rs
index 4e974c768dbd..4ea3cbb340ff 100644
--- a/rust/kernel/jump_label.rs
+++ b/rust/kernel/jump_label.rs
@@ -19,9 +19,9 @@
/// The macro must be used with a real static key defined by C.
#[macro_export]
macro_rules! static_branch_unlikely {
- ($key:path, $keytyp:ty, $field:ident) => {{
+ ($key:path, $keytyp:ty, $field:ident $(.$field_cont:ident)*) => {{
let _key: *const $keytyp = ::core::ptr::addr_of!($key);
- let _key: *const $crate::bindings::static_key_false = ::core::ptr::addr_of!((*_key).$field);
+ let _key: *const $crate::bindings::static_key_false = ::core::ptr::addr_of!((*_key).$field$(.$field_cont)*);
let _key: *const $crate::bindings::static_key = _key.cast();
#[cfg(not(CONFIG_JUMP_LABEL))]
@@ -30,7 +30,7 @@ macro_rules! static_branch_unlikely {
}
#[cfg(CONFIG_JUMP_LABEL)]
- $crate::jump_label::arch_static_branch! { $key, $keytyp, $field, false }
+ $crate::jump_label::arch_static_branch! { $key, $keytyp, $field$(.$field_cont)*, false }
}};
}
pub use static_branch_unlikely;
@@ -46,14 +46,14 @@ macro_rules! static_branch_unlikely {
#[doc(hidden)]
#[cfg(CONFIG_JUMP_LABEL)]
macro_rules! arch_static_branch {
- ($key:path, $keytyp:ty, $field:ident, $branch:expr) => {'my_label: {
+ ($key:path, $keytyp:ty, $field:ident $(.$field_cont:ident)*, $branch:expr) => {'my_label: {
$crate::asm!(
include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_static_branch_asm.rs"));
l_yes = label {
break 'my_label true;
},
symb = sym $key,
- off = const ::core::mem::offset_of!($keytyp, $field),
+ off = const ::core::mem::offset_of!($keytyp, $field$(.$field_cont)*),
branch = const $crate::jump_label::bool_to_int($branch),
);
--
2.49.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC PATCH 2/3] rust: device add support for dynamic debug to pr_debug!
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 20:29 ` Andrew Ballance
2025-06-11 21:38 ` 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
3 siblings, 1 reply; 9+ messages in thread
From: Andrew Ballance @ 2025-06-11 20:29 UTC (permalink / raw)
To: jbaron, jim.cromie, daniel.almeida, acourbot, ojeda, alex.gaynor,
boqun.feng, gary, bjorn3_gh, lossin, a.hindborg, aliceryhl,
tmgross, dakr, gregkh, rafael, rostedt, andrewjballance
Cc: viresh.kumar, lina+kernel, tamird, jubalh, rust-for-linux,
linux-kernel
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
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC PATCH 3/3] rust: device add support for dynamic debug to dev_dbg!
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 20:29 ` [RFC PATCH 2/3] rust: device add support for dynamic debug to pr_debug! Andrew Ballance
@ 2025-06-11 20:29 ` Andrew Ballance
2025-06-11 20:36 ` [RFC PATCH 0/3] rust: add suppord for dynamic debug Andrew Ballance
3 siblings, 0 replies; 9+ messages in thread
From: Andrew Ballance @ 2025-06-11 20:29 UTC (permalink / raw)
To: jbaron, jim.cromie, daniel.almeida, acourbot, ojeda, alex.gaynor,
boqun.feng, gary, bjorn3_gh, lossin, a.hindborg, aliceryhl,
tmgross, dakr, gregkh, rafael, rostedt, andrewjballance
Cc: viresh.kumar, lina+kernel, tamird, jubalh, rust-for-linux,
linux-kernel
adds support for dynamic debug for the dev_dbg macro.
Signed-off-by: Andrew Ballance <andrewjballance@gmail.com>
---
rust/kernel/device.rs | 102 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 100 insertions(+), 2 deletions(-)
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index dea06b79ecb5..f59fed944876 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -536,11 +536,14 @@ 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.
+///
+/// This has support for [`dynamic debug`].
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
/// [`core::fmt`] and [`std::format!`].
///
+/// [`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
///
@@ -555,5 +558,100 @@ macro_rules! dev_info {
/// ```
#[macro_export]
macro_rules! dev_dbg {
- ($($f:tt)*) => { $crate::dev_printk!(pr_dbg, $($f)*); }
+ ($($f:tt)*) => {
+ #[cfg(any(DYNAMIC_DEBUG_MODULE, CONFIG_DYNAMIC_DEBUG))]
+ { $crate::dynamic_dev_dbg_unlikely!($($f)*); }
+
+ #[cfg(not(any(DYNAMIC_DEBUG_MODULE, CONFIG_DYNAMIC_DEBUG)))]
+ { $crate::dev_printk!(pr_dbg, $($f)*); }
+ }
+}
+
+/// this contains all of the code that is used for dynamic debug for dev_dbg!
+/// 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 {
+
+ use super::Device;
+ use kernel::c_str;
+ use kernel::print::dynamic_debug::_Ddebug;
+
+ /// a wrapper function around the c function `__dynamic_dev_dbg`.
+ /// # Safety
+ /// - descriptor must be a valid reference to a `static mut` _Ddebug
+ pub unsafe fn dynamic_dev_dbg(
+ descriptor: &mut _Ddebug,
+ dev: &Device,
+ args: core::fmt::Arguments<'_>,
+ ) {
+ // SAFETY:
+ // - "%pA" is null terminated and is the format for rust printing
+ // - dev.as_raw() is a valid pointer to struct device
+ unsafe {
+ bindings::__dynamic_dev_dbg(
+ &raw mut descriptor.inner,
+ dev.as_raw(),
+ c_str!("%pA").as_char_ptr(),
+ (&raw const args).cast::<ffi::c_void>(),
+ )
+ };
+ }
+
+ /// macro for dynamic debug equilant to the C `dev_dbg` macro
+ #[doc(hidden)]
+ #[macro_export]
+ macro_rules! dynamic_dev_dbg_unlikely {
+ ($dev:expr, $($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!("dev_dbg!");
+ 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)]
+ {
+ ::kernel::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::device::dynamic_debug::dynamic_dev_dbg(
+ &mut DEBUG_INFO,
+ $dev,
+ format_args!($($f)*)
+ );
+ }
+ }
+ }};
+ }
}
--
2.49.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 0/3] rust: add suppord for dynamic debug
2025-06-11 20:29 [RFC PATCH 0/3] rust: add suppord for dynamic debug Andrew Ballance
` (2 preceding siblings ...)
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 ` Andrew Ballance
3 siblings, 0 replies; 9+ messages in thread
From: Andrew Ballance @ 2025-06-11 20:36 UTC (permalink / raw)
To: jbaron, jim.cromie, daniel.almeida, acourbot, ojeda, alex.gaynor,
boqun.feng, gary, bjorn3_gh, lossin, a.hindborg, aliceryhl,
tmgross, dakr, gregkh, rafael, rostedt
Cc: viresh.kumar, lina+kernel, tamird, jubalh, rust-for-linux,
linux-kernel
On 6/11/25 3:29 PM, Andrew Ballance wrote:
> This uses the module_path! macro to get the module name, which will not
> be exactly the same as the c version if a kernel module contains multiple
> rust modules. e.g. it might be "kernel_module_name::rust_module_name".
> this does give a more accurate description of where the print statement
> is located but it exactly what the c version does.
oops. typo.
is *not* exactly what the c version does.
Best Regards
Andrew Ballance
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 1/3] rust: static jump: add support for nested arguments
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
0 siblings, 0 replies; 9+ messages in thread
From: Alice Ryhl @ 2025-06-11 21:32 UTC (permalink / raw)
To: Andrew Ballance
Cc: jbaron, jim.cromie, daniel.almeida, acourbot, ojeda, alex.gaynor,
boqun.feng, gary, bjorn3_gh, lossin, a.hindborg, tmgross, dakr,
gregkh, rafael, rostedt, viresh.kumar, lina+kernel, tamird,
jubalh, rust-for-linux, linux-kernel
On Wed, Jun 11, 2025 at 10:30 PM Andrew Ballance
<andrewjballance@gmail.com> wrote:
>
> allows for nested arguments to be used with the static_branch macro.
> e.g. `outer.inner.key` can now be accessed by the macro
>
> Signed-off-by: Andrew Ballance <andrewjballance@gmail.com>
> ---
> rust/kernel/jump_label.rs | 10 +++++-----
> 1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/rust/kernel/jump_label.rs b/rust/kernel/jump_label.rs
> index 4e974c768dbd..4ea3cbb340ff 100644
> --- a/rust/kernel/jump_label.rs
> +++ b/rust/kernel/jump_label.rs
> @@ -19,9 +19,9 @@
> /// The macro must be used with a real static key defined by C.
> #[macro_export]
> macro_rules! static_branch_unlikely {
> - ($key:path, $keytyp:ty, $field:ident) => {{
> + ($key:path, $keytyp:ty, $field:ident $(.$field_cont:ident)*) => {{
I think this can be:
($key:path, $keytyp:ty, $($field:ident).+) => {{
this means "one or more identifiers separated by dots.
> let _key: *const $keytyp = ::core::ptr::addr_of!($key);
> - let _key: *const $crate::bindings::static_key_false = ::core::ptr::addr_of!((*_key).$field);
> + let _key: *const $crate::bindings::static_key_false = ::core::ptr::addr_of!((*_key).$field$(.$field_cont)*);
> let _key: *const $crate::bindings::static_key = _key.cast();
>
> #[cfg(not(CONFIG_JUMP_LABEL))]
> @@ -30,7 +30,7 @@ macro_rules! static_branch_unlikely {
> }
>
> #[cfg(CONFIG_JUMP_LABEL)]
> - $crate::jump_label::arch_static_branch! { $key, $keytyp, $field, false }
> + $crate::jump_label::arch_static_branch! { $key, $keytyp, $field$(.$field_cont)*, false }
> }};
> }
> pub use static_branch_unlikely;
> @@ -46,14 +46,14 @@ macro_rules! static_branch_unlikely {
> #[doc(hidden)]
> #[cfg(CONFIG_JUMP_LABEL)]
> macro_rules! arch_static_branch {
> - ($key:path, $keytyp:ty, $field:ident, $branch:expr) => {'my_label: {
> + ($key:path, $keytyp:ty, $field:ident $(.$field_cont:ident)*, $branch:expr) => {'my_label: {
> $crate::asm!(
> include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_static_branch_asm.rs"));
> l_yes = label {
> break 'my_label true;
> },
> symb = sym $key,
> - off = const ::core::mem::offset_of!($keytyp, $field),
> + off = const ::core::mem::offset_of!($keytyp, $field$(.$field_cont)*),
> branch = const $crate::jump_label::bool_to_int($branch),
> );
>
> --
> 2.49.0
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 2/3] rust: device add support for dynamic debug to pr_debug!
2025-06-11 20:29 ` [RFC PATCH 2/3] rust: device add support for dynamic debug to pr_debug! Andrew Ballance
@ 2025-06-11 21:38 ` Alice Ryhl
2025-06-12 4:02 ` Andrew Ballance
0 siblings, 1 reply; 9+ messages in thread
From: Alice Ryhl @ 2025-06-11 21:38 UTC (permalink / raw)
To: Andrew Ballance
Cc: jbaron, jim.cromie, daniel.almeida, acourbot, ojeda, alex.gaynor,
boqun.feng, gary, bjorn3_gh, lossin, a.hindborg, tmgross, dakr,
gregkh, rafael, rostedt, viresh.kumar, lina+kernel, tamird,
jubalh, rust-for-linux, linux-kernel
On Wed, Jun 11, 2025 at 10:30 PM Andrew Ballance
<andrewjballance@gmail.com> wrote:
>
> 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() },
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
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 2/3] rust: device add support for dynamic debug to pr_debug!
2025-06-11 21:38 ` Alice Ryhl
@ 2025-06-12 4:02 ` Andrew Ballance
2025-06-12 7:17 ` Alice Ryhl
0 siblings, 1 reply; 9+ messages in thread
From: Andrew Ballance @ 2025-06-12 4:02 UTC (permalink / raw)
To: Alice Ryhl
Cc: jbaron, jim.cromie, daniel.almeida, acourbot, ojeda, alex.gaynor,
boqun.feng, gary, bjorn3_gh, lossin, a.hindborg, tmgross, dakr,
gregkh, rafael, rostedt, viresh.kumar, lina+kernel, tamird,
jubalh, rust-for-linux, linux-kernel
On 6/11/25 4:38 PM, Alice Ryhl wrote:
> 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.
Will do for the v2.
> 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.
>
Unfortunately, static_branch_unlikely does not work with keys contained
within a Opaque, because it uses offset_of and sym. I can create a macro
specifically for dealing with Opaque::<type_that_contains_a_static_key>
because I imagine that many uses of static branch will end up wrapped
in an Opaque.
Best regards,
Andrew Ballance
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 2/3] rust: device add support for dynamic debug to pr_debug!
2025-06-12 4:02 ` Andrew Ballance
@ 2025-06-12 7:17 ` Alice Ryhl
0 siblings, 0 replies; 9+ messages in thread
From: Alice Ryhl @ 2025-06-12 7:17 UTC (permalink / raw)
To: Andrew Ballance
Cc: jbaron, jim.cromie, daniel.almeida, acourbot, ojeda, alex.gaynor,
boqun.feng, gary, bjorn3_gh, lossin, a.hindborg, tmgross, dakr,
gregkh, rafael, rostedt, viresh.kumar, lina+kernel, tamird,
jubalh, rust-for-linux, linux-kernel
On Thu, Jun 12, 2025 at 6:02 AM Andrew Ballance
<andrewjballance@gmail.com> wrote:
>
> On 6/11/25 4:38 PM, Alice Ryhl wrote:
> > 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.
>
> Will do for the v2.
>
> > 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.
> >
>
> Unfortunately, static_branch_unlikely does not work with keys contained
> within a Opaque, because it uses offset_of and sym. I can create a macro
> specifically for dealing with Opaque::<type_that_contains_a_static_key>
> because I imagine that many uses of static branch will end up wrapped
> in an Opaque.
Ah, fair enough. In that case, you can also do this:
$crate::print::dynamic_debug::dynamic_pr_debug(
&raw mut DEBUG_INFO,
format_args!($($f)*)
);
using &raw mut creates a raw pointer directly without creating a
reference, so that also solves my concern.
Alice
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-06-12 7:17 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [RFC PATCH 2/3] rust: device add support for dynamic debug to pr_debug! Andrew Ballance
2025-06-11 21:38 ` 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
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.