Skip to content

Commit efbcb28

Browse files
authored
Merge pull request torvalds#624 from wedsonaf/dev-printk
rust: add `dev_*` print macros.
2 parents 32e5120 + 426247f commit efbcb28

File tree

2 files changed

+327
-2
lines changed

2 files changed

+327
-2
lines changed

rust/kernel/device.rs

Lines changed: 323 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
use crate::{clk::Clk, error::from_kernel_err_ptr};
99

1010
use crate::{
11-
bindings,
11+
bindings, c_str, c_types,
1212
revocable::{Revocable, RevocableGuard},
1313
str::CStr,
1414
sync::{NeedsLockClass, RevocableMutex, RevocableMutexGuard, UniqueRef},
1515
Result,
1616
};
1717
use core::{
18+
fmt,
1819
ops::{Deref, DerefMut},
1920
pin::Pin,
2021
};
@@ -64,6 +65,92 @@ pub unsafe trait RawDevice {
6465
// SAFETY: clock is initialized with valid pointer returned from `bindings::clk_get` call.
6566
unsafe { Ok(Clk::new(clk_ptr)) }
6667
}
68+
69+
/// Prints an emergency-level message (level 0) prefixed with device information.
70+
///
71+
/// More details are available from [`dev_emerg`].
72+
fn pr_emerg(&self, args: fmt::Arguments<'_>) {
73+
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
74+
unsafe { self.printk(bindings::KERN_EMERG, args) };
75+
}
76+
77+
/// Prints an alert-level message (level 1) prefixed with device information.
78+
///
79+
/// More details are available from [`dev_alert`].
80+
fn pr_alert(&self, args: fmt::Arguments<'_>) {
81+
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
82+
unsafe { self.printk(bindings::KERN_ALERT, args) };
83+
}
84+
85+
/// Prints a critical-level message (level 2) prefixed with device information.
86+
///
87+
/// More details are available from [`dev_crit`].
88+
fn pr_crit(&self, args: fmt::Arguments<'_>) {
89+
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
90+
unsafe { self.printk(bindings::KERN_CRIT, args) };
91+
}
92+
93+
/// Prints an error-level message (level 3) prefixed with device information.
94+
///
95+
/// More details are available from [`dev_err`].
96+
fn pr_err(&self, args: fmt::Arguments<'_>) {
97+
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
98+
unsafe { self.printk(bindings::KERN_ERR, args) };
99+
}
100+
101+
/// Prints a warning-level message (level 4) prefixed with device information.
102+
///
103+
/// More details are available from [`dev_warn`].
104+
fn pr_warn(&self, args: fmt::Arguments<'_>) {
105+
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
106+
unsafe { self.printk(bindings::KERN_WARNING, args) };
107+
}
108+
109+
/// Prints a notice-level message (level 5) prefixed with device information.
110+
///
111+
/// More details are available from [`dev_notice`].
112+
fn pr_notice(&self, args: fmt::Arguments<'_>) {
113+
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
114+
unsafe { self.printk(bindings::KERN_NOTICE, args) };
115+
}
116+
117+
/// Prints an info-level message (level 6) prefixed with device information.
118+
///
119+
/// More details are available from [`dev_info`].
120+
fn pr_info(&self, args: fmt::Arguments<'_>) {
121+
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
122+
unsafe { self.printk(bindings::KERN_INFO, args) };
123+
}
124+
125+
/// Prints a debug-level message (level 7) prefixed with device information.
126+
///
127+
/// More details are available from [`dev_dbg`].
128+
fn pr_dbg(&self, args: fmt::Arguments<'_>) {
129+
if cfg!(debug_assertions) {
130+
// SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
131+
unsafe { self.printk(bindings::KERN_DEBUG, args) };
132+
}
133+
}
134+
135+
/// Prints the provided message to the console.
136+
///
137+
/// # Safety
138+
///
139+
/// Callers must ensure that `klevel` is null-terminated; in particular, one of the
140+
/// `KERN_*`constants, for example, `KERN_CRIT`, `KERN_ALERT`, etc.
141+
unsafe fn printk(&self, klevel: &[u8], msg: fmt::Arguments<'_>) {
142+
// SAFETY: `klevel` is null-terminated and one of the kernel constants. `self.raw_device`
143+
// is valid because `self` is valid. The "%pA" format string expects a pointer to
144+
// `fmt::Arguments`, which is what we're passing as the last argument.
145+
unsafe {
146+
bindings::_dev_printk(
147+
klevel as *const _ as *const c_types::c_char,
148+
self.raw_device(),
149+
c_str!("%pA").as_char_ptr(),
150+
&msg as *const _ as *const c_types::c_void,
151+
)
152+
};
153+
}
67154
}
68155

