Skip to content

Commit eaa8885

Browse files
committed
New printing support
Features: - Adds macros like `info!` (with newline) and `pr_info!` (without newline) for the usual levels that the kernel support. - Includes the "continuation" level. - Includes automatically the module name in the string. - Includes, hopefully, pretty detailed logs. - Includes aliases to make it even easier to find the equivalent to `println!` for newcomers. Implementation: - Stack usage should be 1 KiB at most, regardless of the number of invocations of the macro in a single function. This should make it possible to use even when optimizations are not enabled. See code comments for the details. - The formatting string is compile-time, shared as a `static`, and always the same. We could perhaps pre-generate them per-module to avoid another `%.*s` in `printk()`, but I don't think it is worth the complexity at the moment, and it would increase memory usage anyway. Naming: - The `pr_*` names are the same as the kernel ones, and behave similarly, i.e. no newline at the end. - The non-`pr_*` ones are the same but without the prefix. They look better (shorter, no underscore), have the newline like `println!`, and they are what people should almost always use except if they need continuation. And they look pretty similar to the Rust `log` crate ones, too! - I think we can afford these short names (in the prelude, even!) since this is new code and nobody should be defining macros in the kernel with such short names, ever! Future: - I will open an issue with a few things that can be added on top, similar to the kernel parameters feature. - When we have tidy support (or custom clippy lints), we can add one to find the pattern: pr_*("...\n", ...); and suggest the non-prefixed, non-newline version instead: *("...", "..."); Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
1 parent 7ed5aa1 commit eaa8885

25 files changed

+966
-159
lines changed

.github/workflows/ci.yaml

+89-43
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
on:
22
pull_request: {}
33
push:
4-
branches: [rust]
4+
branches: [rust, print]
55

