Skip to content

Commit

Permalink
New printing support
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
ojeda committed Apr 11, 2021
1 parent 7ed5aa1 commit ca19455
Show file tree
Hide file tree
Showing 25 changed files with 965 additions and 158 deletions.
130 changes: 88 additions & 42 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,6 @@ jobs:
cp samples/rust/rust_module_parameters.rs samples/rust/rust_module_parameters_loadable_default.rs
cp samples/rust/rust_module_parameters.rs samples/rust/rust_module_parameters_loadable_custom.rs
sed -i 's:" my_:" built-in default my_:g' samples/rust/rust_module_parameters_builtin_default.rs
sed -i 's:" my_:" built-in custom my_:g' samples/rust/rust_module_parameters_builtin_custom.rs
sed -i 's:" my_:" loadable default my_:g' samples/rust/rust_module_parameters_loadable_default.rs
sed -i 's:" my_:" loadable custom my_:g' samples/rust/rust_module_parameters_loadable_custom.rs
sed -i 's:rust_module_parameters:rust_module_parameters_builtin_default:g' samples/rust/rust_module_parameters_builtin_default.rs
sed -i 's:rust_module_parameters:rust_module_parameters_builtin_custom:g' samples/rust/rust_module_parameters_builtin_custom.rs
sed -i 's:rust_module_parameters:rust_module_parameters_loadable_default:g' samples/rust/rust_module_parameters_loadable_default.rs
Expand Down Expand Up @@ -217,43 +212,94 @@ jobs:
# Check
- run: |
grep '] Rust minimal sample (init)$' qemu-stdout.log
grep '] Rust minimal sample (exit)$' qemu-stdout.log
grep '] Rust module parameters sample (init)$' qemu-stdout.log
grep '] built-in default my_bool: true$' qemu-stdout.log
grep '] built-in default my_i32: 42$' qemu-stdout.log
grep '] built-in default my_str: default str val$' qemu-stdout.log
grep '] built-in default my_usize: 42$' qemu-stdout.log
grep '] built-in default my_array: \[0, 1]$' qemu-stdout.log
grep '] built-in custom my_bool: false$' qemu-stdout.log
grep '] built-in custom my_i32: 345543$' qemu-stdout.log
grep '] built-in custom my_str: 🦀mod$' qemu-stdout.log
grep '] built-in custom my_usize: 84$' qemu-stdout.log
grep '] built-in custom my_array: \[1, 2, 3]$' qemu-stdout.log
grep '] loadable default my_bool: true$' qemu-stdout.log
grep '] loadable default my_i32: 42$' qemu-stdout.log
grep '] loadable default my_str: default str val$' qemu-stdout.log
grep '] loadable default my_usize: 42$' qemu-stdout.log
grep '] loadable default my_array: \[0, 1]$' qemu-stdout.log
grep '] loadable custom my_bool: false$' qemu-stdout.log
grep '] loadable custom my_i32: 345543$' qemu-stdout.log
grep '] loadable custom my_str: 🦀mod$' qemu-stdout.log
grep '] loadable custom my_usize: 84$' qemu-stdout.log
grep '] loadable custom my_array: \[1, 2, 3]$' qemu-stdout.log
grep '] Rust module parameters sample (exit)$' qemu-stdout.log
grep '] Rust synchronisation primitives sample (init)$' qemu-stdout.log
grep '] Rust synchronisation primitives sample (exit)$' qemu-stdout.log
grep '] Rust character device sample (init)$' qemu-stdout.log
grep '] Rust character device sample (exit)$' qemu-stdout.log
grep '] Rust miscellaneous device sample (init)$' qemu-stdout.log
grep '] Rust miscellaneous device sample (exit)$' qemu-stdout.log
grep '] Rust stack probing sample (init)$' qemu-stdout.log
grep '] Rust stack probing sample (exit)$' qemu-stdout.log
grep '] rust_minimal: Rust minimal sample (init)$' qemu-stdout.log
grep '] rust_minimal: Rust minimal sample (exit)$' qemu-stdout.log
- run: |
grep '] rust_print: Rust printing macros sample (init)$' qemu-stdout.log
grep '] rust_print: Emergency message (level 0) with newline w/o args$' qemu-stdout.log
grep '] rust_print: Alert message (level 1) with newline w/o args$' qemu-stdout.log
grep '] rust_print: Critical message (level 2) with newline w/o args$' qemu-stdout.log
grep '] rust_print: Error message (level 3) with newline w/o args$' qemu-stdout.log
grep '] rust_print: Warning message (level 4) with newline w/o args$' qemu-stdout.log
grep '] rust_print: Notice message (level 5) with newline w/o args$' qemu-stdout.log
grep '] rust_print: Info message (level 6) with newline w/o args$' qemu-stdout.log
grep '] rust_print: A line that is continued with newline w/o args$' qemu-stdout.log
grep '] rust_print: Emergency message (level 0) w/o newline w/o args$' qemu-stdout.log
grep '] rust_print: Alert message (level 1) w/o newline w/o args$' qemu-stdout.log
grep '] rust_print: Critical message (level 2) w/o newline w/o args$' qemu-stdout.log
grep '] rust_print: Error message (level 3) w/o newline w/o args$' qemu-stdout.log
grep '] rust_print: Warning message (level 4) w/o newline w/o args$' qemu-stdout.log
grep '] rust_print: Notice message (level 5) w/o newline w/o args$' qemu-stdout.log
grep '] rust_print: Info message (level 6) w/o newline w/o args$' qemu-stdout.log
grep '] rust_print: A line that is continued w/o newline w/o args$' qemu-stdout.log
grep '] rust_print: Emergency message (level 0) with newline with args$' qemu-stdout.log
grep '] rust_print: Alert message (level 1) with newline with args$' qemu-stdout.log
grep '] rust_print: Critical message (level 2) with newline with args$' qemu-stdout.log
grep '] rust_print: Error message (level 3) with newline with args$' qemu-stdout.log
grep '] rust_print: Warning message (level 4) with newline with args$' qemu-stdout.log
grep '] rust_print: Notice message (level 5) with newline with args$' qemu-stdout.log
grep '] rust_print: Info message (level 6) with newline with args$' qemu-stdout.log
grep '] rust_print: A line that is continued with newline with args$' qemu-stdout.log
grep '] rust_print: Emergency message (level 0) w/o newline with args$' qemu-stdout.log
grep '] rust_print: Alert message (level 1) w/o newline with args$' qemu-stdout.log
grep '] rust_print: Critical message (level 2) w/o newline with args$' qemu-stdout.log
grep '] rust_print: Error message (level 3) w/o newline with args$' qemu-stdout.log
grep '] rust_print: Warning message (level 4) w/o newline with args$' qemu-stdout.log
grep '] rust_print: Notice message (level 5) w/o newline with args$' qemu-stdout.log
grep '] rust_print: Info message (level 6) w/o newline with args$' qemu-stdout.log
grep '] rust_print: A line that is continued w/o newline with args$' qemu-stdout.log
grep '] rust_print: Rust printing macros sample (exit)$' qemu-stdout.log
- run: |
grep '] rust_module_parameters: Rust module parameters sample (init)$' qemu-stdout.log
grep '] rust_module_parameters_builtin_default: my_bool: true$' qemu-stdout.log
grep '] rust_module_parameters_builtin_default: my_i32: 42$' qemu-stdout.log
grep '] rust_module_parameters_builtin_default: my_str: default str val$' qemu-stdout.log
grep '] rust_module_parameters_builtin_default: my_usize: 42$' qemu-stdout.log
grep '] rust_module_parameters_builtin_default: my_array: \[0, 1]$' qemu-stdout.log
grep '] rust_module_parameters_builtin_custom: my_bool: false$' qemu-stdout.log
grep '] rust_module_parameters_builtin_custom: my_i32: 345543$' qemu-stdout.log
grep '] rust_module_parameters_builtin_custom: my_str: 🦀mod$' qemu-stdout.log
grep '] rust_module_parameters_builtin_custom: my_usize: 84$' qemu-stdout.log
grep '] rust_module_parameters_builtin_custom: my_array: \[1, 2, 3]$' qemu-stdout.log
grep '] rust_module_parameters_loadable_default: my_bool: true$' qemu-stdout.log
grep '] rust_module_parameters_loadable_default: my_i32: 42$' qemu-stdout.log
grep '] rust_module_parameters_loadable_default: my_str: default str val$' qemu-stdout.log
grep '] rust_module_parameters_loadable_default: my_usize: 42$' qemu-stdout.log
grep '] rust_module_parameters_loadable_default: my_array: \[0, 1]$' qemu-stdout.log
grep '] rust_module_parameters_loadable_custom: my_bool: false$' qemu-stdout.log
grep '] rust_module_parameters_loadable_custom: my_i32: 345543$' qemu-stdout.log
grep '] rust_module_parameters_loadable_custom: my_str: 🦀mod$' qemu-stdout.log
grep '] rust_module_parameters_loadable_custom: my_usize: 84$' qemu-stdout.log
grep '] rust_module_parameters_loadable_custom: my_array: \[1, 2, 3]$' qemu-stdout.log
grep '] rust_module_parameters: Rust module parameters sample (exit)$' qemu-stdout.log
- run: |
grep '] rust_sync: Rust synchronisation primitives sample (init)$' qemu-stdout.log
grep '] rust_sync: Rust synchronisation primitives sample (exit)$' qemu-stdout.log
- run: |
grep '] rust_chrdev: Rust character device sample (init)$' qemu-stdout.log
grep '] rust_chrdev: Rust character device sample (exit)$' qemu-stdout.log
- run: |
grep '] rust_miscdev: Rust miscellaneous device sample (init)$' qemu-stdout.log
grep '] rust_miscdev: Rust miscellaneous device sample (exit)$' qemu-stdout.log
- run: |
grep '] rust_stack_probing: Rust stack probing sample (init)$' qemu-stdout.log
grep '] rust_stack_probing: Rust stack probing sample (exit)$' qemu-stdout.log
# Report
- run: |
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-arm64-debug.config
Original file line number Diff line number Diff line change
Expand Up @@ -1421,6 +1421,7 @@ CONFIG_SAMPLES=y
# CONFIG_SAMPLE_WATCHDOG is not set
CONFIG_SAMPLES_RUST=y
CONFIG_SAMPLE_RUST_MINIMAL=m
CONFIG_SAMPLE_RUST_PRINT=m
CONFIG_SAMPLE_RUST_MODULE_PARAMETERS=m
CONFIG_SAMPLE_RUST_SYNC=m
CONFIG_SAMPLE_RUST_CHRDEV=m
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-arm64-release.config
Original file line number Diff line number Diff line change
Expand Up @@ -1339,6 +1339,7 @@ CONFIG_SAMPLES=y
# CONFIG_SAMPLE_WATCHDOG is not set
CONFIG_SAMPLES_RUST=y
CONFIG_SAMPLE_RUST_MINIMAL=m
CONFIG_SAMPLE_RUST_PRINT=m
CONFIG_SAMPLE_RUST_MODULE_PARAMETERS=m
CONFIG_SAMPLE_RUST_SYNC=m
CONFIG_SAMPLE_RUST_CHRDEV=m
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-ppc64le-debug.config
Original file line number Diff line number Diff line change
Expand Up @@ -1481,6 +1481,7 @@ CONFIG_SAMPLES=y
# CONFIG_SAMPLE_WATCHDOG is not set
CONFIG_SAMPLES_RUST=y
CONFIG_SAMPLE_RUST_MINIMAL=m
CONFIG_SAMPLE_RUST_PRINT=m
CONFIG_SAMPLE_RUST_MODULE_PARAMETERS=m
CONFIG_SAMPLE_RUST_SYNC=m
CONFIG_SAMPLE_RUST_CHRDEV=m
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-ppc64le-release.config
Original file line number Diff line number Diff line change
Expand Up @@ -1443,6 +1443,7 @@ CONFIG_SAMPLES=y
# CONFIG_SAMPLE_WATCHDOG is not set
CONFIG_SAMPLES_RUST=y
CONFIG_SAMPLE_RUST_MINIMAL=m
CONFIG_SAMPLE_RUST_PRINT=m
CONFIG_SAMPLE_RUST_MODULE_PARAMETERS=m
CONFIG_SAMPLE_RUST_SYNC=m
CONFIG_SAMPLE_RUST_CHRDEV=m
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-x86_64-debug.config
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,7 @@ CONFIG_SAMPLES=y
# CONFIG_SAMPLE_WATCHDOG is not set
CONFIG_SAMPLES_RUST=y
CONFIG_SAMPLE_RUST_MINIMAL=m
CONFIG_SAMPLE_RUST_PRINT=m
CONFIG_SAMPLE_RUST_MODULE_PARAMETERS=m
CONFIG_SAMPLE_RUST_SYNC=m
CONFIG_SAMPLE_RUST_CHRDEV=m
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-x86_64-release.config
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,7 @@ CONFIG_SAMPLES=y
# CONFIG_SAMPLE_WATCHDOG is not set
CONFIG_SAMPLES_RUST=y
CONFIG_SAMPLE_RUST_MINIMAL=m
CONFIG_SAMPLE_RUST_PRINT=m
CONFIG_SAMPLE_RUST_MODULE_PARAMETERS=m
CONFIG_SAMPLE_RUST_SYNC=m
CONFIG_SAMPLE_RUST_CHRDEV=m
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/qemu-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
busybox insmod rust_minimal.ko
busybox rmmod rust_minimal.ko

