On Mon, Mar 31, 2025 at 07:26:33PM -0500, saman wrote: > This change introduces initial support for tracing and logging in Rust-based > QEMU code. As an example, tracing and logging have been implemented in the > pl011 device, which is written in Rust. > > - Updated `rust/wrapper.h` to include the `qemu/log.h` and `hw/char/trace.h` > header. > - Added log.rs to wrap `qemu_log_mask` and `qemu_log_mask_and_addr` > - Modified `tracetool` scripts to move C function implementation from > header to .c > - Added log and trace in rust version of PL011 device > > Future enhancements could include generating idiomatic Rust APIs for tracing > using the tracetool scripts > > Signed-off-by: saman <sa...@enumclass.cc> > --- > include/qemu/log-for-trace.h | 5 +-- > rust/hw/char/pl011/src/device.rs | 34 +++++++++++++++--- > rust/hw/char/pl011/src/registers.rs | 20 +++++++++++ > rust/qemu-api/meson.build | 1 + > rust/qemu-api/src/lib.rs | 1 + > rust/qemu-api/src/log.rs | 54 +++++++++++++++++++++++++++++ > rust/wrapper.h | 2 ++ > scripts/tracetool/format/c.py | 16 +++++++++ > scripts/tracetool/format/h.py | 11 ++---- > util/log.c | 5 +++ > 10 files changed, 131 insertions(+), 18 deletions(-) > create mode 100644 rust/qemu-api/src/log.rs > > diff --git a/include/qemu/log-for-trace.h b/include/qemu/log-for-trace.h > index d47c9cd446..ad5cd0dd24 100644 > --- a/include/qemu/log-for-trace.h > +++ b/include/qemu/log-for-trace.h > @@ -24,10 +24,7 @@ extern int qemu_loglevel; > #define LOG_TRACE (1 << 15) > > /* Returns true if a bit is set in the current loglevel mask */ > -static inline bool qemu_loglevel_mask(int mask) > -{ > - return (qemu_loglevel & mask) != 0; > -} > +bool qemu_loglevel_mask(int mask); > > /* main logging function */ > void G_GNUC_PRINTF(1, 2) qemu_log(const char *fmt, ...); > diff --git a/rust/hw/char/pl011/src/device.rs > b/rust/hw/char/pl011/src/device.rs > index bf88e0b00a..42385a7bf6 100644 > --- a/rust/hw/char/pl011/src/device.rs > +++ b/rust/hw/char/pl011/src/device.rs > @@ -2,15 +2,21 @@ > // Author(s): Manos Pitsidianakis <manos.pitsidiana...@linaro.org> > // SPDX-License-Identifier: GPL-2.0-or-later > > -use std::{ffi::CStr, mem::size_of, ptr::addr_of_mut}; > +use std::{ > + ffi::{CStr, CString}, > + mem::size_of, > + ptr::addr_of_mut, > +}; > > use qemu_api::{ > chardev::{CharBackend, Chardev, Event}, > impl_vmstate_forward, > irq::{IRQState, InterruptSource}, > + log::Mask, > memory::{hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder}, > prelude::*, > qdev::{Clock, ClockEvent, DeviceImpl, DeviceState, Property, ResetType, > ResettablePhasesImpl}, > + qemu_log_mask, > qom::{ObjectImpl, Owned, ParentField}, > static_assert, > sysbus::{SysBusDevice, SysBusDeviceImpl}, > @@ -298,7 +304,7 @@ pub(self) fn write( > DMACR => { > self.dmacr = value; > if value & 3 > 0 { > - // qemu_log_mask(LOG_UNIMP, "pl011: DMA not > implemented\n"); > + qemu_log_mask!(Mask::log_unimp, "pl011: DMA not > implemented\n"); > eprintln!("pl011: DMA not implemented"); > } > } > @@ -535,11 +541,21 @@ fn read(&self, offset: hwaddr, _size: u32) -> u64 { > u64::from(device_id[(offset - 0xfe0) >> 2]) > } > Err(_) => { > - // qemu_log_mask(LOG_GUEST_ERROR, "pl011_read: Bad offset > 0x%x\n", (int)offset); > + qemu_log_mask!( > + Mask::log_guest_error, > + "pl011_read: Bad offset 0x%x\n", > + offset as i32 > + ); > 0 > } > Ok(field) => { > + let regname = field.as_str(); > let (update_irq, result) = > self.regs.borrow_mut().read(field); > + let c_string = CString::new(regname).expect("CString::new > failed"); > + let name_ptr = c_string.as_ptr(); > + unsafe { > + qemu_api::bindings::trace_pl011_read(offset as u32, > result, name_ptr); > + }
I didn't look closely to see whether CString::new(field.as_str()) boils down to allocating a new string or just pointing to a NUL-terminated string constant in the .rodata section of the binary, but this looks suspicious. It has the pattern: ...do work to produce trace event arguments... trace_foo(arg1, arg2, arg3); Tracing is intended to be as low-overhead as possible when trace events are disabled but compiled in. The work to produce event arguments must be done only when the trace event is enabled.
signature.asc
Description: PGP signature