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:
commit
5c6b3c50cc
4
.gitignore
vendored
4
.gitignore
vendored
@ -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
|
||||
|
6
Makefile
6
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
|
||||
|
@ -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
|
||||
@ -100,6 +100,11 @@ common-obj-y += disas/
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
7
include/trace-tcg.h
Normal file
7
include/trace-tcg.h
Normal 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 */
|
@ -2,5 +2,6 @@
|
||||
#define TRACE_H
|
||||
|
||||
#include "trace/generated-tracers.h"
|
||||
#include "trace/generated-events.h"
|
||||
|
||||
#endif /* TRACE_H */
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
||||
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):
|
||||
"""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)
|
||||
|
@ -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"',
|
||||
|
71
scripts/tracetool/format/simpletrace_stap.py
Normal file
71
scripts/tracetool/format/simpletrace_stap.py
Normal 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()
|
@ -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
|
||||
|
||||
|
57
scripts/tracetool/format/tcg_h.py
Normal file
57
scripts/tracetool/format/tcg_h.py
Normal 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 */')
|
50
scripts/tracetool/format/tcg_helper_c.py
Normal file
50
scripts/tracetool/format/tcg_helper_c.py
Normal 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),
|
||||
)
|
50
scripts/tracetool/format/tcg_helper_h.py
Normal file
50
scripts/tracetool/format/tcg_helper_h.py
Normal 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,
|
||||
)
|
70
scripts/tracetool/format/tcg_helper_wrapper_h.py
Normal file
70
scripts/tracetool/format/tcg_helper_wrapper_h.py
Normal 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]),
|
||||
)
|
@ -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 + ')')
|
||||
|
||||
|
166
scripts/tracetool/transform.py
Normal file
166
scripts/tracetool/transform.py
Normal 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,
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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__)
|
||||
|
@ -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
|
||||
|
@ -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__)
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -31,6 +31,9 @@
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/helper-gen.h"
|
||||
|
||||
#include "trace-tcg.h"
|
||||
|
||||
|
||||
#define OPENRISC_DISAS
|
||||
|
||||
#ifdef OPENRISC_DISAS
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -32,6 +32,9 @@
|
||||
|
||||
#include "exec/helper-gen.h"
|
||||
|
||||
#include "trace-tcg.h"
|
||||
|
||||
|
||||
#define DEBUG_DISAS
|
||||
|
||||
#define DYNAMIC_PC 1 /* dynamic pc value */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
14
trace-events
14
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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user