mirror of https://github.com/xemu-project/xemu.git
-----BEGIN PGP SIGNATURE-----
iQEcBAABAgAGBQJX/feXAAoJEJykq7OBq3PIatAIAKoT0dQpc6L0kPM9QYX0soBR sQ75/EyPyHK+7ly6huS0Zp78RHd98CVePdH/hn+Ha3in87ScBV/NXxgKJ/aUP8Mm 04aMkXgn0tydBndtSTom2sBHOyAl5RUCRH8JBhGQ5p+dbzfeeSU9or4UZdEiChp2 DyvmF7gjjGl8jsDl1G9KsxqOYzwgpxSVZzvzzjjK7ZlJ0fW0gkYInDIzyna/YGJP Ea7Dc0lLN4wM7rHUk1CgTD8KzSACsmmVy4OfTUo+ij6RugtrCcsiouHqWZ3nYzbN FHux0hXl02wnUuaZmSChgHxLDVG8pcNcWVt4wuh7wHXo8aNih8UeQLQnkdDnx9o= =bcLW -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stefanha/tags/tracing-pull-request' into staging # gpg: Signature made Wed 12 Oct 2016 09:43:03 BST # gpg: using RSA key 0x9CA4ABB381AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" # Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35 775A 9CA4 ABB3 81AB 73C8 * remotes/stefanha/tags/tracing-pull-request: trace: Add missing execution mode of guest events trace: introduce a formal group name for trace events trace: pass trace-events to tracetool as a positional param trace: push reading of events up a level to tracetool main trace: rename _read_events to read_events trace: get rid of generated-events.h/generated-events.c trace: dynamically allocate event IDs at runtime trace: dynamically allocate trace_dstate in CPUState trace: provide mechanism for registering trace events trace: don't abort qemu if ftrace can't be initialized trace: emit name <-> ID mapping in simpletrace header trace: remove the TraceEventID and TraceEventVCPUID enums trace: give each trace event a named TraceEvent struct trace: break circular dependency in event-internal.h trace: remove duplicate control.h includes in generated-tracers.h trace: remove global 'uint16 dstate[]' array trace: remove some now unused functions trace: convert code to use event iterators trace: add trace event iterator APIs trace: move colo trace events to net/ sub-directory Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
ae4b28ace9
3
Makefile
3
Makefile
|
@ -56,9 +56,6 @@ GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
|
||||||
GENERATED_HEADERS += qmp-introspect.h
|
GENERATED_HEADERS += qmp-introspect.h
|
||||||
GENERATED_SOURCES += qmp-introspect.c
|
GENERATED_SOURCES += qmp-introspect.c
|
||||||
|
|
||||||
GENERATED_HEADERS += trace/generated-events.h
|
|
||||||
GENERATED_SOURCES += trace/generated-events.c
|
|
||||||
|
|
||||||
GENERATED_HEADERS += trace/generated-tracers.h
|
GENERATED_HEADERS += trace/generated-tracers.h
|
||||||
ifeq ($(findstring dtrace,$(TRACE_BACKENDS)),dtrace)
|
ifeq ($(findstring dtrace,$(TRACE_BACKENDS)),dtrace)
|
||||||
GENERATED_HEADERS += trace/generated-tracers-dtrace.h
|
GENERATED_HEADERS += trace/generated-tracers-dtrace.h
|
||||||
|
|
|
@ -55,7 +55,7 @@ $(QEMU_PROG).stp-installed: $(BUILD_DIR)/trace-events-all
|
||||||
--binary=$(bindir)/$(QEMU_PROG) \
|
--binary=$(bindir)/$(QEMU_PROG) \
|
||||||
--target-name=$(TARGET_NAME) \
|
--target-name=$(TARGET_NAME) \
|
||||||
--target-type=$(TARGET_TYPE) \
|
--target-type=$(TARGET_TYPE) \
|
||||||
< $< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG).stp-installed")
|
$< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG).stp-installed")
|
||||||
|
|
||||||
$(QEMU_PROG).stp: $(BUILD_DIR)/trace-events-all
|
$(QEMU_PROG).stp: $(BUILD_DIR)/trace-events-all
|
||||||
$(call quiet-command,$(TRACETOOL) \
|
$(call quiet-command,$(TRACETOOL) \
|
||||||
|
@ -64,14 +64,14 @@ $(QEMU_PROG).stp: $(BUILD_DIR)/trace-events-all
|
||||||
--binary=$(realpath .)/$(QEMU_PROG) \
|
--binary=$(realpath .)/$(QEMU_PROG) \
|
||||||
--target-name=$(TARGET_NAME) \
|
--target-name=$(TARGET_NAME) \
|
||||||
--target-type=$(TARGET_TYPE) \
|
--target-type=$(TARGET_TYPE) \
|
||||||
< $< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG).stp")
|
$< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG).stp")
|
||||||
|
|
||||||
$(QEMU_PROG)-simpletrace.stp: $(BUILD_DIR)/trace-events-all
|
$(QEMU_PROG)-simpletrace.stp: $(BUILD_DIR)/trace-events-all
|
||||||
$(call quiet-command,$(TRACETOOL) \
|
$(call quiet-command,$(TRACETOOL) \
|
||||||
--format=simpletrace-stap \
|
--format=simpletrace-stap \
|
||||||
--backends=$(TRACE_BACKENDS) \
|
--backends=$(TRACE_BACKENDS) \
|
||||||
--probe-prefix=qemu.$(TARGET_TYPE).$(TARGET_NAME) \
|
--probe-prefix=qemu.$(TARGET_TYPE).$(TARGET_NAME) \
|
||||||
< $< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG)-simpletrace.stp")
|
$< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG)-simpletrace.stp")
|
||||||
|
|
||||||
else
|
else
|
||||||
stap:
|
stap:
|
||||||
|
|
|
@ -740,6 +740,7 @@ int main(int argc, char **argv)
|
||||||
if (argc <= 1)
|
if (argc <= 1)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
|
module_call_init(MODULE_INIT_TRACE);
|
||||||
qemu_init_cpu_list();
|
qemu_init_cpu_list();
|
||||||
module_call_init(MODULE_INIT_QOM);
|
module_call_init(MODULE_INIT_QOM);
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ typedef enum {
|
||||||
MODULE_INIT_OPTS,
|
MODULE_INIT_OPTS,
|
||||||
MODULE_INIT_QAPI,
|
MODULE_INIT_QAPI,
|
||||||
MODULE_INIT_QOM,
|
MODULE_INIT_QOM,
|
||||||
|
MODULE_INIT_TRACE,
|
||||||
MODULE_INIT_MAX
|
MODULE_INIT_MAX
|
||||||
} module_init_type;
|
} module_init_type;
|
||||||
|
|
||||||
|
@ -51,6 +52,7 @@ typedef enum {
|
||||||
#define opts_init(function) module_init(function, MODULE_INIT_OPTS)
|
#define opts_init(function) module_init(function, MODULE_INIT_OPTS)
|
||||||
#define qapi_init(function) module_init(function, MODULE_INIT_QAPI)
|
#define qapi_init(function) module_init(function, MODULE_INIT_QAPI)
|
||||||
#define type_init(function) module_init(function, MODULE_INIT_QOM)
|
#define type_init(function) module_init(function, MODULE_INIT_QOM)
|
||||||
|
#define trace_init(function) module_init(function, MODULE_INIT_TRACE)
|
||||||
|
|
||||||
#define block_module_load_one(lib) module_load_one("block-", lib)
|
#define block_module_load_one(lib) module_load_one("block-", lib)
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include "qemu/bitmap.h"
|
#include "qemu/bitmap.h"
|
||||||
#include "qemu/queue.h"
|
#include "qemu/queue.h"
|
||||||
#include "qemu/thread.h"
|
#include "qemu/thread.h"
|
||||||
#include "trace/generated-events.h"
|
|
||||||
|
|
||||||
typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
|
typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
|
@ -345,8 +344,12 @@ struct CPUState {
|
||||||
struct KVMState *kvm_state;
|
struct KVMState *kvm_state;
|
||||||
struct kvm_run *kvm_run;
|
struct kvm_run *kvm_run;
|
||||||
|
|
||||||
/* Used for events with 'vcpu' and *without* the 'disabled' properties */
|
/*
|
||||||
DECLARE_BITMAP(trace_dstate, TRACE_VCPU_EVENT_COUNT);
|
* Used for events with 'vcpu' and *without* the 'disabled' properties.
|
||||||
|
* Dynamically allocated based on bitmap requried to hold up to
|
||||||
|
* trace_get_vcpu_event_count() entries.
|
||||||
|
*/
|
||||||
|
unsigned long *trace_dstate;
|
||||||
|
|
||||||
/* TODO Move common fields from CPUArchState here. */
|
/* TODO Move common fields from CPUArchState here. */
|
||||||
int cpu_index; /* used by alpha TCG */
|
int cpu_index; /* used by alpha TCG */
|
||||||
|
|
|
@ -2,6 +2,5 @@
|
||||||
#define TRACE_TCG_H
|
#define TRACE_TCG_H
|
||||||
|
|
||||||
#include "trace/generated-tcg-tracers.h"
|
#include "trace/generated-tcg-tracers.h"
|
||||||
#include "trace/generated-events.h"
|
|
||||||
|
|
||||||
#endif /* TRACE_TCG_H */
|
#endif /* TRACE_TCG_H */
|
||||||
|
|
|
@ -2,6 +2,5 @@
|
||||||
#define TRACE_H
|
#define TRACE_H
|
||||||
|
|
||||||
#include "trace/generated-tracers.h"
|
#include "trace/generated-tracers.h"
|
||||||
#include "trace/generated-events.h"
|
|
||||||
|
|
||||||
#endif /* TRACE_H */
|
#endif /* TRACE_H */
|
||||||
|
|
|
@ -4158,6 +4158,7 @@ int main(int argc, char **argv, char **envp)
|
||||||
int ret;
|
int ret;
|
||||||
int execfd;
|
int execfd;
|
||||||
|
|
||||||
|
module_call_init(MODULE_INIT_TRACE);
|
||||||
qemu_init_cpu_list();
|
qemu_init_cpu_list();
|
||||||
module_call_init(MODULE_INIT_QOM);
|
module_call_init(MODULE_INIT_QOM);
|
||||||
|
|
||||||
|
|
26
monitor.c
26
monitor.c
|
@ -3330,13 +3330,14 @@ void info_trace_events_completion(ReadLineState *rs, int nb_args, const char *st
|
||||||
len = strlen(str);
|
len = strlen(str);
|
||||||
readline_set_completion_index(rs, len);
|
readline_set_completion_index(rs, len);
|
||||||
if (nb_args == 2) {
|
if (nb_args == 2) {
|
||||||
TraceEventID id;
|
TraceEventIter iter;
|
||||||
for (id = 0; id < trace_event_count(); id++) {
|
TraceEvent *ev;
|
||||||
const char *event_name = trace_event_get_name(trace_event_id(id));
|
char *pattern = g_strdup_printf("%s*", str);
|
||||||
if (!strncmp(str, event_name, len)) {
|
trace_event_iter_init(&iter, pattern);
|
||||||
readline_add_completion(rs, event_name);
|
while ((ev = trace_event_iter_next(&iter)) != NULL) {
|
||||||
}
|
readline_add_completion(rs, trace_event_get_name(ev));
|
||||||
}
|
}
|
||||||
|
g_free(pattern);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3347,13 +3348,14 @@ void trace_event_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||||
len = strlen(str);
|
len = strlen(str);
|
||||||
readline_set_completion_index(rs, len);
|
readline_set_completion_index(rs, len);
|
||||||
if (nb_args == 2) {
|
if (nb_args == 2) {
|
||||||
TraceEventID id;
|
TraceEventIter iter;
|
||||||
for (id = 0; id < trace_event_count(); id++) {
|
TraceEvent *ev;
|
||||||
const char *event_name = trace_event_get_name(trace_event_id(id));
|
char *pattern = g_strdup_printf("%s*", str);
|
||||||
if (!strncmp(str, event_name, len)) {
|
trace_event_iter_init(&iter, pattern);
|
||||||
readline_add_completion(rs, event_name);
|
while ((ev = trace_event_iter_next(&iter)) != NULL) {
|
||||||
}
|
readline_add_completion(rs, trace_event_get_name(ev));
|
||||||
}
|
}
|
||||||
|
g_free(pattern);
|
||||||
} else if (nb_args == 3) {
|
} else if (nb_args == 3) {
|
||||||
add_completion_option(rs, str, "on");
|
add_completion_option(rs, str, "on");
|
||||||
add_completion_option(rs, str, "off");
|
add_completion_option(rs, str, "off");
|
||||||
|
|
|
@ -2,3 +2,19 @@
|
||||||
|
|
||||||
# net/vhost-user.c
|
# net/vhost-user.c
|
||||||
vhost_user_event(const char *chr, int event) "chr: %s got event: %d"
|
vhost_user_event(const char *chr, int event) "chr: %s got event: %d"
|
||||||
|
|
||||||
|
# net/colo.c
|
||||||
|
colo_proxy_main(const char *chr) ": %s"
|
||||||
|
|
||||||
|
# net/colo-compare.c
|
||||||
|
colo_compare_main(const char *chr) ": %s"
|
||||||
|
colo_compare_udp_miscompare(const char *sta, int size) ": %s = %d"
|
||||||
|
colo_compare_icmp_miscompare(const char *sta, int size) ": %s = %d"
|
||||||
|
colo_compare_ip_info(int psize, const char *sta, const char *stb, int ssize, const char *stc, const char *std) "ppkt size = %d, ip_src = %s, ip_dst = %s, spkt size = %d, ip_src = %s, ip_dst = %s"
|
||||||
|
colo_old_packet_check_found(int64_t old_time) "%" PRId64
|
||||||
|
colo_compare_miscompare(void) ""
|
||||||
|
|
||||||
|
# net/filter-rewriter.c
|
||||||
|
colo_filter_rewriter_debug(void) ""
|
||||||
|
colo_filter_rewriter_pkt_info(const char *func, const char *src, const char *dst, uint32_t seq, uint32_t ack, uint32_t flag) "%s: src/dst: %s/%s p: seq/ack=%u/%u flags=%x\n"
|
||||||
|
colo_filter_rewriter_conn_offset(uint32_t offset) ": offset=%u\n"
|
||||||
|
|
|
@ -4165,6 +4165,7 @@ int main(int argc, char **argv)
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
module_call_init(MODULE_INIT_TRACE);
|
||||||
error_set_progname(argv[0]);
|
error_set_progname(argv[0]);
|
||||||
qemu_init_exec_dir(argv[0]);
|
qemu_init_exec_dir(argv[0]);
|
||||||
|
|
||||||
|
|
|
@ -467,6 +467,7 @@ int main(int argc, char **argv)
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
module_call_init(MODULE_INIT_TRACE);
|
||||||
progname = basename(argv[0]);
|
progname = basename(argv[0]);
|
||||||
qemu_init_exec_dir(argv[0]);
|
qemu_init_exec_dir(argv[0]);
|
||||||
|
|
||||||
|
|
|
@ -533,6 +533,7 @@ int main(int argc, char **argv)
|
||||||
sa_sigterm.sa_handler = termsig_handler;
|
sa_sigterm.sa_handler = termsig_handler;
|
||||||
sigaction(SIGTERM, &sa_sigterm, NULL);
|
sigaction(SIGTERM, &sa_sigterm, NULL);
|
||||||
|
|
||||||
|
module_call_init(MODULE_INIT_TRACE);
|
||||||
qcrypto_init(&error_fatal);
|
qcrypto_init(&error_fatal);
|
||||||
|
|
||||||
module_call_init(MODULE_INIT_QOM);
|
module_call_init(MODULE_INIT_QOM);
|
||||||
|
|
|
@ -360,12 +360,15 @@ static void cpu_common_initfn(Object *obj)
|
||||||
qemu_mutex_init(&cpu->work_mutex);
|
qemu_mutex_init(&cpu->work_mutex);
|
||||||
QTAILQ_INIT(&cpu->breakpoints);
|
QTAILQ_INIT(&cpu->breakpoints);
|
||||||
QTAILQ_INIT(&cpu->watchpoints);
|
QTAILQ_INIT(&cpu->watchpoints);
|
||||||
bitmap_zero(cpu->trace_dstate, TRACE_VCPU_EVENT_COUNT);
|
|
||||||
|
cpu->trace_dstate = bitmap_new(trace_get_vcpu_event_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpu_common_finalize(Object *obj)
|
static void cpu_common_finalize(Object *obj)
|
||||||
{
|
{
|
||||||
cpu_exec_exit(CPU(obj));
|
CPUState *cpu = CPU(obj);
|
||||||
|
cpu_exec_exit(cpu);
|
||||||
|
g_free(cpu->trace_dstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t cpu_common_get_arch_id(CPUState *cpu)
|
static int64_t cpu_common_get_arch_id(CPUState *cpu)
|
||||||
|
|
|
@ -12,13 +12,16 @@
|
||||||
import struct
|
import struct
|
||||||
import re
|
import re
|
||||||
import inspect
|
import inspect
|
||||||
from tracetool import _read_events, Event
|
from tracetool import read_events, Event
|
||||||
from tracetool.backend.simple import is_string
|
from tracetool.backend.simple import is_string
|
||||||
|
|
||||||
header_event_id = 0xffffffffffffffff
|
header_event_id = 0xffffffffffffffff
|
||||||
header_magic = 0xf2b177cb0aa429b4
|
header_magic = 0xf2b177cb0aa429b4
|
||||||
dropped_event_id = 0xfffffffffffffffe
|
dropped_event_id = 0xfffffffffffffffe
|
||||||
|
|
||||||
|
record_type_mapping = 0
|
||||||
|
record_type_event = 1
|
||||||
|
|
||||||
log_header_fmt = '=QQQ'
|
log_header_fmt = '=QQQ'
|
||||||
rec_header_fmt = '=QQII'
|
rec_header_fmt = '=QQII'
|
||||||
|
|
||||||
|
@ -30,14 +33,16 @@ def read_header(fobj, hfmt):
|
||||||
return None
|
return None
|
||||||
return struct.unpack(hfmt, hdr)
|
return struct.unpack(hfmt, hdr)
|
||||||
|
|
||||||
def get_record(edict, rechdr, fobj):
|
def get_record(edict, idtoname, rechdr, fobj):
|
||||||
"""Deserialize a trace record from a file into a tuple (event_num, timestamp, pid, arg1, ..., arg6)."""
|
"""Deserialize a trace record from a file into a tuple
|
||||||
|
(name, timestamp, pid, arg1, ..., arg6)."""
|
||||||
if rechdr is None:
|
if rechdr is None:
|
||||||
return None
|
return None
|
||||||
rec = (rechdr[0], rechdr[1], rechdr[3])
|
|
||||||
if rechdr[0] != dropped_event_id:
|
if rechdr[0] != dropped_event_id:
|
||||||
event_id = rechdr[0]
|
event_id = rechdr[0]
|
||||||
event = edict[event_id]
|
name = idtoname[event_id]
|
||||||
|
rec = (name, rechdr[1], rechdr[3])
|
||||||
|
event = edict[name]
|
||||||
for type, name in event.args:
|
for type, name in event.args:
|
||||||
if is_string(type):
|
if is_string(type):
|
||||||
l = fobj.read(4)
|
l = fobj.read(4)
|
||||||
|
@ -48,15 +53,22 @@ def get_record(edict, rechdr, fobj):
|
||||||
(value,) = struct.unpack('=Q', fobj.read(8))
|
(value,) = struct.unpack('=Q', fobj.read(8))
|
||||||
rec = rec + (value,)
|
rec = rec + (value,)
|
||||||
else:
|
else:
|
||||||
|
rec = ("dropped", rechdr[1], rechdr[3])
|
||||||
(value,) = struct.unpack('=Q', fobj.read(8))
|
(value,) = struct.unpack('=Q', fobj.read(8))
|
||||||
rec = rec + (value,)
|
rec = rec + (value,)
|
||||||
return rec
|
return rec
|
||||||
|
|
||||||
|
def get_mapping(fobj):
|
||||||
|
(event_id, ) = struct.unpack('=Q', fobj.read(8))
|
||||||
|
(len, ) = struct.unpack('=L', fobj.read(4))
|
||||||
|
name = fobj.read(len)
|
||||||
|
|
||||||
def read_record(edict, fobj):
|
return (event_id, name)
|
||||||
|
|
||||||
|
def read_record(edict, idtoname, fobj):
|
||||||
"""Deserialize a trace record from a file into a tuple (event_num, timestamp, pid, arg1, ..., arg6)."""
|
"""Deserialize a trace record from a file into a tuple (event_num, timestamp, pid, arg1, ..., arg6)."""
|
||||||
rechdr = read_header(fobj, rec_header_fmt)
|
rechdr = read_header(fobj, rec_header_fmt)
|
||||||
return get_record(edict, rechdr, fobj) # return tuple of record elements
|
return get_record(edict, idtoname, rechdr, fobj)
|
||||||
|
|
||||||
def read_trace_header(fobj):
|
def read_trace_header(fobj):
|
||||||
"""Read and verify trace file header"""
|
"""Read and verify trace file header"""
|
||||||
|
@ -67,19 +79,29 @@ def read_trace_header(fobj):
|
||||||
raise ValueError('Not a valid trace file!')
|
raise ValueError('Not a valid trace file!')
|
||||||
|
|
||||||
log_version = header[2]
|
log_version = header[2]
|
||||||
if log_version not in [0, 2, 3]:
|
if log_version not in [0, 2, 3, 4]:
|
||||||
raise ValueError('Unknown version of tracelog format!')
|
raise ValueError('Unknown version of tracelog format!')
|
||||||
if log_version != 3:
|
if log_version != 4:
|
||||||
raise ValueError('Log format %d not supported with this QEMU release!'
|
raise ValueError('Log format %d not supported with this QEMU release!'
|
||||||
% log_version)
|
% log_version)
|
||||||
|
|
||||||
def read_trace_records(edict, fobj):
|
def read_trace_records(edict, fobj):
|
||||||
"""Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6)."""
|
"""Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6)."""
|
||||||
|
idtoname = {
|
||||||
|
dropped_event_id: "dropped"
|
||||||
|
}
|
||||||
while True:
|
while True:
|
||||||
rec = read_record(edict, fobj)
|
t = fobj.read(8)
|
||||||
if rec is None:
|
if len(t) == 0:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
(rectype, ) = struct.unpack('=Q', t)
|
||||||
|
if rectype == record_type_mapping:
|
||||||
|
event_id, name = get_mapping(fobj)
|
||||||
|
idtoname[event_id] = name
|
||||||
|
else:
|
||||||
|
rec = read_record(edict, idtoname, fobj)
|
||||||
|
|
||||||
yield rec
|
yield rec
|
||||||
|
|
||||||
class Analyzer(object):
|
class Analyzer(object):
|
||||||
|
@ -107,7 +129,7 @@ class Analyzer(object):
|
||||||
def process(events, log, analyzer, read_header=True):
|
def process(events, log, analyzer, read_header=True):
|
||||||
"""Invoke an analyzer on each event in a log."""
|
"""Invoke an analyzer on each event in a log."""
|
||||||
if isinstance(events, str):
|
if isinstance(events, str):
|
||||||
events = _read_events(open(events, 'r'))
|
events = read_events(open(events, 'r'))
|
||||||
if isinstance(log, str):
|
if isinstance(log, str):
|
||||||
log = open(log, 'rb')
|
log = open(log, 'rb')
|
||||||
|
|
||||||
|
@ -115,10 +137,10 @@ def process(events, log, analyzer, read_header=True):
|
||||||
read_trace_header(log)
|
read_trace_header(log)
|
||||||
|
|
||||||
dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)")
|
dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)")
|
||||||
edict = {dropped_event_id: dropped_event}
|
edict = {"dropped": dropped_event}
|
||||||
|
|
||||||
for num, event in enumerate(events):
|
for event in events:
|
||||||
edict[num] = event
|
edict[event.name] = event
|
||||||
|
|
||||||
def build_fn(analyzer, event):
|
def build_fn(analyzer, event):
|
||||||
if isinstance(event, str):
|
if isinstance(event, str):
|
||||||
|
@ -166,7 +188,7 @@ def run(analyzer):
|
||||||
'<trace-file>\n' % sys.argv[0])
|
'<trace-file>\n' % sys.argv[0])
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
events = _read_events(open(sys.argv[1], 'r'))
|
events = read_events(open(sys.argv[1], 'r'))
|
||||||
process(events, sys.argv[2], analyzer, read_header=read_header)
|
process(events, sys.argv[2], analyzer, read_header=read_header)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -15,6 +15,8 @@ __email__ = "stefanha@linux.vnet.ibm.com"
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import getopt
|
import getopt
|
||||||
|
import os.path
|
||||||
|
import re
|
||||||
|
|
||||||
from tracetool import error_write, out
|
from tracetool import error_write, out
|
||||||
import tracetool.backend
|
import tracetool.backend
|
||||||
|
@ -60,6 +62,15 @@ Options:
|
||||||
else:
|
else:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
def make_group_name(filename):
|
||||||
|
dirname = os.path.realpath(os.path.dirname(filename))
|
||||||
|
basedir = os.path.join(os.path.dirname(__file__), os.pardir)
|
||||||
|
basedir = os.path.realpath(os.path.abspath(basedir))
|
||||||
|
dirname = dirname[len(basedir) + 1:]
|
||||||
|
|
||||||
|
if dirname == "":
|
||||||
|
return "common"
|
||||||
|
return re.sub(r"/|-", "_", dirname)
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
global _SCRIPT
|
global _SCRIPT
|
||||||
|
@ -129,8 +140,15 @@ def main(args):
|
||||||
if probe_prefix is None:
|
if probe_prefix is None:
|
||||||
probe_prefix = ".".join(["qemu", target_type, target_name])
|
probe_prefix = ".".join(["qemu", target_type, target_name])
|
||||||
|
|
||||||
|
if len(args) != 1:
|
||||||
|
error_opt("missing trace-events filepath")
|
||||||
|
with open(args[0], "r") as fh:
|
||||||
|
events = tracetool.read_events(fh)
|
||||||
|
|
||||||
|
group = make_group_name(args[0])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tracetool.generate(sys.stdin, arg_format, arg_backends,
|
tracetool.generate(events, group, arg_format, arg_backends,
|
||||||
binary=binary, probe_prefix=probe_prefix)
|
binary=binary, probe_prefix=probe_prefix)
|
||||||
except tracetool.TracetoolError as e:
|
except tracetool.TracetoolError as e:
|
||||||
error_opt(str(e))
|
error_opt(str(e))
|
||||||
|
|
|
@ -265,11 +265,13 @@ class Event(object):
|
||||||
|
|
||||||
QEMU_TRACE = "trace_%(name)s"
|
QEMU_TRACE = "trace_%(name)s"
|
||||||
QEMU_TRACE_TCG = QEMU_TRACE + "_tcg"
|
QEMU_TRACE_TCG = QEMU_TRACE + "_tcg"
|
||||||
|
QEMU_DSTATE = "_TRACE_%(NAME)s_DSTATE"
|
||||||
|
QEMU_EVENT = "_TRACE_%(NAME)s_EVENT"
|
||||||
|
|
||||||
def api(self, fmt=None):
|
def api(self, fmt=None):
|
||||||
if fmt is None:
|
if fmt is None:
|
||||||
fmt = Event.QEMU_TRACE
|
fmt = Event.QEMU_TRACE
|
||||||
return fmt % {"name": self.name}
|
return fmt % {"name": self.name, "NAME": self.name.upper()}
|
||||||
|
|
||||||
def transform(self, *trans):
|
def transform(self, *trans):
|
||||||
"""Return a new Event with transformed Arguments."""
|
"""Return a new Event with transformed Arguments."""
|
||||||
|
@ -280,7 +282,17 @@ class Event(object):
|
||||||
self)
|
self)
|
||||||
|
|
||||||
|
|
||||||
def _read_events(fobj):
|
def read_events(fobj):
|
||||||
|
"""Generate the output for the given (format, backends) pair.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
fobj : file
|
||||||
|
Event description file.
|
||||||
|
|
||||||
|
Returns a list of Event objects
|
||||||
|
"""
|
||||||
|
|
||||||
events = []
|
events = []
|
||||||
for line in fobj:
|
for line in fobj:
|
||||||
if not line.strip():
|
if not line.strip():
|
||||||
|
@ -352,14 +364,16 @@ def try_import(mod_name, attr_name=None, attr_default=None):
|
||||||
return False, None
|
return False, None
|
||||||
|
|
||||||
|
|
||||||
def generate(fevents, format, backends,
|
def generate(events, group, format, backends,
|
||||||
binary=None, probe_prefix=None):
|
binary=None, probe_prefix=None):
|
||||||
"""Generate the output for the given (format, backends) pair.
|
"""Generate the output for the given (format, backends) pair.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
fevents : file
|
events : list
|
||||||
Event description file.
|
list of Event objects to generate for
|
||||||
|
group: str
|
||||||
|
Name of the tracing group
|
||||||
format : str
|
format : str
|
||||||
Output format name.
|
Output format name.
|
||||||
backends : list
|
backends : list
|
||||||
|
@ -389,6 +403,4 @@ def generate(fevents, format, backends,
|
||||||
tracetool.backend.dtrace.BINARY = binary
|
tracetool.backend.dtrace.BINARY = binary
|
||||||
tracetool.backend.dtrace.PROBEPREFIX = probe_prefix
|
tracetool.backend.dtrace.PROBEPREFIX = probe_prefix
|
||||||
|
|
||||||
events = _read_events(fevents)
|
tracetool.format.generate(events, format, backend, group)
|
||||||
|
|
||||||
tracetool.format.generate(events, format, backend)
|
|
||||||
|
|
|
@ -113,11 +113,11 @@ class Wrapper:
|
||||||
if func is not None:
|
if func is not None:
|
||||||
func(*args, **kwargs)
|
func(*args, **kwargs)
|
||||||
|
|
||||||
def generate_begin(self, events):
|
def generate_begin(self, events, group):
|
||||||
self._run_function("generate_%s_begin", events)
|
self._run_function("generate_%s_begin", events, group)
|
||||||
|
|
||||||
def generate(self, event):
|
def generate(self, event, group):
|
||||||
self._run_function("generate_%s", event)
|
self._run_function("generate_%s", event, group)
|
||||||
|
|
||||||
def generate_end(self, events):
|
def generate_end(self, events, group):
|
||||||
self._run_function("generate_%s_end", events)
|
self._run_function("generate_%s_end", events, group)
|
||||||
|
|
|
@ -35,12 +35,12 @@ def binary():
|
||||||
return BINARY
|
return BINARY
|
||||||
|
|
||||||
|
|
||||||
def generate_h_begin(events):
|
def generate_h_begin(events, group):
|
||||||
out('#include "trace/generated-tracers-dtrace.h"',
|
out('#include "trace/generated-tracers-dtrace.h"',
|
||||||
'')
|
'')
|
||||||
|
|
||||||
|
|
||||||
def generate_h(event):
|
def generate_h(event, group):
|
||||||
out(' QEMU_%(uppername)s(%(argnames)s);',
|
out(' QEMU_%(uppername)s(%(argnames)s);',
|
||||||
uppername=event.name.upper(),
|
uppername=event.name.upper(),
|
||||||
argnames=", ".join(event.args.names()))
|
argnames=", ".join(event.args.names()))
|
||||||
|
|
|
@ -19,13 +19,12 @@ from tracetool import out
|
||||||
PUBLIC = True
|
PUBLIC = True
|
||||||
|
|
||||||
|
|
||||||
def generate_h_begin(events):
|
def generate_h_begin(events, group):
|
||||||
out('#include "trace/ftrace.h"',
|
out('#include "trace/ftrace.h"',
|
||||||
'#include "trace/control.h"',
|
|
||||||
'')
|
'')
|
||||||
|
|
||||||
|
|
||||||
def generate_h(event):
|
def generate_h(event, group):
|
||||||
argnames = ", ".join(event.args.names())
|
argnames = ", ".join(event.args.names())
|
||||||
if len(event.args) > 0:
|
if len(event.args) > 0:
|
||||||
argnames = ", " + argnames
|
argnames = ", " + argnames
|
||||||
|
|
|
@ -19,13 +19,12 @@ from tracetool import out
|
||||||
PUBLIC = True
|
PUBLIC = True
|
||||||
|
|
||||||
|
|
||||||
def generate_h_begin(events):
|
def generate_h_begin(events, group):
|
||||||
out('#include "trace/control.h"',
|
out('#include "qemu/log.h"',
|
||||||
'#include "qemu/log.h"',
|
|
||||||
'')
|
'')
|
||||||
|
|
||||||
|
|
||||||
def generate_h(event):
|
def generate_h(event, group):
|
||||||
argnames = ", ".join(event.args.names())
|
argnames = ", ".join(event.args.names())
|
||||||
if len(event.args) > 0:
|
if len(event.args) > 0:
|
||||||
argnames = ", " + argnames
|
argnames = ", " + argnames
|
||||||
|
|
|
@ -27,7 +27,7 @@ def is_string(arg):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def generate_h_begin(events):
|
def generate_h_begin(events, group):
|
||||||
for event in events:
|
for event in events:
|
||||||
out('void _simple_%(api)s(%(args)s);',
|
out('void _simple_%(api)s(%(args)s);',
|
||||||
api=event.api(),
|
api=event.api(),
|
||||||
|
@ -35,13 +35,13 @@ def generate_h_begin(events):
|
||||||
out('')
|
out('')
|
||||||
|
|
||||||
|
|
||||||
def generate_h(event):
|
def generate_h(event, group):
|
||||||
out(' _simple_%(api)s(%(args)s);',
|
out(' _simple_%(api)s(%(args)s);',
|
||||||
api=event.api(),
|
api=event.api(),
|
||||||
args=", ".join(event.args.names()))
|
args=", ".join(event.args.names()))
|
||||||
|
|
||||||
|
|
||||||
def generate_c_begin(events):
|
def generate_c_begin(events, group):
|
||||||
out('#include "qemu/osdep.h"',
|
out('#include "qemu/osdep.h"',
|
||||||
'#include "trace.h"',
|
'#include "trace.h"',
|
||||||
'#include "trace/control.h"',
|
'#include "trace/control.h"',
|
||||||
|
@ -49,7 +49,7 @@ def generate_c_begin(events):
|
||||||
'')
|
'')
|
||||||
|
|
||||||
|
|
||||||
def generate_c(event):
|
def generate_c(event, group):
|
||||||
out('void _simple_%(api)s(%(args)s)',
|
out('void _simple_%(api)s(%(args)s)',
|
||||||
'{',
|
'{',
|
||||||
' TraceBufferRecord rec;',
|
' TraceBufferRecord rec;',
|
||||||
|
@ -80,11 +80,11 @@ def generate_c(event):
|
||||||
' return;',
|
' return;',
|
||||||
' }',
|
' }',
|
||||||
'',
|
'',
|
||||||
' if (trace_record_start(&rec, %(event_id)s, %(size_str)s)) {',
|
' if (trace_record_start(&rec, %(event_obj)s.id, %(size_str)s)) {',
|
||||||
' return; /* Trace Buffer Full, Event Dropped ! */',
|
' return; /* Trace Buffer Full, Event Dropped ! */',
|
||||||
' }',
|
' }',
|
||||||
cond=cond,
|
cond=cond,
|
||||||
event_id=event_id,
|
event_obj=event.api(event.QEMU_EVENT),
|
||||||
size_str=sizestr)
|
size_str=sizestr)
|
||||||
|
|
||||||
if len(event.args) > 0:
|
if len(event.args) > 0:
|
||||||
|
|
|
@ -19,13 +19,12 @@ from tracetool import out
|
||||||
PUBLIC = True
|
PUBLIC = True
|
||||||
|
|
||||||
|
|
||||||
def generate_h_begin(events):
|
def generate_h_begin(events, group):
|
||||||
out('#include <syslog.h>',
|
out('#include <syslog.h>',
|
||||||
'#include "trace/control.h"',
|
|
||||||
'')
|
'')
|
||||||
|
|
||||||
|
|
||||||
def generate_h(event):
|
def generate_h(event, group):
|
||||||
argnames = ", ".join(event.args.names())
|
argnames = ", ".join(event.args.names())
|
||||||
if len(event.args) > 0:
|
if len(event.args) > 0:
|
||||||
argnames = ", " + argnames
|
argnames = ", " + argnames
|
||||||
|
|
|
@ -19,13 +19,13 @@ from tracetool import out
|
||||||
PUBLIC = True
|
PUBLIC = True
|
||||||
|
|
||||||
|
|
||||||
def generate_h_begin(events):
|
def generate_h_begin(events, group):
|
||||||
out('#include <lttng/tracepoint.h>',
|
out('#include <lttng/tracepoint.h>',
|
||||||
'#include "trace/generated-ust-provider.h"',
|
'#include "trace/generated-ust-provider.h"',
|
||||||
'')
|
'')
|
||||||
|
|
||||||
|
|
||||||
def generate_h(event):
|
def generate_h(event, group):
|
||||||
argnames = ", ".join(event.args.names())
|
argnames = ", ".join(event.args.names())
|
||||||
if len(event.args) > 0:
|
if len(event.args) > 0:
|
||||||
argnames = ", " + argnames
|
argnames = ", " + argnames
|
||||||
|
|
|
@ -74,7 +74,7 @@ def exists(name):
|
||||||
return tracetool.try_import("tracetool.format." + name)[1]
|
return tracetool.try_import("tracetool.format." + name)[1]
|
||||||
|
|
||||||
|
|
||||||
def generate(events, format, backend):
|
def generate(events, format, backend, group):
|
||||||
if not exists(format):
|
if not exists(format):
|
||||||
raise ValueError("unknown format: %s" % format)
|
raise ValueError("unknown format: %s" % format)
|
||||||
format = format.replace("-", "_")
|
format = format.replace("-", "_")
|
||||||
|
@ -82,4 +82,4 @@ def generate(events, format, backend):
|
||||||
"generate")[1]
|
"generate")[1]
|
||||||
if func is None:
|
if func is None:
|
||||||
raise AttributeError("format has no 'generate': %s" % format)
|
raise AttributeError("format has no 'generate': %s" % format)
|
||||||
func(events, backend)
|
func(events, backend, group)
|
||||||
|
|
|
@ -16,13 +16,55 @@ __email__ = "stefanha@linux.vnet.ibm.com"
|
||||||
from tracetool import out
|
from tracetool import out
|
||||||
|
|
||||||
|
|
||||||
def generate(events, backend):
|
def generate(events, backend, group):
|
||||||
events = [e for e in events
|
active_events = [e for e in events
|
||||||
if "disable" not in e.properties]
|
if "disable" not in e.properties]
|
||||||
|
|
||||||
out('/* This file is autogenerated by tracetool, do not edit. */',
|
out('/* This file is autogenerated by tracetool, do not edit. */',
|
||||||
|
'',
|
||||||
|
'#include "qemu/osdep.h"',
|
||||||
|
'#include "trace.h"',
|
||||||
'')
|
'')
|
||||||
backend.generate_begin(events)
|
|
||||||
for event in events:
|
for e in events:
|
||||||
backend.generate(event)
|
out('uint16_t %s;' % e.api(e.QEMU_DSTATE))
|
||||||
backend.generate_end(events)
|
|
||||||
|
for e in events:
|
||||||
|
if "vcpu" in e.properties:
|
||||||
|
vcpu_id = 0
|
||||||
|
else:
|
||||||
|
vcpu_id = "TRACE_VCPU_EVENT_NONE"
|
||||||
|
out('TraceEvent %(event)s = {',
|
||||||
|
' .id = 0,',
|
||||||
|
' .vcpu_id = %(vcpu_id)s,',
|
||||||
|
' .name = \"%(name)s\",',
|
||||||
|
' .sstate = %(sstate)s,',
|
||||||
|
' .dstate = &%(dstate)s ',
|
||||||
|
'};',
|
||||||
|
event = e.api(e.QEMU_EVENT),
|
||||||
|
vcpu_id = vcpu_id,
|
||||||
|
name = e.name,
|
||||||
|
sstate = "TRACE_%s_ENABLED" % e.name.upper(),
|
||||||
|
dstate = e.api(e.QEMU_DSTATE))
|
||||||
|
|
||||||
|
out('TraceEvent *%(group)s_trace_events[] = {',
|
||||||
|
group = group.lower())
|
||||||
|
|
||||||
|
for e in events:
|
||||||
|
out(' &%(event)s,', event = e.api(e.QEMU_EVENT))
|
||||||
|
|
||||||
|
out(' NULL,',
|
||||||
|
'};',
|
||||||
|
'')
|
||||||
|
|
||||||
|
out('static void trace_%(group)s_register_events(void)',
|
||||||
|
'{',
|
||||||
|
' trace_event_register_group(%(group)s_trace_events);',
|
||||||
|
'}',
|
||||||
|
'trace_init(trace_%(group)s_register_events)',
|
||||||
|
group = group.lower())
|
||||||
|
|
||||||
|
backend.generate_begin(active_events, group)
|
||||||
|
for event in active_events:
|
||||||
|
backend.generate(event, group)
|
||||||
|
backend.generate_end(active_events, group)
|
||||||
|
|
|
@ -29,7 +29,7 @@ RESERVED_WORDS = (
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def generate(events, backend):
|
def generate(events, backend, group):
|
||||||
events = [e for e in events
|
events = [e for e in events
|
||||||
if "disable" not in e.properties]
|
if "disable" not in e.properties]
|
||||||
|
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
trace/generated-events.c
|
|
||||||
"""
|
|
||||||
|
|
||||||
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
|
|
||||||
__copyright__ = "Copyright 2012-2016, Lluís Vilanova <vilanova@ac.upc.edu>"
|
|
||||||
__license__ = "GPL version 2 or (at your option) any later version"
|
|
||||||
|
|
||||||
__maintainer__ = "Stefan Hajnoczi"
|
|
||||||
__email__ = "stefanha@linux.vnet.ibm.com"
|
|
||||||
|
|
||||||
|
|
||||||
from tracetool import out
|
|
||||||
|
|
||||||
|
|
||||||
def generate(events, backend):
|
|
||||||
out('/* This file is autogenerated by tracetool, do not edit. */',
|
|
||||||
'',
|
|
||||||
'#include "qemu/osdep.h"',
|
|
||||||
'#include "trace.h"',
|
|
||||||
'#include "trace/generated-events.h"',
|
|
||||||
'#include "trace/control.h"',
|
|
||||||
'')
|
|
||||||
|
|
||||||
out('TraceEvent trace_events[TRACE_EVENT_COUNT] = {')
|
|
||||||
|
|
||||||
for e in events:
|
|
||||||
if "vcpu" in e.properties:
|
|
||||||
vcpu_id = "TRACE_VCPU_" + e.name.upper()
|
|
||||||
else:
|
|
||||||
vcpu_id = "TRACE_VCPU_EVENT_COUNT"
|
|
||||||
out(' { .id = %(id)s, .vcpu_id = %(vcpu_id)s,'
|
|
||||||
' .name = \"%(name)s\",'
|
|
||||||
' .sstate = %(sstate)s },',
|
|
||||||
id = "TRACE_" + e.name.upper(),
|
|
||||||
vcpu_id = vcpu_id,
|
|
||||||
name = e.name,
|
|
||||||
sstate = "TRACE_%s_ENABLED" % e.name.upper())
|
|
||||||
|
|
||||||
out('};',
|
|
||||||
'')
|
|
|
@ -1,60 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
trace/generated-events.h
|
|
||||||
"""
|
|
||||||
|
|
||||||
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
|
|
||||||
__copyright__ = "Copyright 2012-2016, Lluís Vilanova <vilanova@ac.upc.edu>"
|
|
||||||
__license__ = "GPL version 2 or (at your option) any later version"
|
|
||||||
|
|
||||||
__maintainer__ = "Stefan Hajnoczi"
|
|
||||||
__email__ = "stefanha@linux.vnet.ibm.com"
|
|
||||||
|
|
||||||
|
|
||||||
from tracetool import out
|
|
||||||
|
|
||||||
|
|
||||||
def generate(events, backend):
|
|
||||||
out('/* This file is autogenerated by tracetool, do not edit. */',
|
|
||||||
'',
|
|
||||||
'#ifndef TRACE__GENERATED_EVENTS_H',
|
|
||||||
'#define TRACE__GENERATED_EVENTS_H',
|
|
||||||
'')
|
|
||||||
|
|
||||||
# event identifiers
|
|
||||||
out('typedef enum {')
|
|
||||||
|
|
||||||
for e in events:
|
|
||||||
out(' TRACE_%s,' % e.name.upper())
|
|
||||||
|
|
||||||
out(' TRACE_EVENT_COUNT',
|
|
||||||
'} TraceEventID;')
|
|
||||||
|
|
||||||
# per-vCPU event identifiers
|
|
||||||
out('typedef enum {')
|
|
||||||
|
|
||||||
for e in events:
|
|
||||||
if "vcpu" in e.properties:
|
|
||||||
out(' TRACE_VCPU_%s,' % e.name.upper())
|
|
||||||
|
|
||||||
out(' TRACE_VCPU_EVENT_COUNT',
|
|
||||||
'} TraceEventVCPUID;')
|
|
||||||
|
|
||||||
# static state
|
|
||||||
for e in events:
|
|
||||||
if 'disable' in e.properties:
|
|
||||||
enabled = 0
|
|
||||||
else:
|
|
||||||
enabled = 1
|
|
||||||
if "tcg-exec" in e.properties:
|
|
||||||
# a single define for the two "sub-events"
|
|
||||||
out('#define TRACE_%(name)s_ENABLED %(enabled)d',
|
|
||||||
name=e.original.name.upper(),
|
|
||||||
enabled=enabled)
|
|
||||||
out('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled))
|
|
||||||
|
|
||||||
out('#include "trace/event-internal.h"',
|
|
||||||
'',
|
|
||||||
'#endif /* TRACE__GENERATED_EVENTS_H */')
|
|
|
@ -16,24 +16,43 @@ __email__ = "stefanha@linux.vnet.ibm.com"
|
||||||
from tracetool import out
|
from tracetool import out
|
||||||
|
|
||||||
|
|
||||||
def generate(events, backend):
|
def generate(events, backend, group):
|
||||||
out('/* This file is autogenerated by tracetool, do not edit. */',
|
out('/* This file is autogenerated by tracetool, do not edit. */',
|
||||||
'',
|
'',
|
||||||
'#ifndef TRACE__GENERATED_TRACERS_H',
|
'#ifndef TRACE_%s_GENERATED_TRACERS_H' % group.upper(),
|
||||||
'#define TRACE__GENERATED_TRACERS_H',
|
'#define TRACE_%s_GENERATED_TRACERS_H' % group.upper(),
|
||||||
'',
|
'',
|
||||||
'#include "qemu-common.h"',
|
'#include "qemu-common.h"',
|
||||||
'#include "trace/control.h"',
|
'#include "trace/control.h"',
|
||||||
'')
|
'')
|
||||||
|
|
||||||
backend.generate_begin(events)
|
for e in events:
|
||||||
|
out('extern TraceEvent %(event)s;',
|
||||||
|
event = e.api(e.QEMU_EVENT))
|
||||||
|
|
||||||
|
for e in events:
|
||||||
|
out('extern uint16_t %s;' % e.api(e.QEMU_DSTATE))
|
||||||
|
|
||||||
|
# static state
|
||||||
|
for e in events:
|
||||||
|
if 'disable' in e.properties:
|
||||||
|
enabled = 0
|
||||||
|
else:
|
||||||
|
enabled = 1
|
||||||
|
if "tcg-exec" in e.properties:
|
||||||
|
# a single define for the two "sub-events"
|
||||||
|
out('#define TRACE_%(name)s_ENABLED %(enabled)d',
|
||||||
|
name=e.original.name.upper(),
|
||||||
|
enabled=enabled)
|
||||||
|
out('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled))
|
||||||
|
|
||||||
|
backend.generate_begin(events, group)
|
||||||
|
|
||||||
for e in events:
|
for e in events:
|
||||||
if "vcpu" in e.properties:
|
if "vcpu" in e.properties:
|
||||||
trace_cpu = next(iter(e.args))[1]
|
trace_cpu = next(iter(e.args))[1]
|
||||||
cond = "trace_event_get_vcpu_state(%(cpu)s,"\
|
cond = "trace_event_get_vcpu_state(%(cpu)s,"\
|
||||||
" TRACE_%(id)s,"\
|
" TRACE_%(id)s)"\
|
||||||
" TRACE_VCPU_%(id)s)"\
|
|
||||||
% dict(
|
% dict(
|
||||||
cpu=trace_cpu,
|
cpu=trace_cpu,
|
||||||
id=e.name.upper())
|
id=e.name.upper())
|
||||||
|
@ -49,11 +68,11 @@ def generate(events, backend):
|
||||||
cond=cond)
|
cond=cond)
|
||||||
|
|
||||||
if "disable" not in e.properties:
|
if "disable" not in e.properties:
|
||||||
backend.generate(e)
|
backend.generate(e, group)
|
||||||
|
|
||||||
out(' }',
|
out(' }',
|
||||||
'}')
|
'}')
|
||||||
|
|
||||||
backend.generate_end(events)
|
backend.generate_end(events, group)
|
||||||
|
|
||||||
out('#endif /* TRACE__GENERATED_TRACERS_H */')
|
out('#endif /* TRACE_%s_GENERATED_TRACERS_H */' % group.upper())
|
||||||
|
|
|
@ -19,8 +19,27 @@ from tracetool.backend.simple import is_string
|
||||||
from tracetool.format.stap import stap_escape
|
from tracetool.format.stap import stap_escape
|
||||||
|
|
||||||
|
|
||||||
def generate(events, backend):
|
def generate(events, backend, group):
|
||||||
out('/* This file is autogenerated by tracetool, do not edit. */',
|
out('/* This file is autogenerated by tracetool, do not edit. */',
|
||||||
|
'',
|
||||||
|
'global event_name_to_id_map',
|
||||||
|
'global event_next_id',
|
||||||
|
'function simple_trace_map_event(name)',
|
||||||
|
'',
|
||||||
|
'{',
|
||||||
|
' if (!([name] in event_name_to_id_map)) {',
|
||||||
|
' event_name_to_id_map[name] = event_next_id',
|
||||||
|
' name_len = strlen(name)',
|
||||||
|
' printf("%%8b%%8b%%4b%%.*s", 0, ',
|
||||||
|
' event_next_id, name_len, name_len, name)',
|
||||||
|
' event_next_id = event_next_id + 1',
|
||||||
|
' }',
|
||||||
|
' return event_name_to_id_map[name]',
|
||||||
|
'}',
|
||||||
|
'probe begin',
|
||||||
|
'{',
|
||||||
|
' printf("%%8b%%8b%%8b", 0xffffffffffffffff, 0xf2b177cb0aa429b4, 4)',
|
||||||
|
'}',
|
||||||
'')
|
'')
|
||||||
|
|
||||||
for event_id, e in enumerate(events):
|
for event_id, e in enumerate(events):
|
||||||
|
@ -29,6 +48,7 @@ def generate(events, backend):
|
||||||
|
|
||||||
out('probe %(probeprefix)s.simpletrace.%(name)s = %(probeprefix)s.%(name)s ?',
|
out('probe %(probeprefix)s.simpletrace.%(name)s = %(probeprefix)s.%(name)s ?',
|
||||||
'{',
|
'{',
|
||||||
|
' id = simple_trace_map_event("%(name)s")',
|
||||||
probeprefix=probeprefix(),
|
probeprefix=probeprefix(),
|
||||||
name=e.name)
|
name=e.name)
|
||||||
|
|
||||||
|
@ -48,7 +68,7 @@ def generate(events, backend):
|
||||||
sizestr = ' + '.join(sizes)
|
sizestr = ' + '.join(sizes)
|
||||||
|
|
||||||
# Generate format string and value pairs for record header and arguments
|
# Generate format string and value pairs for record header and arguments
|
||||||
fields = [('8b', str(event_id)),
|
fields = [('8b', 'id'),
|
||||||
('8b', 'gettimeofday_ns()'),
|
('8b', 'gettimeofday_ns()'),
|
||||||
('4b', sizestr),
|
('4b', sizestr),
|
||||||
('4b', 'pid()')]
|
('4b', 'pid()')]
|
||||||
|
@ -63,7 +83,7 @@ def generate(events, backend):
|
||||||
# Emit the entire record in a single SystemTap printf()
|
# Emit the entire record in a single SystemTap printf()
|
||||||
fmt_str = '%'.join(fmt for fmt, _ in fields)
|
fmt_str = '%'.join(fmt for fmt, _ in fields)
|
||||||
arg_str = ', '.join(arg for _, arg in fields)
|
arg_str = ', '.join(arg for _, arg in fields)
|
||||||
out(' printf("%%%(fmt_str)s", %(arg_str)s)',
|
out(' printf("%%8b%%%(fmt_str)s", 1, %(arg_str)s)',
|
||||||
fmt_str=fmt_str, arg_str=arg_str)
|
fmt_str=fmt_str, arg_str=arg_str)
|
||||||
|
|
||||||
out('}')
|
out('}')
|
||||||
|
|
|
@ -34,7 +34,7 @@ def stap_escape(identifier):
|
||||||
return identifier
|
return identifier
|
||||||
|
|
||||||
|
|
||||||
def generate(events, backend):
|
def generate(events, backend, group):
|
||||||
events = [e for e in events
|
events = [e for e in events
|
||||||
if "disable" not in e.properties]
|
if "disable" not in e.properties]
|
||||||
|
|
||||||
|
|
|
@ -27,12 +27,12 @@ def vcpu_transform_args(args):
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
def generate(events, backend):
|
def generate(events, backend, group):
|
||||||
out('/* This file is autogenerated by tracetool, do not edit. */',
|
out('/* This file is autogenerated by tracetool, do not edit. */',
|
||||||
'/* You must include this file after the inclusion of helper.h */',
|
'/* You must include this file after the inclusion of helper.h */',
|
||||||
'',
|
'',
|
||||||
'#ifndef TRACE__GENERATED_TCG_TRACERS_H',
|
'#ifndef TRACE_%s_GENERATED_TCG_TRACERS_H' % group.upper(),
|
||||||
'#define TRACE__GENERATED_TCG_TRACERS_H',
|
'#define TRACE_%s_GENERATED_TCG_TRACERS_H' % group.upper(),
|
||||||
'',
|
'',
|
||||||
'#include "trace.h"',
|
'#include "trace.h"',
|
||||||
'#include "exec/helper-proto.h"',
|
'#include "exec/helper-proto.h"',
|
||||||
|
@ -63,4 +63,4 @@ def generate(events, backend):
|
||||||
out('}')
|
out('}')
|
||||||
|
|
||||||
out('',
|
out('',
|
||||||
'#endif /* TRACE__GENERATED_TCG_TRACERS_H */')
|
'#endif /* TRACE_%s_GENERATED_TCG_TRACERS_H */' % group.upper())
|
||||||
|
|
|
@ -40,7 +40,7 @@ def vcpu_transform_args(args, mode):
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
|
||||||
def generate(events, backend):
|
def generate(events, backend, group):
|
||||||
events = [e for e in events
|
events = [e for e in events
|
||||||
if "disable" not in e.properties]
|
if "disable" not in e.properties]
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ from tracetool.transform import *
|
||||||
import tracetool.vcpu
|
import tracetool.vcpu
|
||||||
|
|
||||||
|
|
||||||
def generate(events, backend):
|
def generate(events, backend, group):
|
||||||
events = [e for e in events
|
events = [e for e in events
|
||||||
if "disable" not in e.properties]
|
if "disable" not in e.properties]
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ from tracetool.transform import *
|
||||||
import tracetool.vcpu
|
import tracetool.vcpu
|
||||||
|
|
||||||
|
|
||||||
def generate(events, backend):
|
def generate(events, backend, group):
|
||||||
events = [e for e in events
|
events = [e for e in events
|
||||||
if "disable" not in e.properties]
|
if "disable" not in e.properties]
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ __email__ = "stefanha@redhat.com"
|
||||||
from tracetool import out
|
from tracetool import out
|
||||||
|
|
||||||
|
|
||||||
def generate(events, backend):
|
def generate(events, backend, group):
|
||||||
events = [e for e in events
|
events = [e for e in events
|
||||||
if "disabled" not in e.properties]
|
if "disabled" not in e.properties]
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ __email__ = "stefanha@redhat.com"
|
||||||
from tracetool import out
|
from tracetool import out
|
||||||
|
|
||||||
|
|
||||||
def generate(events, backend):
|
def generate(events, backend, group):
|
||||||
events = [e for e in events
|
events = [e for e in events
|
||||||
if "disabled" not in e.properties]
|
if "disabled" not in e.properties]
|
||||||
|
|
||||||
|
@ -28,8 +28,9 @@ def generate(events, backend):
|
||||||
'#undef TRACEPOINT_INCLUDE_FILE',
|
'#undef TRACEPOINT_INCLUDE_FILE',
|
||||||
'#define TRACEPOINT_INCLUDE_FILE ./generated-ust-provider.h',
|
'#define TRACEPOINT_INCLUDE_FILE ./generated-ust-provider.h',
|
||||||
'',
|
'',
|
||||||
'#if !defined (TRACE__GENERATED_UST_H) || defined(TRACEPOINT_HEADER_MULTI_READ)',
|
'#if !defined (TRACE_%s_GENERATED_UST_H) || \\' % group.upper(),
|
||||||
'#define TRACE__GENERATED_UST_H',
|
' defined(TRACEPOINT_HEADER_MULTI_READ)',
|
||||||
|
'#define TRACE_%s_GENERATED_UST_H' % group.upper(),
|
||||||
'',
|
'',
|
||||||
'#include "qemu-common.h"',
|
'#include "qemu-common.h"',
|
||||||
'#include <lttng/tracepoint.h>',
|
'#include <lttng/tracepoint.h>',
|
||||||
|
@ -94,7 +95,7 @@ def generate(events, backend):
|
||||||
'',
|
'',
|
||||||
name=e.name)
|
name=e.name)
|
||||||
|
|
||||||
out('#endif /* TRACE__GENERATED_UST_H */',
|
out('#endif /* TRACE_%s_GENERATED_UST_H */' % group.upper(),
|
||||||
'',
|
'',
|
||||||
'/* This part must be outside ifdef protection */',
|
'/* This part must be outside ifdef protection */',
|
||||||
'#include <lttng/tracepoint-event.h>')
|
'#include <lttng/tracepoint-event.h>')
|
||||||
|
|
|
@ -18,22 +18,21 @@ void trace_event_set_state_dynamic_init(TraceEvent *ev, bool state)
|
||||||
|
|
||||||
void trace_event_set_state_dynamic(TraceEvent *ev, bool state)
|
void trace_event_set_state_dynamic(TraceEvent *ev, bool state)
|
||||||
{
|
{
|
||||||
TraceEventID id;
|
|
||||||
bool state_pre;
|
bool state_pre;
|
||||||
assert(trace_event_get_state_static(ev));
|
assert(trace_event_get_state_static(ev));
|
||||||
id = trace_event_get_id(ev);
|
|
||||||
/*
|
/*
|
||||||
* We ignore the "vcpu" property here, since there's no target code. Then
|
* We ignore the "vcpu" property here, since there's no target code. Then
|
||||||
* dstate can only be 1 or 0.
|
* dstate can only be 1 or 0.
|
||||||
*/
|
*/
|
||||||
state_pre = trace_events_dstate[id];
|
state_pre = *(ev->dstate);
|
||||||
if (state_pre != state) {
|
if (state_pre != state) {
|
||||||
if (state) {
|
if (state) {
|
||||||
trace_events_enabled_count++;
|
trace_events_enabled_count++;
|
||||||
trace_events_dstate[id] = 1;
|
*(ev->dstate) = 1;
|
||||||
} else {
|
} else {
|
||||||
trace_events_enabled_count--;
|
trace_events_enabled_count--;
|
||||||
trace_events_dstate[id] = 0;
|
*(ev->dstate) = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
18
trace-events
18
trace-events
|
@ -122,22 +122,6 @@ memory_region_subpage_write(int cpu_index, void *mr, uint64_t offset, uint64_t v
|
||||||
memory_region_tb_read(int cpu_index, uint64_t addr, uint64_t value, unsigned size) "cpu %d addr %#"PRIx64" value %#"PRIx64" size %u"
|
memory_region_tb_read(int cpu_index, uint64_t addr, uint64_t value, unsigned size) "cpu %d addr %#"PRIx64" value %#"PRIx64" size %u"
|
||||||
memory_region_tb_write(int cpu_index, uint64_t addr, uint64_t value, unsigned size) "cpu %d addr %#"PRIx64" value %#"PRIx64" size %u"
|
memory_region_tb_write(int cpu_index, uint64_t addr, uint64_t value, unsigned size) "cpu %d addr %#"PRIx64" value %#"PRIx64" size %u"
|
||||||
|
|
||||||
# net/colo.c
|
|
||||||
colo_proxy_main(const char *chr) ": %s"
|
|
||||||
|
|
||||||
# net/colo-compare.c
|
|
||||||
colo_compare_main(const char *chr) ": %s"
|
|
||||||
colo_compare_udp_miscompare(const char *sta, int size) ": %s = %d"
|
|
||||||
colo_compare_icmp_miscompare(const char *sta, int size) ": %s = %d"
|
|
||||||
colo_compare_ip_info(int psize, const char *sta, const char *stb, int ssize, const char *stc, const char *std) "ppkt size = %d, ip_src = %s, ip_dst = %s, spkt size = %d, ip_src = %s, ip_dst = %s"
|
|
||||||
colo_old_packet_check_found(int64_t old_time) "%" PRId64
|
|
||||||
colo_compare_miscompare(void) ""
|
|
||||||
|
|
||||||
# net/filter-rewriter.c
|
|
||||||
colo_filter_rewriter_debug(void) ""
|
|
||||||
colo_filter_rewriter_pkt_info(const char *func, const char *src, const char *dst, uint32_t seq, uint32_t ack, uint32_t flag) "%s: src/dst: %s/%s p: seq/ack=%u/%u flags=%x\n"
|
|
||||||
colo_filter_rewriter_conn_offset(uint32_t offset) ": offset=%u\n"
|
|
||||||
|
|
||||||
### Guest events, keep at bottom
|
### Guest events, keep at bottom
|
||||||
|
|
||||||
|
|
||||||
|
@ -145,11 +129,13 @@ colo_filter_rewriter_conn_offset(uint32_t offset) ": offset=%u\n"
|
||||||
|
|
||||||
# Hot-plug a new virtual (guest) CPU
|
# Hot-plug a new virtual (guest) CPU
|
||||||
#
|
#
|
||||||
|
# Mode: user, softmmu
|
||||||
# Targets: all
|
# Targets: all
|
||||||
vcpu guest_cpu_enter(void)
|
vcpu guest_cpu_enter(void)
|
||||||
|
|
||||||
# Reset the state of a virtual (guest) CPU
|
# Reset the state of a virtual (guest) CPU
|
||||||
#
|
#
|
||||||
|
# Mode: user, softmmu
|
||||||
# Targets: all
|
# Targets: all
|
||||||
vcpu guest_cpu_reset(void)
|
vcpu guest_cpu_reset(void)
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ $(obj)/generated-ust-provider.h-timestamp: $(BUILD_DIR)/trace-events-all $(trace
|
||||||
$(call quiet-command,$(TRACETOOL) \
|
$(call quiet-command,$(TRACETOOL) \
|
||||||
--format=ust-events-h \
|
--format=ust-events-h \
|
||||||
--backends=$(TRACE_BACKENDS) \
|
--backends=$(TRACE_BACKENDS) \
|
||||||
< $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
$< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
||||||
|
|
||||||
$(obj)/generated-ust.c: $(obj)/generated-ust.c-timestamp $(BUILD_DIR)/config-host.mak
|
$(obj)/generated-ust.c: $(obj)/generated-ust.c-timestamp $(BUILD_DIR)/config-host.mak
|
||||||
@cmp $< $@ >/dev/null 2>&1 || cp $< $@
|
@cmp $< $@ >/dev/null 2>&1 || cp $< $@
|
||||||
|
@ -30,34 +30,13 @@ $(obj)/generated-ust.c-timestamp: $(BUILD_DIR)/trace-events-all $(tracetool-y)
|
||||||
$(call quiet-command,$(TRACETOOL) \
|
$(call quiet-command,$(TRACETOOL) \
|
||||||
--format=ust-events-c \
|
--format=ust-events-c \
|
||||||
--backends=$(TRACE_BACKENDS) \
|
--backends=$(TRACE_BACKENDS) \
|
||||||
< $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
$< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
||||||
|
|
||||||
$(obj)/generated-events.h: $(obj)/generated-ust-provider.h
|
$(obj)/generated-tracers.h: $(obj)/generated-ust-provider.h
|
||||||
$(obj)/generated-events.c: $(obj)/generated-ust.c
|
$(obj)/generated-tracers.c: $(obj)/generated-ust.c
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# Auto-generated event descriptions
|
|
||||||
|
|
||||||
$(obj)/generated-events.h: $(obj)/generated-events.h-timestamp
|
|
||||||
@cmp $< $@ >/dev/null 2>&1 || cp $< $@
|
|
||||||
$(obj)/generated-events.h-timestamp: $(BUILD_DIR)/trace-events-all $(tracetool-y)
|
|
||||||
$(call quiet-command,$(TRACETOOL) \
|
|
||||||
--format=events-h \
|
|
||||||
--backends=$(TRACE_BACKENDS) \
|
|
||||||
< $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
|
||||||
|
|
||||||
$(obj)/generated-events.c: $(obj)/generated-events.c-timestamp $(BUILD_DIR)/config-host.mak
|
|
||||||
@cmp $< $@ >/dev/null 2>&1 || cp $< $@
|
|
||||||
$(obj)/generated-events.c-timestamp: $(BUILD_DIR)/trace-events-all $(tracetool-y)
|
|
||||||
$(call quiet-command,$(TRACETOOL) \
|
|
||||||
--format=events-c \
|
|
||||||
--backends=$(TRACE_BACKENDS) \
|
|
||||||
< $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
|
||||||
|
|
||||||
util-obj-y += generated-events.o
|
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Auto-generated tracing routines
|
# Auto-generated tracing routines
|
||||||
|
@ -71,7 +50,7 @@ $(obj)/generated-tracers.h-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR)
|
||||||
$(call quiet-command,$(TRACETOOL) \
|
$(call quiet-command,$(TRACETOOL) \
|
||||||
--format=h \
|
--format=h \
|
||||||
--backends=$(TRACE_BACKENDS) \
|
--backends=$(TRACE_BACKENDS) \
|
||||||
< $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
$< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
||||||
|
|
||||||
##############################
|
##############################
|
||||||
# non-DTrace
|
# non-DTrace
|
||||||
|
@ -82,7 +61,7 @@ $(obj)/generated-tracers.c-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR)
|
||||||
$(call quiet-command,$(TRACETOOL) \
|
$(call quiet-command,$(TRACETOOL) \
|
||||||
--format=c \
|
--format=c \
|
||||||
--backends=$(TRACE_BACKENDS) \
|
--backends=$(TRACE_BACKENDS) \
|
||||||
< $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
$< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
||||||
|
|
||||||
$(obj)/generated-tracers.o: $(obj)/generated-tracers.c $(obj)/generated-tracers.h
|
$(obj)/generated-tracers.o: $(obj)/generated-tracers.c $(obj)/generated-tracers.h
|
||||||
|
|
||||||
|
@ -100,7 +79,7 @@ $(obj)/generated-tracers-dtrace.dtrace-timestamp: $(BUILD_DIR)/trace-events-all
|
||||||
$(call quiet-command,$(TRACETOOL) \
|
$(call quiet-command,$(TRACETOOL) \
|
||||||
--format=d \
|
--format=d \
|
||||||
--backends=$(TRACE_BACKENDS) \
|
--backends=$(TRACE_BACKENDS) \
|
||||||
< $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
$< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
||||||
|
|
||||||
$(obj)/generated-tracers-dtrace.h: $(obj)/generated-tracers-dtrace.dtrace
|
$(obj)/generated-tracers-dtrace.h: $(obj)/generated-tracers-dtrace.dtrace
|
||||||
$(call quiet-command,dtrace -o $@ -h -s $<,"GEN","$@")
|
$(call quiet-command,dtrace -o $@ -h -s $<,"GEN","$@")
|
||||||
|
@ -119,7 +98,7 @@ $(obj)/generated-helpers-wrappers.h-timestamp: $(BUILD_DIR)/trace-events-all $(B
|
||||||
$(call quiet-command,$(TRACETOOL) \
|
$(call quiet-command,$(TRACETOOL) \
|
||||||
--format=tcg-helper-wrapper-h \
|
--format=tcg-helper-wrapper-h \
|
||||||
--backend=$(TRACE_BACKENDS) \
|
--backend=$(TRACE_BACKENDS) \
|
||||||
< $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
$< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
||||||
|
|
||||||
$(obj)/generated-helpers.h: $(obj)/generated-helpers.h-timestamp
|
$(obj)/generated-helpers.h: $(obj)/generated-helpers.h-timestamp
|
||||||
@cmp $< $@ >/dev/null 2>&1 || cp $< $@
|
@cmp $< $@ >/dev/null 2>&1 || cp $< $@
|
||||||
|
@ -127,7 +106,7 @@ $(obj)/generated-helpers.h-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR)
|
||||||
$(call quiet-command,$(TRACETOOL) \
|
$(call quiet-command,$(TRACETOOL) \
|
||||||
--format=tcg-helper-h \
|
--format=tcg-helper-h \
|
||||||
--backend=$(TRACE_BACKENDS) \
|
--backend=$(TRACE_BACKENDS) \
|
||||||
< $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
$< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
||||||
|
|
||||||
$(obj)/generated-helpers.c: $(obj)/generated-helpers.c-timestamp
|
$(obj)/generated-helpers.c: $(obj)/generated-helpers.c-timestamp
|
||||||
@cmp $< $@ >/dev/null 2>&1 || cp $< $@
|
@cmp $< $@ >/dev/null 2>&1 || cp $< $@
|
||||||
|
@ -135,7 +114,7 @@ $(obj)/generated-helpers.c-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR)
|
||||||
$(call quiet-command,$(TRACETOOL) \
|
$(call quiet-command,$(TRACETOOL) \
|
||||||
--format=tcg-helper-c \
|
--format=tcg-helper-c \
|
||||||
--backend=$(TRACE_BACKENDS) \
|
--backend=$(TRACE_BACKENDS) \
|
||||||
< $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
$< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
||||||
|
|
||||||
$(obj)/generated-helpers.o: $(obj)/generated-helpers.c
|
$(obj)/generated-helpers.o: $(obj)/generated-helpers.c
|
||||||
|
|
||||||
|
@ -148,13 +127,14 @@ $(obj)/generated-tcg-tracers.h-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_
|
||||||
$(call quiet-command,$(TRACETOOL) \
|
$(call quiet-command,$(TRACETOOL) \
|
||||||
--format=tcg-h \
|
--format=tcg-h \
|
||||||
--backend=$(TRACE_BACKENDS) \
|
--backend=$(TRACE_BACKENDS) \
|
||||||
< $< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
$< > $@,"GEN","$(patsubst %-timestamp,%,$@)")
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Backend code
|
# Backend code
|
||||||
|
|
||||||
util-obj-$(CONFIG_TRACE_SIMPLE) += simple.o generated-tracers.o
|
util-obj-y += generated-tracers.o
|
||||||
|
util-obj-$(CONFIG_TRACE_SIMPLE) += simple.o
|
||||||
util-obj-$(CONFIG_TRACE_FTRACE) += ftrace.o
|
util-obj-$(CONFIG_TRACE_FTRACE) += ftrace.o
|
||||||
util-obj-$(CONFIG_TRACE_UST) += generated-ust.o
|
util-obj-$(CONFIG_TRACE_UST) += generated-ust.o
|
||||||
util-obj-y += control.o
|
util-obj-y += control.o
|
||||||
|
|
|
@ -15,42 +15,29 @@
|
||||||
#include "qom/cpu.h"
|
#include "qom/cpu.h"
|
||||||
|
|
||||||
|
|
||||||
extern TraceEvent trace_events[];
|
|
||||||
extern uint16_t trace_events_dstate[];
|
|
||||||
extern int trace_events_enabled_count;
|
extern int trace_events_enabled_count;
|
||||||
|
|
||||||
|
|
||||||
static inline TraceEventID trace_event_count(void)
|
|
||||||
{
|
|
||||||
return TRACE_EVENT_COUNT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline TraceEvent *trace_event_id(TraceEventID id)
|
|
||||||
{
|
|
||||||
assert(id < trace_event_count());
|
|
||||||
return &trace_events[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool trace_event_is_pattern(const char *str)
|
static inline bool trace_event_is_pattern(const char *str)
|
||||||
{
|
{
|
||||||
assert(str != NULL);
|
assert(str != NULL);
|
||||||
return strchr(str, '*') != NULL;
|
return strchr(str, '*') != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline TraceEventID trace_event_get_id(TraceEvent *ev)
|
static inline uint32_t trace_event_get_id(TraceEvent *ev)
|
||||||
{
|
{
|
||||||
assert(ev != NULL);
|
assert(ev != NULL);
|
||||||
return ev->id;
|
return ev->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline TraceEventVCPUID trace_event_get_vcpu_id(TraceEvent *ev)
|
static inline uint32_t trace_event_get_vcpu_id(TraceEvent *ev)
|
||||||
{
|
{
|
||||||
return ev->vcpu_id;
|
return ev->vcpu_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool trace_event_is_vcpu(TraceEvent *ev)
|
static inline bool trace_event_is_vcpu(TraceEvent *ev)
|
||||||
{
|
{
|
||||||
return ev->vcpu_id != TRACE_VCPU_EVENT_COUNT;
|
return ev->vcpu_id != TRACE_VCPU_EVENT_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const char * trace_event_get_name(TraceEvent *ev)
|
static inline const char * trace_event_get_name(TraceEvent *ev)
|
||||||
|
@ -65,26 +52,22 @@ static inline bool trace_event_get_state_static(TraceEvent *ev)
|
||||||
return ev->sstate;
|
return ev->sstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool trace_event_get_state_dynamic_by_id(TraceEventID id)
|
/* it's on fast path, avoid consistency checks (asserts) */
|
||||||
{
|
#define trace_event_get_state_dynamic_by_id(id) \
|
||||||
/* it's on fast path, avoid consistency checks (asserts) */
|
(unlikely(trace_events_enabled_count) && _ ## id ## _DSTATE)
|
||||||
return unlikely(trace_events_enabled_count) && trace_events_dstate[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool trace_event_get_state_dynamic(TraceEvent *ev)
|
static inline bool trace_event_get_state_dynamic(TraceEvent *ev)
|
||||||
{
|
{
|
||||||
TraceEventID id;
|
return unlikely(trace_events_enabled_count) && *ev->dstate;
|
||||||
assert(trace_event_get_state_static(ev));
|
|
||||||
id = trace_event_get_id(ev);
|
|
||||||
return trace_event_get_state_dynamic_by_id(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool trace_event_get_vcpu_state_dynamic_by_vcpu_id(CPUState *vcpu,
|
static inline bool
|
||||||
TraceEventVCPUID id)
|
trace_event_get_vcpu_state_dynamic_by_vcpu_id(CPUState *vcpu,
|
||||||
|
uint32_t vcpu_id)
|
||||||
{
|
{
|
||||||
/* it's on fast path, avoid consistency checks (asserts) */
|
/* it's on fast path, avoid consistency checks (asserts) */
|
||||||
if (unlikely(trace_events_enabled_count)) {
|
if (unlikely(trace_events_enabled_count)) {
|
||||||
return test_bit(id, vcpu->trace_dstate);
|
return test_bit(vcpu_id, vcpu->trace_dstate);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -93,10 +76,13 @@ static inline bool trace_event_get_vcpu_state_dynamic_by_vcpu_id(CPUState *vcpu,
|
||||||
static inline bool trace_event_get_vcpu_state_dynamic(CPUState *vcpu,
|
static inline bool trace_event_get_vcpu_state_dynamic(CPUState *vcpu,
|
||||||
TraceEvent *ev)
|
TraceEvent *ev)
|
||||||
{
|
{
|
||||||
TraceEventVCPUID id;
|
uint32_t vcpu_id;
|
||||||
assert(trace_event_is_vcpu(ev));
|
assert(trace_event_is_vcpu(ev));
|
||||||
id = trace_event_get_vcpu_id(ev);
|
vcpu_id = trace_event_get_vcpu_id(ev);
|
||||||
return trace_event_get_vcpu_state_dynamic_by_vcpu_id(vcpu, id);
|
return trace_event_get_vcpu_state_dynamic_by_vcpu_id(vcpu, vcpu_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void trace_event_register_group(TraceEvent **events);
|
||||||
|
|
||||||
#endif /* TRACE__CONTROL_INTERNAL_H */
|
#endif /* TRACE__CONTROL_INTERNAL_H */
|
||||||
|
|
|
@ -16,21 +16,20 @@
|
||||||
|
|
||||||
void trace_event_set_state_dynamic_init(TraceEvent *ev, bool state)
|
void trace_event_set_state_dynamic_init(TraceEvent *ev, bool state)
|
||||||
{
|
{
|
||||||
TraceEventID id = trace_event_get_id(ev);
|
|
||||||
bool state_pre;
|
bool state_pre;
|
||||||
assert(trace_event_get_state_static(ev));
|
assert(trace_event_get_state_static(ev));
|
||||||
/*
|
/*
|
||||||
* We ignore the "vcpu" property here, since no vCPUs have been created
|
* We ignore the "vcpu" property here, since no vCPUs have been created
|
||||||
* yet. Then dstate can only be 1 or 0.
|
* yet. Then dstate can only be 1 or 0.
|
||||||
*/
|
*/
|
||||||
state_pre = trace_events_dstate[id];
|
state_pre = *ev->dstate;
|
||||||
if (state_pre != state) {
|
if (state_pre != state) {
|
||||||
if (state) {
|
if (state) {
|
||||||
trace_events_enabled_count++;
|
trace_events_enabled_count++;
|
||||||
trace_events_dstate[id] = 1;
|
*ev->dstate = 1;
|
||||||
} else {
|
} else {
|
||||||
trace_events_enabled_count--;
|
trace_events_enabled_count--;
|
||||||
trace_events_dstate[id] = 0;
|
*ev->dstate = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,15 +44,14 @@ void trace_event_set_state_dynamic(TraceEvent *ev, bool state)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Without the "vcpu" property, dstate can only be 1 or 0 */
|
/* Without the "vcpu" property, dstate can only be 1 or 0 */
|
||||||
TraceEventID id = trace_event_get_id(ev);
|
bool state_pre = *ev->dstate;
|
||||||
bool state_pre = trace_events_dstate[id];
|
|
||||||
if (state_pre != state) {
|
if (state_pre != state) {
|
||||||
if (state) {
|
if (state) {
|
||||||
trace_events_enabled_count++;
|
trace_events_enabled_count++;
|
||||||
trace_events_dstate[id] = 1;
|
*ev->dstate = 1;
|
||||||
} else {
|
} else {
|
||||||
trace_events_enabled_count--;
|
trace_events_enabled_count--;
|
||||||
trace_events_dstate[id] = 0;
|
*ev->dstate = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,23 +60,21 @@ void trace_event_set_state_dynamic(TraceEvent *ev, bool state)
|
||||||
void trace_event_set_vcpu_state_dynamic(CPUState *vcpu,
|
void trace_event_set_vcpu_state_dynamic(CPUState *vcpu,
|
||||||
TraceEvent *ev, bool state)
|
TraceEvent *ev, bool state)
|
||||||
{
|
{
|
||||||
TraceEventID id;
|
uint32_t vcpu_id;
|
||||||
TraceEventVCPUID vcpu_id;
|
|
||||||
bool state_pre;
|
bool state_pre;
|
||||||
assert(trace_event_get_state_static(ev));
|
assert(trace_event_get_state_static(ev));
|
||||||
assert(trace_event_is_vcpu(ev));
|
assert(trace_event_is_vcpu(ev));
|
||||||
id = trace_event_get_id(ev);
|
|
||||||
vcpu_id = trace_event_get_vcpu_id(ev);
|
vcpu_id = trace_event_get_vcpu_id(ev);
|
||||||
state_pre = test_bit(vcpu_id, vcpu->trace_dstate);
|
state_pre = test_bit(vcpu_id, vcpu->trace_dstate);
|
||||||
if (state_pre != state) {
|
if (state_pre != state) {
|
||||||
if (state) {
|
if (state) {
|
||||||
trace_events_enabled_count++;
|
trace_events_enabled_count++;
|
||||||
set_bit(vcpu_id, vcpu->trace_dstate);
|
set_bit(vcpu_id, vcpu->trace_dstate);
|
||||||
trace_events_dstate[id]++;
|
(*ev->dstate)++;
|
||||||
} else {
|
} else {
|
||||||
trace_events_enabled_count--;
|
trace_events_enabled_count--;
|
||||||
clear_bit(vcpu_id, vcpu->trace_dstate);
|
clear_bit(vcpu_id, vcpu->trace_dstate);
|
||||||
trace_events_dstate[id]--;
|
(*ev->dstate)--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,18 +94,18 @@ static bool adding_first_cpu(void)
|
||||||
|
|
||||||
void trace_init_vcpu(CPUState *vcpu)
|
void trace_init_vcpu(CPUState *vcpu)
|
||||||
{
|
{
|
||||||
TraceEvent *ev = NULL;
|
TraceEventIter iter;
|
||||||
|
TraceEvent *ev;
|
||||||
while ((ev = trace_event_pattern("*", ev)) != NULL) {
|
trace_event_iter_init(&iter, NULL);
|
||||||
|
while ((ev = trace_event_iter_next(&iter)) != NULL) {
|
||||||
if (trace_event_is_vcpu(ev) &&
|
if (trace_event_is_vcpu(ev) &&
|
||||||
trace_event_get_state_static(ev) &&
|
trace_event_get_state_static(ev) &&
|
||||||
trace_event_get_state_dynamic(ev)) {
|
trace_event_get_state_dynamic(ev)) {
|
||||||
TraceEventID id = trace_event_get_id(ev);
|
|
||||||
if (adding_first_cpu()) {
|
if (adding_first_cpu()) {
|
||||||
/* check preconditions */
|
/* check preconditions */
|
||||||
assert(trace_events_dstate[id] == 1);
|
assert(*ev->dstate == 1);
|
||||||
/* disable early-init state ... */
|
/* disable early-init state ... */
|
||||||
trace_events_dstate[id] = 0;
|
*ev->dstate = 0;
|
||||||
trace_events_enabled_count--;
|
trace_events_enabled_count--;
|
||||||
/* ... and properly re-enable */
|
/* ... and properly re-enable */
|
||||||
trace_event_set_vcpu_state_dynamic(vcpu, ev, true);
|
trace_event_set_vcpu_state_dynamic(vcpu, ev, true);
|
||||||
|
@ -118,6 +114,5 @@ void trace_init_vcpu(CPUState *vcpu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_guest_cpu_enter(vcpu);
|
trace_guest_cpu_enter(vcpu);
|
||||||
}
|
}
|
||||||
|
|
121
trace/control.c
121
trace/control.c
|
@ -28,12 +28,15 @@
|
||||||
#include "monitor/monitor.h"
|
#include "monitor/monitor.h"
|
||||||
|
|
||||||
int trace_events_enabled_count;
|
int trace_events_enabled_count;
|
||||||
/*
|
|
||||||
* Interpretation depends on wether the event has the 'vcpu' property:
|
typedef struct TraceEventGroup {
|
||||||
* - false: Boolean value indicating whether the event is active.
|
TraceEvent **events;
|
||||||
* - true : Integral counting the number of vCPUs that have this event enabled.
|
} TraceEventGroup;
|
||||||
*/
|
|
||||||
uint16_t trace_events_dstate[TRACE_EVENT_COUNT];
|
static TraceEventGroup *event_groups;
|
||||||
|
static size_t nevent_groups;
|
||||||
|
static uint32_t next_id;
|
||||||
|
static uint32_t next_vcpu_id;
|
||||||
|
|
||||||
QemuOptsList qemu_trace_opts = {
|
QemuOptsList qemu_trace_opts = {
|
||||||
.name = "trace",
|
.name = "trace",
|
||||||
|
@ -56,13 +59,29 @@ QemuOptsList qemu_trace_opts = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void trace_event_register_group(TraceEvent **events)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; events[i] != NULL; i++) {
|
||||||
|
events[i]->id = next_id++;
|
||||||
|
if (events[i]->vcpu_id != TRACE_VCPU_EVENT_NONE) {
|
||||||
|
events[i]->vcpu_id = next_vcpu_id++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
event_groups = g_renew(TraceEventGroup, event_groups, nevent_groups + 1);
|
||||||
|
event_groups[nevent_groups].events = events;
|
||||||
|
nevent_groups++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TraceEvent *trace_event_name(const char *name)
|
TraceEvent *trace_event_name(const char *name)
|
||||||
{
|
{
|
||||||
assert(name != NULL);
|
assert(name != NULL);
|
||||||
|
|
||||||
TraceEventID i;
|
TraceEventIter iter;
|
||||||
for (i = 0; i < trace_event_count(); i++) {
|
TraceEvent *ev;
|
||||||
TraceEvent *ev = trace_event_id(i);
|
trace_event_iter_init(&iter, NULL);
|
||||||
|
while ((ev = trace_event_iter_next(&iter)) != NULL) {
|
||||||
if (strcmp(trace_event_get_name(ev), name) == 0) {
|
if (strcmp(trace_event_get_name(ev), name) == 0) {
|
||||||
return ev;
|
return ev;
|
||||||
}
|
}
|
||||||
|
@ -101,25 +120,29 @@ static bool pattern_glob(const char *pat, const char *ev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev)
|
|
||||||
|
void trace_event_iter_init(TraceEventIter *iter, const char *pattern)
|
||||||
{
|
{
|
||||||
assert(pat != NULL);
|
iter->event = 0;
|
||||||
|
iter->group = 0;
|
||||||
|
iter->pattern = pattern;
|
||||||
|
}
|
||||||
|
|
||||||
TraceEventID i;
|
TraceEvent *trace_event_iter_next(TraceEventIter *iter)
|
||||||
|
{
|
||||||
if (ev == NULL) {
|
while (iter->group < nevent_groups &&
|
||||||
i = -1;
|
event_groups[iter->group].events[iter->event] != NULL) {
|
||||||
} else {
|
TraceEvent *ev = event_groups[iter->group].events[iter->event];
|
||||||
i = trace_event_get_id(ev);
|
iter->event++;
|
||||||
|
if (event_groups[iter->group].events[iter->event] == NULL) {
|
||||||
|
iter->event = 0;
|
||||||
|
iter->group++;
|
||||||
}
|
}
|
||||||
i++;
|
if (!iter->pattern ||
|
||||||
|
pattern_glob(iter->pattern,
|
||||||
while (i < trace_event_count()) {
|
trace_event_get_name(ev))) {
|
||||||
TraceEvent *res = trace_event_id(i);
|
return ev;
|
||||||
if (pattern_glob(pat, trace_event_get_name(res))) {
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -127,10 +150,11 @@ TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev)
|
||||||
|
|
||||||
void trace_list_events(void)
|
void trace_list_events(void)
|
||||||
{
|
{
|
||||||
int i;
|
TraceEventIter iter;
|
||||||
for (i = 0; i < trace_event_count(); i++) {
|
TraceEvent *ev;
|
||||||
TraceEvent *res = trace_event_id(i);
|
trace_event_iter_init(&iter, NULL);
|
||||||
fprintf(stderr, "%s\n", trace_event_get_name(res));
|
while ((ev = trace_event_iter_next(&iter)) != NULL) {
|
||||||
|
fprintf(stderr, "%s\n", trace_event_get_name(ev));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,25 +162,31 @@ static void do_trace_enable_events(const char *line_buf)
|
||||||
{
|
{
|
||||||
const bool enable = ('-' != line_buf[0]);
|
const bool enable = ('-' != line_buf[0]);
|
||||||
const char *line_ptr = enable ? line_buf : line_buf + 1;
|
const char *line_ptr = enable ? line_buf : line_buf + 1;
|
||||||
|
TraceEventIter iter;
|
||||||
|
TraceEvent *ev;
|
||||||
|
bool is_pattern = trace_event_is_pattern(line_ptr);
|
||||||
|
|
||||||
if (trace_event_is_pattern(line_ptr)) {
|
trace_event_iter_init(&iter, line_ptr);
|
||||||
TraceEvent *ev = NULL;
|
while ((ev = trace_event_iter_next(&iter)) != NULL) {
|
||||||
while ((ev = trace_event_pattern(line_ptr, ev)) != NULL) {
|
if (!trace_event_get_state_static(ev)) {
|
||||||
if (trace_event_get_state_static(ev)) {
|
if (!is_pattern) {
|
||||||
trace_event_set_state_dynamic_init(ev, enable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
TraceEvent *ev = trace_event_name(line_ptr);
|
|
||||||
if (ev == NULL) {
|
|
||||||
error_report("WARNING: trace event '%s' does not exist",
|
|
||||||
line_ptr);
|
|
||||||
} else if (!trace_event_get_state_static(ev)) {
|
|
||||||
error_report("WARNING: trace event '%s' is not traceable",
|
error_report("WARNING: trace event '%s' is not traceable",
|
||||||
line_ptr);
|
line_ptr);
|
||||||
} else {
|
return;
|
||||||
trace_event_set_state_dynamic_init(ev, enable);
|
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* start tracing */
|
||||||
|
trace_event_set_state_dynamic(ev, enable);
|
||||||
|
if (!is_pattern) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_pattern) {
|
||||||
|
error_report("WARNING: trace event '%s' does not exist",
|
||||||
|
line_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,3 +299,8 @@ char *trace_opt_parse(const char *optarg)
|
||||||
|
|
||||||
return trace_file;
|
return trace_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t trace_get_vcpu_event_count(void)
|
||||||
|
{
|
||||||
|
return next_vcpu_id;
|
||||||
|
}
|
||||||
|
|
112
trace/control.h
112
trace/control.h
|
@ -11,35 +11,37 @@
|
||||||
#define TRACE__CONTROL_H
|
#define TRACE__CONTROL_H
|
||||||
|
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "trace/generated-events.h"
|
#include "event-internal.h"
|
||||||
|
|
||||||
|
typedef struct TraceEventIter {
|
||||||
|
size_t event;
|
||||||
|
size_t group;
|
||||||
|
const char *pattern;
|
||||||
|
} TraceEventIter;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TraceEventID:
|
* trace_event_iter_init:
|
||||||
|
* @iter: the event iterator struct
|
||||||
|
* @pattern: optional pattern to filter events on name
|
||||||
*
|
*
|
||||||
* Unique tracing event identifier.
|
* Initialize the event iterator struct @iter,
|
||||||
*
|
* optionally using @pattern to filter out events
|
||||||
* These are named as 'TRACE_${EVENT_NAME}'.
|
* with non-matching names.
|
||||||
*
|
|
||||||
* See also: "trace/generated-events.h"
|
|
||||||
*/
|
*/
|
||||||
enum TraceEventID;
|
void trace_event_iter_init(TraceEventIter *iter, const char *pattern);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* trace_event_id:
|
* trace_event_iter_next:
|
||||||
* @id: Event identifier.
|
* @iter: the event iterator struct
|
||||||
*
|
*
|
||||||
* Get an event by its identifier.
|
* Get the next event, if any. When this returns NULL,
|
||||||
*
|
* the iterator should no longer be used.
|
||||||
* This routine has a constant cost, as opposed to trace_event_name and
|
|
||||||
* trace_event_pattern.
|
|
||||||
*
|
|
||||||
* Pre-conditions: The identifier is valid.
|
|
||||||
*
|
|
||||||
* Returns: pointer to #TraceEvent.
|
|
||||||
*
|
*
|
||||||
|
* Returns: the next event, or NULL if no more events exist
|
||||||
*/
|
*/
|
||||||
static TraceEvent *trace_event_id(TraceEventID id);
|
TraceEvent *trace_event_iter_next(TraceEventIter *iter);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* trace_event_name:
|
* trace_event_name:
|
||||||
|
@ -51,17 +53,6 @@ static TraceEvent *trace_event_id(TraceEventID id);
|
||||||
*/
|
*/
|
||||||
TraceEvent *trace_event_name(const char *name);
|
TraceEvent *trace_event_name(const char *name);
|
||||||
|
|
||||||
/**
|
|
||||||
* trace_event_pattern:
|
|
||||||
* @pat: Event name pattern.
|
|
||||||
* @ev: Event to start searching from (not included).
|
|
||||||
*
|
|
||||||
* Get all events with a given name pattern.
|
|
||||||
*
|
|
||||||
* Returns: pointer to #TraceEvent or NULL if not found.
|
|
||||||
*/
|
|
||||||
TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* trace_event_is_pattern:
|
* trace_event_is_pattern:
|
||||||
*
|
*
|
||||||
|
@ -69,31 +60,23 @@ TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev);
|
||||||
*/
|
*/
|
||||||
static bool trace_event_is_pattern(const char *str);
|
static bool trace_event_is_pattern(const char *str);
|
||||||
|
|
||||||
/**
|
|
||||||
* trace_event_count:
|
|
||||||
*
|
|
||||||
* Return the number of events.
|
|
||||||
*/
|
|
||||||
static TraceEventID trace_event_count(void);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* trace_event_get_id:
|
* trace_event_get_id:
|
||||||
*
|
*
|
||||||
* Get the identifier of an event.
|
* Get the identifier of an event.
|
||||||
*/
|
*/
|
||||||
static TraceEventID trace_event_get_id(TraceEvent *ev);
|
static uint32_t trace_event_get_id(TraceEvent *ev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* trace_event_get_vcpu_id:
|
* trace_event_get_vcpu_id:
|
||||||
*
|
*
|
||||||
* Get the per-vCPU identifier of an event.
|
* Get the per-vCPU identifier of an event.
|
||||||
*
|
*
|
||||||
* Special value #TRACE_VCPU_EVENT_COUNT means the event is not vCPU-specific
|
* Special value #TRACE_VCPU_EVENT_NONE means the event is not vCPU-specific
|
||||||
* (does not have the "vcpu" property).
|
* (does not have the "vcpu" property).
|
||||||
*/
|
*/
|
||||||
static TraceEventVCPUID trace_event_get_vcpu_id(TraceEvent *ev);
|
static uint32_t trace_event_get_vcpu_id(TraceEvent *ev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* trace_event_is_vcpu:
|
* trace_event_is_vcpu:
|
||||||
|
@ -111,14 +94,12 @@ static const char * trace_event_get_name(TraceEvent *ev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* trace_event_get_state:
|
* trace_event_get_state:
|
||||||
* @id: Event identifier.
|
* @id: Event identifier name.
|
||||||
*
|
*
|
||||||
* Get the tracing state of an event (both static and dynamic).
|
* Get the tracing state of an event (both static and dynamic).
|
||||||
*
|
*
|
||||||
* If the event has the disabled property, the check will have no performance
|
* If the event has the disabled property, the check will have no performance
|
||||||
* impact.
|
* impact.
|
||||||
*
|
|
||||||
* As a down side, you must always use an immediate #TraceEventID value.
|
|
||||||
*/
|
*/
|
||||||
#define trace_event_get_state(id) \
|
#define trace_event_get_state(id) \
|
||||||
((id ##_ENABLED) && trace_event_get_state_dynamic_by_id(id))
|
((id ##_ENABLED) && trace_event_get_state_dynamic_by_id(id))
|
||||||
|
@ -126,19 +107,18 @@ static const char * trace_event_get_name(TraceEvent *ev);
|
||||||
/**
|
/**
|
||||||
* trace_event_get_vcpu_state:
|
* trace_event_get_vcpu_state:
|
||||||
* @vcpu: Target vCPU.
|
* @vcpu: Target vCPU.
|
||||||
* @id: Event identifier (TraceEventID).
|
* @id: Event identifier name.
|
||||||
* @vcpu_id: Per-vCPU event identifier (TraceEventVCPUID).
|
|
||||||
*
|
*
|
||||||
* Get the tracing state of an event (both static and dynamic) for the given
|
* Get the tracing state of an event (both static and dynamic) for the given
|
||||||
* vCPU.
|
* vCPU.
|
||||||
*
|
*
|
||||||
* If the event has the disabled property, the check will have no performance
|
* If the event has the disabled property, the check will have no performance
|
||||||
* impact.
|
* impact.
|
||||||
*
|
|
||||||
* As a down side, you must always use an immediate #TraceEventID value.
|
|
||||||
*/
|
*/
|
||||||
#define trace_event_get_vcpu_state(vcpu, id, vcpu_id) \
|
#define trace_event_get_vcpu_state(vcpu, id) \
|
||||||
((id ##_ENABLED) && trace_event_get_vcpu_state_dynamic_by_vcpu_id(vcpu, vcpu_id))
|
((id ##_ENABLED) && \
|
||||||
|
trace_event_get_vcpu_state_dynamic_by_vcpu_id( \
|
||||||
|
vcpu, _ ## id ## _EVENT.vcpu_id))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* trace_event_get_state_static:
|
* trace_event_get_state_static:
|
||||||
|
@ -167,31 +147,6 @@ static bool trace_event_get_state_dynamic(TraceEvent *ev);
|
||||||
*/
|
*/
|
||||||
static bool trace_event_get_vcpu_state_dynamic(CPUState *vcpu, TraceEvent *ev);
|
static bool trace_event_get_vcpu_state_dynamic(CPUState *vcpu, TraceEvent *ev);
|
||||||
|
|
||||||
/**
|
|
||||||
* trace_event_set_state:
|
|
||||||
*
|
|
||||||
* Set the tracing state of an event (only if possible).
|
|
||||||
*/
|
|
||||||
#define trace_event_set_state(id, state) \
|
|
||||||
do { \
|
|
||||||
if ((id ##_ENABLED)) { \
|
|
||||||
TraceEvent *_e = trace_event_id(id); \
|
|
||||||
trace_event_set_state_dynamic(_e, state); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* trace_event_set_vcpu_state:
|
|
||||||
*
|
|
||||||
* Set the tracing state of an event for the given vCPU (only if not disabled).
|
|
||||||
*/
|
|
||||||
#define trace_event_set_vcpu_state(vcpu, id, state) \
|
|
||||||
do { \
|
|
||||||
if ((id ##_ENABLED)) { \
|
|
||||||
TraceEvent *_e = trace_event_id(id); \
|
|
||||||
trace_event_set_vcpu_state_dynamic(vcpu, _e, state); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* trace_event_set_state_dynamic:
|
* trace_event_set_state_dynamic:
|
||||||
|
@ -277,6 +232,13 @@ extern QemuOptsList qemu_trace_opts;
|
||||||
*/
|
*/
|
||||||
char *trace_opt_parse(const char *optarg);
|
char *trace_opt_parse(const char *optarg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* trace_get_vcpu_event_count:
|
||||||
|
*
|
||||||
|
* Return the number of known vcpu-specific events
|
||||||
|
*/
|
||||||
|
uint32_t trace_get_vcpu_event_count(void);
|
||||||
|
|
||||||
|
|
||||||
#include "trace/control-internal.h"
|
#include "trace/control-internal.h"
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,11 @@
|
||||||
#ifndef TRACE__EVENT_INTERNAL_H
|
#ifndef TRACE__EVENT_INTERNAL_H
|
||||||
#define TRACE__EVENT_INTERNAL_H
|
#define TRACE__EVENT_INTERNAL_H
|
||||||
|
|
||||||
#include "trace/generated-events.h"
|
/*
|
||||||
|
* Special value for TraceEvent.vcpu_id field to indicate
|
||||||
|
* that the event is not VCPU specific
|
||||||
|
*/
|
||||||
|
#define TRACE_VCPU_EVENT_NONE ((uint32_t)-1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TraceEvent:
|
* TraceEvent:
|
||||||
|
@ -19,14 +22,21 @@
|
||||||
* @vcpu_id: Unique per-vCPU event identifier.
|
* @vcpu_id: Unique per-vCPU event identifier.
|
||||||
* @name: Event name.
|
* @name: Event name.
|
||||||
* @sstate: Static tracing state.
|
* @sstate: Static tracing state.
|
||||||
|
* @dstate: Dynamic tracing state
|
||||||
|
*
|
||||||
|
* Interpretation of @dstate depends on whether the event has the 'vcpu'
|
||||||
|
* property:
|
||||||
|
* - false: Boolean value indicating whether the event is active.
|
||||||
|
* - true : Integral counting the number of vCPUs that have this event enabled.
|
||||||
*
|
*
|
||||||
* Opaque generic description of a tracing event.
|
* Opaque generic description of a tracing event.
|
||||||
*/
|
*/
|
||||||
typedef struct TraceEvent {
|
typedef struct TraceEvent {
|
||||||
TraceEventID id;
|
uint32_t id;
|
||||||
TraceEventVCPUID vcpu_id;
|
uint32_t vcpu_id;
|
||||||
const char * name;
|
const char * name;
|
||||||
const bool sstate;
|
const bool sstate;
|
||||||
|
uint16_t *dstate;
|
||||||
} TraceEvent;
|
} TraceEvent;
|
||||||
|
|
||||||
void trace_event_set_state_dynamic_init(TraceEvent *ev, bool state);
|
void trace_event_set_state_dynamic_init(TraceEvent *ev, bool state);
|
||||||
|
|
|
@ -51,6 +51,12 @@ bool ftrace_init(void)
|
||||||
snprintf(path, PATH_MAX, "%s/tracing/tracing_on", debugfs);
|
snprintf(path, PATH_MAX, "%s/tracing/tracing_on", debugfs);
|
||||||
trace_fd = open(path, O_WRONLY);
|
trace_fd = open(path, O_WRONLY);
|
||||||
if (trace_fd < 0) {
|
if (trace_fd < 0) {
|
||||||
|
if (errno == EACCES) {
|
||||||
|
trace_marker_fd = open("/dev/null", O_WRONLY);
|
||||||
|
if (trace_marker_fd != -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
perror("Could not open ftrace 'tracing_on' file");
|
perror("Could not open ftrace 'tracing_on' file");
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
|
16
trace/qmp.c
16
trace/qmp.c
|
@ -52,8 +52,10 @@ static bool check_events(bool has_vcpu, bool ignore_unavailable, bool is_pattern
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
/* error for unavailable events */
|
/* error for unavailable events */
|
||||||
TraceEvent *ev = NULL;
|
TraceEventIter iter;
|
||||||
while ((ev = trace_event_pattern(name, ev)) != NULL) {
|
TraceEvent *ev;
|
||||||
|
trace_event_iter_init(&iter, name);
|
||||||
|
while ((ev = trace_event_iter_next(&iter)) != NULL) {
|
||||||
if (!ignore_unavailable && !trace_event_get_state_static(ev)) {
|
if (!ignore_unavailable && !trace_event_get_state_static(ev)) {
|
||||||
error_setg(errp, "event \"%s\" is disabled", trace_event_get_name(ev));
|
error_setg(errp, "event \"%s\" is disabled", trace_event_get_name(ev));
|
||||||
return false;
|
return false;
|
||||||
|
@ -69,6 +71,7 @@ TraceEventInfoList *qmp_trace_event_get_state(const char *name,
|
||||||
{
|
{
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
TraceEventInfoList *events = NULL;
|
TraceEventInfoList *events = NULL;
|
||||||
|
TraceEventIter iter;
|
||||||
TraceEvent *ev;
|
TraceEvent *ev;
|
||||||
bool is_pattern = trace_event_is_pattern(name);
|
bool is_pattern = trace_event_is_pattern(name);
|
||||||
CPUState *cpu;
|
CPUState *cpu;
|
||||||
|
@ -86,8 +89,8 @@ TraceEventInfoList *qmp_trace_event_get_state(const char *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get states (all errors checked above) */
|
/* Get states (all errors checked above) */
|
||||||
ev = NULL;
|
trace_event_iter_init(&iter, name);
|
||||||
while ((ev = trace_event_pattern(name, ev)) != NULL) {
|
while ((ev = trace_event_iter_next(&iter)) != NULL) {
|
||||||
TraceEventInfoList *elem;
|
TraceEventInfoList *elem;
|
||||||
bool is_vcpu = trace_event_is_vcpu(ev);
|
bool is_vcpu = trace_event_is_vcpu(ev);
|
||||||
if (has_vcpu && !is_vcpu) {
|
if (has_vcpu && !is_vcpu) {
|
||||||
|
@ -132,6 +135,7 @@ void qmp_trace_event_set_state(const char *name, bool enable,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
TraceEventIter iter;
|
||||||
TraceEvent *ev;
|
TraceEvent *ev;
|
||||||
bool is_pattern = trace_event_is_pattern(name);
|
bool is_pattern = trace_event_is_pattern(name);
|
||||||
CPUState *cpu;
|
CPUState *cpu;
|
||||||
|
@ -150,8 +154,8 @@ void qmp_trace_event_set_state(const char *name, bool enable,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply changes (all errors checked above) */
|
/* Apply changes (all errors checked above) */
|
||||||
ev = NULL;
|
trace_event_iter_init(&iter, name);
|
||||||
while ((ev = trace_event_pattern(name, ev)) != NULL) {
|
while ((ev = trace_event_iter_next(&iter)) != NULL) {
|
||||||
if (!trace_event_get_state_static(ev) ||
|
if (!trace_event_get_state_static(ev) ||
|
||||||
(has_vcpu && !trace_event_is_vcpu(ev))) {
|
(has_vcpu && !trace_event_is_vcpu(ev))) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -17,14 +17,14 @@
|
||||||
#include "trace/control.h"
|
#include "trace/control.h"
|
||||||
#include "trace/simple.h"
|
#include "trace/simple.h"
|
||||||
|
|
||||||
/** Trace file header event ID */
|
/** Trace file header event ID, picked to avoid conflict with real event IDs */
|
||||||
#define HEADER_EVENT_ID (~(uint64_t)0) /* avoids conflicting with TraceEventIDs */
|
#define HEADER_EVENT_ID (~(uint64_t)0)
|
||||||
|
|
||||||
/** Trace file magic number */
|
/** Trace file magic number */
|
||||||
#define HEADER_MAGIC 0xf2b177cb0aa429b4ULL
|
#define HEADER_MAGIC 0xf2b177cb0aa429b4ULL
|
||||||
|
|
||||||
/** Trace file version number, bump if format changes */
|
/** Trace file version number, bump if format changes */
|
||||||
#define HEADER_VERSION 3
|
#define HEADER_VERSION 4
|
||||||
|
|
||||||
/** Records were dropped event ID */
|
/** Records were dropped event ID */
|
||||||
#define DROPPED_EVENT_ID (~(uint64_t)0 - 1)
|
#define DROPPED_EVENT_ID (~(uint64_t)0 - 1)
|
||||||
|
@ -56,9 +56,12 @@ static uint32_t trace_pid;
|
||||||
static FILE *trace_fp;
|
static FILE *trace_fp;
|
||||||
static char *trace_file_name;
|
static char *trace_file_name;
|
||||||
|
|
||||||
|
#define TRACE_RECORD_TYPE_MAPPING 0
|
||||||
|
#define TRACE_RECORD_TYPE_EVENT 1
|
||||||
|
|
||||||
/* * Trace buffer entry */
|
/* * Trace buffer entry */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t event; /* TraceEventID */
|
uint64_t event; /* event ID value */
|
||||||
uint64_t timestamp_ns;
|
uint64_t timestamp_ns;
|
||||||
uint32_t length; /* in bytes */
|
uint32_t length; /* in bytes */
|
||||||
uint32_t pid;
|
uint32_t pid;
|
||||||
|
@ -160,6 +163,7 @@ static gpointer writeout_thread(gpointer opaque)
|
||||||
unsigned int idx = 0;
|
unsigned int idx = 0;
|
||||||
int dropped_count;
|
int dropped_count;
|
||||||
size_t unused __attribute__ ((unused));
|
size_t unused __attribute__ ((unused));
|
||||||
|
uint64_t type = TRACE_RECORD_TYPE_EVENT;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
wait_for_trace_records_available();
|
wait_for_trace_records_available();
|
||||||
|
@ -174,10 +178,12 @@ static gpointer writeout_thread(gpointer opaque)
|
||||||
} while (!g_atomic_int_compare_and_exchange(&dropped_events,
|
} while (!g_atomic_int_compare_and_exchange(&dropped_events,
|
||||||
dropped_count, 0));
|
dropped_count, 0));
|
||||||
dropped.rec.arguments[0] = dropped_count;
|
dropped.rec.arguments[0] = dropped_count;
|
||||||
|
unused = fwrite(&type, sizeof(type), 1, trace_fp);
|
||||||
unused = fwrite(&dropped.rec, dropped.rec.length, 1, trace_fp);
|
unused = fwrite(&dropped.rec, dropped.rec.length, 1, trace_fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (get_trace_record(idx, &recordptr)) {
|
while (get_trace_record(idx, &recordptr)) {
|
||||||
|
unused = fwrite(&type, sizeof(type), 1, trace_fp);
|
||||||
unused = fwrite(recordptr, recordptr->length, 1, trace_fp);
|
unused = fwrite(recordptr, recordptr->length, 1, trace_fp);
|
||||||
writeout_idx += recordptr->length;
|
writeout_idx += recordptr->length;
|
||||||
free(recordptr); /* don't use g_free, can deadlock when traced */
|
free(recordptr); /* don't use g_free, can deadlock when traced */
|
||||||
|
@ -202,7 +208,7 @@ void trace_record_write_str(TraceBufferRecord *rec, const char *s, uint32_t slen
|
||||||
rec->rec_off = write_to_buffer(rec->rec_off, (void*)s, slen);
|
rec->rec_off = write_to_buffer(rec->rec_off, (void*)s, slen);
|
||||||
}
|
}
|
||||||
|
|
||||||
int trace_record_start(TraceBufferRecord *rec, TraceEventID event, size_t datasize)
|
int trace_record_start(TraceBufferRecord *rec, uint32_t event, size_t datasize)
|
||||||
{
|
{
|
||||||
unsigned int idx, rec_off, old_idx, new_idx;
|
unsigned int idx, rec_off, old_idx, new_idx;
|
||||||
uint32_t rec_len = sizeof(TraceRecord) + datasize;
|
uint32_t rec_len = sizeof(TraceRecord) + datasize;
|
||||||
|
@ -273,6 +279,28 @@ void trace_record_finish(TraceBufferRecord *rec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int st_write_event_mapping(void)
|
||||||
|
{
|
||||||
|
uint64_t type = TRACE_RECORD_TYPE_MAPPING;
|
||||||
|
TraceEventIter iter;
|
||||||
|
TraceEvent *ev;
|
||||||
|
|
||||||
|
trace_event_iter_init(&iter, NULL);
|
||||||
|
while ((ev = trace_event_iter_next(&iter)) != NULL) {
|
||||||
|
uint64_t id = trace_event_get_id(ev);
|
||||||
|
const char *name = trace_event_get_name(ev);
|
||||||
|
uint32_t len = strlen(name);
|
||||||
|
if (fwrite(&type, sizeof(type), 1, trace_fp) != 1 ||
|
||||||
|
fwrite(&id, sizeof(id), 1, trace_fp) != 1 ||
|
||||||
|
fwrite(&len, sizeof(len), 1, trace_fp) != 1 ||
|
||||||
|
fwrite(name, len, 1, trace_fp) != 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void st_set_trace_file_enabled(bool enable)
|
void st_set_trace_file_enabled(bool enable)
|
||||||
{
|
{
|
||||||
if (enable == !!trace_fp) {
|
if (enable == !!trace_fp) {
|
||||||
|
@ -297,7 +325,8 @@ void st_set_trace_file_enabled(bool enable)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fwrite(&header, sizeof header, 1, trace_fp) != 1) {
|
if (fwrite(&header, sizeof header, 1, trace_fp) != 1 ||
|
||||||
|
st_write_event_mapping() < 0) {
|
||||||
fclose(trace_fp);
|
fclose(trace_fp);
|
||||||
trace_fp = NULL;
|
trace_fp = NULL;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -11,10 +11,6 @@
|
||||||
#ifndef TRACE_SIMPLE_H
|
#ifndef TRACE_SIMPLE_H
|
||||||
#define TRACE_SIMPLE_H
|
#define TRACE_SIMPLE_H
|
||||||
|
|
||||||
|
|
||||||
#include "trace/generated-events.h"
|
|
||||||
|
|
||||||
|
|
||||||
void st_print_trace_file_status(FILE *stream, fprintf_function stream_printf);
|
void st_print_trace_file_status(FILE *stream, fprintf_function stream_printf);
|
||||||
void st_set_trace_file_enabled(bool enable);
|
void st_set_trace_file_enabled(bool enable);
|
||||||
void st_set_trace_file(const char *file);
|
void st_set_trace_file(const char *file);
|
||||||
|
@ -33,7 +29,7 @@ typedef struct {
|
||||||
*
|
*
|
||||||
* @arglen number of bytes required for arguments
|
* @arglen number of bytes required for arguments
|
||||||
*/
|
*/
|
||||||
int trace_record_start(TraceBufferRecord *rec, TraceEventID id, size_t arglen);
|
int trace_record_start(TraceBufferRecord *rec, uint32_t id, size_t arglen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a 64-bit argument to a trace record
|
* Append a 64-bit argument to a trace record
|
||||||
|
|
2
vl.c
2
vl.c
|
@ -3024,6 +3024,8 @@ int main(int argc, char **argv, char **envp)
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
bool list_data_dirs = false;
|
bool list_data_dirs = false;
|
||||||
|
|
||||||
|
module_call_init(MODULE_INIT_TRACE);
|
||||||
|
|
||||||
qemu_init_cpu_list();
|
qemu_init_cpu_list();
|
||||||
qemu_init_cpu_loop();
|
qemu_init_cpu_loop();
|
||||||
qemu_mutex_lock_iothread();
|
qemu_mutex_lock_iothread();
|
||||||
|
|
Loading…
Reference in New Issue