66
jobs:
77
ci:
@@ -166,11 +166,6 @@ jobs:
166166
cp samples/rust/rust_module_parameters.rs samples/rust/rust_module_parameters_loadable_default.rs
167167
cp samples/rust/rust_module_parameters.rs samples/rust/rust_module_parameters_loadable_custom.rs
168168
169-
sed -i 's:" my_:" built-in default my_:g' samples/rust/rust_module_parameters_builtin_default.rs
170-
sed -i 's:" my_:" built-in custom my_:g' samples/rust/rust_module_parameters_builtin_custom.rs
171-
sed -i 's:" my_:" loadable default my_:g' samples/rust/rust_module_parameters_loadable_default.rs
172-
sed -i 's:" my_:" loadable custom my_:g' samples/rust/rust_module_parameters_loadable_custom.rs
173-
174169
sed -i 's:rust_module_parameters:rust_module_parameters_builtin_default:g' samples/rust/rust_module_parameters_builtin_default.rs
175170
sed -i 's:rust_module_parameters:rust_module_parameters_builtin_custom:g' samples/rust/rust_module_parameters_builtin_custom.rs
176171
sed -i 's:rust_module_parameters:rust_module_parameters_loadable_default:g' samples/rust/rust_module_parameters_loadable_default.rs
@@ -217,43 +212,94 @@ jobs:
217212
218213
# Check
219214
- run: |
220-
grep '] Rust minimal sample (init)$' qemu-stdout.log
221-
grep '] Rust minimal sample (exit)$' qemu-stdout.log
222-
223-
grep '] Rust module parameters sample (init)$' qemu-stdout.log
224-
grep '] built-in default my_bool: true$' qemu-stdout.log
225-
grep '] built-in default my_i32: 42$' qemu-stdout.log
226-
grep '] built-in default my_str: default str val$' qemu-stdout.log
227-
grep '] built-in default my_usize: 42$' qemu-stdout.log
228-
grep '] built-in default my_array: \[0, 1]$' qemu-stdout.log
229-
grep '] built-in custom my_bool: false$' qemu-stdout.log
230-
grep '] built-in custom my_i32: 345543$' qemu-stdout.log
231-
grep '] built-in custom my_str: 🦀mod$' qemu-stdout.log
232-
grep '] built-in custom my_usize: 84$' qemu-stdout.log
233-
grep '] built-in custom my_array: \[1, 2, 3]$' qemu-stdout.log
234-
grep '] loadable default my_bool: true$' qemu-stdout.log
235-
grep '] loadable default my_i32: 42$' qemu-stdout.log
236-
grep '] loadable default my_str: default str val$' qemu-stdout.log
237-
grep '] loadable default my_usize: 42$' qemu-stdout.log
238-
grep '] loadable default my_array: \[0, 1]$' qemu-stdout.log
239-
grep '] loadable custom my_bool: false$' qemu-stdout.log
240-
grep '] loadable custom my_i32: 345543$' qemu-stdout.log
241-
grep '] loadable custom my_str: 🦀mod$' qemu-stdout.log
242-
grep '] loadable custom my_usize: 84$' qemu-stdout.log
243-
grep '] loadable custom my_array: \[1, 2, 3]$' qemu-stdout.log
244-
grep '] Rust module parameters sample (exit)$' qemu-stdout.log
245-
246-
grep '] Rust synchronisation primitives sample (init)$' qemu-stdout.log
247-
grep '] Rust synchronisation primitives sample (exit)$' qemu-stdout.log
248-
249-
grep '] Rust character device sample (init)$' qemu-stdout.log
250-
grep '] Rust character device sample (exit)$' qemu-stdout.log
251-
252-
grep '] Rust miscellaneous device sample (init)$' qemu-stdout.log
253-
grep '] Rust miscellaneous device sample (exit)$' qemu-stdout.log
254-
255-
grep '] Rust stack probing sample (init)$' qemu-stdout.log
256-
grep '] Rust stack probing sample (exit)$' qemu-stdout.log
215+
grep '] rust_minimal: Rust minimal sample (init)$' qemu-stdout.log
216+
grep '] rust_minimal: Rust minimal sample (exit)$' qemu-stdout.log
217+
218+
- run: |
219+
grep '] rust_print: Rust printing macros sample (init)$' qemu-stdout.log
220+
221+
grep '] rust_print: Emergency message (level 0) with newline w/o args$' qemu-stdout.log
222+
grep '] rust_print: Alert message (level 1) with newline w/o args$' qemu-stdout.log
223+
grep '] rust_print: Critical message (level 2) with newline w/o args$' qemu-stdout.log
224+
grep '] rust_print: Error message (level 3) with newline w/o args$' qemu-stdout.log
225+
grep '] rust_print: Warning message (level 4) with newline w/o args$' qemu-stdout.log
226+
grep '] rust_print: Notice message (level 5) with newline w/o args$' qemu-stdout.log
227+
grep '] rust_print: Info message (level 6) with newline w/o args$' qemu-stdout.log
228+
grep '] rust_print: A line that is continued with newline w/o args$' qemu-stdout.log
229+
230+
grep '] rust_print: Emergency message (level 0) w/o newline w/o args$' qemu-stdout.log
231+
grep '] rust_print: Alert message (level 1) w/o newline w/o args$' qemu-stdout.log
232+
grep '] rust_print: Critical message (level 2) w/o newline w/o args$' qemu-stdout.log
233+
grep '] rust_print: Error message (level 3) w/o newline w/o args$' qemu-stdout.log
234+
grep '] rust_print: Warning message (level 4) w/o newline w/o args$' qemu-stdout.log
235+
grep '] rust_print: Notice message (level 5) w/o newline w/o args$' qemu-stdout.log
236+
grep '] rust_print: Info message (level 6) w/o newline w/o args$' qemu-stdout.log
237+
grep '] rust_print: A line that is continued w/o newline w/o args$' qemu-stdout.log
238+
239+
grep '] rust_print: Emergency message (level 0) with newline with args$' qemu-stdout.log
240+
grep '] rust_print: Alert message (level 1) with newline with args$' qemu-stdout.log
241+
grep '] rust_print: Critical message (level 2) with newline with args$' qemu-stdout.log
242+
grep '] rust_print: Error message (level 3) with newline with args$' qemu-stdout.log
243+
grep '] rust_print: Warning message (level 4) with newline with args$' qemu-stdout.log
244+
grep '] rust_print: Notice message (level 5) with newline with args$' qemu-stdout.log
245+
grep '] rust_print: Info message (level 6) with newline with args$' qemu-stdout.log
246+
grep '] rust_print: A line that is continued with newline with args$' qemu-stdout.log
247+
248+
grep '] rust_print: Emergency message (level 0) w/o newline with args$' qemu-stdout.log
249+
grep '] rust_print: Alert message (level 1) w/o newline with args$' qemu-stdout.log
250+
grep '] rust_print: Critical message (level 2) w/o newline with args$' qemu-stdout.log
251+
grep '] rust_print: Error message (level 3) w/o newline with args$' qemu-stdout.log
252+
grep '] rust_print: Warning message (level 4) w/o newline with args$' qemu-stdout.log
253+
grep '] rust_print: Notice message (level 5) w/o newline with args$' qemu-stdout.log
254+
grep '] rust_print: Info message (level 6) w/o newline with args$' qemu-stdout.log
255+
grep '] rust_print: A line that is continued w/o newline with args$' qemu-stdout.log
256+
257+
grep '] rust_print: Rust printing macros sample (exit)$' qemu-stdout.log
258+
259+
- run: |
260+
grep '] rust_module_parameters: Rust module parameters sample (init)$' qemu-stdout.log
261+
262+
grep '] rust_module_parameters_builtin_default: my_bool: true$' qemu-stdout.log
263+
grep '] rust_module_parameters_builtin_default: my_i32: 42$' qemu-stdout.log
264+
grep '] rust_module_parameters_builtin_default: my_str: default str val$' qemu-stdout.log
265+
grep '] rust_module_parameters_builtin_default: my_usize: 42$' qemu-stdout.log
266+
grep '] rust_module_parameters_builtin_default: my_array: \[0, 1]$' qemu-stdout.log
267+
268+
grep '] rust_module_parameters_builtin_custom: my_bool: false$' qemu-stdout.log
269+
grep '] rust_module_parameters_builtin_custom: my_i32: 345543$' qemu-stdout.log
270+
grep '] rust_module_parameters_builtin_custom: my_str: 🦀mod$' qemu-stdout.log
271+
grep '] rust_module_parameters_builtin_custom: my_usize: 84$' qemu-stdout.log
272+
grep '] rust_module_parameters_builtin_custom: my_array: \[1, 2, 3]$' qemu-stdout.log
273+
274+
grep '] rust_module_parameters_loadable_default: my_bool: true$' qemu-stdout.log
275+
grep '] rust_module_parameters_loadable_default: my_i32: 42$' qemu-stdout.log
276+
grep '] rust_module_parameters_loadable_default: my_str: default str val$' qemu-stdout.log
277+
grep '] rust_module_parameters_loadable_default: my_usize: 42$' qemu-stdout.log
278+
grep '] rust_module_parameters_loadable_default: my_array: \[0, 1]$' qemu-stdout.log
279+
280+
grep '] rust_module_parameters_loadable_custom: my_bool: false$' qemu-stdout.log
281+
grep '] rust_module_parameters_loadable_custom: my_i32: 345543$' qemu-stdout.log
282+
grep '] rust_module_parameters_loadable_custom: my_str: 🦀mod$' qemu-stdout.log
283+
grep '] rust_module_parameters_loadable_custom: my_usize: 84$' qemu-stdout.log
284+
grep '] rust_module_parameters_loadable_custom: my_array: \[1, 2, 3]$' qemu-stdout.log
285+
286+
grep '] rust_module_parameters: Rust module parameters sample (exit)$' qemu-stdout.log
287+
288+
- run: |
289+
grep '] rust_sync: Rust synchronisation primitives sample (init)$' qemu-stdout.log
290+
grep '] rust_sync: Rust synchronisation primitives sample (exit)$' qemu-stdout.log
291+
292+
- run: |
293+
grep '] rust_chrdev: Rust character device sample (init)$' qemu-stdout.log
294+
grep '] rust_chrdev: Rust character device sample (exit)$' qemu-stdout.log
295+
296+
- run: |
297+
grep '] rust_miscdev: Rust miscellaneous device sample (init)$' qemu-stdout.log
298+
grep '] rust_miscdev: Rust miscellaneous device sample (exit)$' qemu-stdout.log
299+
300+
- run: |
301+
grep '] rust_stack_probing: Rust stack probing sample (init)$' qemu-stdout.log
302+
grep '] rust_stack_probing: Rust stack probing sample (exit)$' qemu-stdout.log
257303
258304
# Report
259305
- run: |

