Tracing pull request

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJT6hhYAAoJEJykq7OBq3PIH44IAIC42HoYJFgE1RkLl/77PhpV
 WNNDJ/SIh/084PS6XKvHja0aUGjmQM/QmlCuV17MLp7ub1XeMDoncP9AnVhiWTyL
 a3c5TJw8OasBadffSFLXh5ZmW/fgkie+TjXIWud4dB+hZmd28uV46tLLRrJFJA6O
 uCpAKUUCVyN78LDhsGVUzZAYjXzeFQQ9Eq5z4dysfCO5x4y5rvcTs6MJ6X5vxUBP
 rF3RTKb5DmcFZvuOYJxVx9WiDOe6RiMS72sitQCszvGspmBtVP0CvJQnHu7nMOVf
 Ljti0XVui3t3Jto+DJSH4ki0i025MSetgAMhk1bYcVnK4XQ2t03DrQExOM+VjjM=
 =+ba+
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Peter Maydell 2014-08-15 16:37:17 +01:00
commit 5c6b3c50cc
42 changed files with 808 additions and 28 deletions

4
.gitignore vendored
View File

@ -11,6 +11,10 @@
/trace/generated-tracers.dtrace /trace/generated-tracers.dtrace
/trace/generated-events.h /trace/generated-events.h
/trace/generated-events.c /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-provider.h
/trace/generated-ust.c /trace/generated-ust.c
/libcacard/trace/generated-tracers.c /libcacard/trace/generated-tracers.c

View File

@ -57,6 +57,12 @@ GENERATED_HEADERS += trace/generated-tracers-dtrace.h
endif endif
GENERATED_SOURCES += trace/generated-tracers.c 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) ifeq ($(findstring ust,$(TRACE_BACKENDS)),ust)
GENERATED_HEADERS += trace/generated-ust-provider.h GENERATED_HEADERS += trace/generated-ust-provider.h
GENERATED_SOURCES += trace/generated-ust.c GENERATED_SOURCES += trace/generated-ust.c

View File

@ -1,7 +1,7 @@
####################################################################### #######################################################################
# Common libraries for tools and emulators # Common libraries for tools and emulators
stub-obj-y = stubs/ 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 # block-obj-y is code used by both qemu system emulation and qemu-img
@ -100,6 +100,11 @@ common-obj-y += disas/
version-obj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.o version-obj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.o
version-lobj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.lo version-lobj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.lo
######################################################################
# tracing
util-obj-y += trace/
target-obj-y += trace/
###################################################################### ######################################################################
# guest agent # guest agent

View File

