aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-08-15 16:37:17 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-08-15 16:37:17 +0100
commit5c6b3c50cca2106e5fbcbc6efa94c2f8b9d29fd8 (patch)
tree130b8de581b48b1bf1862b4f5f1e8001955cc47e
parentf2fb1da9412ae7b4cb512cfbd86c0185f191e2f9 (diff)
parent4ac4458076e1aaf3b01a6361154117df20e22215 (diff)
Merge remote-tracking branch 'remotes/stefanha/tags/tracing-pull-request' into staging
Tracing pull request * remotes/stefanha/tags/tracing-pull-request: virtio-rng: add some trace events trace: add some tcg tracing support trace: teach lttng backend to use format strings trace: [tcg] Include TCG-tracing header on all targets trace: [tcg] Include event definitions in "trace.h" trace: [tcg] Generate TCG tracing routines trace: [tcg] Include TCG-tracing helpers trace: [tcg] Define TCG tracing helper routine wrappers trace: [tcg] Define TCG tracing helper routines trace: [tcg] Declare TCG tracing helper routines trace: [tcg] Add 'tcg' event property trace: [tcg] Argument type transformation machinery trace: [tcg] Argument type transformation rules trace: [tcg] Add documentation trace: install simpletrace SystemTap tapset simpletrace: add simpletrace.py --no-header option trace: add tracetool simpletrace_stap format trace: extract stap_escape() function for reuse Conflicts: Makefile.objs
-rw-r--r--.gitignore4
-rw-r--r--Makefile6
-rw-r--r--Makefile.objs7
-rw-r--r--Makefile.target15
-rw-r--r--cpu-exec.c6
-rw-r--r--docs/tracing.txt40
-rw-r--r--hw/virtio/virtio-rng.c6
-rw-r--r--include/exec/helper-gen.h2
-rw-r--r--include/exec/helper-proto.h1
-rw-r--r--include/exec/helper-tcg.h1
-rw-r--r--include/trace-tcg.h7
-rw-r--r--include/trace.h1
-rwxr-xr-xscripts/simpletrace.py24
-rw-r--r--scripts/tracetool/__init__.py105
-rw-r--r--scripts/tracetool/format/events_h.py5
-rw-r--r--scripts/tracetool/format/simpletrace_stap.py71
-rw-r--r--scripts/tracetool/format/stap.py11
-rw-r--r--scripts/tracetool/format/tcg_h.py57
-rw-r--r--scripts/tracetool/format/tcg_helper_c.py50
-rw-r--r--scripts/tracetool/format/tcg_helper_h.py50
-rw-r--r--scripts/tracetool/format/tcg_helper_wrapper_h.py70
-rw-r--r--scripts/tracetool/format/ust_events_h.py15
-rw-r--r--scripts/tracetool/transform.py166
-rw-r--r--target-alpha/translate.c3
-rw-r--r--target-arm/translate-a64.c2
-rw-r--r--target-arm/translate.c3
-rw-r--r--target-cris/translate.c3
-rw-r--r--target-i386/translate.c3
-rw-r--r--target-lm32/translate.c3
-rw-r--r--target-m68k/translate.c3
-rw-r--r--target-microblaze/translate.c3
-rw-r--r--target-mips/translate.c3
-rw-r--r--target-openrisc/translate.c3
-rw-r--r--target-ppc/translate.c3
-rw-r--r--target-s390x/translate.c2
-rw-r--r--target-sh4/translate.c3
-rw-r--r--target-sparc/translate.c3
-rw-r--r--target-unicore32/translate.c3
-rw-r--r--target-xtensa/translate.c3
-rw-r--r--trace-events14
-rw-r--r--trace/Makefile.objs53
-rw-r--r--translate-all.c3
42 files changed, 808 insertions, 28 deletions
diff --git a/.gitignore b/.gitignore
index 2286d0a109..e32a58417a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,10 @@
/trace/generated-tracers.dtrace
/trace/generated-events.h
/trace/generated-events.c
+/trace/generated-helpers-wrappers.h
+/trace/generated-helpers.h
+/trace/generated-helpers.c
+/trace/generated-tcg-tracers.h
/trace/generated-ust-provider.h
/trace/generated-ust.c
/libcacard/trace/generated-tracers.c
diff --git a/Makefile b/Makefile
index c5751b879a..b33aaacde6 100644
--- a/Makefile
+++ b/Makefile
@@ -57,6 +57,12 @@ GENERATED_HEADERS += trace/generated-tracers-dtrace.h
endif
GENERATED_SOURCES += trace/generated-tracers.c
+GENERATED_HEADERS += trace/generated-tcg-tracers.h
+
+GENERATED_HEADERS += trace/generated-helpers-wrappers.h
+GENERATED_HEADERS += trace/generated-helpers.h
+GENERATED_SOURCES += trace/generated-helpers.c
+
ifeq ($(findstring ust,$(TRACE_BACKENDS)),ust)
GENERATED_HEADERS += trace/generated-ust-provider.h
GENERATED_SOURCES += trace/generated-ust.c
diff --git a/Makefile.objs b/Makefile.objs
index efd9768e86..97db978d16 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -1,7 +1,7 @@
#######################################################################
# Common libraries for tools and emulators
stub-obj-y = stubs/
-util-obj-y = util/ qobject/ qapi/ trace/ qapi-types.o qapi-visit.o qapi-event.o
+util-obj-y = util/ qobject/ qapi/ qapi-types.o qapi-visit.o qapi-event.o
#######################################################################
# block-obj-y is code used by both qemu system emulation and qemu-img
@@ -101,6 +101,11 @@ version-obj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.o
version-lobj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.lo
######################################################################
+# tracing
+util-obj-y += trace/
+target-obj-y += trace/
+
+######################################################################
# guest agent
# FIXME: a few definitions from qapi-types.o/qapi-visit.o are needed
diff --git a/Makefile.target b/Makefile.target
index 137d0b0517..1e8d7abcb3 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -38,7 +38,7 @@ config-target.h: config-target.h-timestamp
config-target.h-timestamp: config-target.mak
ifdef CONFIG_TRACE_SYSTEMTAP
-stap: $(QEMU_PROG).stp-installed $(QEMU_PROG).stp
+stap: $(QEMU_PROG).stp-installed $(QEMU_PROG).stp $(QEMU_PROG)-simpletrace.stp
ifdef CONFIG_USER_ONLY
TARGET_TYPE=user
@@ -64,6 +64,13 @@ $(QEMU_PROG).stp: $(SRC_PATH)/trace-events
--target-type=$(TARGET_TYPE) \
< $< > $@," GEN $(TARGET_DIR)$(QEMU_PROG).stp")
+$(QEMU_PROG)-simpletrace.stp: $(SRC_PATH)/trace-events
+ $(call quiet-command,$(TRACETOOL) \
+ --format=simpletrace-stap \
+ --backends=$(TRACE_BACKENDS) \
+ --probe-prefix=qemu.$(TARGET_TYPE).$(TARGET_NAME) \
+ < $< > $@," GEN $(TARGET_DIR)$(QEMU_PROG)-simpletrace.stp")
+
else
stap:
endif
@@ -152,15 +159,20 @@ endif # CONFIG_SOFTMMU
dummy := $(call unnest-vars,,obj-y)
all-obj-y := $(obj-y)
+target-obj-y :=
block-obj-y :=
common-obj-y :=
include $(SRC_PATH)/Makefile.objs
+dummy := $(call unnest-vars,,target-obj-y)
+target-obj-y-save := $(target-obj-y)
dummy := $(call unnest-vars,.., \
block-obj-y \
block-obj-m \
common-obj-y \
common-obj-m)
+target-obj-y := $(target-obj-y-save)
all-obj-y += $(common-obj-y)
+all-obj-y += $(target-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y)
# build either PROG or PROGW
@@ -191,6 +203,7 @@ endif
ifdef CONFIG_TRACE_SYSTEMTAP
$(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset"
$(INSTALL_DATA) $(QEMU_PROG).stp-installed "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset/$(QEMU_PROG).stp"
+ $(INSTALL_DATA) $(QEMU_PROG)-simpletrace.stp "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset/$(QEMU_PROG)-simpletrace.stp"
endif
GENERATED_HEADERS += config-target.h
diff --git a/cpu-exec.c b/cpu-exec.c
index cbc8067b37..c6aad742e1 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -18,6 +18,7 @@
*/
#include "config.h"
#include "cpu.h"
+#include "trace.h"
#include "disas/disas.h"
#include "tcg.h"
#include "qemu/atomic.h"
@@ -168,6 +169,9 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr)
#endif /* DEBUG_DISAS */
next_tb = tcg_qemu_tb_exec(env, tb_ptr);
+ trace_exec_tb_exit((void *) (next_tb & ~TB_EXIT_MASK),
+ next_tb & TB_EXIT_MASK);
+
if ((next_tb & TB_EXIT_MASK) > TB_EXIT_IDX1) {
/* We didn't start executing this TB (eg because the instruction
* counter hit zero); we must restore the guest PC to the address
@@ -208,6 +212,7 @@ static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
max_cycles);
cpu->current_tb = tb;
/* execute the generated code */
+ trace_exec_tb_nocache(tb, tb->pc);
cpu_tb_exec(cpu, tb->tc_ptr);
cpu->current_tb = NULL;
tb_phys_invalidate(tb, -1);
@@ -749,6 +754,7 @@ int cpu_exec(CPUArchState *env)
cpu->current_tb = tb;
barrier();
if (likely(!cpu->exit_request)) {
+ trace_exec_tb(tb, tb->pc);
tc_ptr = tb->tc_ptr;
/* execute the generated code */
next_tb = cpu_tb_exec(cpu, tc_ptr);
diff --git a/docs/tracing.txt b/docs/tracing.txt
index c6ab1c11c1..2e035a5b3c 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -307,3 +307,43 @@ guard such computations and avoid its compilation when the event is disabled:
You can check both if the event has been disabled and is dynamically enabled at
the same time using the 'trace_event_get_state' routine (see header
"trace/control.h" for more information).
+
+=== "tcg" ===
+
+Guest code generated by TCG can be traced by defining an event with the "tcg"
+event property. Internally, this property generates two events:
+"<eventname>_trans" to trace the event at translation time, and
+"<eventname>_exec" to trace the event at execution time.
+
+Instead of using these two events, you should instead use the function
+"trace_<eventname>_tcg" during translation (TCG code generation). This function
+will automatically call "trace_<eventname>_trans", and will generate the
+necessary TCG code to call "trace_<eventname>_exec" during guest code execution.
+
+Events with the "tcg" property can be declared in the "trace-events" file with a
+mix of native and TCG types, and "trace_<eventname>_tcg" will gracefully forward
+them to the "<eventname>_trans" and "<eventname>_exec" events. Since TCG values
+are not known at translation time, these are ignored by the "<eventname>_trans"
+event. Because of this, the entry in the "trace-events" file needs two printing
+formats (separated by a comma):
+
+ tcg foo(uint8_t a1, TCGv_i32 a2) "a1=%d", "a1=%d a2=%d"
+
+For example:
+
+ #include "trace-tcg.h"
+
+ void some_disassembly_func (...)
+ {
+ uint8_t a1 = ...;
+ TCGv_i32 a2 = ...;
+ trace_foo_tcg(a1, a2);
+ }
+
+This will immediately call:
+
+ void trace_foo_trans(uint8_t a1);
+
+and will generate the TCG code to call:
+
+ void trace_foo(uint8_t a1, uint32_t a2);
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index 03fd04a1e5..e85a979754 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -16,6 +16,7 @@
#include "hw/virtio/virtio-rng.h"
#include "sysemu/rng.h"
#include "qom/object_interfaces.h"
+#include "trace.h"
static bool is_guest_ready(VirtIORNG *vrng)
{
@@ -24,6 +25,7 @@ static bool is_guest_ready(VirtIORNG *vrng)
&& (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
return true;
}
+ trace_virtio_rng_guest_not_ready(vrng);
return false;
}
@@ -62,6 +64,7 @@ static void chr_read(void *opaque, const void *buf, size_t size)
offset += len;
virtqueue_push(vrng->vq, &elem, len);
+ trace_virtio_rng_pushed(vrng, len);
}
virtio_notify(vdev, vrng->vq);
}
@@ -81,6 +84,9 @@ static void virtio_rng_process(VirtIORNG *vrng)
quota = MIN((uint64_t)vrng->quota_remaining, (uint64_t)UINT32_MAX);
}
size = get_request_size(vrng->vq, quota);
+
+ trace_virtio_rng_request(vrng, size, quota);
+
size = MIN(vrng->quota_remaining, size);
if (size) {
rng_backend_request_entropy(vrng->rng, size, chr_read, vrng);
diff --git a/include/exec/helper-gen.h b/include/exec/helper-gen.h
index a04a0341e2..0d0da3aeb3 100644
--- a/include/exec/helper-gen.h
+++ b/include/exec/helper-gen.h
@@ -57,6 +57,8 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
}
#include "helper.h"
+#include "trace/generated-helpers.h"
+#include "trace/generated-helpers-wrappers.h"
#include "tcg-runtime.h"
#undef DEF_HELPER_FLAGS_0
diff --git a/include/exec/helper-proto.h b/include/exec/helper-proto.h
index 828951c609..effdd4383a 100644
--- a/include/exec/helper-proto.h
+++ b/include/exec/helper-proto.h
@@ -27,6 +27,7 @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
dh_ctype(t4), dh_ctype(t5));
#include "helper.h"
+#include "trace/generated-helpers.h"
#include "tcg-runtime.h"
#undef DEF_HELPER_FLAGS_0
diff --git a/include/exec/helper-tcg.h b/include/exec/helper-tcg.h
index d704c81126..79fa3c8c81 100644
--- a/include/exec/helper-tcg.h
+++ b/include/exec/helper-tcg.h
@@ -36,6 +36,7 @@
| dh_sizemask(t5, 5) },
#include "helper.h"
+#include "trace/generated-helpers.h"
#include "tcg-runtime.h"
#undef DEF_HELPER_FLAGS_0
diff --git a/include/trace-tcg.h b/include/trace-tcg.h
new file mode 100644
index 0000000000..6f6bdbb44a
--- /dev/null
+++ b/include/trace-tcg.h
@@ -0,0 +1,7 @@
+#ifndef TRACE_TCG_H
+#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 c15f498128..44a1f1f8c7 100644
--- a/include/trace.h
+++ b/include/trace.h
@@ -2,5 +2,6 @@
#define TRACE_H
#include "trace/generated-tracers.h"
+#include "trace/generated-events.h"
#endif /* TRACE_H */
diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py
index 1aa9460e49..3916c6d14a 100755
--- a/scripts/simpletrace.py
+++ b/scripts/simpletrace.py
@@ -58,8 +58,8 @@ def read_record(edict, fobj):
rechdr = read_header(fobj, rec_header_fmt)
return get_record(edict, rechdr, fobj) # return tuple of record elements
-def read_trace_file(edict, fobj):
- """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6)."""
+def read_trace_header(fobj):
+ """Read and verify trace file header"""
header = read_header(fobj, log_header_fmt)
if header is None or \
header[0] != header_event_id or \
@@ -73,6 +73,8 @@ def read_trace_file(edict, fobj):
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)."""
while True:
rec = read_record(edict, fobj)
if rec is None:
@@ -102,13 +104,16 @@ class Analyzer(object):
"""Called at the end of the trace."""
pass
-def process(events, log, analyzer):
+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'))
if isinstance(log, str):
log = open(log, 'rb')
+ if read_header:
+ read_trace_header(log)
+
dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)")
edict = {dropped_event_id: dropped_event}
@@ -137,7 +142,7 @@ def process(events, log, analyzer):
analyzer.begin()
fn_cache = {}
- for rec in read_trace_file(edict, log):
+ for rec in read_trace_records(edict, log):
event_num = rec[0]
event = edict[event_num]
if event_num not in fn_cache:
@@ -152,12 +157,17 @@ def run(analyzer):
advanced scripts will want to call process() instead."""
import sys
- if len(sys.argv) != 3:
- sys.stderr.write('usage: %s <trace-events> <trace-file>\n' % sys.argv[0])
+ read_header = True
+ if len(sys.argv) == 4 and sys.argv[1] == '--no-header':
+ read_header = False
+ del sys.argv[1]
+ elif len(sys.argv) != 3:
+ sys.stderr.write('usage: %s [--no-header] <trace-events> ' \
+ '<trace-file>\n' % sys.argv[0])
sys.exit(1)
events = _read_events(open(sys.argv[1], 'r'))
- process(events, sys.argv[2], analyzer)
+ process(events, sys.argv[2], analyzer, read_header=read_header)
if __name__ == '__main__':
class Formatter(Analyzer):
diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py
index e8e8edcc4c..36c789de8f 100644
--- a/scripts/tracetool/__init__.py
+++ b/scripts/tracetool/__init__.py
@@ -15,9 +15,11 @@ __email__ = "stefanha@linux.vnet.ibm.com"
import re
import sys
+import weakref
import tracetool.format
import tracetool.backend
+import tracetool.transform
def error_write(*lines):
@@ -108,6 +110,18 @@ class Arguments:
"""List of argument types."""
return [ type_ for type_, _ in self._args ]
+ def transform(self, *trans):
+ """Return a new Arguments instance with transformed types.
+
+ The types in the resulting Arguments instance are transformed according
+ to tracetool.transform.transform_type.
+ """
+ res = []
+ for type_, name in self._args:
+ res.append((tracetool.transform.transform_type(type_, *trans),
+ name))
+ return Arguments(res)
+
class Event(object):
"""Event description.
@@ -122,13 +136,21 @@ class Event(object):
Properties of the event.
args : Arguments
The event arguments.
+ arg_fmts : str
+ The format strings for each argument.
"""
- _CRE = re.compile("((?P<props>.*)\s+)?(?P<name>[^(\s]+)\((?P<args>[^)]*)\)\s*(?P<fmt>\".*)?")
+ _CRE = re.compile("((?P<props>.*)\s+)?"
+ "(?P<name>[^(\s]+)"
+ "\((?P<args>[^)]*)\)"
+ "\s*"
+ "(?:(?:(?P<fmt_trans>\".+),)?\s*(?P<fmt>\".+))?"
+ "\s*")
+ _FMT = re.compile("(%\w+|%.*PRI\S+)")
- _VALID_PROPS = set(["disable"])
+ _VALID_PROPS = set(["disable", "tcg", "tcg-trans", "tcg-exec"])
- def __init__(self, name, props, fmt, args):
+ def __init__(self, name, props, fmt, args, arg_fmts, orig=None):
"""
Parameters
----------
@@ -136,20 +158,32 @@ class Event(object):
Event name.
props : list of str
Property names.
- fmt : str
- Event printing format.
+ fmt : str, list of str
+ Event printing format (or formats).
args : Arguments
Event arguments.
+ arg_fmts : list of str
+ Format strings for each argument.
+ orig : Event or None
+ Original Event before transformation.
+
"""
self.name = name
self.properties = props
self.fmt = fmt
self.args = args
+ self.arg_fmts = arg_fmts
+
+ if orig is None:
+ self.original = weakref.ref(self)
+ else:
+ self.original = orig
unknown_props = set(self.properties) - self._VALID_PROPS
if len(unknown_props) > 0:
raise ValueError("Unknown properties: %s"
% ", ".join(unknown_props))
+ assert isinstance(self.fmt, str) or len(self.fmt) == 2
def copy(self):
"""Create a new copy."""
@@ -172,24 +206,50 @@ class Event(object):
name = groups["name"]
props = groups["props"].split()
fmt = groups["fmt"]
+ fmt_trans = groups["fmt_trans"]
+ if len(fmt_trans) > 0:
+ fmt = [fmt_trans, fmt]
args = Arguments.build(groups["args"])
+ arg_fmts = Event._FMT.findall(fmt)
+
+ if "tcg-trans" in props:
+ raise ValueError("Invalid property 'tcg-trans'")
+ if "tcg-exec" in props:
+ raise ValueError("Invalid property 'tcg-exec'")
+ if "tcg" not in props and not isinstance(fmt, str):
+ raise ValueError("Only events with 'tcg' property can have two formats")
+ if "tcg" in props and isinstance(fmt, str):
+ raise ValueError("Events with 'tcg' property must have two formats")
- return Event(name, props, fmt, args)
+ return Event(name, props, fmt, args, arg_fmts)
def __repr__(self):
"""Evaluable string representation for this object."""
+ if isinstance(self.fmt, str):
+ fmt = self.fmt
+ else:
+ fmt = "%s, %s" % (self.fmt[0], self.fmt[1])
return "Event('%s %s(%s) %s')" % (" ".join(self.properties),
self.name,
self.args,
- self.fmt)
+ fmt)
QEMU_TRACE = "trace_%(name)s"
+ QEMU_TRACE_TCG = QEMU_TRACE + "_tcg"
def api(self, fmt=None):
if fmt is None:
fmt = Event.QEMU_TRACE
return fmt % {"name": self.name}
+ def transform(self, *trans):
+ """Return a new Event with transformed Arguments."""
+ return Event(self.name,
+ list(self.properties),
+ self.fmt,
+ self.args.transform(*trans),
+ self)
+
def _read_events(fobj):
res = []
@@ -272,4 +332,35 @@ def generate(fevents, format, backends,
events = _read_events(fevents)
+ # transform TCG-enabled events
+ new_events = []
+ for event in events:
+ if "tcg" not in event.properties:
+ new_events.append(event)
+ else:
+ event_trans = event.copy()
+ event_trans.name += "_trans"
+ event_trans.properties += ["tcg-trans"]
+ event_trans.fmt = event.fmt[0]
+ args_trans = []
+ for atrans, aorig in zip(
+ event_trans.transform(tracetool.transform.TCG_2_HOST).args,
+ event.args):
+ if atrans == aorig:
+ args_trans.append(atrans)
+ event_trans.args = Arguments(args_trans)
+ event_trans = event_trans.copy()
+
+ event_exec = event.copy()
+ event_exec.name += "_exec"
+ event_exec.properties += ["tcg-exec"]
+ event_exec.fmt = event.fmt[1]
+ event_exec = event_exec.transform(tracetool.transform.TCG_2_HOST)
+
+ new_event = [event_trans, event_exec]
+ event.event_trans, event.event_exec = new_event
+
+ new_events.extend(new_event)
+ events = new_events
+
tracetool.format.generate(events, format, backend)
diff --git a/scripts/tracetool/format/events_h.py b/scripts/tracetool/format/events_h.py
index 25d913bb25..9f114a3497 100644
--- a/scripts/tracetool/format/events_h.py
+++ b/scripts/tracetool/format/events_h.py
@@ -40,6 +40,11 @@ def generate(events, backend):
enabled = 0
else:
enabled = 1
+ if "tcg-trans" in e.properties:
+ # a single define for the two "sub-events"
+ out('#define TRACE_%(name)s_ENABLED %(enabled)d',
+ name=e.original.original.name.upper(),
+ enabled=enabled)
out('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled))
out('#include "trace/event-internal.h"',
diff --git a/scripts/tracetool/format/simpletrace_stap.py b/scripts/tracetool/format/simpletrace_stap.py
new file mode 100644
index 0000000000..7e44bc1811
--- /dev/null
+++ b/scripts/tracetool/format/simpletrace_stap.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate .stp file that outputs simpletrace binary traces (DTrace with SystemTAP only).
+"""
+
+__author__ = "Stefan Hajnoczi <redhat.com>"
+__copyright__ = "Copyright (C) 2014, Red Hat, Inc."
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@redhat.com"
+
+
+from tracetool import out
+from tracetool.backend.dtrace import binary, probeprefix
+from tracetool.backend.simple import is_string
+from tracetool.format.stap import stap_escape
+
+
+def generate(events, backend):
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '')
+
+ for event_id, e in enumerate(events):
+ if 'disable' in e.properties:
+ continue
+
+ out('probe %(probeprefix)s.simpletrace.%(name)s = %(probeprefix)s.%(name)s ?',
+ '{',
+ probeprefix=probeprefix(),
+ name=e.name)
+
+ # Calculate record size
+ sizes = ['24'] # sizeof(TraceRecord)
+ for type_, name in e.args:
+ name = stap_escape(name)
+ if is_string(type_):
+ out(' try {',
+ ' arg%(name)s_str = %(name)s ? user_string_n(%(name)s, 512) : "<null>"',
+ ' } catch {}',
+ ' arg%(name)s_len = strlen(arg%(name)s_str)',
+ name=name)
+ sizes.append('4 + arg%s_len' % name)
+ else:
+ sizes.append('8')
+ sizestr = ' + '.join(sizes)
+
+ # Generate format string and value pairs for record header and arguments
+ fields = [('8b', str(event_id)),
+ ('8b', 'gettimeofday_ns()'),
+ ('4b', sizestr),
+ ('4b', 'pid()')]
+ for type_, name in e.args:
+ name = stap_escape(name)
+ if is_string(type_):
+ fields.extend([('4b', 'arg%s_len' % name),
+ ('.*s', 'arg%s_len, arg%s_str' % (name, name))])
+ else:
+ fields.append(('8b', name))
+
+ # 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)',
+ fmt_str=fmt_str, arg_str=arg_str)
+
+ out('}')
+
+ out()
diff --git a/scripts/tracetool/format/stap.py b/scripts/tracetool/format/stap.py
index e24abf7f11..9e780f1b06 100644
--- a/scripts/tracetool/format/stap.py
+++ b/scripts/tracetool/format/stap.py
@@ -27,6 +27,13 @@ RESERVED_WORDS = (
)
+def stap_escape(identifier):
+ # Append underscore to reserved keywords
+ if identifier in RESERVED_WORDS:
+ return identifier + '_'
+ return identifier
+
+
def generate(events, backend):
events = [e for e in events
if "disable" not in e.properties]
@@ -45,9 +52,7 @@ def generate(events, backend):
i = 1
if len(e.args) > 0:
for name in e.args.names():
- # Append underscore to reserved keywords
- if name in RESERVED_WORDS:
- name += '_'
+ name = stap_escape(name)
out(' %s = $arg%d;' % (name, i))
i += 1
diff --git a/scripts/tracetool/format/tcg_h.py b/scripts/tracetool/format/tcg_h.py
new file mode 100644
index 0000000000..f676b66622
--- /dev/null
+++ b/scripts/tracetool/format/tcg_h.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate .h file for TCG code generation.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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. */',
+ '/* You must include this file after the inclusion of helper.h */',
+ '',
+ '#ifndef TRACE__GENERATED_TCG_TRACERS_H',
+ '#define TRACE__GENERATED_TCG_TRACERS_H',
+ '',
+ '#include <stdint.h>',
+ '',
+ '#include "trace.h"',
+ '#include "exec/helper-proto.h"',
+ '',
+ )
+
+ for e in events:
+ # just keep one of them
+ if "tcg-trans" not in e.properties:
+ continue
+
+ # get the original event definition
+ e = e.original.original
+
+ out('static inline void %(name_tcg)s(%(args)s)',
+ '{',
+ name_tcg=e.api(e.QEMU_TRACE_TCG),
+ args=e.args)
+
+ if "disable" not in e.properties:
+ out(' %(name_trans)s(%(argnames_trans)s);',
+ ' gen_helper_%(name_exec)s(%(argnames_exec)s);',
+ name_trans=e.event_trans.api(e.QEMU_TRACE),
+ name_exec=e.event_exec.api(e.QEMU_TRACE),
+ argnames_trans=", ".join(e.event_trans.args.names()),
+ argnames_exec=", ".join(e.event_exec.args.names()))
+
+ out('}')
+
+ out('',
+ '#endif /* TRACE__GENERATED_TCG_TRACERS_H */')
diff --git a/scripts/tracetool/format/tcg_helper_c.py b/scripts/tracetool/format/tcg_helper_c.py
new file mode 100644
index 0000000000..96655a0590
--- /dev/null
+++ b/scripts/tracetool/format/tcg_helper_c.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate trace/generated-helpers.c.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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
+from tracetool.transform import *
+
+
+def generate(events, backend):
+ events = [e for e in events
+ if "disable" not in e.properties]
+
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ '#include "qemu-common.h"',
+ '#include "trace.h"',
+ '#include "exec/helper-proto.h"',
+ '',
+ )
+
+ for e in events:
+ if "tcg-exec" not in e.properties:
+ continue
+
+ # tracetool.generate always transforms types to host
+ e_args = e.original.args
+
+ values = ["(%s)%s" % (t, n)
+ for t, n in e.args.transform(TCG_2_TCG_HELPER_DEF)]
+
+ out('void %(name_tcg)s(%(args)s)',
+ '{',
+ ' %(name)s(%(values)s);',
+ '}',
+ name_tcg="helper_%s_proxy" % e.api(),
+ name=e.api(),
+ args=e_args.transform(HOST_2_TCG_COMPAT, TCG_2_TCG_HELPER_DEF),
+ values=", ".join(values),
+ )
diff --git a/scripts/tracetool/format/tcg_helper_h.py b/scripts/tracetool/format/tcg_helper_h.py
new file mode 100644
index 0000000000..a8ba7ba8e3
--- /dev/null
+++ b/scripts/tracetool/format/tcg_helper_h.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate trace/generated-helpers.h.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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
+from tracetool.transform import *
+
+
+def generate(events, backend):
+ events = [e for e in events
+ if "disable" not in e.properties]
+
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ )
+
+ for e in events:
+ if "tcg-exec" not in e.properties:
+ continue
+
+ # tracetool.generate always transforms types to host
+ e_args = e.original.args
+
+ # TCG helper proxy declaration
+ fmt = "DEF_HELPER_FLAGS_%(argc)d(%(name)s, %(flags)svoid%(types)s)"
+ args = e_args.transform(HOST_2_TCG_COMPAT, HOST_2_TCG,
+ TCG_2_TCG_HELPER_DECL)
+ types = ", ".join(args.types())
+ if types != "":
+ types = ", " + types
+
+ flags = "TCG_CALL_NO_RWG, "
+
+ out(fmt,
+ flags=flags,
+ argc=len(args),
+ name=e.api() + "_proxy",
+ types=types,
+ )
diff --git a/scripts/tracetool/format/tcg_helper_wrapper_h.py b/scripts/tracetool/format/tcg_helper_wrapper_h.py
new file mode 100644
index 0000000000..cac5a878f9
--- /dev/null
+++ b/scripts/tracetool/format/tcg_helper_wrapper_h.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate trace/generated-helpers-wrappers.h.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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
+from tracetool.transform import *
+
+
+def generate(events, backend):
+ events = [e for e in events
+ if "disable" not in e.properties]
+
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ '#define tcg_temp_new_nop(v) (v)',
+ '#define tcg_temp_free_nop(v)',
+ '',
+ )
+
+ for e in events:
+ if "tcg-exec" not in e.properties:
+ continue
+
+ # tracetool.generate always transforms types to host
+ e_args = e.original.args
+
+ # mixed-type to TCG helper bridge
+ args_tcg_compat = e_args.transform(HOST_2_TCG_COMPAT)
+
+ code_new = [
+ "%(tcg_type)s __%(name)s = %(tcg_func)s(%(name)s);" %
+ {"tcg_type": transform_type(type_, HOST_2_TCG),
+ "tcg_func": transform_type(type_, HOST_2_TCG_TMP_NEW),
+ "name": name}
+ for (type_, name) in args_tcg_compat
+ ]
+
+ code_free = [
+ "%(tcg_func)s(__%(name)s);" %
+ {"tcg_func": transform_type(type_, HOST_2_TCG_TMP_FREE),
+ "name": name}
+ for (type_, name) in args_tcg_compat
+ ]
+
+ gen_name = "gen_helper_" + e.api()
+
+ out('static inline void %(name)s(%(args)s)',
+ '{',
+ ' %(code_new)s',
+ ' %(proxy_name)s(%(tmp_names)s);',
+ ' %(code_free)s',
+ '}',
+ name=gen_name,
+ args=e_args,
+ proxy_name=gen_name + "_proxy",
+ code_new="\n ".join(code_new),
+ code_free="\n ".join(code_free),
+ tmp_names=", ".join(["__%s" % name for _, name in e_args]),
+ )
diff --git a/scripts/tracetool/format/ust_events_h.py b/scripts/tracetool/format/ust_events_h.py
index 5102565470..d18989942a 100644
--- a/scripts/tracetool/format/ust_events_h.py
+++ b/scripts/tracetool/format/ust_events_h.py
@@ -63,13 +63,20 @@ def generate(events, backend):
name=e.name,
args=", ".join(", ".join(i) for i in e.args))
- for t, n in e.args:
- if ('int' in t) or ('long' in t) or ('unsigned' in t) or ('size_t' in t):
+ types = e.args.types()
+ names = e.args.names()
+ fmts = e.arg_fmts
+ for t,n,f in zip(types, names, fmts):
+ if ('char *' in t) or ('char*' in t):
+ out(' ctf_string(' + n + ', ' + n + ')')
+ elif ("%p" in f) or ("x" in f) or ("PRIx" in f):
+ out(' ctf_integer_hex('+ t + ', ' + n + ', ' + n + ')')
+ elif ("ptr" in t) or ("*" in t):
+ out(' ctf_integer_hex('+ t + ', ' + n + ', ' + n + ')')
+ elif ('int' in t) or ('long' in t) or ('unsigned' in t) or ('size_t' in t):
out(' ctf_integer(' + t + ', ' + n + ', ' + n + ')')
elif ('double' in t) or ('float' in t):
out(' ctf_float(' + t + ', ' + n + ', ' + n + ')')
- elif ('char *' in t) or ('char*' in t):
- out(' ctf_string(' + n + ', ' + n + ')')
elif ('void *' in t) or ('void*' in t):
out(' ctf_integer_hex(unsigned long, ' + n + ', ' + n + ')')
diff --git a/scripts/tracetool/transform.py b/scripts/tracetool/transform.py
new file mode 100644
index 0000000000..fc5e679ed4
--- /dev/null
+++ b/scripts/tracetool/transform.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Type-transformation rules.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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"
+
+
+def _transform_type(type_, trans):
+ if isinstance(trans, str):
+ return trans
+ elif isinstance(trans, dict):
+ if type_ in trans:
+ return _transform_type(type_, trans[type_])
+ elif None in trans:
+ return _transform_type(type_, trans[None])
+ else:
+ return type_
+ elif callable(trans):
+ return trans(type_)
+ else:
+ raise ValueError("Invalid type transformation rule: %s" % trans)
+
+
+def transform_type(type_, *trans):
+ """Return a new type transformed according to the given rules.
+
+ Applies each of the transformation rules in trans in order.
+
+ If an element of trans is a string, return it.
+
+ If an element of trans is a function, call it with type_ as its only
+ argument.
+
+ If an element of trans is a dict, search type_ in its keys. If type_ is
+ a key, use the value as a transformation rule for type_. Otherwise, if
+ None is a key use the value as a transformation rule for type_.
+
+ Otherwise, return type_.
+
+ Parameters
+ ----------
+ type_ : str
+ Type to transform.
+ trans : list of function or dict
+ Type transformation rules.
+ """
+ if len(trans) == 0:
+ raise ValueError
+ res = type_
+ for t in trans:
+ res = _transform_type(res, t)
+ return res
+
+
+##################################################
+# tcg -> host
+
+def _tcg_2_host(type_):
+ if type_ == "TCGv":
+ # force a fixed-size type (target-independent)
+ return "uint64_t"
+ else:
+ return type_
+
+TCG_2_HOST = {
+ "TCGv_i32": "uint32_t",
+ "TCGv_i64": "uint64_t",
+ "TCGv_ptr": "void *",
+ None: _tcg_2_host,
+ }
+
+
+##################################################
+# host -> host compatible with tcg sizes
+
+HOST_2_TCG_COMPAT = {
+ "uint8_t": "uint32_t",
+ }
+
+
+##################################################
+# host/tcg -> tcg
+
+def _host_2_tcg(type_):
+ if type_.startswith("TCGv"):
+ return type_
+ raise ValueError("Don't know how to translate '%s' into a TCG type\n" % type_)
+
+HOST_2_TCG = {
+ "uint32_t": "TCGv_i32",
+ "uint64_t": "TCGv_i64",
+ "void *" : "TCGv_ptr",
+ None: _host_2_tcg,
+ }
+
+
+##################################################
+# tcg -> tcg helper definition
+
+def _tcg_2_helper_def(type_):
+ if type_ == "TCGv":
+ return "target_ulong"
+ else:
+ return type_
+
+TCG_2_TCG_HELPER_DEF = {
+ "TCGv_i32": "uint32_t",
+ "TCGv_i64": "uint64_t",
+ "TCGv_ptr": "void *",
+ None: _tcg_2_helper_def,
+ }
+
+
+##################################################
+# tcg -> tcg helper declaration
+
+def _tcg_2_tcg_helper_decl_error(type_):
+ raise ValueError("Don't know how to translate type '%s' into a TCG helper declaration type\n" % type_)
+
+TCG_2_TCG_HELPER_DECL = {
+ "TCGv" : "tl",
+ "TCGv_ptr": "ptr",
+ "TCGv_i32": "i32",
+ "TCGv_i64": "i64",
+ None: _tcg_2_tcg_helper_decl_error,
+ }
+
+
+##################################################
+# host/tcg -> tcg temporal constant allocation
+
+def _host_2_tcg_tmp_new(type_):
+ if type_.startswith("TCGv"):
+ return "tcg_temp_new_nop"
+ raise ValueError("Don't know how to translate type '%s' into a TCG temporal allocation" % type_)
+
+HOST_2_TCG_TMP_NEW = {
+ "uint32_t": "tcg_const_i32",
+ "uint64_t": "tcg_const_i64",
+ "void *" : "tcg_const_ptr",
+ None: _host_2_tcg_tmp_new,
+ }
+
+
+##################################################
+# host/tcg -> tcg temporal constant deallocation
+
+def _host_2_tcg_tmp_free(type_):
+ if type_.startswith("TCGv"):
+ return "tcg_temp_free_nop"
+ raise ValueError("Don't know how to translate type '%s' into a TCG temporal deallocation" % type_)
+
+HOST_2_TCG_TMP_FREE = {
+ "uint32_t": "tcg_temp_free_i32",
+ "uint64_t": "tcg_temp_free_i64",
+ "void *" : "tcg_temp_free_ptr",
+ None: _host_2_tcg_tmp_free,
+ }
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index cc81e774df..76658a074a 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -26,6 +26,9 @@
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
+#include "trace-tcg.h"
+
+
#undef ALPHA_DEBUG_DISAS
#define CONFIG_SOFTFLOAT_INLINE
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 33b5025fee..f04ca49631 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -35,6 +35,8 @@
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
+#include "trace-tcg.h"
+
static TCGv_i64 cpu_X[32];
static TCGv_i64 cpu_pc;
static TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index cf4e767ff8..40121858d6 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -35,6 +35,9 @@
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
+#include "trace-tcg.h"
+
+
#define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T)
#define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5)
/* currently all emulated v5 cores are also v5TE, so don't bother */
diff --git a/target-cris/translate.c b/target-cris/translate.c
index ab0e47962b..e37b04e69d 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -33,6 +33,9 @@
#include "exec/helper-gen.h"
+#include "trace-tcg.h"
+
+
#define DISAS_CRIS 0
#if DISAS_CRIS
# define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 6fcd8245d2..418173e0ea 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -32,6 +32,9 @@
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
+#include "trace-tcg.h"
+
+
#define PREFIX_REPZ 0x01
#define PREFIX_REPNZ 0x02
#define PREFIX_LOCK 0x04
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index a51ade9a15..8454e8b517 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -27,6 +27,9 @@
#include "exec/helper-gen.h"
+#include "trace-tcg.h"
+
+
#define DISAS_LM32 1
#if DISAS_LM32
# define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 50df4d3844..efd4cfc3c7 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -27,6 +27,9 @@
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
+#include "trace-tcg.h"
+
+
//#define DEBUG_DISPATCH 1
/* Fake floating point. */
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 03ea15803b..fd2b771645 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -26,6 +26,9 @@
#include "exec/cpu_ldst.h"
#include "exec/helper-gen.h"
+#include "trace-tcg.h"
+
+
#define SIM_COMPAT 0
#define DISAS_GNU 1
#define DISAS_MB 1
diff --git a/target-mips/translate.c b/target-mips/translate.c
index c381366506..06db150325 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -30,6 +30,9 @@
#include "exec/helper-gen.h"
#include "sysemu/kvm.h"
+#include "trace-tcg.h"
+
+
#define MIPS_DEBUG_DISAS 0
//#define MIPS_DEBUG_SIGN_EXTENSIONS
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 55ff935d5e..407bd9762f 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -31,6 +31,9 @@
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
+#include "trace-tcg.h"
+
+
#define OPENRISC_DISAS
#ifdef OPENRISC_DISAS
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index b23933f7bd..c07bb01a7a 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -27,6 +27,9 @@
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
+#include "trace-tcg.h"
+
+
#define CPU_SINGLE_STEP 0x1
#define CPU_BRANCH_STEP 0x2
#define GDBSTUB_SINGLE_STEP 0x4
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e2a1d05f15..0cb036f667 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -42,6 +42,8 @@ static TCGv_ptr cpu_env;
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
+#include "trace-tcg.h"
+
/* Information that (most) every instruction needs to manipulate. */
typedef struct DisasContext DisasContext;
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 8126818142..3088edc6a6 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -28,6 +28,9 @@
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
+#include "trace-tcg.h"
+
+
typedef struct DisasContext {
struct TranslationBlock *tb;
target_ulong pc;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 1ab07a18a2..78c4e21cff 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -32,6 +32,9 @@
#include "exec/helper-gen.h"
+#include "trace-tcg.h"
+
+
#define DEBUG_DISAS
#define DYNAMIC_PC 1 /* dynamic pc value */
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index e3643c23cd..653c225187 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -23,6 +23,9 @@
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
+#include "trace-tcg.h"
+
+
/* internal defines */
typedef struct DisasContext {
target_ulong pc;
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 2f22cce845..badca195f4 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -41,6 +41,9 @@
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
+#include "trace-tcg.h"
+
+
typedef struct DisasContext {
const XtensaConfig *config;
TranslationBlock *tb;
diff --git a/trace-events b/trace-events
index 11a17a8a40..81bc915edd 100644
--- a/trace-events
+++ b/trace-events
@@ -41,6 +41,11 @@ virtio_irq(void *vq) "vq %p"
virtio_notify(void *vdev, void *vq) "vdev %p vq %p"
virtio_set_status(void *vdev, uint8_t val) "vdev %p val %u"
+# hw/virtio/virtio-rng.c
+virtio_rng_guest_not_ready(void *rng) "rng %p: guest not ready"
+virtio_rng_pushed(void *rng, size_t len) "rng %p: %zd bytes pushed"
+virtio_rng_request(void *rng, size_t size, unsigned quota) "rng %p: %zd bytes requested, %u bytes quota left"
+
# hw/char/virtio-serial-bus.c
virtio_serial_send_control_event(unsigned int port, uint16_t event, uint16_t value) "port %u, event %u, value %u"
virtio_serial_throttle_port(unsigned int port, bool throttle) "port %u, throttle %d"
@@ -1265,6 +1270,15 @@ kvm_failed_spr_get(int str, const char *msg) "Warning: Unable to retrieve SPR %d
kvm_failed_reg_get(uint64_t id, const char *msg) "Warning: Unable to retrieve ONEREG %" PRIu64 " from KVM: %s"
kvm_failed_reg_set(uint64_t id, const char *msg) "Warning: Unable to set ONEREG %" PRIu64 " to KVM: %s"
+# TCG related tracing (mostly disabled by default)
+# cpu-exec.c
+disable exec_tb(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR
+disable exec_tb_nocache(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR
+disable exec_tb_exit(void *next_tb, unsigned int flags) "tb:%p flags=%x"
+
+# translate-all.c
+translate_block(void *tb, uintptr_t pc, uint8_t *tb_code) "tb:%p, pc:0x%"PRIxPTR", tb_code:%p"
+
# memory.c
memory_region_ops_read(void *mr, uint64_t addr, uint64_t value, unsigned size) "mr %p addr %#"PRIx64" value %#"PRIx64" size %u"
memory_region_ops_write(void *mr, uint64_t addr, uint64_t value, unsigned size) "mr %p addr %#"PRIx64" value %#"PRIx64" size %u"
diff --git a/trace/Makefile.objs b/trace/Makefile.objs
index d7a86969a4..387f191fd4 100644
--- a/trace/Makefile.objs
+++ b/trace/Makefile.objs
@@ -49,6 +49,9 @@ util-obj-y += generated-events.o
######################################################################
# Auto-generated tracing routines
+##################################################
+# Execution level
+
$(obj)/generated-tracers.h: $(obj)/generated-tracers.h-timestamp
@cmp -s $< $@ || cp $< $@
$(obj)/generated-tracers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
@@ -57,8 +60,8 @@ $(obj)/generated-tracers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/conf
--backends=$(TRACE_BACKENDS) \
< $< > $@," GEN $(patsubst %-timestamp,%,$@)")
-######################################################################
-# Auto-generated tracing routines (non-DTrace)
+##############################
+# non-DTrace
$(obj)/generated-tracers.c: $(obj)/generated-tracers.c-timestamp
@cmp -s $< $@ || cp $< $@
@@ -70,9 +73,8 @@ $(obj)/generated-tracers.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/conf
$(obj)/generated-tracers.o: $(obj)/generated-tracers.c $(obj)/generated-tracers.h
-
-######################################################################
-# Auto-generated DTrace code
+##############################
+# DTrace
# Normal practice is to name DTrace probe file with a '.d' extension
# but that gets picked up by QEMU's Makefile as an external dependency
@@ -94,6 +96,47 @@ $(obj)/generated-tracers-dtrace.o: $(obj)/generated-tracers-dtrace.dtrace
util-obj-y += generated-tracers-dtrace.o
endif
+##################################################
+# Translation level
+
+$(obj)/generated-helpers-wrappers.h: $(obj)/generated-helpers-wrappers.h-timestamp
+$(obj)/generated-helpers-wrappers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
+ $(call quiet-command,$(TRACETOOL) \
+ --format=tcg-helper-wrapper-h \
+ --backend=$(TRACE_BACKENDS) \
+ < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
+
+$(obj)/generated-helpers.h: $(obj)/generated-helpers.h-timestamp
+$(obj)/generated-helpers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
+ $(call quiet-command,$(TRACETOOL) \
+ --format=tcg-helper-h \
+ --backend=$(TRACE_BACKENDS) \
+ < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
+
+$(obj)/generated-helpers.c: $(obj)/generated-helpers.c-timestamp
+$(obj)/generated-helpers.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
+ $(call quiet-command,$(TRACETOOL) \
+ --format=tcg-helper-c \
+ --backend=$(TRACE_BACKENDS) \
+ < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
+
+$(obj)/generated-helpers.o: $(obj)/generated-helpers.c
+
+target-obj-y += generated-helpers.o
+
+
+$(obj)/generated-tcg-tracers.h: $(obj)/generated-tcg-tracers.h-timestamp
+$(obj)/generated-tcg-tracers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
+ $(call quiet-command,$(TRACETOOL) \
+ --format=tcg-h \
+ --backend=$(TRACE_BACKENDS) \
+ < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
+
+
######################################################################
# Backend code
diff --git a/translate-all.c b/translate-all.c
index 8f7e11b0a5..2e0265ae27 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -33,6 +33,7 @@
#include "qemu-common.h"
#define NO_CPU_IO_DEFS
#include "cpu.h"
+#include "trace.h"
#include "disas/disas.h"
#include "tcg.h"
#if defined(CONFIG_USER_ONLY)
@@ -158,6 +159,8 @@ int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr
gen_intermediate_code(env, tb);
+ trace_translate_block(tb, tb->pc, tb->tc_ptr);
+
/* generate machine code */
gen_code_buf = tb->tc_ptr;
tb->tb_next_offset[0] = 0xffff;