69156
/// A ref-counted device.
@@ -76,6 +163,13 @@ pub struct Device {
76163
pub(crate) ptr: *mut bindings::device,
77164
}
78165

166+
// SAFETY: `Device` only holds a pointer to a C device, which is safe to be used from any thread.
167+
unsafe impl Send for Device {}
168+
169+
// SAFETY: `Device` only holds a pointer to a C device, references to which are safe to be used
170+
// from any thread.
171+
unsafe impl Sync for Device {}
172+
79173
impl Device {
80174
/// Creates a new device instance.
81175
///
@@ -98,6 +192,13 @@ impl Device {
98192
}
99193
}
100194

195+
// SAFETY: The device returned by `raw_device` is the one for which we hold a reference.
196+
unsafe impl RawDevice for Device {
197+
fn raw_device(&self) -> *mut bindings::device {
198+
self.ptr
199+
}
200+
}
201+
101202
impl Drop for Device {
102203
fn drop(&mut self) {
103204
// SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to
@@ -225,3 +326,224 @@ impl<T, U, V> DerefMut for Data<T, U, V> {
225326
&mut self.general
226327
}
227328
}
329+
330+
#[doc(hidden)]
331+
#[macro_export]
332+
macro_rules! dev_printk {
333+
($method:ident, $dev:expr, $($f:tt)*) => {
334+
{
335+
// We have an explicity `use` statement here so that callers of this macro are not
336+
// required to explicitly use the `RawDevice` trait to use its functions.
337+
use $crate::device::RawDevice;
338+
($dev).$method(core::format_args!($($f)*));
339+
}
340+
}
341+
}
342+
343+
/// Prints an emergency-level message (level 0) prefixed with device information.
344+
///
345+
/// This level should be used if the system is unusable.
346+
///
347+
/// Equivalent to the kernel's `dev_emerg` macro.
348+
///
349+
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
350+
/// [`core::fmt`] and [`alloc::format!`].
351+
///
352+
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
353+
///
354+
/// # Examples
355+
///
356+
/// ```
357+
/// # use kernel::prelude::*;
358+
/// # use kernel::device::Device;
359+
///
360+
/// fn example(dev: &Device) {
361+
/// dev_emerg!(dev, "hello {}\n", "there");
362+
/// }
363+
/// ```
364+
#[macro_export]
365+
macro_rules! dev_emerg {
366+
($($f:tt)*) => { $crate::dev_printk!(pr_emerg, $($f)*); }
367+
}
368+
369+
/// Prints an alert-level message (level 1) prefixed with device information.
370+
///
371+
/// This level should be used if action must be taken immediately.
372+
///
373+
/// Equivalent to the kernel's `dev_alert` macro.
374+
///
375+
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
376+
/// [`core::fmt`] and [`alloc::format!`].
377+
///
378+
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
379+
///
380+
/// # Examples
381+
///
382+
/// ```
383+
/// # use kernel::prelude::*;
384+
/// # use kernel::device::Device;
385+
///
386+
/// fn example(dev: &Device) {
387+
/// dev_alert!(dev, "hello {}\n", "there");
388+
/// }
389+
/// ```
390+
#[macro_export]
391+
macro_rules! dev_alert {
392+
($($f:tt)*) => { $crate::dev_printk!(pr_alert, $($f)*); }
393+
}
394+
395+
/// Prints a critical-level message (level 2) prefixed with device information.
396+
///
397+
/// This level should be used in critical conditions.
398+
///
399+
/// Equivalent to the kernel's `dev_crit` macro.
400+
///
401+
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
402+
/// [`core::fmt`] and [`alloc::format!`].
403+
///
404+
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
405+
///
406+
/// # Examples
407+
///
408+
/// ```
409+
/// # use kernel::prelude::*;
410+
/// # use kernel::device::Device;
411+
///
412+
/// fn example(dev: &Device) {
413+
/// dev_crit!(dev, "hello {}\n", "there");
414+
/// }
415+
/// ```
416+
#[macro_export]
417+
macro_rules! dev_crit {
418+
($($f:tt)*) => { $crate::dev_printk!(pr_crit, $($f)*); }
419+
}
420+
421+
/// Prints an error-level message (level 3) prefixed with device information.
422+
///
423+
/// This level should be used in error conditions.
424+
///
425+
/// Equivalent to the kernel's `dev_err` macro.
426+
///
427+
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
428+
/// [`core::fmt`] and [`alloc::format!`].
429+
///
430+
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
431+
///
432+
/// # Examples
433+
///
434+
/// ```
435+
/// # use kernel::prelude::*;
436+
/// # use kernel::device::Device;
437+
///
438+
/// fn example(dev: &Device) {
439+
/// dev_err!(dev, "hello {}\n", "there");
440+
/// }
441+
/// ```
442+
#[macro_export]
443+
macro_rules! dev_err {
444+
($($f:tt)*) => { $crate::dev_printk!(pr_err, $($f)*); }
445+
}
446+
447+
/// Prints a warning-level message (level 4) prefixed with device information.
448+
///
449+
/// This level should be used in warning conditions.
450+
///
451+
/// Equivalent to the kernel's `dev_warn` macro.
452+
///
453+
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
454+
/// [`core::fmt`] and [`alloc::format!`].
455+
///
456+
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
457+
///
458+
/// # Examples
459+
///
460+
/// ```
461+
/// # use kernel::prelude::*;
462+
/// # use kernel::device::Device;
463+
///
464+
/// fn example(dev: &Device) {
465+
/// dev_warn!(dev, "hello {}\n", "there");
466+
/// }
467+
/// ```
468+
#[macro_export]
469+
macro_rules! dev_warn {
470+
($($f:tt)*) => { $crate::dev_printk!(pr_warn, $($f)*); }
471+
}
472+
473+
/// Prints a notice-level message (level 5) prefixed with device information.
474+
///
475+
/// This level should be used in normal but significant conditions.
476+
///
477+
/// Equivalent to the kernel's `dev_notice` macro.
478+
///
479+
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
480+
/// [`core::fmt`] and [`alloc::format!`].
481+
///
482+
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
483+
///
484+
/// # Examples
485+
///
486+
/// ```
487+
/// # use kernel::prelude::*;
488+
/// # use kernel::device::Device;
489+
///
490+
/// fn example(dev: &Device) {
491+
/// dev_notice!(dev, "hello {}\n", "there");
492+
/// }
493+
/// ```
494+
#[macro_export]
495+
macro_rules! dev_notice {
496+
($($f:tt)*) => { $crate::dev_printk!(pr_notice, $($f)*); }
497+
}
498+
499+
/// Prints an info-level message (level 6) prefixed with device information.
500+
///
501+
/// This level should be used for informational messages.
502+
///
503+
/// Equivalent to the kernel's `dev_info` macro.
504+
///
505+
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
506+
/// [`core::fmt`] and [`alloc::format!`].
507+
///
508+
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
509+
///
510+
/// # Examples
511+
///
512+
/// ```
513+
/// # use kernel::prelude::*;
514+
/// # use kernel::device::Device;
515+
///
516+
/// fn example(dev: &Device) {
517+
/// dev_info!(dev, "hello {}\n", "there");
518+
/// }
519+
/// ```
520+
#[macro_export]
521+
macro_rules! dev_info {
522+
($($f:tt)*) => { $crate::dev_printk!(pr_info, $($f)*); }
523+
}
524+
525+
/// Prints a debug-level message (level 7) prefixed with device information.
526+
///
527+
/// This level should be used for debug messages.
528+
///
529+
/// Equivalent to the kernel's `dev_dbg` macro, except that it doesn't support dynamic debug yet.
530+
///
531+
/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
532+
/// [`core::fmt`] and [`alloc::format!`].
533+
///
534+
/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
535+
///
536+
/// # Examples
537+
///
538+
/// ```
539+
/// # use kernel::prelude::*;
540+
/// # use kernel::device::Device;
541+
///
542+
/// fn example(dev: &Device) {
543+
/// dev_dbg!(dev, "hello {}\n", "there");
544+
/// }
545+
/// ```
546+
#[macro_export]
547+
macro_rules! dev_dbg {
548+
($($f:tt)*) => { $crate::dev_printk!(pr_dbg, $($f)*); }
549+
}

rust/kernel/prelude.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ pub use macros::module;
1919

2020
pub use super::build_assert;
2121

22-
pub use super::{dbg, pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
22+
pub use super::{
23+
dbg, dev_alert, dev_crit, dev_dbg, dev_emerg, dev_err, dev_info, dev_notice, dev_warn,
24+
pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn,
25+
};
2326

2427
pub use super::module_misc_device;
2528

0 commit comments

Comments
 (0)