@ -38,7 +38,7 @@ config-target.h: config-target.h-timestamp
config-target.h-timestamp: config-target.mak config-target.h-timestamp: config-target.mak
ifdef CONFIG_TRACE_SYSTEMTAP 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 ifdef CONFIG_USER_ONLY
TARGET_TYPE=user TARGET_TYPE=user
@ -64,6 +64,13 @@ $(QEMU_PROG).stp: $(SRC_PATH)/trace-events
--target-type=$(TARGET_TYPE) \ --target-type=$(TARGET_TYPE) \
< $< > $@," GEN $(TARGET_DIR)$(QEMU_PROG).stp") < $< > $@," 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 else
stap: stap:
endif endif
@ -152,15 +159,20 @@ endif # CONFIG_SOFTMMU
dummy := $(call unnest-vars,,obj-y) dummy := $(call unnest-vars,,obj-y)
all-obj-y := $(obj-y) all-obj-y := $(obj-y)
target-obj-y :=
block-obj-y := block-obj-y :=
common-obj-y := common-obj-y :=
include $(SRC_PATH)/Makefile.objs include $(SRC_PATH)/Makefile.objs
dummy := $(call unnest-vars,,target-obj-y)
target-obj-y-save := $(target-obj-y)
dummy := $(call unnest-vars,.., \ dummy := $(call unnest-vars,.., \
block-obj-y \ block-obj-y \
block-obj-m \ block-obj-m \
common-obj-y \ common-obj-y \
common-obj-m) common-obj-m)
target-obj-y := $(target-obj-y-save)
all-obj-y += $(common-obj-y) all-obj-y += $(common-obj-y)
all-obj-y += $(target-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y) all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y)
# build either PROG or PROGW # build either PROG or PROGW
@ -191,6 +203,7 @@ endif
ifdef CONFIG_TRACE_SYSTEMTAP ifdef CONFIG_TRACE_SYSTEMTAP
$(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset" $(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).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 endif
GENERATED_HEADERS += config-target.h GENERATED_HEADERS += config-target.h

View File

@ -18,6 +18,7 @@
*/ */
#include "config.h" #include "config.h"
#include "cpu.h" #include "cpu.h"
#include "trace.h"
#include "disas/disas.h" #include "disas/disas.h"
#include "tcg.h" #include "tcg.h"
#include "qemu/atomic.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 */ #endif /* DEBUG_DISAS */
next_tb = tcg_qemu_tb_exec(env, tb_ptr); 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) { if ((next_tb & TB_EXIT_MASK) > TB_EXIT_IDX1) {
/* We didn't start executing this TB (eg because the instruction /* We didn't start executing this TB (eg because the instruction
* counter hit zero); we must restore the guest PC to the address * 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); max_cycles);
cpu->current_tb = tb; cpu->current_tb = tb;
/* execute the generated code */ /* execute the generated code */
trace_exec_tb_nocache(tb, tb->pc);
cpu_tb_exec(cpu, tb->tc_ptr); cpu_tb_exec(cpu, tb->tc_ptr);
cpu->current_tb = NULL; cpu->current_tb = NULL;
tb_phys_invalidate(tb, -1); tb_phys_invalidate(tb, -1);
@ -749,6 +754,7 @@ int cpu_exec(CPUArchState *env)
cpu->current_tb = tb; cpu->current_tb = tb;
barrier(); barrier();
if (likely(!cpu->exit_request)) { if (likely(!cpu->exit_request)) {
trace_exec_tb(tb, tb->pc);
tc_ptr = tb->tc_ptr; tc_ptr = tb->tc_ptr;
/* execute the generated code */ /* execute the generated code */
next_tb = cpu_tb_exec(cpu, tc_ptr); next_tb = cpu_tb_exec(cpu, tc_ptr);

View File

@ -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 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 the same time using the 'trace_event_get_state' routine (see header
"trace/control.h" for more information). "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);

View File

@ -16,6 +16,7 @@
#include "hw/virtio/virtio-rng.h" #include "hw/virtio/virtio-rng.h"
#include "sysemu/rng.h" #include "sysemu/rng.h"
#include "qom/object_interfaces.h" #include "qom/object_interfaces.h"
#include "trace.h"
static bool is_guest_ready(VirtIORNG *vrng) 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)) { && (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
return true; return true;
} }
trace_virtio_rng_guest_not_ready(vrng);
return false; return false;
} }
@ -62,6 +64,7 @@ static void chr_read(void *opaque, const void *buf, size_t size)
offset += len; offset += len;
virtqueue_push(vrng->vq, &elem, len); virtqueue_push(vrng->vq, &elem, len);
trace_virtio_rng_pushed(vrng, len);
} }
virtio_notify(vdev, vrng->vq); 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); quota = MIN((uint64_t)vrng->quota_remaining, (uint64_t)UINT32_MAX);
} }
size = get_request_size(vrng->vq, quota); size = get_request_size(vrng->vq, quota);
trace_virtio_rng_request(vrng, size, quota);
size = MIN(vrng->quota_remaining, size); size = MIN(vrng->quota_remaining, size);
if (size) { if (size) {
rng_backend_request_entropy(vrng->rng, size, chr_read, vrng); rng_backend_request_entropy(vrng->rng, size, chr_read, vrng);

View File

@ -57,6 +57,8 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
} }
#include "helper.h" #include "helper.h"
#include "trace/generated-helpers.h"
#include "trace/generated-helpers-wrappers.h"
#include "tcg-runtime.h" #include "tcg-runtime.h"
#undef DEF_HELPER_FLAGS_0 #undef DEF_HELPER_FLAGS_0

