* [PATCH RFC 00/11] rust: add support for dynamic debug
@ 2026-10-11 12:52 Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 01/11] rust: print: use CStr for __LOG_PREFIX Thomas Weißschuh
` (10 more replies)
0 siblings, 11 replies; 21+ messages in thread
From: Thomas Weißschuh @ 2026-10-11 12:52 UTC (permalink / raw)
To: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core, Thomas Weißschuh
Add the Rust infrastructure to integrate with the dynamic debug
infrastructure.
Static keys are not used for now, as the full bindings are missing
for those. A follow-up series will add that.
Also custom classes are not supported yet, but could be added on top.
Patches 1-4: Generic Rust preparation patches.
Patches 5-7: C dynamic debug preparation patches.
Patches 8: Rust Dynamic debug infrastructure.
Patches 9-11: Rust Dynamic debug enablement.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
Thomas Weißschuh (11):
rust: print: use CStr for __LOG_PREFIX
rust: sync: atomic: Add Atomic<u{8,16}>
rust: num: Add Bounded::USABLE_BITS
samples: rust_print: add debug messages
dyndbg: use u32 for struct _ddebug bitfields
dyndbg: make _ddebug::flags its own field
dyndbg: use READ_ONCE()/WRITE_ONCE() to access descriptor flags
rust: add support for dynamic debug
rust: print: enable dynamic debug for pr_debug!()
rust: device: remove logging methods
rust: device: enable dynamic debug for dev_dbg!()
MAINTAINERS | 1 +
include/linux/dynamic_debug.h | 13 +-
lib/dynamic_debug.c | 24 ++--
rust/bindings/bindings_helper.h | 1 +
rust/kernel/device.rs | 175 +++++++++++------------
rust/kernel/dynamic_debug.rs | 264 +++++++++++++++++++++++++++++++++++
rust/kernel/lib.rs | 6 +-
rust/kernel/num/bounded.rs | 3 +
rust/kernel/print.rs | 21 +--
rust/kernel/sync/atomic/predefine.rs | 44 ++++--
rust/macros/module.rs | 4 +-
samples/rust/Makefile | 2 +
samples/rust/rust_print_main.rs | 2 +
scripts/rustdoc_test_gen.rs | 4 +-
14 files changed, 428 insertions(+), 136 deletions(-)
---
base-commit: 2dee3d3adcadcc57d62ba6608cd02f50b0c10264
change-id: 20260921-rust-dyndbg-17b822f24894
Best regards,
--
Thomas Weißschuh <linux@weissschuh.net>
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 01/11] rust: print: use CStr for __LOG_PREFIX
2026-10-11 12:52 [PATCH RFC 00/11] rust: add support for dynamic debug Thomas Weißschuh
@ 2026-10-11 12:52 ` Thomas Weißschuh
2026-10-11 13:01 ` Gary Guo
2026-10-11 12:52 ` [PATCH RFC 02/11] rust: sync: atomic: Add Atomic<u{8,16}> Thomas Weißschuh
` (9 subsequent siblings)
10 siblings, 1 reply; 21+ messages in thread
From: Thomas Weißschuh @ 2026-10-11 12:52 UTC (permalink / raw)
To: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core, Thomas Weißschuh
The users of __LOG_PREFIX require that it is 0-terminated.
Currently this requirement is only encoded in safety comments.
Switch to CStr which can guarantee this invariant through the type
system.
As __LOG_PREFIX and Module::NAME are now identical, reuse the former to
implement the latter.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
rust/kernel/lib.rs | 4 ++--
rust/kernel/print.rs | 11 ++++-------
rust/macros/module.rs | 4 ++--
scripts/rustdoc_test_gen.rs | 4 ++--
4 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 7225abc64084..7d48f931877d 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -159,7 +159,7 @@
pub use uapi;
/// Prefix to appear before log messages printed from within the `kernel` crate.
-const __LOG_PREFIX: &[u8] = b"rust_kernel\0";
+const __LOG_PREFIX: &str::CStr = c"rust_kernel";
/// Dummy module type for `#[vtable]` `impl` blocks within the `kernel` crate (e.g. KUnit tests).
// The `allow` is needed since it may be unused (e.g. KUnit tests may be disabled).
@@ -167,7 +167,7 @@
struct LocalModule;
impl ModuleMetadata for LocalModule {
- const NAME: &'static str::CStr = c"rust_kernel";
+ const NAME: &'static str::CStr = __LOG_PREFIX;
const THIS_MODULE: ThisModule = {
// SAFETY: `try_module_get`/`module_put` handle null module pointers gracefully.
diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs
index 0d62beeedca5..9ce52b9fa69f 100644
--- a/rust/kernel/print.rs
+++ b/rust/kernel/print.rs
@@ -96,15 +96,14 @@ pub mod format_strings {
///
/// # Safety
///
-/// The format string must be one of the ones in [`format_strings`], and
-/// the module name must be null-terminated.
+/// The format string must be one of the ones in [`format_strings`].
///
/// [`_printk`]: srctree/include/linux/printk.h
#[doc(hidden)]
#[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))]
pub unsafe fn call_printk(
format_string: &[u8; format_strings::LENGTH],
- module_name: &[u8],
+ module_name: &CStr,
args: fmt::Arguments<'_>,
) {
// `_printk` does not seem to fail in any path.
@@ -113,7 +112,7 @@ pub unsafe fn call_printk(
unsafe {
bindings::_printk(
format_string.as_ptr(),
- module_name.as_ptr(),
+ module_name.as_char_ptr(),
core::ptr::from_ref(&args).cast::<c_void>(),
);
}
@@ -157,9 +156,7 @@ macro_rules! print_macro (
match $crate::prelude::fmt!($($arg)+) {
// SAFETY: This hidden macro should only be called by the documented
// printing macros which ensure the format string is one of the fixed
- // ones. All `__LOG_PREFIX`s are null-terminated as they are generated
- // by the `module!` proc macro or fixed values defined in a kernel
- // crate.
+ // ones.
args => unsafe {
$crate::print::call_printk(
&$format_string,
diff --git a/rust/macros/module.rs b/rust/macros/module.rs
index 0a7b9e24c960..6228fe23c310 100644
--- a/rust/macros/module.rs
+++ b/rust/macros/module.rs
@@ -496,14 +496,14 @@ pub(crate) fn module(info: ModuleInfo) -> Result<TokenStream> {
/// The module name.
///
/// Used by the printing macros, e.g. [`info!`].
- const __LOG_PREFIX: &[u8] = #name_cstr.to_bytes_with_nul();
+ const __LOG_PREFIX: &::kernel::str::CStr = #name_cstr;
/// The `LocalModule` type is the type of the module created by `module!`,
/// `module_pci_driver!`, `module_platform_driver!`, etc.
type LocalModule = #type_;
impl ::kernel::ModuleMetadata for #type_ {
- const NAME: &'static ::kernel::str::CStr = #name_cstr;
+ const NAME: &'static ::kernel::str::CStr = __LOG_PREFIX;
#[cfg(MODULE)]
const THIS_MODULE: ::kernel::ThisModule = {
diff --git a/scripts/rustdoc_test_gen.rs b/scripts/rustdoc_test_gen.rs
index 754c5aafcce4..488de817b425 100644
--- a/scripts/rustdoc_test_gen.rs
+++ b/scripts/rustdoc_test_gen.rs
@@ -224,7 +224,7 @@ macro_rules! line {{
BufWriter::new(File::create("rust/doctests_kernel_generated.rs").unwrap()),
r#"//! `kernel` crate documentation tests.
-const __LOG_PREFIX: &[u8] = b"rust_doctests_kernel\0";
+const __LOG_PREFIX: &kernel::str::CStr = c"rust_doctests_kernel";
/// Dummy module type for doctest context.
struct LocalModule;
@@ -237,7 +237,7 @@ macro_rules! line {{
use core::ptr::null_mut;
impl ModuleMetadata for LocalModule {{
- const NAME: &'static CStr = c"rust_doctests_kernel";
+ const NAME: &'static CStr = __LOG_PREFIX;
const THIS_MODULE: ThisModule = {{
// SAFETY: `try_module_get`/`module_put` handle null module pointers gracefully.
unsafe {{ ThisModule::from_ptr(null_mut()) }}
--
2.56.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 02/11] rust: sync: atomic: Add Atomic<u{8,16}>
2026-10-11 12:52 [PATCH RFC 00/11] rust: add support for dynamic debug Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 01/11] rust: print: use CStr for __LOG_PREFIX Thomas Weißschuh
@ 2026-10-11 12:52 ` Thomas Weißschuh
2026-10-11 13:04 ` Gary Guo
2026-10-11 12:52 ` [PATCH RFC 03/11] rust: num: Add Bounded::USABLE_BITS Thomas Weißschuh
` (8 subsequent siblings)
10 siblings, 1 reply; 21+ messages in thread
From: Thomas Weißschuh @ 2026-10-11 12:52 UTC (permalink / raw)
To: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core, Thomas Weißschuh
Add generic atomic support for small unsigned integers that have an
`AtomicImpl` with the same size and alignment.
Also extend the unit tests.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
rust/kernel/sync/atomic/predefine.rs | 44 ++++++++++++++++++++++++++++--------
1 file changed, 35 insertions(+), 9 deletions(-)
diff --git a/rust/kernel/sync/atomic/predefine.rs b/rust/kernel/sync/atomic/predefine.rs
index 3d63f40791fa..4c1fb5e08dc2 100644
--- a/rust/kernel/sync/atomic/predefine.rs
+++ b/rust/kernel/sync/atomic/predefine.rs
@@ -113,6 +113,32 @@ fn rhs_into_delta(rhs: isize) -> isize_atomic_repr {
}
}
+// SAFETY: `u8` and `i8` has the same size and alignment, and `u8` is round-trip transmutable to
+// `i8`.
+unsafe impl super::AtomicType for u8 {
+ type Repr = i8;
+}
+
+// SAFETY: The wrapping add result of two `i8`s is a valid `u8`.
+unsafe impl super::AtomicAdd<u8> for u8 {
+ fn rhs_into_delta(rhs: u8) -> i8 {
+ rhs as i8
+ }
+}
+
+// SAFETY: `u16` and `i16` has the same size and alignment, and `u16` is round-trip transmutable to
+// `i16`.
+unsafe impl super::AtomicType for u16 {
+ type Repr = i16;
+}
+
+// SAFETY: The wrapping add result of two `i16`s is a valid `u16`.
+unsafe impl super::AtomicAdd<u16> for u16 {
+ fn rhs_into_delta(rhs: u16) -> i16 {
+ rhs as i16
+ }
+}
+
// SAFETY: `u32` and `i32` has the same size and alignment, and `u32` is round-trip transmutable to
// `i32`.
unsafe impl super::AtomicType for u32 {
@@ -170,13 +196,13 @@ macro_rules! for_each_type {
#[test]
fn atomic_basic_tests() {
- for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
+ for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| {
let x = Atomic::new(v);
assert_eq!(v, x.load(Relaxed));
});
- for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
+ for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| {
let x = Atomic::new(v);
let ptr = x.as_ptr();
@@ -187,14 +213,14 @@ fn atomic_basic_tests() {
#[test]
fn atomic_acquire_release_tests() {
- for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
+ for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| {
let x = Atomic::new(0);
x.store(v, Release);
assert_eq!(v, x.load(Acquire));
});
- for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
+ for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| {
let x = Atomic::new(0);
let ptr = x.as_ptr();
@@ -208,7 +234,7 @@ fn atomic_acquire_release_tests() {
#[test]
fn atomic_xchg_tests() {
- for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
+ for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| {
let x = Atomic::new(v);
let old = v;
@@ -218,7 +244,7 @@ fn atomic_xchg_tests() {
assert_eq!(new, x.load(Relaxed));
});
- for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
+ for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| {
let x = Atomic::new(v);
let ptr = x.as_ptr();
@@ -233,7 +259,7 @@ fn atomic_xchg_tests() {
#[test]
fn atomic_cmpxchg_tests() {
- for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
+ for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| {
let x = Atomic::new(v);
let old = v;
@@ -245,7 +271,7 @@ fn atomic_cmpxchg_tests() {
assert_eq!(new, x.load(Relaxed));
});
- for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
+ for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| {
let x = Atomic::new(v);
let ptr = x.as_ptr();
@@ -263,7 +289,7 @@ fn atomic_cmpxchg_tests() {
#[test]
fn atomic_arithmetic_tests() {
- for_each_type!(42 in [i32, i64, u32, u64, isize, usize] |v| {
+ for_each_type!(42 in [i32, i64, u64, isize, usize] |v| {
let x = Atomic::new(v);
assert_eq!(v, x.fetch_add(12, Full));
--
2.56.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 03/11] rust: num: Add Bounded::USABLE_BITS
2026-10-11 12:52 [PATCH RFC 00/11] rust: add support for dynamic debug Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 01/11] rust: print: use CStr for __LOG_PREFIX Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 02/11] rust: sync: atomic: Add Atomic<u{8,16}> Thomas Weißschuh
@ 2026-10-11 12:52 ` Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 04/11] samples: rust_print: add debug messages Thomas Weißschuh
` (7 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Thomas Weißschuh @ 2026-10-11 12:52 UTC (permalink / raw)
To: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core, Thomas Weißschuh
Expose the types usable bits as an associated constant.
This can be used for example with static_assert!() to validate
the Bounded type against bindings constants it reflects.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
rust/kernel/num/bounded.rs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/rust/kernel/num/bounded.rs b/rust/kernel/num/bounded.rs
index 2a2b0a4bca5e..4045e5aeb7dc 100644
--- a/rust/kernel/num/bounded.rs
+++ b/rust/kernel/num/bounded.rs
@@ -285,6 +285,9 @@ impl<T, const N: u32> Bounded<T, N>
where
T: Integer,
{
+ /// Number of usable bits in this [`Bounded`] type.
+ pub const USABLE_BITS: u32 = N;
+
/// Private constructor enforcing the type invariants.
///
/// All instances of [`Bounded`] must be created through this method as it enforces most of the
--
2.56.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 04/11] samples: rust_print: add debug messages
2026-10-11 12:52 [PATCH RFC 00/11] rust: add support for dynamic debug Thomas Weißschuh
` (2 preceding siblings ...)
2026-10-11 12:52 ` [PATCH RFC 03/11] rust: num: Add Bounded::USABLE_BITS Thomas Weißschuh
@ 2026-10-11 12:52 ` Thomas Weißschuh
2026-10-11 13:53 ` Miguel Ojeda
2026-10-11 12:52 ` [PATCH RFC 05/11] dyndbg: use u32 for struct _ddebug bitfields Thomas Weißschuh
` (6 subsequent siblings)
10 siblings, 1 reply; 21+ messages in thread
From: Thomas Weißschuh @ 2026-10-11 12:52 UTC (permalink / raw)
To: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core, Thomas Weißschuh
The sample prints messages for all levels, except for debug.
Add such messages.
To make sure they are actually printed, enable debug assertions.
This example will become even more useful when dynamic debug is
implemented for Rust.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
samples/rust/Makefile | 2 ++
samples/rust/rust_print_main.rs | 2 ++
2 files changed, 4 insertions(+)
diff --git a/samples/rust/Makefile b/samples/rust/Makefile
index b986b681cde5..bc27f8851571 100644
--- a/samples/rust/Makefile
+++ b/samples/rust/Makefile
@@ -18,6 +18,8 @@ obj-$(CONFIG_SAMPLE_RUST_DRIVER_SERDEV) += rust_driver_serdev.o
obj-$(CONFIG_SAMPLE_RUST_CONFIGFS) += rust_configfs.o
obj-$(CONFIG_SAMPLE_RUST_SOC) += rust_soc.o
+RUSTFLAGS_rust_print_main.o += -Cdebug-assertions=y
+
rust_print-y := rust_print_main.o rust_print_events.o
subdir-$(CONFIG_SAMPLE_RUST_HOSTPROGS) += hostprogs
diff --git a/samples/rust/rust_print_main.rs b/samples/rust/rust_print_main.rs
index 01729e87d6b5..6b9f59d7fec7 100644
--- a/samples/rust/rust_print_main.rs
+++ b/samples/rust/rust_print_main.rs
@@ -69,6 +69,7 @@ fn init(_module: &'static ThisModule) -> Result<Self> {
pr_warn!("Warning message (level 4) without args\n");
pr_notice!("Notice message (level 5) without args\n");
pr_info!("Info message (level 6) without args\n");
+ pr_debug!("Debug message (level 7) without args\n");
pr_info!("A line that");
pr_cont!(" is continued");
@@ -81,6 +82,7 @@ fn init(_module: &'static ThisModule) -> Result<Self> {
pr_warn!("{} message (level {}) with args\n", "Warning", 4);
pr_notice!("{} message (level {}) with args\n", "Notice", 5);
pr_info!("{} message (level {}) with args\n", "Info", 6);
+ pr_debug!("{} message (level {}) with args\n", "Debug", 7);
pr_info!("A {} that", "line");
pr_cont!(" is {}", "continued");
--
2.56.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 05/11] dyndbg: use u32 for struct _ddebug bitfields
2026-10-11 12:52 [PATCH RFC 00/11] rust: add support for dynamic debug Thomas Weißschuh
` (3 preceding siblings ...)
2026-10-11 12:52 ` [PATCH RFC 04/11] samples: rust_print: add debug messages Thomas Weißschuh
@ 2026-10-11 12:52 ` Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 06/11] dyndbg: make _ddebug::flags its own field Thomas Weißschuh
` (5 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Thomas Weißschuh @ 2026-10-11 12:52 UTC (permalink / raw)
To: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core, Thomas Weißschuh
Make it more obvious that the bitfield is 32 bits wide.
This will be especially useful as the next commit will change the
bitfield.
No functional change.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
include/linux/dynamic_debug.h | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 05743900a116..0b34343df594 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -7,6 +7,7 @@
#endif
#include <linux/build_bug.h>
+#include <linux/types.h>
/*
* An instance of this structure is created in a special
@@ -22,9 +23,9 @@ struct _ddebug {
const char *function;
const char *filename;
const char *format;
- unsigned int lineno:18;
+ u32 lineno:18;
#define CLS_BITS 6
- unsigned int class_id:CLS_BITS;
+ u32 class_id:CLS_BITS;
#define _DPRINTK_CLASS_DFLT ((1 << CLS_BITS) - 1)
/*
* The flags field controls the behaviour at the callsite.
@@ -50,7 +51,7 @@ struct _ddebug {
#else
#define _DPRINTK_FLAGS_DEFAULT 0
#endif
- unsigned int flags:8;
+ u32 flags:8;
#ifdef CONFIG_JUMP_LABEL
union {
struct static_key_true dd_key_true;
--
2.56.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 06/11] dyndbg: make _ddebug::flags its own field
2026-10-11 12:52 [PATCH RFC 00/11] rust: add support for dynamic debug Thomas Weißschuh
` (4 preceding siblings ...)
2026-10-11 12:52 ` [PATCH RFC 05/11] dyndbg: use u32 for struct _ddebug bitfields Thomas Weißschuh
@ 2026-10-11 12:52 ` Thomas Weißschuh
2026-10-11 13:23 ` Gary Guo
2026-10-11 12:52 ` [PATCH RFC 07/11] dyndbg: use READ_ONCE()/WRITE_ONCE() to access descriptor flags Thomas Weißschuh
` (4 subsequent siblings)
10 siblings, 1 reply; 21+ messages in thread
From: Thomas Weißschuh @ 2026-10-11 12:52 UTC (permalink / raw)
To: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core, Thomas Weißschuh
Keeping the flags as part of the bitfield prevents the usage of
READ_ONCE()/WRITE_ONCE() with it. It also makes access from Rust
awkward.
Make it a dedicated field.
The new field will stay in the exact same location in the parent
structure.
No functional change.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
include/linux/dynamic_debug.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 0b34343df594..b1ff7c0e9a5f 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -51,7 +51,7 @@ struct _ddebug {
#else
#define _DPRINTK_FLAGS_DEFAULT 0
#endif
- u32 flags:8;
+ u8 flags;
#ifdef CONFIG_JUMP_LABEL
union {
struct static_key_true dd_key_true;
--
2.56.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 07/11] dyndbg: use READ_ONCE()/WRITE_ONCE() to access descriptor flags
2026-10-11 12:52 [PATCH RFC 00/11] rust: add support for dynamic debug Thomas Weißschuh
` (5 preceding siblings ...)
2026-10-11 12:52 ` [PATCH RFC 06/11] dyndbg: make _ddebug::flags its own field Thomas Weißschuh
@ 2026-10-11 12:52 ` Thomas Weißschuh
2026-10-11 13:16 ` Gary Guo
2026-10-11 12:52 ` [PATCH RFC 08/11] rust: add support for dynamic debug Thomas Weißschuh
` (3 subsequent siblings)
10 siblings, 1 reply; 21+ messages in thread
From: Thomas Weißschuh @ 2026-10-11 12:52 UTC (permalink / raw)
To: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core, Thomas Weißschuh
The descriptor flags are accessed concurrently. Use
READ_ONCE()/WRITE_ONCE() to keep their contents consistent.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
I am not entirely sure about this. We are only using single bits, so
torn reads/writes should not matter. But LKMM has no guidance on this as
far as I can see. Also for Rust this seems to be necessary.
---
include/linux/dynamic_debug.h | 6 +++---
lib/dynamic_debug.c | 24 +++++++++++++-----------
2 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index b1ff7c0e9a5f..6986142928ef 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -164,7 +164,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
#define __dynamic_dump_stack(desc) \
{ \
- if (desc.flags & _DPRINTK_FLAGS_INCL_STACK) \
+ if (READ_ONCE(desc.flags) & _DPRINTK_FLAGS_INCL_STACK) \
dump_stack(); \
}
@@ -207,10 +207,10 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
#ifdef DEBUG
#define DYNAMIC_DEBUG_BRANCH(descriptor) \
- likely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
+ likely(READ_ONCE(descriptor.flags) & _DPRINTK_FLAGS_PRINT)
#else
#define DYNAMIC_DEBUG_BRANCH(descriptor) \
- unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
+ unlikely(READ_ONCE(descriptor.flags) & _DPRINTK_FLAGS_PRINT)
#endif
#endif /* CONFIG_JUMP_LABEL */
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 18a71a9108d3..6dfd125fa6be 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -244,7 +244,7 @@ static int ddebug_change(const struct ddebug_query *query,
nfound++;
- newflags = (dp->flags & modifiers->mask) | modifiers->flags;
+ newflags = (READ_ONCE(dp->flags) & modifiers->mask) | modifiers->flags;
if (newflags == dp->flags)
continue;
#ifdef CONFIG_JUMP_LABEL
@@ -260,7 +260,7 @@ static int ddebug_change(const struct ddebug_query *query,
dt->mod_name, dp->function,
ddebug_describe_flags(dp->flags, &fbuf),
ddebug_describe_flags(newflags, &nbuf));
- dp->flags = newflags;
+ WRITE_ONCE(dp->flags, newflags);
}
}
mutex_unlock(&ddebug_lock);
@@ -822,12 +822,12 @@ static int remaining(int wrote)
return 0;
}
-static char *__dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
+static char *__dynamic_emit_prefix(const struct _ddebug *desc, u8 flags, char *buf)
{
int pos_after_tid;
int pos = 0;
- if (desc->flags & _DPRINTK_FLAGS_INCL_TID) {
+ if (flags & _DPRINTK_FLAGS_INCL_TID) {
if (in_interrupt())
pos += snprintf(buf + pos, remaining(pos), "<intr> ");
else
@@ -835,16 +835,16 @@ static char *__dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
task_pid_vnr(current));
}
pos_after_tid = pos;
- if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME)
+ if (flags & _DPRINTK_FLAGS_INCL_MODNAME)
pos += snprintf(buf + pos, remaining(pos), "%s:",
desc->modname);
- if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
+ if (flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
pos += snprintf(buf + pos, remaining(pos), "%s:",
desc->function);
- if (desc->flags & _DPRINTK_FLAGS_INCL_SOURCENAME)
+ if (flags & _DPRINTK_FLAGS_INCL_SOURCENAME)
pos += snprintf(buf + pos, remaining(pos), "%s:",
trim_prefix(desc->filename));
- if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO)
+ if (flags & _DPRINTK_FLAGS_INCL_LINENO)
pos += snprintf(buf + pos, remaining(pos), "%d:",
desc->lineno);
if (pos - pos_after_tid)
@@ -857,8 +857,10 @@ static char *__dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
static inline char *dynamic_emit_prefix(struct _ddebug *desc, char *buf)
{
- if (unlikely(desc->flags & _DPRINTK_FLAGS_INCL_ANY))
- return __dynamic_emit_prefix(desc, buf);
+ u8 flags = READ_ONCE(desc->flags);
+
+ if (unlikely(flags & _DPRINTK_FLAGS_INCL_ANY))
+ return __dynamic_emit_prefix(desc, flags, buf);
return buf;
}
@@ -1146,7 +1148,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
seq_printf(m, "%s:%u [%s]%s =%s \"",
trim_prefix(dp->filename), dp->lineno,
iter->table->mod_name, dp->function,
- ddebug_describe_flags(dp->flags, &flags));
+ ddebug_describe_flags(READ_ONCE(dp->flags), &flags));
seq_escape_str(m, dp->format, ESCAPE_SPACE, "\t\r\n\"");
seq_putc(m, '"');
--
2.56.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 08/11] rust: add support for dynamic debug
2026-10-11 12:52 [PATCH RFC 00/11] rust: add support for dynamic debug Thomas Weißschuh
` (6 preceding siblings ...)
2026-10-11 12:52 ` [PATCH RFC 07/11] dyndbg: use READ_ONCE()/WRITE_ONCE() to access descriptor flags Thomas Weißschuh
@ 2026-10-11 12:52 ` Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 09/11] rust: print: enable dynamic debug for pr_debug!() Thomas Weißschuh
` (2 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Thomas Weißschuh @ 2026-10-11 12:52 UTC (permalink / raw)
To: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core, Thomas Weißschuh
Add the Rust infrastructure to integrate with the dynamic debug
infrastructure.
Static keys are not used for now, as the full bindings are missing
for those. Also custom classes are not supported yet, but could be
added on top.
pr_debug!() and dev_dbg!() will be wired up in later patches.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
MAINTAINERS | 1 +
rust/bindings/bindings_helper.h | 1 +
rust/kernel/dynamic_debug.rs | 264 ++++++++++++++++++++++++++++++++++++++++
rust/kernel/lib.rs | 2 +
4 files changed, 268 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 72294ddfa5b7..c36e3c9bfe89 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9261,6 +9261,7 @@ S: Maintained
F: include/linux/dynamic_debug.h
F: lib/dynamic_debug.c
F: lib/test_dynamic_debug.c
+F: rust/kernel/dynamic_debug.rs
DYNAMIC INTERRUPT MODERATION
M: Tal Gilboa <talgi@nvidia.com>
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index c706dda5b5ca..e6b7de0d7773 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -55,6 +55,7 @@
#include <linux/dma-direction.h>
#include <linux/dma-mapping.h>
#include <linux/dma-resv.h>
+#include <linux/dynamic_debug.h>
#include <linux/errname.h>
#include <linux/ethtool.h>
#include <linux/fdtable.h>
diff --git a/rust/kernel/dynamic_debug.rs b/rust/kernel/dynamic_debug.rs
new file mode 100644
index 000000000000..2fdc691eaac9
--- /dev/null
+++ b/rust/kernel/dynamic_debug.rs
@@ -0,0 +1,264 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2026 Thomas Weißschuh <linux@weissschuh.net>
+
+//! Dynamic debug support for printk.
+//!
+//! C header: [`include/linux/dynamic_debug.h`](srctree/include/linux/dynamic_debug.h)
+
+use crate::num::casts;
+use crate::num::Bounded;
+use crate::ptr::project;
+use crate::static_assert;
+use crate::str::{as_char_ptr_in_const_context, CStr};
+use crate::sync::atomic;
+use core::marker::PhantomData;
+use core::mem::{align_of, size_of};
+use pin_init::zeroed;
+
+mod flags {
+ use crate::num::casts::u32_into_u8;
+
+ pub(super) const NONE: u8 = u32_into_u8::<{ bindings::_DPRINTK_FLAGS_NONE }>();
+ pub(super) const PRINT: u8 = u32_into_u8::<{ bindings::_DPRINTK_FLAGS_PRINT }>();
+ pub(super) const INCL_STACK: u8 = u32_into_u8::<{ bindings::_DPRINTK_FLAGS_INCL_STACK }>();
+}
+
+/// Line number type.
+///
+/// Constrained to ensure that all values can be encoded in a [`Descriptor`].
+pub type LineNumber = Bounded<u32, 18>;
+
+/// Class ID type.
+///
+/// Constrained to ensure that all values can be encoded in a [`Descriptor`].
+pub type ClassId = Bounded<u32, 6>;
+
+static_assert!(ClassId::USABLE_BITS == bindings::CLS_BITS);
+static_assert!(
+ LineNumber::USABLE_BITS + ClassId::USABLE_BITS
+ == casts::usize_into_u32::<{ size_of::<BitfieldBindgenUnit>() }>() * u8::BITS
+);
+
+type BitfieldBindgenUnit = bindings::__BindgenBitfieldUnit<[u8; 3]>;
+
+const fn encode_bitfield(line_number: LineNumber, class_id: ClassId) -> BitfieldBindgenUnit {
+ let line_number = line_number.get();
+ let class_id = class_id.get();
+
+ // TODO: Use bindings::_ddebug::new_bitfield_1() when usable in const functions.
+ let bytes = if cfg!(target_endian = "big") {
+ [
+ (line_number >> 10) as u8,
+ (line_number >> 2) as u8,
+ (line_number as u8) << 6 | class_id as u8,
+ ]
+ } else {
+ [
+ line_number as u8,
+ (line_number >> 8) as u8,
+ (line_number >> 16) as u8 | (class_id as u8) << 2,
+ ]
+ };
+
+ BitfieldBindgenUnit::new(bytes)
+}
+
+/// Wrapper around a `struct _ddebug` descriptor.
+#[repr(transparent)]
+pub struct Descriptor<'a>(bindings::_ddebug, PhantomData<&'a ()>);
+
+static_assert!(size_of::<Descriptor<'_>>() == size_of::<bindings::_ddebug>());
+// Required by the dynamic debug core.
+static_assert!(align_of::<Descriptor<'_>>() == 8);
+
+// SAFETY: Only the flags field is changed at runtime using atomic operations.
+unsafe impl<'a> Sync for Descriptor<'a> {}
+
+impl<'a> Descriptor<'a> {
+ /// Create a new descriptor.
+ pub const fn new(
+ default_enabled: bool,
+ modname: &'a CStr,
+ filename: &'a CStr,
+ function: &'a CStr,
+ format: &'a CStr,
+ line_number: LineNumber,
+ class_id: Option<ClassId>,
+ ) -> Self {
+ let class_id = match class_id {
+ Some(c) => c,
+ None => ClassId::new::<{ bindings::_DPRINTK_CLASS_DFLT }>(),
+ };
+
+ let flags = if default_enabled {
+ flags::NONE | flags::PRINT
+ } else {
+ flags::NONE
+ };
+
+ Self(
+ #[allow(clippy::needless_update)]
+ bindings::_ddebug {
+ modname: as_char_ptr_in_const_context(modname),
+ function: as_char_ptr_in_const_context(function),
+ filename: as_char_ptr_in_const_context(filename),
+ format: as_char_ptr_in_const_context(format),
+ _bitfield_1: encode_bitfield(line_number, class_id),
+ flags,
+ #[cfg(CONFIG_JUMP_LABEL)]
+ key: Self::new_static_key(),
+ ..zeroed()
+ },
+ PhantomData,
+ )
+ }
+
+ #[cfg(CONFIG_JUMP_LABEL)]
+ const fn new_static_key() -> bindings::_ddebug__bindgen_ty_1 {
+ /*
+ * Always use static_key_false for now. branch_and_stack() below does not use it (yet),
+ * and the dynamic debug core doesn't know how it was initialized in any case.
+ */
+ bindings::_ddebug__bindgen_ty_1 {
+ dd_key_false: bindings::static_key_false {
+ key: bindings::static_key {
+ enabled: bindings::atomic_t { counter: 0 },
+ __bindgen_anon_1: bindings::static_key__bindgen_ty_1 {
+ type_: casts::u32_as_usize(bindings::JUMP_TYPE_FALSE),
+ },
+ },
+ },
+ }
+ }
+
+ /// Execute `func` if the descriptor active. Also print a stacktrace if enabled.
+ ///
+ /// # Safety
+ ///
+ /// The given `desc` must be valid throughout the call of the function.
+ #[inline(always)]
+ pub unsafe fn branch_and_stack<F: FnOnce()>(desc: *mut Descriptor<'static>, func: F) {
+ // TODO: Use static keys.
+
+ let flags_ptr = project!(mut desc, .0.flags);
+ // SAFETY: As per the function safety requirement `desc` is valid, and properly aligned,
+ // so `flags_ptr` is so, too. Updates from C are atomic.
+ let flags = unsafe { atomic::atomic_load(flags_ptr, atomic::ordering::Relaxed) };
+
+ if flags & flags::PRINT != 0 {
+ func();
+
+ if flags & flags::INCL_STACK != 0 {
+ // SAFETY: Can be called from any context where printk can be used.
+ unsafe {
+ bindings::dump_stack();
+ }
+ }
+ }
+ }
+}
+
+/// Allocate a dynamic debug descriptor.
+#[macro_export]
+#[expect(clippy::crate_in_macro_def)]
+macro_rules! dynamic_debug_metadata_cls {
+ ($default_enabled:expr, $cls:expr, $fmt:expr) => {{
+ use $crate::c_str;
+ use $crate::dynamic_debug::{Descriptor, LineNumber};
+
+ #[link_section = "__dyndbg"]
+ #[used(compiler)]
+ static mut descriptor: Descriptor = Descriptor::new(
+ $default_enabled,
+ crate::__LOG_PREFIX,
+ c_str!(file!()),
+ // Rust does not provide the current function, approximate with module_path!().
+ c_str!(module_path!()),
+ c_str!($fmt),
+ LineNumber::new::<{ line!() }>(),
+ $cls,
+ );
+
+ ::core::ptr::addr_of_mut!(descriptor)
+ }};
+}
+
+/// Add a runtime-configurable function invocation for a specific class.
+#[macro_export]
+macro_rules! dynamic_func_call_cls {
+ ($cls:expr, $fmt:expr, $func:expr) => {{
+ const default_enabled: bool = cfg!(debug_assertions);
+
+ let descriptor = $crate::dynamic_debug_metadata_cls!(default_enabled, $cls, $fmt);
+
+ // SAFETY: `descriptor` has static lifetime, so it is always valid.
+ unsafe {
+ $crate::dynamic_debug::Descriptor::branch_and_stack(descriptor, $func);
+ }
+ }};
+}
+
+/// Add a runtime-configurable function invocation.
+#[macro_export]
+macro_rules! dynamic_func_call {
+ ($fmt:expr, $func:expr) => {{
+ $crate::dynamic_func_call_cls!(None, $fmt, $func);
+ }};
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! __format_string {
+ ($fmt:literal) => {
+ $fmt
+ };
+
+ ($fmt:literal, $($arg:tt)*) => {
+ $fmt
+ };
+}
+
+#[macros::kunit_tests(rust_dynamic_debug)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_bitfield_encoding() -> Result<(), ()> {
+ struct TestCase {
+ line_number: u32,
+ class_id: u32,
+ }
+
+ let test_cases = [
+ TestCase {
+ line_number: 0b101010101010101010,
+ class_id: 0b101010,
+ },
+ TestCase {
+ line_number: 0b111111111111111111,
+ class_id: 0b000000,
+ },
+ TestCase {
+ line_number: 0b000000000000000000,
+ class_id: 0b111111,
+ },
+ TestCase {
+ line_number: 0b101100111000111100,
+ class_id: 0b111111,
+ },
+ ];
+
+ for case in test_cases {
+ let line_number = LineNumber::try_new(case.line_number).ok_or(())?;
+ let class_id = ClassId::try_new(case.class_id).ok_or(())?;
+
+ assert_eq!(
+ bindings::_ddebug::new_bitfield_1(*line_number, *class_id,),
+ encode_bitfield(line_number, class_id),
+ );
+ }
+
+ Ok(())
+ }
+}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 7d48f931877d..ff4bdd24353d 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -70,6 +70,8 @@
pub mod driver;
#[cfg(CONFIG_DRM = "y")]
pub mod drm;
+#[cfg(CONFIG_DYNAMIC_DEBUG_CORE)]
+pub mod dynamic_debug;
pub mod error;
pub mod faux;
#[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
--
2.56.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 09/11] rust: print: enable dynamic debug for pr_debug!()
2026-10-11 12:52 [PATCH RFC 00/11] rust: add support for dynamic debug Thomas Weißschuh
` (7 preceding siblings ...)
2026-10-11 12:52 ` [PATCH RFC 08/11] rust: add support for dynamic debug Thomas Weißschuh
@ 2026-10-11 12:52 ` Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 10/11] rust: device: remove logging methods Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 11/11] rust: device: enable dynamic debug for dev_dbg!() Thomas Weißschuh
10 siblings, 0 replies; 21+ messages in thread
From: Thomas Weißschuh @ 2026-10-11 12:52 UTC (permalink / raw)
To: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core, Thomas Weißschuh
Wire up dynamic debug to work for the pr_debug!() macro.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
rust/kernel/print.rs | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs
index 9ce52b9fa69f..9a0870c2df94 100644
--- a/rust/kernel/print.rs
+++ b/rust/kernel/print.rs
@@ -373,8 +373,7 @@ 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.
///
/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
/// [`std::format!`] for information about the formatting syntax.
@@ -392,6 +391,13 @@ macro_rules! pr_info (
#[doc(alias = "print")]
macro_rules! pr_debug (
($($arg:tt)*) => (
+ // TODO: Switch to cfg_select!() when that is usable.
+ #[cfg(any(CONFIG_DYNAMIC_DEBUG, all(CONFIG_DYNAMIC_DEBUG_CORE, debug_assertions)))]
+ $crate::dynamic_func_call!($crate::__format_string!($($arg)+), || {
+ $crate::print_macro!($crate::print::format_strings::DEBUG, false, $($arg)*)
+ });
+
+ #[cfg(not(any(CONFIG_DYNAMIC_DEBUG, all(CONFIG_DYNAMIC_DEBUG_CORE, debug_assertions))))]
if cfg!(debug_assertions) {
$crate::print_macro!($crate::print::format_strings::DEBUG, false, $($arg)*)
}
--
2.56.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 10/11] rust: device: remove logging methods
2026-10-11 12:52 [PATCH RFC 00/11] rust: add support for dynamic debug Thomas Weißschuh
` (8 preceding siblings ...)
2026-10-11 12:52 ` [PATCH RFC 09/11] rust: print: enable dynamic debug for pr_debug!() Thomas Weißschuh
@ 2026-10-11 12:52 ` Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 11/11] rust: device: enable dynamic debug for dev_dbg!() Thomas Weißschuh
10 siblings, 0 replies; 21+ messages in thread
From: Thomas Weißschuh @ 2026-10-11 12:52 UTC (permalink / raw)
To: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core, Thomas Weißschuh
To support dynamic debug, the logging needs to happen through a macro
call. Only a macro provides the possibility to statically allocate the
descriptor used by the dynamic debug core.
For consistency also remove the other logging methods.
They have no external users anyways.
All functions are thin wrappers around Device::printk() anyways.
Only Device::pr_dbg() contains additional logic, move that to
!dev_dbg().
As a side-effect this now evaluates cfg(debug_assertions) in the context
of the caller and not device.rs. Which matches the C macros better.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
rust/kernel/device.rs | 164 +++++++++++++++++++++-----------------------------
1 file changed, 70 insertions(+), 94 deletions(-)
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index 2291d85b6849..2d49063f4f7c 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -298,88 +298,6 @@ pub unsafe fn from_raw<'a>(ptr: *mut bindings::device) -> &'a Self {
unsafe { &*ptr.cast() }
}
- /// Prints an emergency-level message (level 0) prefixed with device information.
- ///
- /// More details are available from [`dev_emerg`].
- ///
- /// [`dev_emerg`]: crate::dev_emerg
- pub fn pr_emerg(&self, args: fmt::Arguments<'_>) {
- // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
- unsafe { self.printk(bindings::KERN_EMERG, args) };
- }
-
- /// Prints an alert-level message (level 1) prefixed with device information.
- ///
- /// More details are available from [`dev_alert`].
- ///
- /// [`dev_alert`]: crate::dev_alert
- pub fn pr_alert(&self, args: fmt::Arguments<'_>) {
- // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
- unsafe { self.printk(bindings::KERN_ALERT, args) };
- }
-
- /// Prints a critical-level message (level 2) prefixed with device information.
- ///
- /// More details are available from [`dev_crit`].
- ///
- /// [`dev_crit`]: crate::dev_crit
- pub fn pr_crit(&self, args: fmt::Arguments<'_>) {
- // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
- unsafe { self.printk(bindings::KERN_CRIT, args) };
- }
-
- /// Prints an error-level message (level 3) prefixed with device information.
- ///
- /// More details are available from [`dev_err`].
- ///
- /// [`dev_err`]: crate::dev_err
- pub fn pr_err(&self, args: fmt::Arguments<'_>) {
- // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
- unsafe { self.printk(bindings::KERN_ERR, args) };
- }
-
- /// Prints a warning-level message (level 4) prefixed with device information.
- ///
- /// More details are available from [`dev_warn`].
- ///
- /// [`dev_warn`]: crate::dev_warn
- pub fn pr_warn(&self, args: fmt::Arguments<'_>) {
- // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
- unsafe { self.printk(bindings::KERN_WARNING, args) };
- }
-
- /// Prints a notice-level message (level 5) prefixed with device information.
- ///
- /// More details are available from [`dev_notice`].
- ///
- /// [`dev_notice`]: crate::dev_notice
- pub fn pr_notice(&self, args: fmt::Arguments<'_>) {
- // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
- unsafe { self.printk(bindings::KERN_NOTICE, args) };
- }
-
- /// Prints an info-level message (level 6) prefixed with device information.
- ///
- /// More details are available from [`dev_info`].
- ///
- /// [`dev_info`]: crate::dev_info
- pub fn pr_info(&self, args: fmt::Arguments<'_>) {
- // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
- unsafe { self.printk(bindings::KERN_INFO, args) };
- }
-
- /// Prints a debug-level message (level 7) prefixed with device information.
- ///
- /// More details are available from [`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) };
- }
- }
-
/// Prints the provided message to the console.
///
/// # Safety
@@ -387,7 +305,7 @@ pub fn pr_dbg(&self, args: fmt::Arguments<'_>) {
/// Callers must ensure that `klevel` is null-terminated; in particular, one of the
/// `KERN_*`constants, for example, `KERN_CRIT`, `KERN_ALERT`, etc.
#[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))]
- unsafe fn printk(&self, klevel: &[u8], msg: fmt::Arguments<'_>) {
+ pub unsafe fn printk(&self, klevel: &[u8], msg: fmt::Arguments<'_>) {
// SAFETY: `klevel` is null-terminated and one of the kernel constants. `self.as_raw`
// is valid because `self` is valid. The "%pA" format string expects a pointer to
// `fmt::Arguments`, which is what we're passing as the last argument.
@@ -738,9 +656,9 @@ macro_rules! impl_device_context_into_aref {
#[doc(hidden)]
#[macro_export]
macro_rules! dev_printk {
- ($method:ident, $dev:expr, $($f:tt)*) => {
- $crate::device::Device::$method($dev.as_ref(), $crate::prelude::fmt!($($f)*))
- }
+ ($klevel:expr, $dev:expr, $args:expr) => {
+ $crate::device::Device::printk($dev.as_ref(), $klevel, $args)
+ };
}
/// Prints an emergency-level message (level 0) prefixed with device information.
@@ -766,7 +684,14 @@ macro_rules! dev_printk {
/// ```
#[macro_export]
macro_rules! dev_emerg {
- ($($f:tt)*) => { $crate::dev_printk!(pr_emerg, $($f)*) }
+ ($dev:expr, $($f:tt)*) => {
+ match (&$dev, $crate::prelude::fmt!($($f)*)) {
+ (dev, args) => {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { $crate::dev_printk!($crate::bindings::KERN_EMERG, dev, args) }
+ }
+ }
+ }
}
/// Prints an alert-level message (level 1) prefixed with device information.
@@ -792,7 +717,14 @@ macro_rules! dev_emerg {
/// ```
#[macro_export]
macro_rules! dev_alert {
- ($($f:tt)*) => { $crate::dev_printk!(pr_alert, $($f)*) }
+ ($dev:expr, $($f:tt)*) => {
+ match (&$dev, $crate::prelude::fmt!($($f)*)) {
+ (dev, args) => {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { $crate::dev_printk!($crate::bindings::KERN_ALERT, dev, args) }
+ }
+ }
+ }
}
/// Prints a critical-level message (level 2) prefixed with device information.
@@ -818,7 +750,14 @@ macro_rules! dev_alert {
/// ```
#[macro_export]
macro_rules! dev_crit {
- ($($f:tt)*) => { $crate::dev_printk!(pr_crit, $($f)*) }
+ ($dev:expr, $($f:tt)*) => {
+ match (&$dev, $crate::prelude::fmt!($($f)*)) {
+ (dev, args) => {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { $crate::dev_printk!($crate::bindings::KERN_CRIT, dev, args) }
+ }
+ }
+ }
}
/// Prints an error-level message (level 3) prefixed with device information.
@@ -844,7 +783,14 @@ macro_rules! dev_crit {
/// ```
#[macro_export]
macro_rules! dev_err {
- ($($f:tt)*) => { $crate::dev_printk!(pr_err, $($f)*) }
+ ($dev:expr, $($f:tt)*) => {
+ match (&$dev, $crate::prelude::fmt!($($f)*)) {
+ (dev, args) => {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { $crate::dev_printk!($crate::bindings::KERN_ERR, dev, args) }
+ }
+ }
+ }
}
/// Prints a warning-level message (level 4) prefixed with device information.
@@ -870,7 +816,14 @@ macro_rules! dev_err {
/// ```
#[macro_export]
macro_rules! dev_warn {
- ($($f:tt)*) => { $crate::dev_printk!(pr_warn, $($f)*) }
+ ($dev:expr, $($f:tt)*) => {
+ match (&$dev, $crate::prelude::fmt!($($f)*)) {
+ (dev, args) => {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { $crate::dev_printk!($crate::bindings::KERN_WARNING, dev, args) }
+ }
+ }
+ }
}
/// Prints a notice-level message (level 5) prefixed with device information.
@@ -896,7 +849,14 @@ macro_rules! dev_warn {
/// ```
#[macro_export]
macro_rules! dev_notice {
- ($($f:tt)*) => { $crate::dev_printk!(pr_notice, $($f)*) }
+ ($dev:expr, $($f:tt)*) => {
+ match (&$dev, $crate::prelude::fmt!($($f)*)) {
+ (dev, args) => {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { $crate::dev_printk!($crate::bindings::KERN_NOTICE, dev, args) }
+ }
+ }
+ }
}
/// Prints an info-level message (level 6) prefixed with device information.
@@ -922,7 +882,14 @@ macro_rules! dev_notice {
/// ```
#[macro_export]
macro_rules! dev_info {
- ($($f:tt)*) => { $crate::dev_printk!(pr_info, $($f)*) }
+ ($dev:expr, $($f:tt)*) => {
+ match (&$dev, $crate::prelude::fmt!($($f)*)) {
+ (dev, args) => {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { $crate::dev_printk!($crate::bindings::KERN_INFO, dev, args) }
+ }
+ }
+ }
}
/// Prints a debug-level message (level 7) prefixed with device information.
@@ -948,5 +915,14 @@ macro_rules! dev_info {
/// ```
#[macro_export]
macro_rules! dev_dbg {
- ($($f:tt)*) => { $crate::dev_printk!(pr_dbg, $($f)*) }
+ ($dev:expr, $($f:tt)*) => {
+ match (&$dev, $crate::prelude::fmt!($($f)*)) {
+ (dev, args) => {
+ if cfg!(debug_assertions) {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { $crate::dev_printk!($crate::bindings::KERN_DEBUG, dev, args) }
+ }
+ }
+ }
+ }
}
--
2.56.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 11/11] rust: device: enable dynamic debug for dev_dbg!()
2026-10-11 12:52 [PATCH RFC 00/11] rust: add support for dynamic debug Thomas Weißschuh
` (9 preceding siblings ...)
2026-10-11 12:52 ` [PATCH RFC 10/11] rust: device: remove logging methods Thomas Weißschuh
@ 2026-10-11 12:52 ` Thomas Weißschuh
10 siblings, 0 replies; 21+ messages in thread
From: Thomas Weißschuh @ 2026-10-11 12:52 UTC (permalink / raw)
To: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core, Thomas Weißschuh
Wire up dynamic debug to also work for the dev_dbg!() macro.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
rust/kernel/device.rs | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index 2d49063f4f7c..db2c9adc5410 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -896,7 +896,7 @@ 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.
///
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
/// [`core::fmt`] and [`std::format!`].
@@ -918,6 +918,15 @@ macro_rules! dev_dbg {
($dev:expr, $($f:tt)*) => {
match (&$dev, $crate::prelude::fmt!($($f)*)) {
(dev, args) => {
+ // TODO: Switch to cfg_select!() when that is usable.
+ #[cfg(any(CONFIG_DYNAMIC_DEBUG, all(CONFIG_DYNAMIC_DEBUG_CORE, debug_assertions)))]
+ $crate::dynamic_func_call!($crate::__format_string!($($f)*), || {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { $crate::dev_printk!($crate::bindings::KERN_DEBUG, dev, args) }
+ });
+
+ #[cfg(not(any(CONFIG_DYNAMIC_DEBUG,
+ all(CONFIG_DYNAMIC_DEBUG_CORE, debug_assertions))))]
if cfg!(debug_assertions) {
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
unsafe { $crate::dev_printk!($crate::bindings::KERN_DEBUG, dev, args) }
--
2.56.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH RFC 01/11] rust: print: use CStr for __LOG_PREFIX
2026-10-11 12:52 ` [PATCH RFC 01/11] rust: print: use CStr for __LOG_PREFIX Thomas Weißschuh
@ 2026-10-11 13:01 ` Gary Guo
2026-10-11 14:43 ` Thomas Weißschuh
0 siblings, 1 reply; 21+ messages in thread
From: Gary Guo @ 2026-10-11 13:01 UTC (permalink / raw)
To: Thomas Weißschuh, Jason Baron, Jim Cromie, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
Onur Özkan, Andrew Morton, Will Deacon, Peter Zijlstra,
Mark Rutland, Lyude Paul, Yury Norov, Luis Chamberlain,
Petr Pavlu, Daniel Gomez, Sami Tolvanen, Aaron Tomlin,
Brendan Higgins, David Gow, Rae Moar, Greg Kroah-Hartman,
Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core
On Sun Oct 11, 2026 at 1:52 PM BST, Thomas Weißschuh wrote:
> The users of __LOG_PREFIX require that it is 0-terminated.
> Currently this requirement is only encoded in safety comments.
>
> Switch to CStr which can guarantee this invariant through the type
> system.
>
> As __LOG_PREFIX and Module::NAME are now identical, reuse the former to
> implement the latter.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
See
https://lore.kernel.org/rust-for-linux/20260728-printk-v1-2-855606634d70@garyguo.net/.
Best,
Gary
> ---
> rust/kernel/lib.rs | 4 ++--
> rust/kernel/print.rs | 11 ++++-------
> rust/macros/module.rs | 4 ++--
> scripts/rustdoc_test_gen.rs | 4 ++--
> 4 files changed, 10 insertions(+), 13 deletions(-)
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH RFC 02/11] rust: sync: atomic: Add Atomic<u{8,16}>
2026-10-11 12:52 ` [PATCH RFC 02/11] rust: sync: atomic: Add Atomic<u{8,16}> Thomas Weißschuh
@ 2026-10-11 13:04 ` Gary Guo
0 siblings, 0 replies; 21+ messages in thread
From: Gary Guo @ 2026-10-11 13:04 UTC (permalink / raw)
To: Thomas Weißschuh, Jason Baron, Jim Cromie, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
Onur Özkan, Andrew Morton, Will Deacon, Peter Zijlstra,
Mark Rutland, Lyude Paul, Yury Norov, Luis Chamberlain,
Petr Pavlu, Daniel Gomez, Sami Tolvanen, Aaron Tomlin,
Brendan Higgins, David Gow, Rae Moar, Greg Kroah-Hartman,
Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core
On Sun Oct 11, 2026 at 1:52 PM BST, Thomas Weißschuh wrote:
> Add generic atomic support for small unsigned integers that have an
> `AtomicImpl` with the same size and alignment.
>
> Also extend the unit tests.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
AtomicType is something that I'm getting rid of next cycle. The plan is to
convert atomic to use `kernel::mem::AsRepr`.
Best,
Gary
> ---
> rust/kernel/sync/atomic/predefine.rs | 44 ++++++++++++++++++++++++++++--------
> 1 file changed, 35 insertions(+), 9 deletions(-)
>
> diff --git a/rust/kernel/sync/atomic/predefine.rs b/rust/kernel/sync/atomic/predefine.rs
> index 3d63f40791fa..4c1fb5e08dc2 100644
> --- a/rust/kernel/sync/atomic/predefine.rs
> +++ b/rust/kernel/sync/atomic/predefine.rs
> @@ -113,6 +113,32 @@ fn rhs_into_delta(rhs: isize) -> isize_atomic_repr {
> }
> }
>
> +// SAFETY: `u8` and `i8` has the same size and alignment, and `u8` is round-trip transmutable to
> +// `i8`.
> +unsafe impl super::AtomicType for u8 {
> + type Repr = i8;
> +}
> +
> +// SAFETY: The wrapping add result of two `i8`s is a valid `u8`.
> +unsafe impl super::AtomicAdd<u8> for u8 {
> + fn rhs_into_delta(rhs: u8) -> i8 {
> + rhs as i8
> + }
> +}
> +
> +// SAFETY: `u16` and `i16` has the same size and alignment, and `u16` is round-trip transmutable to
> +// `i16`.
> +unsafe impl super::AtomicType for u16 {
> + type Repr = i16;
> +}
> +
> +// SAFETY: The wrapping add result of two `i16`s is a valid `u16`.
> +unsafe impl super::AtomicAdd<u16> for u16 {
> + fn rhs_into_delta(rhs: u16) -> i16 {
> + rhs as i16
> + }
> +}
> +
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH RFC 07/11] dyndbg: use READ_ONCE()/WRITE_ONCE() to access descriptor flags
2026-10-11 12:52 ` [PATCH RFC 07/11] dyndbg: use READ_ONCE()/WRITE_ONCE() to access descriptor flags Thomas Weißschuh
@ 2026-10-11 13:16 ` Gary Guo
0 siblings, 0 replies; 21+ messages in thread
From: Gary Guo @ 2026-10-11 13:16 UTC (permalink / raw)
To: Thomas Weißschuh, Jason Baron, Jim Cromie, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
Onur Özkan, Andrew Morton, Will Deacon, Peter Zijlstra,
Mark Rutland, Lyude Paul, Yury Norov, Luis Chamberlain,
Petr Pavlu, Daniel Gomez, Sami Tolvanen, Aaron Tomlin,
Brendan Higgins, David Gow, Rae Moar, Greg Kroah-Hartman,
Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core
On Sun Oct 11, 2026 at 1:52 PM BST, Thomas Weißschuh wrote:
> The descriptor flags are accessed concurrently. Use
> READ_ONCE()/WRITE_ONCE() to keep their contents consistent.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
>
> ---
> I am not entirely sure about this. We are only using single bits, so
> torn reads/writes should not matter. But LKMM has no guidance on this as
> far as I can see. Also for Rust this seems to be necessary.
Code should assume plain writes to be atomic. Concurrently accessed data should
use READ_ONCE/WRITE_ONCE so you're right on this one.
I think this patch should be merged with the bitfield definition change, though.
Best,
Gary
> ---
> include/linux/dynamic_debug.h | 6 +++---
> lib/dynamic_debug.c | 24 +++++++++++++-----------
> 2 files changed, 16 insertions(+), 14 deletions(-)
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH RFC 06/11] dyndbg: make _ddebug::flags its own field
2026-10-11 12:52 ` [PATCH RFC 06/11] dyndbg: make _ddebug::flags its own field Thomas Weißschuh
@ 2026-10-11 13:23 ` Gary Guo
2026-10-11 14:47 ` Thomas Weißschuh
0 siblings, 1 reply; 21+ messages in thread
From: Gary Guo @ 2026-10-11 13:23 UTC (permalink / raw)
To: Thomas Weißschuh, Jason Baron, Jim Cromie, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
Onur Özkan, Andrew Morton, Will Deacon, Peter Zijlstra,
Mark Rutland, Lyude Paul, Yury Norov, Luis Chamberlain,
Petr Pavlu, Daniel Gomez, Sami Tolvanen, Aaron Tomlin,
Brendan Higgins, David Gow, Rae Moar, Greg Kroah-Hartman,
Rafael J. Wysocki
Cc: linux-kernel, rust-for-linux, linux-modules, linux-kselftest,
kunit-dev, driver-core
On Sun Oct 11, 2026 at 1:52 PM BST, Thomas Weißschuh wrote:
> Keeping the flags as part of the bitfield prevents the usage of
> READ_ONCE()/WRITE_ONCE() with it. It also makes access from Rust
> awkward.
>
> Make it a dedicated field.
>
> The new field will stay in the exact same location in the parent
> structure.
Incorrect.
>
> No functional change.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
> include/linux/dynamic_debug.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
> index 0b34343df594..b1ff7c0e9a5f 100644
> --- a/include/linux/dynamic_debug.h
> +++ b/include/linux/dynamic_debug.h
> @@ -51,7 +51,7 @@ struct _ddebug {
> #else
> #define _DPRINTK_FLAGS_DEFAULT 0
> #endif
> - u32 flags:8;
> + u8 flags;
This will change the layout of the struct, because it'll no longer be merged
with the previous bitfields.
The layout change can be avoided by make lineno + class explicitly take 3 bytes.
Perhaps reduce lineno to u16 and have class be a standalone u8? No kernel source
file (apart from pre-generated AMDGPU headers, which doesn't use dyndbg anyway)
have more than 65535 lines.
Alternatively we can just say the layout change is fine, as for 64-bit platforms
with jump label patching, there's padding in the struct anyway so this doesn't
grow the full struct size.
Anyhow this needs to be noted explicitly.
Best,
Gary
> #ifdef CONFIG_JUMP_LABEL
> union {
> struct static_key_true dd_key_true;
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH RFC 04/11] samples: rust_print: add debug messages
2026-10-11 12:52 ` [PATCH RFC 04/11] samples: rust_print: add debug messages Thomas Weißschuh
@ 2026-10-11 13:53 ` Miguel Ojeda
2026-10-11 14:48 ` Thomas Weißschuh
0 siblings, 1 reply; 21+ messages in thread
From: Miguel Ojeda @ 2026-10-11 13:53 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel,
rust-for-linux, linux-modules, linux-kselftest, kunit-dev,
driver-core
On Sun, Oct 11, 2026 at 2:53 PM Thomas Weißschuh <linux@weissschuh.net> wrote:
>
> To make sure they are actually printed, enable debug assertions.
Hmm... why do we want to make sure of that? i.e. users can configure
the debug assertions, and the sample may show them if they are
enabled, just like any other code, no?
I guess you may want this for e.g. a CI, but in that CI one ideally
would test both cases, and assert that the messages both appear and
not appear depending on the case.
Cheers,
Miguel
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH RFC 01/11] rust: print: use CStr for __LOG_PREFIX
2026-10-11 13:01 ` Gary Guo
@ 2026-10-11 14:43 ` Thomas Weißschuh
0 siblings, 0 replies; 21+ messages in thread
From: Thomas Weißschuh @ 2026-10-11 14:43 UTC (permalink / raw)
To: Gary Guo
Cc: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel,
rust-for-linux, linux-modules, linux-kselftest, kunit-dev,
driver-core
On 2026-10-11 14:01:45+0100, Gary Guo wrote:
> On Sun Oct 11, 2026 at 1:52 PM BST, Thomas Weißschuh wrote:
> > The users of __LOG_PREFIX require that it is 0-terminated.
> > Currently this requirement is only encoded in safety comments.
> >
> > Switch to CStr which can guarantee this invariant through the type
> > system.
> >
> > As __LOG_PREFIX and Module::NAME are now identical, reuse the former to
> > implement the latter.
> >
> > Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
>
> See
> https://lore.kernel.org/rust-for-linux/20260728-printk-v1-2-855606634d70@garyguo.net/.
Thanks. I'll use that instead.
> Best,
> Gary
>
> > ---
> > rust/kernel/lib.rs | 4 ++--
> > rust/kernel/print.rs | 11 ++++-------
> > rust/macros/module.rs | 4 ++--
> > scripts/rustdoc_test_gen.rs | 4 ++--
> > 4 files changed, 10 insertions(+), 13 deletions(-)
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH RFC 06/11] dyndbg: make _ddebug::flags its own field
2026-10-11 13:23 ` Gary Guo
@ 2026-10-11 14:47 ` Thomas Weißschuh
2026-10-11 15:44 ` Gary Guo
0 siblings, 1 reply; 21+ messages in thread
From: Thomas Weißschuh @ 2026-10-11 14:47 UTC (permalink / raw)
To: Gary Guo
Cc: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel,
rust-for-linux, linux-modules, linux-kselftest, kunit-dev,
driver-core
On 2026-10-11 14:23:21+0100, Gary Guo wrote:
> On Sun Oct 11, 2026 at 1:52 PM BST, Thomas Weißschuh wrote:
> > Keeping the flags as part of the bitfield prevents the usage of
> > READ_ONCE()/WRITE_ONCE() with it. It also makes access from Rust
> > awkward.
> >
> > Make it a dedicated field.
> >
> > The new field will stay in the exact same location in the parent
> > structure.
>
> Incorrect.
>
> >
> > No functional change.
> >
> > Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> > ---
> > include/linux/dynamic_debug.h | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
> > index 0b34343df594..b1ff7c0e9a5f 100644
> > --- a/include/linux/dynamic_debug.h
> > +++ b/include/linux/dynamic_debug.h
> > @@ -51,7 +51,7 @@ struct _ddebug {
> > #else
> > #define _DPRINTK_FLAGS_DEFAULT 0
> > #endif
> > - u32 flags:8;
> > + u8 flags;
>
> This will change the layout of the struct, because it'll no longer be merged
> with the previous bitfields.
It seems to work for me:
struct _ddebug {
const char * modname; /* 0 8 */
const char * function; /* 8 8 */
const char * filename; /* 16 8 */
const char * format; /* 24 8 */
u32 lineno:18; /* 32: 0 4 */
u32 class_id:6; /* 32:18 4 */
/* Bitfield combined with next fields */
u8 flags; /* 35 1 */
/* XXX 4 bytes hole, try to pack */
union {
struct static_key_true dd_key_true __attribute__((__aligned__(8))); /* 40 16 */
struct static_key_false dd_key_false __attribute__((__aligned__(8))); /* 40 16 */
} key __attribute__((__aligned__(8))); /* 40 16 */
/* size: 56, cachelines: 1, members: 8 */
/* sum members: 49, holes: 1, sum holes: 4 */
/* sum bitfield members: 24 bits (3 bytes) */
/* forced alignments: 1, forced holes: 1, sum forced holes: 4 */
/* last cacheline: 56 bytes */
} __attribute__((__aligned__(8)));
(x86_64, GCC 16.2.1)
> The layout change can be avoided by make lineno + class explicitly take 3 bytes.
> Perhaps reduce lineno to u16 and have class be a standalone u8? No kernel source
> file (apart from pre-generated AMDGPU headers, which doesn't use dyndbg anyway)
> have more than 65535 lines.
>
> Alternatively we can just say the layout change is fine, as for 64-bit platforms
> with jump label patching, there's padding in the struct anyway so this doesn't
> grow the full struct size.
I am fine with other solutions if the dynamic debug folks prefer those.
The goal here was to stay as close as possible to the existing code.
> Anyhow this needs to be noted explicitly.
Ack.
> Best,
> Gary
>
> > #ifdef CONFIG_JUMP_LABEL
> > union {
> > struct static_key_true dd_key_true;
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH RFC 04/11] samples: rust_print: add debug messages
2026-10-11 13:53 ` Miguel Ojeda
@ 2026-10-11 14:48 ` Thomas Weißschuh
0 siblings, 0 replies; 21+ messages in thread
From: Thomas Weißschuh @ 2026-10-11 14:48 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel,
rust-for-linux, linux-modules, linux-kselftest, kunit-dev,
driver-core
On 2026-10-11 15:53:26+0200, Miguel Ojeda wrote:
> On Sun, Oct 11, 2026 at 2:53 PM Thomas Weißschuh <linux@weissschuh.net> wrote:
> >
> > To make sure they are actually printed, enable debug assertions.
>
> Hmm... why do we want to make sure of that? i.e. users can configure
> the debug assertions, and the sample may show them if they are
> enabled, just like any other code, no?
Fair enough, I'll drop this bit.
(...)
Thomas
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH RFC 06/11] dyndbg: make _ddebug::flags its own field
2026-10-11 14:47 ` Thomas Weißschuh
@ 2026-10-11 15:44 ` Gary Guo
0 siblings, 0 replies; 21+ messages in thread
From: Gary Guo @ 2026-10-11 15:44 UTC (permalink / raw)
To: Thomas Weißschuh, Gary Guo
Cc: Jason Baron, Jim Cromie, Miguel Ojeda, Boqun Feng,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Andrew Morton, Will Deacon,
Peter Zijlstra, Mark Rutland, Lyude Paul, Yury Norov,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Brendan Higgins, David Gow, Rae Moar,
Greg Kroah-Hartman, Rafael J. Wysocki, linux-kernel,
rust-for-linux, linux-modules, linux-kselftest, kunit-dev,
driver-core
On Sun Oct 11, 2026 at 3:47 PM BST, Thomas Weißschuh wrote:
> On 2026-10-11 14:23:21+0100, Gary Guo wrote:
>> On Sun Oct 11, 2026 at 1:52 PM BST, Thomas Weißschuh wrote:
>> > Keeping the flags as part of the bitfield prevents the usage of
>> > READ_ONCE()/WRITE_ONCE() with it. It also makes access from Rust
>> > awkward.
>> >
>> > Make it a dedicated field.
>> >
>> > The new field will stay in the exact same location in the parent
>> > structure.
>>
>> Incorrect.
>>
>> >
>> > No functional change.
>> >
>> > Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
>> > ---
>> > include/linux/dynamic_debug.h | 2 +-
>> > 1 file changed, 1 insertion(+), 1 deletion(-)
>> >
>> > diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
>> > index 0b34343df594..b1ff7c0e9a5f 100644
>> > --- a/include/linux/dynamic_debug.h
>> > +++ b/include/linux/dynamic_debug.h
>> > @@ -51,7 +51,7 @@ struct _ddebug {
>> > #else
>> > #define _DPRINTK_FLAGS_DEFAULT 0
>> > #endif
>> > - u32 flags:8;
>> > + u8 flags;
>>
>> This will change the layout of the struct, because it'll no longer be merged
>> with the previous bitfields.
>
> It seems to work for me:
>
> struct _ddebug {
> const char * modname; /* 0 8 */
> const char * function; /* 8 8 */
> const char * filename; /* 16 8 */
> const char * format; /* 24 8 */
> u32 lineno:18; /* 32: 0 4 */
> u32 class_id:6; /* 32:18 4 */
>
> /* Bitfield combined with next fields */
>
> u8 flags; /* 35 1 */
>
> /* XXX 4 bytes hole, try to pack */
>
> union {
> struct static_key_true dd_key_true __attribute__((__aligned__(8))); /* 40 16 */
> struct static_key_false dd_key_false __attribute__((__aligned__(8))); /* 40 16 */
> } key __attribute__((__aligned__(8))); /* 40 16 */
>
> /* size: 56, cachelines: 1, members: 8 */
> /* sum members: 49, holes: 1, sum holes: 4 */
> /* sum bitfield members: 24 bits (3 bytes) */
> /* forced alignments: 1, forced holes: 1, sum forced holes: 4 */
> /* last cacheline: 56 bytes */
> } __attribute__((__aligned__(8)));
>
> (x86_64, GCC 16.2.1)
I stand corrected. I thought the type change would force allocation unit to not
be shared; turns out that this is only behaviour of some compiler (e.g. MSVC)
where in GCC this is not the case. C standard says it's an
implementation-defined behaviour, and I guess that's why people don't like using
bit fields :)
Given kernel assumes GCC (or compatible behaviour) I suppose this is alright
and you're right that the layout is unchanged in this case. In that case I think
using what you have is fine, but this should still be merged with the following
patch that adds READ_ONCE/WRITE_ONCE.
Best,
Gary
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2026-10-11 15:45 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-11 12:52 [PATCH RFC 00/11] rust: add support for dynamic debug Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 01/11] rust: print: use CStr for __LOG_PREFIX Thomas Weißschuh
2026-10-11 13:01 ` Gary Guo
2026-10-11 14:43 ` Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 02/11] rust: sync: atomic: Add Atomic<u{8,16}> Thomas Weißschuh
2026-10-11 13:04 ` Gary Guo
2026-10-11 12:52 ` [PATCH RFC 03/11] rust: num: Add Bounded::USABLE_BITS Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 04/11] samples: rust_print: add debug messages Thomas Weißschuh
2026-10-11 13:53 ` Miguel Ojeda
2026-10-11 14:48 ` Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 05/11] dyndbg: use u32 for struct _ddebug bitfields Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 06/11] dyndbg: make _ddebug::flags its own field Thomas Weißschuh
2026-10-11 13:23 ` Gary Guo
2026-10-11 14:47 ` Thomas Weißschuh
2026-10-11 15:44 ` Gary Guo
2026-10-11 12:52 ` [PATCH RFC 07/11] dyndbg: use READ_ONCE()/WRITE_ONCE() to access descriptor flags Thomas Weißschuh
2026-10-11 13:16 ` Gary Guo
2026-10-11 12:52 ` [PATCH RFC 08/11] rust: add support for dynamic debug Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 09/11] rust: print: enable dynamic debug for pr_debug!() Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 10/11] rust: device: remove logging methods Thomas Weißschuh
2026-10-11 12:52 ` [PATCH RFC 11/11] rust: device: enable dynamic debug for dev_dbg!() Thomas Weißschuh
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®