.github/workflows/kernel-arm64-debug.config

+1
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,7 @@ CONFIG_SAMPLES=y
14211421
# CONFIG_SAMPLE_WATCHDOG is not set
14221422
CONFIG_SAMPLES_RUST=y
14231423
CONFIG_SAMPLE_RUST_MINIMAL=m
1424+
CONFIG_SAMPLE_RUST_PRINT=m
14241425
CONFIG_SAMPLE_RUST_MODULE_PARAMETERS=m
14251426
CONFIG_SAMPLE_RUST_SYNC=m
14261427
CONFIG_SAMPLE_RUST_CHRDEV=m

.github/workflows/kernel-arm64-release.config

+1
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,7 @@ CONFIG_SAMPLES=y
13391339
# CONFIG_SAMPLE_WATCHDOG is not set
13401340
CONFIG_SAMPLES_RUST=y
13411341
CONFIG_SAMPLE_RUST_MINIMAL=m
1342+
CONFIG_SAMPLE_RUST_PRINT=m
13421343
CONFIG_SAMPLE_RUST_MODULE_PARAMETERS=m
13431344
CONFIG_SAMPLE_RUST_SYNC=m
13441345
CONFIG_SAMPLE_RUST_CHRDEV=m

.github/workflows/kernel-ppc64le-debug.config