View File

@ -27,6 +27,7 @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
dh_ctype(t4), dh_ctype(t5)); dh_ctype(t4), dh_ctype(t5));
#include "helper.h" #include "helper.h"
#include "trace/generated-helpers.h"
#include "tcg-runtime.h" #include "tcg-runtime.h"
#undef DEF_HELPER_FLAGS_0 #undef DEF_HELPER_FLAGS_0

View File

@ -36,6 +36,7 @@
| dh_sizemask(t5, 5) }, | dh_sizemask(t5, 5) },
#include "helper.h" #include "helper.h"
#include "trace/generated-helpers.h"
#include "tcg-runtime.h" #include "tcg-runtime.h"
#undef DEF_HELPER_FLAGS_0 #undef DEF_HELPER_FLAGS_0

7
include/trace-tcg.h Normal file
View File

@ -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 */

View File

@ -2,5 +2,6 @@
#define TRACE_H #define TRACE_H
#include "trace/generated-tracers.h" #include "trace/generated-tracers.h"
#include "trace/generated-events.h"
#endif /* TRACE_H */ #endif /* TRACE_H */

View File

@ -58,8 +58,8 @@ def read_record(edict, fobj):
rechdr = read_header(fobj, rec_header_fmt) rechdr = read_header(fobj, rec_header_fmt)
return get_record(edict, rechdr, fobj) # return tuple of record elements return get_record(edict, rechdr, fobj) # return tuple of record elements
def read_trace_file(edict, fobj): def read_trace_header(fobj):
"""Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6).""" """Read and verify trace file header"""
header = read_header(fobj, log_header_fmt) header = read_header(fobj, log_header_fmt)
if header is None or \ if header is None or \
header[0] != header_event_id 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!' raise ValueError('Log format %d not supported with this QEMU release!'
% log_version) % 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: while True:
rec = read_record(edict, fobj) rec = read_record(edict, fobj)
if rec is None: if rec is None:
@ -102,13 +104,16 @@ class Analyzer(object):
"""Called at the end of the trace.""" """Called at the end of the trace."""
pass pass
def process(events, log, analyzer): def process(events, log, analyzer, read_header=True):
"""Invoke an analyzer on each event in a log.""" """Invoke an analyzer on each event in a log."""
if isinstance(events, str): if isinstance(events, str):
events = _read_events(open(events, 'r')) events = _read_events(open(events, 'r'))
if isinstance(log, str): if isinstance(log, str):
log = open(log, 'rb') log = open(log, 'rb')
if read_header:
read_trace_header(log)
dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)") dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)")
edict = {dropped_event_id: dropped_event} edict = {dropped_event_id: dropped_event}
@ -137,7 +142,7 @@ def process(events, log, analyzer):
analyzer.begin() analyzer.begin()
fn_cache = {} fn_cache = {}
for rec in read_trace_file(edict, log): for rec in read_trace_records(edict, log):
event_num = rec[0] event_num = rec[0]
event = edict[event_num] event = edict[event_num]
if event_num not in fn_cache: if event_num not in fn_cache:
@ -152,12 +157,17 @@ def run(analyzer):
advanced scripts will want to call process() instead.""" advanced scripts will want to call process() instead."""
import sys import sys
if len(sys.argv) != 3: read_header = True
sys.stderr.write('usage: %s <trace-events> <trace-file>\n' % sys.argv[0]) 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) 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) process(events, sys.argv[2], analyzer, read_header=read_header)
if __name__ == '__main__': if __name__ == '__main__':
class Formatter(Analyzer): class Formatter(Analyzer):

View File

