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-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
|
||||||
|
6
Makefile
6
Makefile
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
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
|
#define TRACE_H
|
||||||
|
|
||||||
#include "trace/generated-tracers.h"
|
#include "trace/generated-tracers.h"
|
||||||
|
#include "trace/generated-events.h"
|
||||||
|
|
||||||
#endif /* TRACE_H */
|
#endif /* TRACE_H */
|
||||||
|
@ -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):
|
||||||
|
@ -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)
|
||||||
|
@ -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"',
|
||||||
|
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):
|
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
|
||||||
|
|
||||||
|
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,
|
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 + ')')
|
||||||
|
|
||||||
|
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-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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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 */
|
||||||
|
@ -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__)
|
||||||
|
@ -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
|
||||||
|
@ -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__)
|
||||||
|
@ -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. */
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
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_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"
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user