+1
Original file line numberDiff line numberDiff line change
@@ -1481,6 +1481,7 @@ CONFIG_SAMPLES=y
14811481
# CONFIG_SAMPLE_WATCHDOG is not set
14821482
CONFIG_SAMPLES_RUST=y
14831483
CONFIG_SAMPLE_RUST_MINIMAL=m
1484+
CONFIG_SAMPLE_RUST_PRINT=m
14841485
CONFIG_SAMPLE_RUST_MODULE_PARAMETERS=m
14851486
CONFIG_SAMPLE_RUST_SYNC=m
14861487
CONFIG_SAMPLE_RUST_CHRDEV=m

.github/workflows/kernel-ppc64le-release.config

+1
Original file line numberDiff line numberDiff line change
@@ -1443,6 +1443,7 @@ CONFIG_SAMPLES=y
14431443
# CONFIG_SAMPLE_WATCHDOG is not set
14441444
CONFIG_SAMPLES_RUST=y
14451445
CONFIG_SAMPLE_RUST_MINIMAL=m
1446+
CONFIG_SAMPLE_RUST_PRINT=m
14461447
CONFIG_SAMPLE_RUST_MODULE_PARAMETERS=m
14471448
CONFIG_SAMPLE_RUST_SYNC=m
14481449
CONFIG_SAMPLE_RUST_CHRDEV=m

.github/workflows/kernel-x86_64-debug.config

+1
Original file line numberDiff line numberDiff line change
@@ -1433,6 +1433,7 @@ CONFIG_SAMPLES=y
14331433
# CONFIG_SAMPLE_WATCHDOG is not set
14341434
CONFIG_SAMPLES_RUST=y
14351435
CONFIG_SAMPLE_RUST_MINIMAL=m
1436+
CONFIG_SAMPLE_RUST_PRINT=m
14361437
CONFIG_SAMPLE_RUST_MODULE_PARAMETERS=m
14371438
CONFIG_SAMPLE_RUST_SYNC=m
14381439
CONFIG_SAMPLE_RUST_CHRDEV=m