@ -15,9 +15,11 @@ __email__ = "stefanha@linux.vnet.ibm.com"
import re import re
import sys import sys
import weakref
import tracetool.format import tracetool.format
import tracetool.backend import tracetool.backend
import tracetool.transform
def error_write(*lines): def error_write(*lines):
@ -108,6 +110,18 @@ class Arguments:
"""List of argument types.""" """List of argument types."""
return [ type_ for type_, _ in self._args ] 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): class Event(object):
"""Event description. """Event description.
@ -122,13 +136,21 @@ class Event(object):
Properties of the event. Properties of the event.
args : Arguments args : Arguments
The event 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 Parameters
---------- ----------
@ -136,20 +158,32 @@ class Event(object):
Event name. Event name.
props : list of str props : list of str
Property names. Property names.
fmt : str fmt : str, list of str
Event printing format. Event printing format (or formats).
args : Arguments args : Arguments
Event 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.name = name
self.properties = props self.properties = props
self.fmt = fmt self.fmt = fmt
self.args = args 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 unknown_props = set(self.properties) - self._VALID_PROPS
if len(unknown_props) > 0: if len(unknown_props) > 0:
raise ValueError("Unknown properties: %s" raise ValueError("Unknown properties: %s"
% ", ".join(unknown_props)) % ", ".join(unknown_props))
assert isinstance(self.fmt, str) or len(self.fmt) == 2
def copy(self): def copy(self):
"""Create a new copy.""" """Create a new copy."""
@ -172,24 +206,50 @@ class Event(object):
name = groups["name"] name = groups["name"]
props = groups["props"].split() props = groups["props"].split()
fmt = groups["fmt"] fmt = groups["fmt"]
fmt_trans = groups["fmt_trans"]
if len(fmt_trans) > 0:
fmt = [fmt_trans, fmt]
args = Arguments.build(groups["args"]) args = Arguments.build(groups["args"])
arg_fmts = Event._FMT.findall(fmt)
return Event(name, props, fmt, args) 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, arg_fmts)
def __repr__(self): def __repr__(self):
"""Evaluable string representation for this object.""" """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), return "Event('%s %s(%s) %s')" % (" ".join(self.properties),
self.name, self.name,
self.args, self.args,
self.fmt) fmt)
QEMU_TRACE = "trace_%(name)s" QEMU_TRACE = "trace_%(name)s"
QEMU_TRACE_TCG = QEMU_TRACE + "_tcg"
def api(self, fmt=None): def api(self, fmt=None):
if fmt is None: if fmt is None:
fmt = Event.QEMU_TRACE fmt = Event.QEMU_TRACE
return fmt % {"name": self.name} return fmt % {"name": self.name}
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): def _read_events(fobj):
res = [] res = []
@ -272,4 +332,35 @@ def generate(fevents, format, backends,
events = _read_events(fevents) 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) tracetool.format.generate(events, format, backend)

View File

@ -40,6 +40,11 @@ def generate(events, backend):
enabled = 0 enabled = 0
else: else:
enabled = 1 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('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled))
out('#include "trace/event-internal.h"', out('#include "trace/event-internal.h"',

View File

@ -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()

View File

@ -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): def generate(events, backend):
events = [e for e in events events = [e for e in events
if "disable" not in e.properties] if "disable" not in e.properties]
@ -45,9 +52,7 @@ def generate(events, backend):
i = 1 i = 1
if len(e.args) > 0: if len(e.args) > 0:
for name in e.args.names(): for name in e.args.names():
# Append underscore to reserved keywords name = stap_escape(name)
if name in RESERVED_WORDS:
name += '_'
out(' %s = $arg%d;' % (name, i)) out(' %s = $arg%d;' % (name, i))
i += 1 i += 1

View File

@ -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 */')

View File

@ -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),
)

View File

@ -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,
)

View File

@ -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]),
)

View File

@ -63,13 +63,20 @@ def generate(events, backend):
name=e.name, name=e.name,
args=", ".join(", ".join(i) for i in e.args)) args=", ".join(", ".join(i) for i in e.args))
for t, n in e.args: types = e.args.types()
if ('int' in t) or ('long' in t) or ('unsigned' in t) or ('size_t' in t): 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 + ')') out(' ctf_integer(' + t + ', ' + n + ', ' + n + ')')
elif ('double' in t) or ('float' in t): elif ('double' in t) or ('float' in t):
out(' ctf_float(' + t + ', ' + n + ', ' + n + ')') 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): elif ('void *' in t) or ('void*' in t):
out(' ctf_integer_hex(unsigned long, ' + n + ', ' + n + ')') out(' ctf_integer_hex(unsigned long, ' + n + ', ' + n + ')')

View File

@ -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,
}

View File

@ -26,6 +26,9 @@
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "trace-tcg.h"
#undef ALPHA_DEBUG_DISAS #undef ALPHA_DEBUG_DISAS
#define CONFIG_SOFTFLOAT_INLINE #define CONFIG_SOFTFLOAT_INLINE

View File

@ -35,6 +35,8 @@
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "trace-tcg.h"
static TCGv_i64 cpu_X[32]; static TCGv_i64 cpu_X[32];
static TCGv_i64 cpu_pc; static TCGv_i64 cpu_pc;
static TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF; static TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF;

View File

@ -35,6 +35,9 @@
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "trace-tcg.h"
#define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T) #define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T)
#define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5) #define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5)
/* currently all emulated v5 cores are also v5TE, so don't bother */ /* currently all emulated v5 cores are also v5TE, so don't bother */

View File

@ -33,6 +33,9 @@
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "trace-tcg.h"
#define DISAS_CRIS 0 #define DISAS_CRIS 0
#if DISAS_CRIS #if DISAS_CRIS
# define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__) # define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)

View File

@ -32,6 +32,9 @@
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "trace-tcg.h"
#define PREFIX_REPZ 0x01 #define PREFIX_REPZ 0x01
#define PREFIX_REPNZ 0x02 #define PREFIX_REPNZ 0x02
#define PREFIX_LOCK 0x04 #define PREFIX_LOCK 0x04

View File

@ -27,6 +27,9 @@
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "trace-tcg.h"
#define DISAS_LM32 1 #define DISAS_LM32 1
#if DISAS_LM32 #if DISAS_LM32
# define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__) # define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)

View File

@ -27,6 +27,9 @@
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "trace-tcg.h"
//#define DEBUG_DISPATCH 1 //#define DEBUG_DISPATCH 1
/* Fake floating point. */ /* Fake floating point. */

View File

@ -26,6 +26,9 @@
#include "exec/cpu_ldst.h" #include "exec/cpu_ldst.h"
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "trace-tcg.h"
#define SIM_COMPAT 0 #define SIM_COMPAT 0
#define DISAS_GNU 1 #define DISAS_GNU 1
#define DISAS_MB 1 #define DISAS_MB 1

View File

@ -30,6 +30,9 @@
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "sysemu/kvm.h" #include "sysemu/kvm.h"
#include "trace-tcg.h"
#define MIPS_DEBUG_DISAS 0 #define MIPS_DEBUG_DISAS 0
//#define MIPS_DEBUG_SIGN_EXTENSIONS //#define MIPS_DEBUG_SIGN_EXTENSIONS

View File

@ -31,6 +31,9 @@
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "trace-tcg.h"
#define OPENRISC_DISAS #define OPENRISC_DISAS
#ifdef OPENRISC_DISAS #ifdef OPENRISC_DISAS

View File

@ -27,6 +27,9 @@
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "trace-tcg.h"
#define CPU_SINGLE_STEP 0x1 #define CPU_SINGLE_STEP 0x1
#define CPU_BRANCH_STEP 0x2 #define CPU_BRANCH_STEP 0x2
#define GDBSTUB_SINGLE_STEP 0x4 #define GDBSTUB_SINGLE_STEP 0x4

View File

@ -42,6 +42,8 @@ static TCGv_ptr cpu_env;
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "trace-tcg.h"
/* Information that (most) every instruction needs to manipulate. */ /* Information that (most) every instruction needs to manipulate. */
typedef struct DisasContext DisasContext; typedef struct DisasContext DisasContext;

View File

@ -28,6 +28,9 @@
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "trace-tcg.h"
typedef struct DisasContext { typedef struct DisasContext {
struct TranslationBlock *tb; struct TranslationBlock *tb;
target_ulong pc; target_ulong pc;

View File

@ -32,6 +32,9 @@
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "trace-tcg.h"
#define DEBUG_DISAS #define DEBUG_DISAS
#define DYNAMIC_PC 1 /* dynamic pc value */ #define DYNAMIC_PC 1 /* dynamic pc value */

View File

@ -23,6 +23,9 @@
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "trace-tcg.h"
/* internal defines */ /* internal defines */
typedef struct DisasContext { typedef struct DisasContext {
target_ulong pc; target_ulong pc;

View File

@ -41,6 +41,9 @@
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "exec/helper-gen.h" #include "exec/helper-gen.h"
#include "trace-tcg.h"
typedef struct DisasContext { typedef struct DisasContext {
const XtensaConfig *config; const XtensaConfig *config;
TranslationBlock *tb; TranslationBlock *tb;

View File

@ -41,6 +41,11 @@ virtio_irq(void *vq) "vq %p"
virtio_notify(void *vdev, void *vq) "vdev %p vq %p" virtio_notify(void *vdev, void *vq) "vdev %p vq %p"
virtio_set_status(void *vdev, uint8_t val) "vdev %p val %u" 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 # 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_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" 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_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" 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.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_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" memory_region_ops_write(void *mr, uint64_t addr, uint64_t value, unsigned size) "mr %p addr %#"PRIx64" value %#"PRIx64" size %u"

View File

@ -49,6 +49,9 @@ util-obj-y += generated-events.o
###################################################################### ######################################################################
# Auto-generated tracing routines # Auto-generated tracing routines
##################################################
# Execution level
$(obj)/generated-tracers.h: $(obj)/generated-tracers.h-timestamp $(obj)/generated-tracers.h: $(obj)/generated-tracers.h-timestamp
@cmp -s $< $@ || cp $< $@ @cmp -s $< $@ || cp $< $@
$(obj)/generated-tracers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak $(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) \ --backends=$(TRACE_BACKENDS) \
< $< > $@," GEN $(patsubst %-timestamp,%,$@)") < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
###################################################################### ##############################
# Auto-generated tracing routines (non-DTrace) # non-DTrace
$(obj)/generated-tracers.c: $(obj)/generated-tracers.c-timestamp $(obj)/generated-tracers.c: $(obj)/generated-tracers.c-timestamp
@cmp -s $< $@ || cp $< $@ @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 $(obj)/generated-tracers.o: $(obj)/generated-tracers.c $(obj)/generated-tracers.h
##############################
###################################################################### # DTrace
# Auto-generated DTrace code
# Normal practice is to name DTrace probe file with a '.d' extension # 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 # 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 util-obj-y += generated-tracers-dtrace.o
endif 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 # Backend code

View File

@ -33,6 +33,7 @@
#include "qemu-common.h" #include "qemu-common.h"
#define NO_CPU_IO_DEFS #define NO_CPU_IO_DEFS
#include "cpu.h" #include "cpu.h"
#include "trace.h"
#include "disas/disas.h" #include "disas/disas.h"
#include "tcg.h" #include "tcg.h"
#if defined(CONFIG_USER_ONLY) #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); gen_intermediate_code(env, tb);
trace_translate_block(tb, tb->pc, tb->tc_ptr);
/* generate machine code */ /* generate machine code */
gen_code_buf = tb->tc_ptr; gen_code_buf = tb->tc_ptr;
tb->tb_next_offset[0] = 0xffff; tb->tb_next_offset[0] = 0xffff;