diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-10-12 11:05:21 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-10-12 11:05:21 +0100 |
commit | ae4b28ace9554385eec50e2e330526159836c33d (patch) | |
tree | 1c4a0ac151d4096f7a16be82bd6533a698d85808 | |
parent | 6b39b06339ee59559b31f860d4af635b046322df (diff) | |
parent | f5e2b3be82ec7e2ec8fed37da3fb2da469ae7d4b (diff) |
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>
51 files changed, 504 insertions, 461 deletions
@@ -56,9 +56,6 @@ GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c GENERATED_HEADERS += qmp-introspect.h GENERATED_SOURCES += qmp-introspect.c -GENERATED_HEADERS += trace/generated-events.h -GENERATED_SOURCES += trace/generated-events.c - GENERATED_HEADERS += trace/generated-tracers.h ifeq ($(findstring dtrace,$(TRACE_BACKENDS)),dtrace) GENERATED_HEADERS += trace/generated-tracers-dtrace.h diff --git a/Makefile.target b/Makefile.target index 9968871d6e..2c46091225 100644 --- a/Makefile.target +++ b/Makefile.target @@ -55,7 +55,7 @@ $(QEMU_PROG).stp-installed: $(BUILD_DIR)/trace-events-all --binary=$(bindir)/$(QEMU_PROG) \ --target-name=$(TARGET_NAME) \ --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 $(call quiet-command,$(TRACETOOL) \ @@ -64,14 +64,14 @@ $(QEMU_PROG).stp: $(BUILD_DIR)/trace-events-all --binary=$(realpath .)/$(QEMU_PROG) \ --target-name=$(TARGET_NAME) \ --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 $(call quiet-command,$(TRACETOOL) \ --format=simpletrace-stap \ --backends=$(TRACE_BACKENDS) \ --probe-prefix=qemu.$(TARGET_TYPE).$(TARGET_NAME) \ - < $< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG)-simpletrace.stp") + $< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG)-simpletrace.stp") else stap: diff --git a/bsd-user/main.c b/bsd-user/main.c index d8367bda46..4fd7b6396d 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -740,6 +740,7 @@ int main(int argc, char **argv) if (argc <= 1) usage(); + module_call_init(MODULE_INIT_TRACE); qemu_init_cpu_list(); module_call_init(MODULE_INIT_QOM); diff --git a/include/qemu/module.h b/include/qemu/module.h index dc2c9d4c4e..877cca7d7b 100644 --- a/include/qemu/module.h +++ b/include/qemu/module.h @@ -44,6 +44,7 @@ typedef enum { MODULE_INIT_OPTS, MODULE_INIT_QAPI, MODULE_INIT_QOM, + MODULE_INIT_TRACE, MODULE_INIT_MAX } module_init_type; @@ -51,6 +52,7 @@ typedef enum { #define opts_init(function) module_init(function, MODULE_INIT_OPTS) #define qapi_init(function) module_init(function, MODULE_INIT_QAPI) #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) diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 22b54d6d93..6d481a1dc0 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -27,7 +27,6 @@ #include "qemu/bitmap.h" #include "qemu/queue.h" #include "qemu/thread.h" -#include "trace/generated-events.h" typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size, void *opaque); @@ -345,8 +344,12 @@ struct CPUState { struct KVMState *kvm_state; 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. */ int cpu_index; /* used by alpha TCG */ diff --git a/include/trace-tcg.h b/include/trace-tcg.h index edab4b159c..da68608c85 100644 --- a/include/trace-tcg.h +++ b/include/trace-tcg.h @@ -2,6 +2,5 @@ #define TRACE_TCG_H #include "trace/generated-tcg-tracers.h" -#include "trace/generated-events.h" #endif /* TRACE_TCG_H */ diff --git a/include/trace.h b/include/trace.h index 9a01e4454b..ac9ff3dddd 100644 --- a/include/trace.h +++ b/include/trace.h @@ -2,6 +2,5 @@ #define TRACE_H #include "trace/generated-tracers.h" -#include "trace/generated-events.h" #endif /* TRACE_H */ diff --git a/linux-user/main.c b/linux-user/main.c index 9e4b430d66..0e31dad684 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -4158,6 +4158,7 @@ int main(int argc, char **argv, char **envp) int ret; int execfd; + module_call_init(MODULE_INIT_TRACE); qemu_init_cpu_list(); module_call_init(MODULE_INIT_QOM); @@ -3330,13 +3330,14 @@ void info_trace_events_completion(ReadLineState *rs, int nb_args, const char *st len = strlen(str); readline_set_completion_index(rs, len); if (nb_args == 2) { - TraceEventID id; - for (id = 0; id < trace_event_count(); id++) { - const char *event_name = trace_event_get_name(trace_event_id(id)); - if (!strncmp(str, event_name, len)) { - readline_add_completion(rs, event_name); - } + TraceEventIter iter; + TraceEvent *ev; + char *pattern = g_strdup_printf("%s*", str); + trace_event_iter_init(&iter, pattern); + 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); readline_set_completion_index(rs, len); if (nb_args == 2) { - TraceEventID id; - for (id = 0; id < trace_event_count(); id++) { - const char *event_name = trace_event_get_name(trace_event_id(id)); - if (!strncmp(str, event_name, len)) { - readline_add_completion(rs, event_name); - } + TraceEventIter iter; + TraceEvent *ev; + char *pattern = g_strdup_printf("%s*", str); + trace_event_iter_init(&iter, pattern); + 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) { add_completion_option(rs, str, "on"); add_completion_option(rs, str, "off"); diff --git a/net/trace-events b/net/trace-events index 65c46a48fb..d67f048825 100644 --- a/net/trace-events +++ b/net/trace-events @@ -2,3 +2,19 @@ # net/vhost-user.c 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" diff --git a/qemu-img.c b/qemu-img.c index ceffefeacb..02c07b913d 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -4165,6 +4165,7 @@ int main(int argc, char **argv) signal(SIGPIPE, SIG_IGN); #endif + module_call_init(MODULE_INIT_TRACE); error_set_progname(argv[0]); qemu_init_exec_dir(argv[0]); @@ -467,6 +467,7 @@ int main(int argc, char **argv) signal(SIGPIPE, SIG_IGN); #endif + module_call_init(MODULE_INIT_TRACE); progname = basename(argv[0]); qemu_init_exec_dir(argv[0]); diff --git a/qemu-nbd.c b/qemu-nbd.c index 705b95ec29..cca4a983b7 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -533,6 +533,7 @@ int main(int argc, char **argv) sa_sigterm.sa_handler = termsig_handler; sigaction(SIGTERM, &sa_sigterm, NULL); + module_call_init(MODULE_INIT_TRACE); qcrypto_init(&error_fatal); module_call_init(MODULE_INIT_QOM); @@ -360,12 +360,15 @@ static void cpu_common_initfn(Object *obj) qemu_mutex_init(&cpu->work_mutex); QTAILQ_INIT(&cpu->breakpoints); 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) { - 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) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 3916c6d14a..4ca903dc0c 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -12,13 +12,16 @@ import struct import re import inspect -from tracetool import _read_events, Event +from tracetool import read_events, Event from tracetool.backend.simple import is_string header_event_id = 0xffffffffffffffff header_magic = 0xf2b177cb0aa429b4 dropped_event_id = 0xfffffffffffffffe +record_type_mapping = 0 +record_type_event = 1 + log_header_fmt = '=QQQ' rec_header_fmt = '=QQII' @@ -30,14 +33,16 @@ def read_header(fobj, hfmt): return None return struct.unpack(hfmt, hdr) -def get_record(edict, rechdr, fobj): - """Deserialize a trace record from a file into a tuple (event_num, timestamp, pid, arg1, ..., arg6).""" +def get_record(edict, idtoname, rechdr, fobj): + """Deserialize a trace record from a file into a tuple + (name, timestamp, pid, arg1, ..., arg6).""" if rechdr is None: return None - rec = (rechdr[0], rechdr[1], rechdr[3]) if rechdr[0] != dropped_event_id: 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: if is_string(type): l = fobj.read(4) @@ -48,15 +53,22 @@ def get_record(edict, rechdr, fobj): (value,) = struct.unpack('=Q', fobj.read(8)) rec = rec + (value,) else: + rec = ("dropped", rechdr[1], rechdr[3]) (value,) = struct.unpack('=Q', fobj.read(8)) rec = rec + (value,) 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) + + return (event_id, name) -def read_record(edict, fobj): +def read_record(edict, idtoname, fobj): """Deserialize a trace record from a file into a tuple (event_num, timestamp, pid, arg1, ..., arg6).""" 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): """Read and verify trace file header""" @@ -67,20 +79,30 @@ def read_trace_header(fobj): raise ValueError('Not a valid trace file!') 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!') - if log_version != 3: + if log_version != 4: raise ValueError('Log format %d not supported with this QEMU release!' % log_version) def read_trace_records(edict, fobj): """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6).""" + idtoname = { + dropped_event_id: "dropped" + } while True: - rec = read_record(edict, fobj) - if rec is None: + t = fobj.read(8) + if len(t) == 0: break - yield rec + (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 class Analyzer(object): """A trace file analyzer which processes trace records. @@ -107,7 +129,7 @@ class Analyzer(object): def process(events, log, analyzer, read_header=True): """Invoke an analyzer on each event in a log.""" if isinstance(events, str): - events = _read_events(open(events, 'r')) + events = read_events(open(events, 'r')) if isinstance(log, str): log = open(log, 'rb') @@ -115,10 +137,10 @@ def process(events, log, analyzer, read_header=True): read_trace_header(log) 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): - edict[num] = event + for event in events: + edict[event.name] = event def build_fn(analyzer, event): if isinstance(event, str): @@ -166,7 +188,7 @@ def run(analyzer): '<trace-file>\n' % sys.argv[0]) 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) if __name__ == '__main__': diff --git a/scripts/tracetool.py b/scripts/tracetool.py index 7b82959e84..629b2593c8 100755 --- a/scripts/tracetool.py +++ b/scripts/tracetool.py @@ -15,6 +15,8 @@ __email__ = "stefanha@linux.vnet.ibm.com" import sys import getopt +import os.path +import re from tracetool import error_write, out import tracetool.backend @@ -60,6 +62,15 @@ Options: else: 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): global _SCRIPT @@ -129,8 +140,15 @@ def main(args): if probe_prefix is None: 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: - tracetool.generate(sys.stdin, arg_format, arg_backends, + tracetool.generate(events, group, arg_format, arg_backends, binary=binary, probe_prefix=probe_prefix) except tracetool.TracetoolError as e: error_opt(str(e)) diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py index be24039c5e..365446fa53 100644 --- a/scripts/tracetool/__init__.py +++ b/scripts/tracetool/__init__.py @@ -265,11 +265,13 @@ class Event(object): QEMU_TRACE = "trace_%(name)s" QEMU_TRACE_TCG = QEMU_TRACE + "_tcg" + QEMU_DSTATE = "_TRACE_%(NAME)s_DSTATE" + QEMU_EVENT = "_TRACE_%(NAME)s_EVENT" def api(self, fmt=None): if fmt is None: fmt = Event.QEMU_TRACE - return fmt % {"name": self.name} + return fmt % {"name": self.name, "NAME": self.name.upper()} def transform(self, *trans): """Return a new Event with transformed Arguments.""" @@ -280,7 +282,17 @@ class Event(object): 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 = [] for line in fobj: if not line.strip(): @@ -352,14 +364,16 @@ def try_import(mod_name, attr_name=None, attr_default=None): return False, None -def generate(fevents, format, backends, +def generate(events, group, format, backends, binary=None, probe_prefix=None): """Generate the output for the given (format, backends) pair. Parameters ---------- - fevents : file - Event description file. + events : list + list of Event objects to generate for + group: str + Name of the tracing group format : str Output format name. backends : list @@ -389,6 +403,4 @@ def generate(fevents, format, backends, tracetool.backend.dtrace.BINARY = binary tracetool.backend.dtrace.PROBEPREFIX = probe_prefix - events = _read_events(fevents) - - tracetool.format.generate(events, format, backend) + tracetool.format.generate(events, format, backend, group) diff --git a/scripts/tracetool/backend/__init__.py b/scripts/tracetool/backend/__init__.py index d4b6dab9ca..f735a259c0 100644 --- a/scripts/tracetool/backend/__init__.py +++ b/scripts/tracetool/backend/__init__.py @@ -113,11 +113,11 @@ class Wrapper: if func is not None: func(*args, **kwargs) - def generate_begin(self, events): - self._run_function("generate_%s_begin", events) + def generate_begin(self, events, group): + self._run_function("generate_%s_begin", events, group) - def generate(self, event): - self._run_function("generate_%s", event) + def generate(self, event, group): + self._run_function("generate_%s", event, group) - def generate_end(self, events): - self._run_function("generate_%s_end", events) + def generate_end(self, events, group): + self._run_function("generate_%s_end", events, group) diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py index ab9ecfab30..79505c6b1a 100644 --- a/scripts/tracetool/backend/dtrace.py +++ b/scripts/tracetool/backend/dtrace.py @@ -35,12 +35,12 @@ def binary(): return BINARY -def generate_h_begin(events): +def generate_h_begin(events, group): out('#include "trace/generated-tracers-dtrace.h"', '') -def generate_h(event): +def generate_h(event, group): out(' QEMU_%(uppername)s(%(argnames)s);', uppername=event.name.upper(), argnames=", ".join(event.args.names())) diff --git a/scripts/tracetool/backend/ftrace.py b/scripts/tracetool/backend/ftrace.py index 80dcf30478..db9fe7ad57 100644 --- a/scripts/tracetool/backend/ftrace.py +++ b/scripts/tracetool/backend/ftrace.py @@ -19,13 +19,12 @@ from tracetool import out PUBLIC = True -def generate_h_begin(events): +def generate_h_begin(events, group): out('#include "trace/ftrace.h"', - '#include "trace/control.h"', '') -def generate_h(event): +def generate_h(event, group): argnames = ", ".join(event.args.names()) if len(event.args) > 0: argnames = ", " + argnames diff --git a/scripts/tracetool/backend/log.py b/scripts/tracetool/backend/log.py index b3ff064011..4f4a4d38b1 100644 --- a/scripts/tracetool/backend/log.py +++ b/scripts/tracetool/backend/log.py @@ -19,13 +19,12 @@ from tracetool import out PUBLIC = True -def generate_h_begin(events): - out('#include "trace/control.h"', - '#include "qemu/log.h"', +def generate_h_begin(events, group): + out('#include "qemu/log.h"', '') -def generate_h(event): +def generate_h(event, group): argnames = ", ".join(event.args.names()) if len(event.args) > 0: argnames = ", " + argnames diff --git a/scripts/tracetool/backend/simple.py b/scripts/tracetool/backend/simple.py index 1bccada63d..9885e83cd4 100644 --- a/scripts/tracetool/backend/simple.py +++ b/scripts/tracetool/backend/simple.py @@ -27,7 +27,7 @@ def is_string(arg): return False -def generate_h_begin(events): +def generate_h_begin(events, group): for event in events: out('void _simple_%(api)s(%(args)s);', api=event.api(), @@ -35,13 +35,13 @@ def generate_h_begin(events): out('') -def generate_h(event): +def generate_h(event, group): out(' _simple_%(api)s(%(args)s);', api=event.api(), args=", ".join(event.args.names())) -def generate_c_begin(events): +def generate_c_begin(events, group): out('#include "qemu/osdep.h"', '#include "trace.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)', '{', ' TraceBufferRecord rec;', @@ -80,11 +80,11 @@ def generate_c(event): ' 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 ! */', ' }', cond=cond, - event_id=event_id, + event_obj=event.api(event.QEMU_EVENT), size_str=sizestr) if len(event.args) > 0: diff --git a/scripts/tracetool/backend/syslog.py b/scripts/tracetool/backend/syslog.py index 89019bc759..b8ff2790c4 100644 --- a/scripts/tracetool/backend/syslog.py +++ b/scripts/tracetool/backend/syslog.py @@ -19,13 +19,12 @@ from tracetool import out PUBLIC = True -def generate_h_begin(events): +def generate_h_begin(events, group): out('#include <syslog.h>', - '#include "trace/control.h"', '') -def generate_h(event): +def generate_h(event, group): argnames = ", ".join(event.args.names()) if len(event.args) > 0: argnames = ", " + argnames diff --git a/scripts/tracetool/backend/ust.py b/scripts/tracetool/backend/ust.py index ed4c227f69..4594db6128 100644 --- a/scripts/tracetool/backend/ust.py +++ b/scripts/tracetool/backend/ust.py @@ -19,13 +19,13 @@ from tracetool import out PUBLIC = True -def generate_h_begin(events): +def generate_h_begin(events, group): out('#include <lttng/tracepoint.h>', '#include "trace/generated-ust-provider.h"', '') -def generate_h(event): +def generate_h(event, group): argnames = ", ".join(event.args.names()) if len(event.args) > 0: argnames = ", " + argnames diff --git a/scripts/tracetool/format/__init__.py b/scripts/tracetool/format/__init__.py index 812570ff6f..cf6e0e2da5 100644 --- a/scripts/tracetool/format/__init__.py +++ b/scripts/tracetool/format/__init__.py @@ -74,7 +74,7 @@ def exists(name): return tracetool.try_import("tracetool.format." + name)[1] -def generate(events, format, backend): +def generate(events, format, backend, group): if not exists(format): raise ValueError("unknown format: %s" % format) format = format.replace("-", "_") @@ -82,4 +82,4 @@ def generate(events, format, backend): "generate")[1] if func is None: raise AttributeError("format has no 'generate': %s" % format) - func(events, backend) + func(events, backend, group) diff --git a/scripts/tracetool/format/c.py b/scripts/tracetool/format/c.py index 699598fb02..47115ed8af 100644 --- a/scripts/tracetool/format/c.py +++ b/scripts/tracetool/format/c.py @@ -16,13 +16,55 @@ __email__ = "stefanha@linux.vnet.ibm.com" from tracetool import out -def generate(events, backend): - events = [e for e in events - if "disable" not in e.properties] +def generate(events, backend, group): + active_events = [e for e in events + if "disable" not in e.properties] 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: - backend.generate(event) - backend.generate_end(events) + + for e in events: + out('uint16_t %s;' % e.api(e.QEMU_DSTATE)) + + 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) diff --git a/scripts/tracetool/format/d.py b/scripts/tracetool/format/d.py index c77d5b7ab0..78397c24d2 100644 --- a/scripts/tracetool/format/d.py +++ b/scripts/tracetool/format/d.py @@ -29,7 +29,7 @@ RESERVED_WORDS = ( ) -def generate(events, backend): +def generate(events, backend, group): events = [e for e in events if "disable" not in e.properties] diff --git a/scripts/tracetool/format/events_c.py b/scripts/tracetool/format/events_c.py deleted file mode 100644 index 4012063283..0000000000 --- a/scripts/tracetool/format/events_c.py +++ /dev/null @@ -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('};', - '') diff --git a/scripts/tracetool/format/events_h.py b/scripts/tracetool/format/events_h.py deleted file mode 100644 index a9da60b7fa..0000000000 --- a/scripts/tracetool/format/events_h.py +++ /dev/null @@ -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 */') diff --git a/scripts/tracetool/format/h.py b/scripts/tracetool/format/h.py index 3763e9aecb..3682f4e6a8 100644 --- a/scripts/tracetool/format/h.py +++ b/scripts/tracetool/format/h.py @@ -16,24 +16,43 @@ __email__ = "stefanha@linux.vnet.ibm.com" from tracetool import out -def generate(events, backend): +def generate(events, backend, group): out('/* This file is autogenerated by tracetool, do not edit. */', '', - '#ifndef TRACE__GENERATED_TRACERS_H', - '#define TRACE__GENERATED_TRACERS_H', + '#ifndef TRACE_%s_GENERATED_TRACERS_H' % group.upper(), + '#define TRACE_%s_GENERATED_TRACERS_H' % group.upper(), '', '#include "qemu-common.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: if "vcpu" in e.properties: trace_cpu = next(iter(e.args))[1] cond = "trace_event_get_vcpu_state(%(cpu)s,"\ - " TRACE_%(id)s,"\ - " TRACE_VCPU_%(id)s)"\ + " TRACE_%(id)s)"\ % dict( cpu=trace_cpu, id=e.name.upper()) @@ -49,11 +68,11 @@ def generate(events, backend): cond=cond) if "disable" not in e.properties: - backend.generate(e) + backend.generate(e, group) 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()) diff --git a/scripts/tracetool/format/simpletrace_stap.py b/scripts/tracetool/format/simpletrace_stap.py index 7e44bc1811..c35e662e00 100644 --- a/scripts/tracetool/format/simpletrace_stap.py +++ b/scripts/tracetool/format/simpletrace_stap.py @@ -19,8 +19,27 @@ from tracetool.backend.simple import is_string 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. */', + '', + '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): @@ -29,6 +48,7 @@ def generate(events, backend): out('probe %(probeprefix)s.simpletrace.%(name)s = %(probeprefix)s.%(name)s ?', '{', + ' id = simple_trace_map_event("%(name)s")', probeprefix=probeprefix(), name=e.name) @@ -48,7 +68,7 @@ def generate(events, backend): sizestr = ' + '.join(sizes) # Generate format string and value pairs for record header and arguments - fields = [('8b', str(event_id)), + fields = [('8b', 'id'), ('8b', 'gettimeofday_ns()'), ('4b', sizestr), ('4b', 'pid()')] @@ -63,7 +83,7 @@ def generate(events, backend): # Emit the entire record in a single SystemTap printf() fmt_str = '%'.join(fmt for fmt, _ 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) out('}') diff --git a/scripts/tracetool/format/stap.py b/scripts/tracetool/format/stap.py index 9e780f1b06..e8ef3e762d 100644 --- a/scripts/tracetool/format/stap.py +++ b/scripts/tracetool/format/stap.py @@ -34,7 +34,7 @@ def stap_escape(identifier): return identifier -def generate(events, backend): +def generate(events, backend, group): events = [e for e in events if "disable" not in e.properties] diff --git a/scripts/tracetool/format/tcg_h.py b/scripts/tracetool/format/tcg_h.py index e2331f251d..5f213f6cba 100644 --- a/scripts/tracetool/format/tcg_h.py +++ b/scripts/tracetool/format/tcg_h.py @@ -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. */', '/* You must include this file after the inclusion of helper.h */', '', - '#ifndef TRACE__GENERATED_TCG_TRACERS_H', - '#define TRACE__GENERATED_TCG_TRACERS_H', + '#ifndef TRACE_%s_GENERATED_TCG_TRACERS_H' % group.upper(), + '#define TRACE_%s_GENERATED_TCG_TRACERS_H' % group.upper(), '', '#include "trace.h"', '#include "exec/helper-proto.h"', @@ -63,4 +63,4 @@ def generate(events, backend): out('}') out('', - '#endif /* TRACE__GENERATED_TCG_TRACERS_H */') + '#endif /* TRACE_%s_GENERATED_TCG_TRACERS_H */' % group.upper()) diff --git a/scripts/tracetool/format/tcg_helper_c.py b/scripts/tracetool/format/tcg_helper_c.py index e3485b7f92..cc26e03008 100644 --- a/scripts/tracetool/format/tcg_helper_c.py +++ b/scripts/tracetool/format/tcg_helper_c.py @@ -40,7 +40,7 @@ def vcpu_transform_args(args, mode): assert False -def generate(events, backend): +def generate(events, backend, group): events = [e for e in events if "disable" not in e.properties] diff --git a/scripts/tracetool/format/tcg_helper_h.py b/scripts/tracetool/format/tcg_helper_h.py index dc76c15ebc..6b184b641b 100644 --- a/scripts/tracetool/format/tcg_helper_h.py +++ b/scripts/tracetool/format/tcg_helper_h.py @@ -18,7 +18,7 @@ from tracetool.transform import * import tracetool.vcpu -def generate(events, backend): +def generate(events, backend, group): events = [e for e in events if "disable" not in e.properties] diff --git a/scripts/tracetool/format/tcg_helper_wrapper_h.py b/scripts/tracetool/format/tcg_helper_wrapper_h.py index 020f4422a9..ff53447512 100644 --- a/scripts/tracetool/format/tcg_helper_wrapper_h.py +++ b/scripts/tracetool/format/tcg_helper_wrapper_h.py @@ -18,7 +18,7 @@ from tracetool.transform import * import tracetool.vcpu -def generate(events, backend): +def generate(events, backend, group): events = [e for e in events if "disable" not in e.properties] diff --git a/scripts/tracetool/format/ust_events_c.py b/scripts/tracetool/format/ust_events_c.py index 9967c7a82e..cd87d8ab8f 100644 --- a/scripts/tracetool/format/ust_events_c.py +++ b/scripts/tracetool/format/ust_events_c.py @@ -16,7 +16,7 @@ __email__ = "stefanha@redhat.com" from tracetool import out -def generate(events, backend): +def generate(events, backend, group): events = [e for e in events if "disabled" not in e.properties] diff --git a/scripts/tracetool/format/ust_events_h.py b/scripts/tracetool/format/ust_events_h.py index 3e8a7cdf19..d853155d21 100644 --- a/scripts/tracetool/format/ust_events_h.py +++ b/scripts/tracetool/format/ust_events_h.py @@ -16,7 +16,7 @@ __email__ = "stefanha@redhat.com" from tracetool import out -def generate(events, backend): +def generate(events, backend, group): events = [e for e in events if "disabled" not in e.properties] @@ -28,8 +28,9 @@ def generate(events, backend): '#undef TRACEPOINT_INCLUDE_FILE', '#define TRACEPOINT_INCLUDE_FILE ./generated-ust-provider.h', '', - '#if !defined (TRACE__GENERATED_UST_H) || defined(TRACEPOINT_HEADER_MULTI_READ)', - '#define TRACE__GENERATED_UST_H', + '#if !defined (TRACE_%s_GENERATED_UST_H) || \\' % group.upper(), + ' defined(TRACEPOINT_HEADER_MULTI_READ)', + '#define TRACE_%s_GENERATED_UST_H' % group.upper(), '', '#include "qemu-common.h"', '#include <lttng/tracepoint.h>', @@ -94,7 +95,7 @@ def generate(events, backend): '', 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 */', '#include <lttng/tracepoint-event.h>') diff --git a/stubs/trace-control.c b/stubs/trace-control.c index f765a02018..7f856e5c24 100644 --- a/stubs/trace-control.c +++ b/stubs/trace-control.c @@ -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) { - TraceEventID id; bool state_pre; 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 * dstate can only be 1 or 0. */ - state_pre = trace_events_dstate[id]; + state_pre = *(ev->dstate); if (state_pre != state) { if (state) { trace_events_enabled_count++; - trace_events_dstate[id] = 1; + *(ev->dstate) = 1; } else { trace_events_enabled_count--; - trace_events_dstate[id] = 0; + *(ev->dstate) = 0; } } } diff --git a/trace-events b/trace-events index 1a4e092418..8ecded5150 100644 --- a/trace-events +++ b/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_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 @@ -145,11 +129,13 @@ colo_filter_rewriter_conn_offset(uint32_t offset) ": offset=%u\n" # Hot-plug a new virtual (guest) CPU # +# Mode: user, softmmu # Targets: all vcpu guest_cpu_enter(void) # Reset the state of a virtual (guest) CPU # +# Mode: user, softmmu # Targets: all vcpu guest_cpu_reset(void) diff --git a/trace/Makefile.objs b/trace/Makefile.objs index 24d3b3758c..1e1ce7479d 100644 --- a/trace/Makefile.objs +++ b/trace/Makefile.objs @@ -22,7 +22,7 @@ $(obj)/generated-ust-provider.h-timestamp: $(BUILD_DIR)/trace-events-all $(trace $(call quiet-command,$(TRACETOOL) \ --format=ust-events-h \ --backends=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") $(obj)/generated-ust.c: $(obj)/generated-ust.c-timestamp $(BUILD_DIR)/config-host.mak @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) \ --format=ust-events-c \ --backends=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") -$(obj)/generated-events.h: $(obj)/generated-ust-provider.h -$(obj)/generated-events.c: $(obj)/generated-ust.c +$(obj)/generated-tracers.h: $(obj)/generated-ust-provider.h +$(obj)/generated-tracers.c: $(obj)/generated-ust.c 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 @@ -71,7 +50,7 @@ $(obj)/generated-tracers.h-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR) $(call quiet-command,$(TRACETOOL) \ --format=h \ --backends=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") ############################## # non-DTrace @@ -82,7 +61,7 @@ $(obj)/generated-tracers.c-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR) $(call quiet-command,$(TRACETOOL) \ --format=c \ --backends=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") $(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) \ --format=d \ --backends=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") $(obj)/generated-tracers-dtrace.h: $(obj)/generated-tracers-dtrace.dtrace $(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) \ --format=tcg-helper-wrapper-h \ --backend=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") $(obj)/generated-helpers.h: $(obj)/generated-helpers.h-timestamp @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) \ --format=tcg-helper-h \ --backend=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") $(obj)/generated-helpers.c: $(obj)/generated-helpers.c-timestamp @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) \ --format=tcg-helper-c \ --backend=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") $(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) \ --format=tcg-h \ --backend=$(TRACE_BACKENDS) \ - < $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") ###################################################################### # 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_UST) += generated-ust.o util-obj-y += control.o diff --git a/trace/control-internal.h b/trace/control-internal.h index a4e5f4aa06..a9d395a587 100644 --- a/trace/control-internal.h +++ b/trace/control-internal.h @@ -15,42 +15,29 @@ #include "qom/cpu.h" -extern TraceEvent trace_events[]; -extern uint16_t trace_events_dstate[]; 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) { assert(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); 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; } 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) @@ -65,26 +52,22 @@ static inline bool trace_event_get_state_static(TraceEvent *ev) return ev->sstate; } -static inline bool trace_event_get_state_dynamic_by_id(TraceEventID id) -{ - /* it's on fast path, avoid consistency checks (asserts) */ - return unlikely(trace_events_enabled_count) && trace_events_dstate[id]; -} +/* it's on fast path, avoid consistency checks (asserts) */ +#define trace_event_get_state_dynamic_by_id(id) \ + (unlikely(trace_events_enabled_count) && _ ## id ## _DSTATE) static inline bool trace_event_get_state_dynamic(TraceEvent *ev) { - TraceEventID id; - assert(trace_event_get_state_static(ev)); - id = trace_event_get_id(ev); - return trace_event_get_state_dynamic_by_id(id); + return unlikely(trace_events_enabled_count) && *ev->dstate; } -static inline bool trace_event_get_vcpu_state_dynamic_by_vcpu_id(CPUState *vcpu, - TraceEventVCPUID id) +static inline bool +trace_event_get_vcpu_state_dynamic_by_vcpu_id(CPUState *vcpu, + uint32_t vcpu_id) { /* it's on fast path, avoid consistency checks (asserts) */ if (unlikely(trace_events_enabled_count)) { - return test_bit(id, vcpu->trace_dstate); + return test_bit(vcpu_id, vcpu->trace_dstate); } else { 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, TraceEvent *ev) { - TraceEventVCPUID id; + uint32_t vcpu_id; assert(trace_event_is_vcpu(ev)); - id = trace_event_get_vcpu_id(ev); - return trace_event_get_vcpu_state_dynamic_by_vcpu_id(vcpu, id); + vcpu_id = trace_event_get_vcpu_id(ev); + 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 */ diff --git a/trace/control-target.c b/trace/control-target.c index 52fcce5a00..7ebf6e0bcb 100644 --- a/trace/control-target.c +++ b/trace/control-target.c @@ -16,21 +16,20 @@ void trace_event_set_state_dynamic_init(TraceEvent *ev, bool state) { - TraceEventID id = trace_event_get_id(ev); bool state_pre; assert(trace_event_get_state_static(ev)); /* * We ignore the "vcpu" property here, since no vCPUs have been created * 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) { trace_events_enabled_count++; - trace_events_dstate[id] = 1; + *ev->dstate = 1; } else { 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 { /* Without the "vcpu" property, dstate can only be 1 or 0 */ - TraceEventID id = trace_event_get_id(ev); - bool state_pre = trace_events_dstate[id]; + bool state_pre = *ev->dstate; if (state_pre != state) { if (state) { trace_events_enabled_count++; - trace_events_dstate[id] = 1; + *ev->dstate = 1; } else { 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, TraceEvent *ev, bool state) { - TraceEventID id; - TraceEventVCPUID vcpu_id; + uint32_t vcpu_id; bool state_pre; assert(trace_event_get_state_static(ev)); assert(trace_event_is_vcpu(ev)); - id = trace_event_get_id(ev); vcpu_id = trace_event_get_vcpu_id(ev); state_pre = test_bit(vcpu_id, vcpu->trace_dstate); if (state_pre != state) { if (state) { trace_events_enabled_count++; set_bit(vcpu_id, vcpu->trace_dstate); - trace_events_dstate[id]++; + (*ev->dstate)++; } else { trace_events_enabled_count--; 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) { - TraceEvent *ev = NULL; - - while ((ev = trace_event_pattern("*", ev)) != NULL) { + TraceEventIter iter; + TraceEvent *ev; + trace_event_iter_init(&iter, NULL); + while ((ev = trace_event_iter_next(&iter)) != NULL) { if (trace_event_is_vcpu(ev) && trace_event_get_state_static(ev) && trace_event_get_state_dynamic(ev)) { - TraceEventID id = trace_event_get_id(ev); if (adding_first_cpu()) { /* check preconditions */ - assert(trace_events_dstate[id] == 1); + assert(*ev->dstate == 1); /* disable early-init state ... */ - trace_events_dstate[id] = 0; + *ev->dstate = 0; trace_events_enabled_count--; /* ... and properly re-enable */ trace_event_set_vcpu_state_dynamic(vcpu, ev, true); @@ -118,6 +114,5 @@ void trace_init_vcpu(CPUState *vcpu) } } } - trace_guest_cpu_enter(vcpu); } diff --git a/trace/control.c b/trace/control.c index 10b3e9baba..1a7bee6ddc 100644 --- a/trace/control.c +++ b/trace/control.c @@ -28,12 +28,15 @@ #include "monitor/monitor.h" int trace_events_enabled_count; -/* - * Interpretation depends on wether 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. - */ -uint16_t trace_events_dstate[TRACE_EVENT_COUNT]; + +typedef struct TraceEventGroup { + TraceEvent **events; +} TraceEventGroup; + +static TraceEventGroup *event_groups; +static size_t nevent_groups; +static uint32_t next_id; +static uint32_t next_vcpu_id; QemuOptsList qemu_trace_opts = { .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) { assert(name != NULL); - TraceEventID i; - for (i = 0; i < trace_event_count(); i++) { - TraceEvent *ev = trace_event_id(i); + TraceEventIter iter; + TraceEvent *ev; + trace_event_iter_init(&iter, NULL); + while ((ev = trace_event_iter_next(&iter)) != NULL) { if (strcmp(trace_event_get_name(ev), name) == 0) { 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) -{ - assert(pat != NULL); - TraceEventID i; - - if (ev == NULL) { - i = -1; - } else { - i = trace_event_get_id(ev); - } - i++; +void trace_event_iter_init(TraceEventIter *iter, const char *pattern) +{ + iter->event = 0; + iter->group = 0; + iter->pattern = pattern; +} - while (i < trace_event_count()) { - TraceEvent *res = trace_event_id(i); - if (pattern_glob(pat, trace_event_get_name(res))) { - return res; +TraceEvent *trace_event_iter_next(TraceEventIter *iter) +{ + while (iter->group < nevent_groups && + event_groups[iter->group].events[iter->event] != NULL) { + TraceEvent *ev = event_groups[iter->group].events[iter->event]; + iter->event++; + if (event_groups[iter->group].events[iter->event] == NULL) { + iter->event = 0; + iter->group++; + } + if (!iter->pattern || + pattern_glob(iter->pattern, + trace_event_get_name(ev))) { + return ev; } - i++; } return NULL; @@ -127,10 +150,11 @@ TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev) void trace_list_events(void) { - int i; - for (i = 0; i < trace_event_count(); i++) { - TraceEvent *res = trace_event_id(i); - fprintf(stderr, "%s\n", trace_event_get_name(res)); + TraceEventIter iter; + TraceEvent *ev; + trace_event_iter_init(&iter, NULL); + while ((ev = trace_event_iter_next(&iter)) != NULL) { + fprintf(stderr, "%s\n", trace_event_get_name(ev)); } } @@ -138,26 +162,32 @@ static void do_trace_enable_events(const char *line_buf) { const bool enable = ('-' != line_buf[0]); 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)) { - TraceEvent *ev = NULL; - while ((ev = trace_event_pattern(line_ptr, ev)) != NULL) { - if (trace_event_get_state_static(ev)) { - trace_event_set_state_dynamic_init(ev, enable); + trace_event_iter_init(&iter, line_ptr); + while ((ev = trace_event_iter_next(&iter)) != NULL) { + if (!trace_event_get_state_static(ev)) { + if (!is_pattern) { + error_report("WARNING: trace event '%s' is not traceable", + line_ptr); + return; } + continue; } - } 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", - line_ptr); - } else { - trace_event_set_state_dynamic_init(ev, enable); + + /* 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); + } } void trace_enable_events(const char *line_buf) @@ -269,3 +299,8 @@ char *trace_opt_parse(const char *optarg) return trace_file; } + +uint32_t trace_get_vcpu_event_count(void) +{ + return next_vcpu_id; +} diff --git a/trace/control.h b/trace/control.h index a22d11242e..ccaeac8552 100644 --- a/trace/control.h +++ b/trace/control.h @@ -11,35 +11,37 @@ #define TRACE__CONTROL_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: - * - * Unique tracing event identifier. - * - * These are named as 'TRACE_${EVENT_NAME}'. + * trace_event_iter_init: + * @iter: the event iterator struct + * @pattern: optional pattern to filter events on name * - * See also: "trace/generated-events.h" + * Initialize the event iterator struct @iter, + * optionally using @pattern to filter out events + * with non-matching names. */ -enum TraceEventID; +void trace_event_iter_init(TraceEventIter *iter, const char *pattern); /** - * trace_event_id: - * @id: Event identifier. - * - * Get an event by its identifier. + * trace_event_iter_next: + * @iter: the event iterator struct * - * 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. + * Get the next event, if any. When this returns NULL, + * the iterator should no longer be used. * + * 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: @@ -52,48 +54,29 @@ static TraceEvent *trace_event_id(TraceEventID id); 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: * * Whether the given string is an event name pattern. */ 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: * * 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: * * 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). */ -static TraceEventVCPUID trace_event_get_vcpu_id(TraceEvent *ev); +static uint32_t trace_event_get_vcpu_id(TraceEvent *ev); /** * trace_event_is_vcpu: @@ -111,14 +94,12 @@ static const char * trace_event_get_name(TraceEvent *ev); /** * trace_event_get_state: - * @id: Event identifier. + * @id: Event identifier name. * * Get the tracing state of an event (both static and dynamic). * * If the event has the disabled property, the check will have no performance * impact. - * - * As a down side, you must always use an immediate #TraceEventID value. */ #define trace_event_get_state(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: * @vcpu: Target vCPU. - * @id: Event identifier (TraceEventID). - * @vcpu_id: Per-vCPU event identifier (TraceEventVCPUID). + * @id: Event identifier name. * * Get the tracing state of an event (both static and dynamic) for the given * vCPU. * * If the event has the disabled property, the check will have no performance * impact. - * - * As a down side, you must always use an immediate #TraceEventID value. */ -#define trace_event_get_vcpu_state(vcpu, id, vcpu_id) \ - ((id ##_ENABLED) && trace_event_get_vcpu_state_dynamic_by_vcpu_id(vcpu, vcpu_id)) +#define trace_event_get_vcpu_state(vcpu, id) \ + ((id ##_ENABLED) && \ + trace_event_get_vcpu_state_dynamic_by_vcpu_id( \ + vcpu, _ ## id ## _EVENT.vcpu_id)) /** * 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); -/** - * 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: @@ -277,6 +232,13 @@ extern QemuOptsList qemu_trace_opts; */ 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" diff --git a/trace/event-internal.h b/trace/event-internal.h index 074faf6862..f63500b37e 100644 --- a/trace/event-internal.h +++ b/trace/event-internal.h @@ -10,8 +10,11 @@ #ifndef 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: @@ -19,14 +22,21 @@ * @vcpu_id: Unique per-vCPU event identifier. * @name: Event name. * @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. */ typedef struct TraceEvent { - TraceEventID id; - TraceEventVCPUID vcpu_id; + uint32_t id; + uint32_t vcpu_id; const char * name; const bool sstate; + uint16_t *dstate; } TraceEvent; void trace_event_set_state_dynamic_init(TraceEvent *ev, bool state); diff --git a/trace/ftrace.c b/trace/ftrace.c index e953922f5b..3588bb0eb4 100644 --- a/trace/ftrace.c +++ b/trace/ftrace.c @@ -51,6 +51,12 @@ bool ftrace_init(void) snprintf(path, PATH_MAX, "%s/tracing/tracing_on", debugfs); trace_fd = open(path, O_WRONLY); 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"); return false; } else { diff --git a/trace/qmp.c b/trace/qmp.c index 11d2564e7b..ac777d154f 100644 --- a/trace/qmp.c +++ b/trace/qmp.c @@ -52,8 +52,10 @@ static bool check_events(bool has_vcpu, bool ignore_unavailable, bool is_pattern return true; } else { /* error for unavailable events */ - TraceEvent *ev = NULL; - while ((ev = trace_event_pattern(name, ev)) != NULL) { + TraceEventIter iter; + 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)) { error_setg(errp, "event \"%s\" is disabled", trace_event_get_name(ev)); return false; @@ -69,6 +71,7 @@ TraceEventInfoList *qmp_trace_event_get_state(const char *name, { Error *err = NULL; TraceEventInfoList *events = NULL; + TraceEventIter iter; TraceEvent *ev; bool is_pattern = trace_event_is_pattern(name); CPUState *cpu; @@ -86,8 +89,8 @@ TraceEventInfoList *qmp_trace_event_get_state(const char *name, } /* Get states (all errors checked above) */ - ev = NULL; - while ((ev = trace_event_pattern(name, ev)) != NULL) { + trace_event_iter_init(&iter, name); + while ((ev = trace_event_iter_next(&iter)) != NULL) { TraceEventInfoList *elem; bool is_vcpu = trace_event_is_vcpu(ev); if (has_vcpu && !is_vcpu) { @@ -132,6 +135,7 @@ void qmp_trace_event_set_state(const char *name, bool enable, Error **errp) { Error *err = NULL; + TraceEventIter iter; TraceEvent *ev; bool is_pattern = trace_event_is_pattern(name); CPUState *cpu; @@ -150,8 +154,8 @@ void qmp_trace_event_set_state(const char *name, bool enable, } /* Apply changes (all errors checked above) */ - ev = NULL; - while ((ev = trace_event_pattern(name, ev)) != NULL) { + trace_event_iter_init(&iter, name); + while ((ev = trace_event_iter_next(&iter)) != NULL) { if (!trace_event_get_state_static(ev) || (has_vcpu && !trace_event_is_vcpu(ev))) { continue; diff --git a/trace/simple.c b/trace/simple.c index 2f09dafcbc..b263622fa9 100644 --- a/trace/simple.c +++ b/trace/simple.c @@ -17,14 +17,14 @@ #include "trace/control.h" #include "trace/simple.h" -/** Trace file header event ID */ -#define HEADER_EVENT_ID (~(uint64_t)0) /* avoids conflicting with TraceEventIDs */ +/** Trace file header event ID, picked to avoid conflict with real event IDs */ +#define HEADER_EVENT_ID (~(uint64_t)0) /** Trace file magic number */ #define HEADER_MAGIC 0xf2b177cb0aa429b4ULL /** Trace file version number, bump if format changes */ -#define HEADER_VERSION 3 +#define HEADER_VERSION 4 /** Records were dropped event ID */ #define DROPPED_EVENT_ID (~(uint64_t)0 - 1) @@ -56,9 +56,12 @@ static uint32_t trace_pid; static FILE *trace_fp; static char *trace_file_name; +#define TRACE_RECORD_TYPE_MAPPING 0 +#define TRACE_RECORD_TYPE_EVENT 1 + /* * Trace buffer entry */ typedef struct { - uint64_t event; /* TraceEventID */ + uint64_t event; /* event ID value */ uint64_t timestamp_ns; uint32_t length; /* in bytes */ uint32_t pid; @@ -160,6 +163,7 @@ static gpointer writeout_thread(gpointer opaque) unsigned int idx = 0; int dropped_count; size_t unused __attribute__ ((unused)); + uint64_t type = TRACE_RECORD_TYPE_EVENT; for (;;) { wait_for_trace_records_available(); @@ -174,10 +178,12 @@ static gpointer writeout_thread(gpointer opaque) } while (!g_atomic_int_compare_and_exchange(&dropped_events, dropped_count, 0)); dropped.rec.arguments[0] = dropped_count; + unused = fwrite(&type, sizeof(type), 1, trace_fp); unused = fwrite(&dropped.rec, dropped.rec.length, 1, trace_fp); } while (get_trace_record(idx, &recordptr)) { + unused = fwrite(&type, sizeof(type), 1, trace_fp); unused = fwrite(recordptr, recordptr->length, 1, trace_fp); writeout_idx += recordptr->length; 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); } -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; 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) { if (enable == !!trace_fp) { @@ -297,7 +325,8 @@ void st_set_trace_file_enabled(bool enable) 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); trace_fp = NULL; return; diff --git a/trace/simple.h b/trace/simple.h index 1e7de45575..9931808c05 100644 --- a/trace/simple.h +++ b/trace/simple.h @@ -11,10 +11,6 @@ #ifndef 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_set_trace_file_enabled(bool enable); void st_set_trace_file(const char *file); @@ -33,7 +29,7 @@ typedef struct { * * @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 @@ -3024,6 +3024,8 @@ int main(int argc, char **argv, char **envp) Error *err = NULL; bool list_data_dirs = false; + module_call_init(MODULE_INIT_TRACE); + qemu_init_cpu_list(); qemu_init_cpu_loop(); qemu_mutex_lock_iothread(); |