.github/workflows/kernel-x86_64-release.config

+1
Original file line numberDiff line numberDiff line change
@@ -1381,6 +1381,7 @@ CONFIG_SAMPLES=y
13811381
# CONFIG_SAMPLE_WATCHDOG is not set
13821382
CONFIG_SAMPLES_RUST=y
13831383
CONFIG_SAMPLE_RUST_MINIMAL=m
1384+
CONFIG_SAMPLE_RUST_PRINT=m
13841385
CONFIG_SAMPLE_RUST_MODULE_PARAMETERS=m
13851386
CONFIG_SAMPLE_RUST_SYNC=m
13861387
CONFIG_SAMPLE_RUST_CHRDEV=m

.github/workflows/qemu-init.sh

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
busybox insmod rust_minimal.ko
44
busybox rmmod rust_minimal.ko
55

6+
busybox insmod rust_print.ko
7+
busybox rmmod rust_print.ko
8+
69
busybox insmod rust_module_parameters.ko
710
busybox rmmod rust_module_parameters.ko
811

.github/workflows/qemu-initramfs.desc

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ slink /bin/sh /bin/busybox 0755 0 0
66
file /init .github/workflows/qemu-init.sh 0755 0 0
77

88
file /rust_minimal.ko samples/rust/rust_minimal.ko 0755 0 0
9+
file /rust_print.ko samples/rust/rust_print.ko 0755 0 0
910
file /rust_module_parameters.ko samples/rust/rust_module_parameters.ko 0755 0 0
1011
file /rust_sync.ko samples/rust/rust_sync.ko 0755 0 0
1112
file /rust_chrdev.ko samples/rust/rust_chrdev.ko 0755 0 0

kernel/printk/printk.c

+2
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,8 @@ static u64 clear_seq;
410410
#else
411411
#define PREFIX_MAX 32
412412
#endif
413+
414+
/* Keep in sync with rust/kernel/print.rs */
413415
#define LOG_LINE_MAX (1024 - PREFIX_MAX)
414416

415417
#define LOG_LEVEL(v) ((v) & 0x07)

rust/kernel/lib.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
alloc_error_handler,
1818
const_fn,
1919
const_mut_refs,
20+
const_panic,
2021
try_reserve
2122
)]
2223
#![deny(clippy::complexity)]
@@ -47,7 +48,7 @@ pub mod miscdev;
4748
pub mod module_param;
4849

4950
pub mod prelude;
50-
pub mod printk;
51+
pub mod print;
5152
pub mod random;
5253
mod static_assert;
5354
pub mod sync;
@@ -152,7 +153,7 @@ fn panic(_info: &PanicInfo) -> ! {
152153
///
153154
/// fn test() {
154155
/// // This prints `8`.
155-
/// println!("{}", offset_of!(Test, b));
156+
/// info!("{}", offset_of!(Test, b));
156157
/// }
157158
/// ```
158159
#[macro_export]
@@ -193,7 +194,7 @@ macro_rules! offset_of {
193194
/// let b_ptr = &test.b;
194195
/// let test_alias = unsafe { container_of!(b_ptr, Test, b) };
195196
/// // This prints `true`.
196-
/// println!("{}", core::ptr::eq(&test, test_alias));
197+
/// info!("{}", core::ptr::eq(&test, test_alias));
197198
/// }
198199
/// ```
199200
#[macro_export]

rust/kernel/prelude.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,9 @@ pub use alloc::{borrow::ToOwned, string::String};
1515

1616
pub use module::module;
1717

18-
pub use super::{println, static_assert, KernelModule, KernelResult};
18+
pub use super::{alert, cont, crit, emerg, err, info, notice, warn};
19+
pub use super::{pr_alert, pr_cont, pr_crit, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
20+
21+
pub use super::static_assert;
22+
23+
pub use super::{KernelModule, KernelResult};

0 commit comments

Comments
 (0)