A qemu_log_mask!() macro is provided which expects similar arguments as the C version. However, the formatting works as one would expect from Rust.
To maximize code reuse the macro is just a thin wrapper around qemu_log(). Also, just the bare minimum of logging masks is provided which should suffice for the current use case of Rust in QEMU. Signed-off-by: Bernhard Beschow <shen...@gmail.com> --- docs/devel/rust.rst | 1 + rust/wrapper.h | 2 ++ rust/qemu-api/meson.build | 1 + rust/qemu-api/src/lib.rs | 1 + rust/qemu-api/src/log.rs | 55 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 60 insertions(+) create mode 100644 rust/qemu-api/src/log.rs diff --git a/docs/devel/rust.rst b/docs/devel/rust.rst index 88bdec1eb2..bc50216dc6 100644 --- a/docs/devel/rust.rst +++ b/docs/devel/rust.rst @@ -187,6 +187,7 @@ module status ``c_str`` complete ``errno`` complete ``irq`` complete +``log`` proof of concept ``memory`` stable ``module`` complete ``offset_of`` stable diff --git a/rust/wrapper.h b/rust/wrapper.h index d4fec54657..9518face53 100644 --- a/rust/wrapper.h +++ b/rust/wrapper.h @@ -48,6 +48,8 @@ typedef enum memory_order { #endif /* __CLANG_STDATOMIC_H */ #include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/log-for-trace.h" #include "qemu/module.h" #include "qemu-io.h" #include "system/system.h" diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index 858685ddd4..112f6735a9 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -26,6 +26,7 @@ _qemu_api_rs = static_library( 'src/c_str.rs', 'src/errno.rs', 'src/irq.rs', + 'src/log.rs', 'src/memory.rs', 'src/module.rs', 'src/offset_of.rs', diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index 05f38b51d3..b54989a243 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -21,6 +21,7 @@ pub mod chardev; pub mod errno; pub mod irq; +pub mod log; pub mod memory; pub mod module; pub mod offset_of; diff --git a/rust/qemu-api/src/log.rs b/rust/qemu-api/src/log.rs new file mode 100644 index 0000000000..3103a86efa --- /dev/null +++ b/rust/qemu-api/src/log.rs @@ -0,0 +1,55 @@ +// Copyright 2025 Bernhard Beschow <shen...@gmail.com> +// SPDX-License-Identifier: GPL-2.0-or-later + +pub use crate::bindings::{LOG_GUEST_ERROR, LOG_INVALID_MEM, LOG_UNIMP}; + +/// A macro to log messages conditionally based on a provided mask. +/// +/// The `qemu_log_mask` macro checks whether the given mask matches the +/// current log level and, if so, formats and logs the message. +/// +/// # Parameters +/// +/// - `$mask`: The log mask to check. This should be an integer value +/// indicating the log level mask. +/// - `$fmt`: A format string following the syntax and rules of the `format!` +/// macro. It specifies the structure of the log message. +/// - `$args`: Optional arguments to be interpolated into the format string. +/// +/// # Example +/// +/// ``` +/// use qemu_api::log::LOG_GUEST_ERROR; +/// +/// qemu_log_mask!( +/// LOG_GUEST_ERROR, +/// "Address 0x{error_address:x} out of range\n" +/// ); +/// ``` +/// +/// It is also possible to use printf style: +/// +/// ``` +/// use qemu_api::log::LOG_GUEST_ERROR; +/// +/// qemu_log_mask!( +/// LOG_GUEST_ERROR, +/// "Address 0x{:x} out of range\n", +/// error_address +/// ); +/// ``` +#[macro_export] +macro_rules! qemu_log_mask { + ($mask:expr, $fmt:expr $(, $args:expr)*) => {{ + if unsafe { + (::qemu_api::bindings::qemu_loglevel & ($mask as std::os::raw::c_int)) != 0 + } { + let formatted_string = format!($fmt, $($args),*); + let c_string = std::ffi::CString::new(formatted_string).unwrap(); + + unsafe { + ::qemu_api::bindings::qemu_log(c_string.as_ptr()); + } + } + }}; +} -- 2.49.0