diff --git a/rust/Cargo.lock b/rust/Cargo.lock index f520597f25..42ae857fe5 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -230,6 +230,10 @@ dependencies = [ "util", ] +[[package]] +name = "probe" +version = "0.5.2" + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -388,6 +392,7 @@ dependencies = [ "migration", "qom", "system", + "trace", "util", ] @@ -430,6 +435,7 @@ name = "trace" version = "0.1.0" dependencies = [ "libc", + "probe", ] [[package]] diff --git a/rust/trace/Cargo.toml b/rust/trace/Cargo.toml index fc81bce580..11e27f8d28 100644 --- a/rust/trace/Cargo.toml +++ b/rust/trace/Cargo.toml @@ -14,6 +14,7 @@ rust-version.workspace = true [dependencies] libc = { workspace = true } +probe = "0.5" [lints] workspace = true diff --git a/rust/trace/meson.build b/rust/trace/meson.build index 1b3498f7fc..0071a49cf7 100644 --- a/rust/trace/meson.build +++ b/rust/trace/meson.build @@ -11,7 +11,7 @@ _trace_rs = static_library( 'trace', # Library name, lib_rs, trace_rs_targets, # List of generated `.rs` custom targets - dependencies: [libc_rs], + dependencies: [libc_rs, probe_rs], ) trace_rs = declare_dependency(link_with: _trace_rs) diff --git a/rust/trace/src/lib.rs b/rust/trace/src/lib.rs index e03bce43c4..c2abe430a5 100644 --- a/rust/trace/src/lib.rs +++ b/rust/trace/src/lib.rs @@ -6,6 +6,9 @@ #[doc(hidden)] /// Re-exported item to avoid adding libc as a dependency everywhere. pub use libc::{syslog, LOG_INFO}; +#[doc(hidden)] +/// Re-exported item to avoid adding probe as a dependency everywhere. +pub use probe::probe; #[macro_export] /// Define the trace-points from the named directory (which should have slashes @@ -21,6 +24,7 @@ macro_rules! include_trace { #[allow( clippy::ptr_as_ptr, clippy::cast_lossless, + clippy::nonminimal_bool, clippy::used_underscore_binding )] mod trace { diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py index 74062d21a7..61ba6f1ba8 100644 --- a/scripts/tracetool/__init__.py +++ b/scripts/tracetool/__init__.py @@ -461,6 +461,7 @@ def formats(self): QEMU_TRACE = "trace_%(name)s" QEMU_TRACE_TCG = QEMU_TRACE + "_tcg" + QEMU_RUST_DSTATE = "trace_%(name)s_enabled" QEMU_DSTATE = "_TRACE_%(NAME)s_DSTATE" QEMU_BACKEND_DSTATE = "TRACE_%(NAME)s_BACKEND_DSTATE" QEMU_EVENT = "_TRACE_%(NAME)s_EVENT" diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py index b4af403025..f0b58cc158 100644 --- a/scripts/tracetool/backend/dtrace.py +++ b/scripts/tracetool/backend/dtrace.py @@ -70,3 +70,34 @@ def generate_h(event, group): def generate_h_backend_dstate(event, group): out(' QEMU_%(uppername)s_ENABLED() || \\', uppername=event.name.upper()) + + +def generate_rs_begin(events, group): + out('use std::cell::UnsafeCell;', + '', + 'extern "C" {') + # These are the Rust declarations of the .probes section semaphores + # generated by dtrace(1) in its .o file output. + for e in events: + if 'disable' in e.properties: + continue + out(' #[allow(dead_code)]', + f' static qemu_{e.name}_semaphore: UnsafeCell;') + out('}', + '') + + +def generate_rs(event, group): + args = event.args.rust_call_extern() + if args: + args = ', ' + args + + out(f' ::trace::probe!(qemu, {event.name}{args});') + + +def generate_rs_backend_dstate(event, group): + # Rust does not have access to the __ENABLED() macro from + # the dtrace(1) generated .h file. Use the matching semaphore declarations + # generated by generate_rs_begin() instead. + out(' (unsafe {qemu_%(n)s_semaphore.get().read_volatile()}) != 0 ||', + n=event.name) diff --git a/scripts/tracetool/format/rs.py b/scripts/tracetool/format/rs.py index 32ac4e5977..7d9af7edfe 100644 --- a/scripts/tracetool/format/rs.py +++ b/scripts/tracetool/format/rs.py @@ -24,25 +24,43 @@ def generate(events, backend, group): '#[allow(unused_imports)]', 'use util::bindings;', '', + '#[allow(dead_code)]', '#[inline(always)]', 'fn trace_event_state_is_enabled(dstate: u16) -> bool {', ' (unsafe { trace_events_enabled_count }) != 0 && dstate != 0', '}', '', 'extern "C" {', + ' #[allow(dead_code)]', ' static mut trace_events_enabled_count: u32;', '}',) out('extern "C" {') for e in events: - out(' static mut %s: u16;' % e.api(e.QEMU_DSTATE)) - out('}') + out(' #[allow(dead_code)]', + ' static mut %s: u16;' % e.api(e.QEMU_DSTATE)) + out('}', + '') backend.generate_begin(events, group) for e in events: - out('', + out('#[inline(always)]', + '#[allow(dead_code)]', + 'pub fn %(api)s() -> bool', + '{', + api=e.api(e.QEMU_RUST_DSTATE)) + + if "disable" not in e.properties: + backend.generate_backend_dstate(e, group) + if backend.check_trace_event_get_state: + out(' trace_event_state_is_enabled(unsafe { _%(event_id)s_DSTATE}) ||', + event_id = 'TRACE_' + e.name.upper()) + + out(' false', + '}', + '', '#[inline(always)]', '#[allow(dead_code)]', 'pub fn %(api)s(%(args)s)', @@ -59,6 +77,7 @@ def generate(events, backend, group): api=e.api()) backend.generate(e, group, check_trace_event_get_state=True) out(' }') - out('}') + out('}', + '') backend.generate_end(events, group) diff --git a/tests/tracetool/dtrace.rs b/tests/tracetool/dtrace.rs new file mode 100644 index 0000000000..3490fcb271 --- /dev/null +++ b/tests/tracetool/dtrace.rs @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// This file is @generated by tracetool, do not edit. + +#[allow(unused_imports)] +use std::ffi::c_char; +#[allow(unused_imports)] +use util::bindings; + +#[allow(dead_code)] +#[inline(always)] +fn trace_event_state_is_enabled(dstate: u16) -> bool { + (unsafe { trace_events_enabled_count }) != 0 && dstate != 0 +} + +extern "C" { + #[allow(dead_code)] + static mut trace_events_enabled_count: u32; +} +extern "C" { + #[allow(dead_code)] + static mut _TRACE_TEST_BLAH_DSTATE: u16; + #[allow(dead_code)] + static mut _TRACE_TEST_WIBBLE_DSTATE: u16; +} + +use std::cell::UnsafeCell; + +extern "C" { + #[allow(dead_code)] + static qemu_test_blah_semaphore: UnsafeCell; + #[allow(dead_code)] + static qemu_test_wibble_semaphore: UnsafeCell; +} + +#[inline(always)] +#[allow(dead_code)] +pub fn trace_test_blah_enabled() -> bool +{ + (unsafe {qemu_test_blah_semaphore.get().read_volatile()}) != 0 || + false +} + +#[inline(always)] +#[allow(dead_code)] +pub fn trace_test_blah(_context: *mut (), _filename: &std::ffi::CStr) +{ + ::trace::probe!(qemu, test_blah, _context, _filename.as_ptr()); +} + +#[inline(always)] +#[allow(dead_code)] +pub fn trace_test_wibble_enabled() -> bool +{ + (unsafe {qemu_test_wibble_semaphore.get().read_volatile()}) != 0 || + false +} + +#[inline(always)] +#[allow(dead_code)] +pub fn trace_test_wibble(_context: *mut (), _value: std::ffi::c_int) +{ + ::trace::probe!(qemu, test_wibble, _context, _value); +} + diff --git a/tests/tracetool/ftrace.rs b/tests/tracetool/ftrace.rs index 07b9259cf2..34f6600490 100644 --- a/tests/tracetool/ftrace.rs +++ b/tests/tracetool/ftrace.rs @@ -6,19 +6,31 @@ #[allow(unused_imports)] use util::bindings; +#[allow(dead_code)] #[inline(always)] fn trace_event_state_is_enabled(dstate: u16) -> bool { (unsafe { trace_events_enabled_count }) != 0 && dstate != 0 } extern "C" { + #[allow(dead_code)] static mut trace_events_enabled_count: u32; } extern "C" { + #[allow(dead_code)] static mut _TRACE_TEST_BLAH_DSTATE: u16; + #[allow(dead_code)] static mut _TRACE_TEST_WIBBLE_DSTATE: u16; } +#[inline(always)] +#[allow(dead_code)] +pub fn trace_test_blah_enabled() -> bool +{ + trace_event_state_is_enabled(unsafe { _TRACE_TEST_BLAH_DSTATE}) || + false +} + #[inline(always)] #[allow(dead_code)] pub fn trace_test_blah(_context: *mut (), _filename: &std::ffi::CStr) @@ -29,6 +41,14 @@ pub fn trace_test_blah(_context: *mut (), _filename: &std::ffi::CStr) } } +#[inline(always)] +#[allow(dead_code)] +pub fn trace_test_wibble_enabled() -> bool +{ + trace_event_state_is_enabled(unsafe { _TRACE_TEST_WIBBLE_DSTATE}) || + false +} + #[inline(always)] #[allow(dead_code)] pub fn trace_test_wibble(_context: *mut (), _value: std::ffi::c_int) @@ -38,3 +58,4 @@ pub fn trace_test_wibble(_context: *mut (), _value: std::ffi::c_int) unsafe {bindings::ftrace_write(format_string.as_ptr() as *const c_char, _context /* as *mut () */, _value /* as std::ffi::c_int */);} } } + diff --git a/tests/tracetool/log.rs b/tests/tracetool/log.rs index c191895c8f..770758611d 100644 --- a/tests/tracetool/log.rs +++ b/tests/tracetool/log.rs @@ -6,19 +6,31 @@ #[allow(unused_imports)] use util::bindings; +#[allow(dead_code)] #[inline(always)] fn trace_event_state_is_enabled(dstate: u16) -> bool { (unsafe { trace_events_enabled_count }) != 0 && dstate != 0 } extern "C" { + #[allow(dead_code)] static mut trace_events_enabled_count: u32; } extern "C" { + #[allow(dead_code)] static mut _TRACE_TEST_BLAH_DSTATE: u16; + #[allow(dead_code)] static mut _TRACE_TEST_WIBBLE_DSTATE: u16; } +#[inline(always)] +#[allow(dead_code)] +pub fn trace_test_blah_enabled() -> bool +{ + trace_event_state_is_enabled(unsafe { _TRACE_TEST_BLAH_DSTATE}) || + false +} + #[inline(always)] #[allow(dead_code)] pub fn trace_test_blah(_context: *mut (), _filename: &std::ffi::CStr) @@ -31,6 +43,14 @@ pub fn trace_test_blah(_context: *mut (), _filename: &std::ffi::CStr) } } +#[inline(always)] +#[allow(dead_code)] +pub fn trace_test_wibble_enabled() -> bool +{ + trace_event_state_is_enabled(unsafe { _TRACE_TEST_WIBBLE_DSTATE}) || + false +} + #[inline(always)] #[allow(dead_code)] pub fn trace_test_wibble(_context: *mut (), _value: std::ffi::c_int) @@ -42,3 +62,4 @@ pub fn trace_test_wibble(_context: *mut (), _value: std::ffi::c_int) } } } + diff --git a/tests/tracetool/simple.rs b/tests/tracetool/simple.rs index 9ee39495e3..92f896ef17 100644 --- a/tests/tracetool/simple.rs +++ b/tests/tracetool/simple.rs @@ -6,19 +6,31 @@ #[allow(unused_imports)] use util::bindings; +#[allow(dead_code)] #[inline(always)] fn trace_event_state_is_enabled(dstate: u16) -> bool { (unsafe { trace_events_enabled_count }) != 0 && dstate != 0 } extern "C" { + #[allow(dead_code)] static mut trace_events_enabled_count: u32; } extern "C" { + #[allow(dead_code)] static mut _TRACE_TEST_BLAH_DSTATE: u16; + #[allow(dead_code)] static mut _TRACE_TEST_WIBBLE_DSTATE: u16; } +#[inline(always)] +#[allow(dead_code)] +pub fn trace_test_blah_enabled() -> bool +{ + trace_event_state_is_enabled(unsafe { _TRACE_TEST_BLAH_DSTATE}) || + false +} + #[inline(always)] #[allow(dead_code)] pub fn trace_test_blah(_context: *mut (), _filename: &std::ffi::CStr) @@ -29,6 +41,14 @@ pub fn trace_test_blah(_context: *mut (), _filename: &std::ffi::CStr) } } +#[inline(always)] +#[allow(dead_code)] +pub fn trace_test_wibble_enabled() -> bool +{ + trace_event_state_is_enabled(unsafe { _TRACE_TEST_WIBBLE_DSTATE}) || + false +} + #[inline(always)] #[allow(dead_code)] pub fn trace_test_wibble(_context: *mut (), _value: std::ffi::c_int) @@ -38,3 +58,4 @@ pub fn trace_test_wibble(_context: *mut (), _value: std::ffi::c_int) unsafe { _simple_trace_test_wibble(_context, _value); } } } + diff --git a/tests/tracetool/syslog.rs b/tests/tracetool/syslog.rs index 9d3675a0b5..378d03d34b 100644 --- a/tests/tracetool/syslog.rs +++ b/tests/tracetool/syslog.rs @@ -6,19 +6,31 @@ #[allow(unused_imports)] use util::bindings; +#[allow(dead_code)] #[inline(always)] fn trace_event_state_is_enabled(dstate: u16) -> bool { (unsafe { trace_events_enabled_count }) != 0 && dstate != 0 } extern "C" { + #[allow(dead_code)] static mut trace_events_enabled_count: u32; } extern "C" { + #[allow(dead_code)] static mut _TRACE_TEST_BLAH_DSTATE: u16; + #[allow(dead_code)] static mut _TRACE_TEST_WIBBLE_DSTATE: u16; } +#[inline(always)] +#[allow(dead_code)] +pub fn trace_test_blah_enabled() -> bool +{ + trace_event_state_is_enabled(unsafe { _TRACE_TEST_BLAH_DSTATE}) || + false +} + #[inline(always)] #[allow(dead_code)] pub fn trace_test_blah(_context: *mut (), _filename: &std::ffi::CStr) @@ -29,6 +41,14 @@ pub fn trace_test_blah(_context: *mut (), _filename: &std::ffi::CStr) } } +#[inline(always)] +#[allow(dead_code)] +pub fn trace_test_wibble_enabled() -> bool +{ + trace_event_state_is_enabled(unsafe { _TRACE_TEST_WIBBLE_DSTATE}) || + false +} + #[inline(always)] #[allow(dead_code)] pub fn trace_test_wibble(_context: *mut (), _value: std::ffi::c_int) @@ -38,3 +58,4 @@ pub fn trace_test_wibble(_context: *mut (), _value: std::ffi::c_int) unsafe {::trace::syslog(::trace::LOG_INFO, format_string.as_ptr() as *const c_char, _context /* as *mut () */, _value /* as std::ffi::c_int */);} } } + diff --git a/tests/tracetool/tracetool-test.py b/tests/tracetool/tracetool-test.py index 786083ad7f..30006a9919 100755 --- a/tests/tracetool/tracetool-test.py +++ b/tests/tracetool/tracetool-test.py @@ -14,7 +14,7 @@ def get_formats(backend): "c", "h", ] - if backend in {"ftrace", "log", "simple", "syslog"}: + if backend in {"dtrace", "ftrace", "log", "simple", "syslog"}: formats += ["rs"] if backend == "dtrace": formats += [