mirror of
https://github.com/qemu/qemu.git
synced 2026-04-23 14:42:54 +00:00
Implement DTrace/SystemTap SDT by emitting the following: - The probe crate's probe!() macro is used to emit a DTrace/SystemTap SDT probe. - Every trace event gets a corresponding trace_<name>_enabled() -> bool generated function that Rust code can use to avoid expensive computation when a trace event is disabled. This API works for other trace backends too. `#[allow(dead_code)]` additions are necessary for QEMU's dstate in generated trace-<dir>.rs files since they are unused by the dtrace backend. `./configure --enable-trace-backends=` can enable multiple backends, so keep it simple and just silence the warning instead of trying to detect the condition when generating the dstate code can be skipped. The tracetool tests are updated. Take a look at tests/tracetool/dtrace.rs to see what the new generated code looks like. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Link: https://lore.kernel.org/r/20251119205200.173170-5-stefanha@redhat.com Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
104 lines
2.8 KiB
Python
104 lines
2.8 KiB
Python
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
"""
|
|
DTrace/SystemTAP backend.
|
|
"""
|
|
|
|
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
|
|
__copyright__ = "Copyright 2012-2017, Lluís Vilanova <vilanova@ac.upc.edu>"
|
|
__license__ = "GPL version 2 or (at your option) any later version"
|
|
|
|
__maintainer__ = "Stefan Hajnoczi"
|
|
__email__ = "stefanha@redhat.com"
|
|
|
|
|
|
from tracetool import out
|
|
|
|
|
|
PUBLIC = True
|
|
|
|
|
|
PROBEPREFIX = None
|
|
|
|
def probeprefix():
|
|
if PROBEPREFIX is None:
|
|
raise ValueError("you must set PROBEPREFIX")
|
|
return PROBEPREFIX
|
|
|
|
|
|
BINARY = None
|
|
|
|
def binary():
|
|
if BINARY is None:
|
|
raise ValueError("you must set BINARY")
|
|
return BINARY
|
|
|
|
|
|
def generate_h_begin(events, group):
|
|
if group == "root":
|
|
header = "trace-dtrace-root.h"
|
|
else:
|
|
header = "trace-dtrace-%s.h" % group
|
|
|
|
# Workaround for ust backend, which also includes <sys/sdt.h> and may
|
|
# require SDT_USE_VARIADIC to be defined. If dtrace includes <sys/sdt.h>
|
|
# first without defining SDT_USE_VARIADIC then ust breaks because the
|
|
# STAP_PROBEV() macro is not defined.
|
|
out('#ifndef SDT_USE_VARIADIC')
|
|
out('#define SDT_USE_VARIADIC 1')
|
|
out('#endif')
|
|
|
|
out('#include "%s"' % header,
|
|
'')
|
|
|
|
out('#undef SDT_USE_VARIADIC')
|
|
|
|
# SystemTap defines <provider>_<name>_ENABLED() but other DTrace
|
|
# implementations might not.
|
|
for e in events:
|
|
out('#ifndef QEMU_%(uppername)s_ENABLED',
|
|
'#define QEMU_%(uppername)s_ENABLED() true',
|
|
'#endif',
|
|
uppername=e.name.upper())
|
|
|
|
def generate_h(event, group):
|
|
out(' QEMU_%(uppername)s(%(argnames)s);',
|
|
uppername=event.name.upper(),
|
|
argnames=", ".join(event.args.names()))
|
|
|
|
|
|
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<u16>;')
|
|
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 <provider>_<name>_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)
|