busybox insmod rust_print.ko
busybox rmmod rust_print.ko

busybox insmod rust_module_parameters.ko
busybox rmmod rust_module_parameters.ko

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/qemu-initramfs.desc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ slink /bin/sh /bin/busybox 0755 0 0
file /init .github/workflows/qemu-init.sh 0755 0 0

file /rust_minimal.ko samples/rust/rust_minimal.ko 0755 0 0
file /rust_print.ko samples/rust/rust_print.ko 0755 0 0
file /rust_module_parameters.ko samples/rust/rust_module_parameters.ko 0755 0 0
file /rust_sync.ko samples/rust/rust_sync.ko 0755 0 0
file /rust_chrdev.ko samples/rust/rust_chrdev.ko 0755 0 0
Expand Down
2 changes: 2 additions & 0 deletions kernel/printk/printk.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,8 @@ static u64 clear_seq;
#else
#define PREFIX_MAX 32
#endif

/* Keep in sync with rust/kernel/print.rs */
#define LOG_LINE_MAX (1024 - PREFIX_MAX)

#define LOG_LEVEL(v) ((v) & 0x07)
Expand Down
7 changes: 4 additions & 3 deletions rust/kernel/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
alloc_error_handler,
const_fn,
const_mut_refs,
const_panic,
try_reserve
)]
#![deny(clippy::complexity)]
Expand Down Expand Up @@ -47,7 +48,7 @@ pub mod miscdev;
pub mod module_param;

pub mod prelude;
pub mod printk;
pub mod print;
pub mod random;
mod static_assert;
pub mod sync;
Expand Down Expand Up @@ -152,7 +153,7 @@ fn panic(_info: &PanicInfo) -> ! {
///
/// fn test() {
/// // This prints `8`.
/// println!("{}", offset_of!(Test, b));
/// info!("{}", offset_of!(Test, b));
/// }
/// ```
#[macro_export]
Expand Down Expand Up @@ -193,7 +194,7 @@ macro_rules! offset_of {
/// let b_ptr = &test.b;
/// let test_alias = unsafe { container_of!(b_ptr, Test, b) };
/// // This prints `true`.
/// println!("{}", core::ptr::eq(&test, test_alias));
/// info!("{}", core::ptr::eq(&test, test_alias));
/// }
/// ```
#[macro_export]
Expand Down
7 changes: 6 additions & 1 deletion rust/kernel/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,9 @@ pub use alloc::{borrow::ToOwned, string::String};

pub use module::module;

pub use super::{println, static_assert, KernelModule, KernelResult};
pub use super::{alert, cont, crit, emerg, err, info, notice, warn};
pub use super::{pr_alert, pr_cont, pr_crit, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};

pub use super::static_assert;

pub use super::{KernelModule, KernelResult};
Loading

0 comments on commit ca19455

Please sign in to comment.