Generate the necessary TCG helper declarations for tracing events in guest code.
Signed-off-by: Lluís Vilanova <vilan...@ac.upc.edu> --- .gitignore | 1 Makefile | 2 Makefile.objs | 9 ++ def-helper.h | 9 ++ scripts/simpletrace.py | 2 scripts/tracetool | 202 ++++++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 214 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 406f75f..d47b586 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ trace.h trace.c trace-dtrace.h trace-dtrace.dtrace +trace-tcg-helper.h *-timestamp *-softmmu *-darwin-user diff --git a/Makefile b/Makefile index 506db1b..516622a 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ BUILD_DIR=$(CURDIR) GENERATED_HEADERS = config-host.h qemu-options.def -GENERATED_HEADERS += trace.h +GENERATED_HEADERS += trace.h trace-tcg-helper.h ifeq ($(TRACE_BACKEND),dtrace) GENERATED_HEADERS += trace-dtrace.h endif diff --git a/Makefile.objs b/Makefile.objs index d7a6539..8f97709 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -398,6 +398,15 @@ trace-obj-y += $(addprefix trace/, $(trace-nested-y)) $(trace-obj-y): $(GENERATED_HEADERS) ###################################################################### +# trace tcg + +trace-tcg-helper.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak + $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool $(TRACETOOL_EXTRA) --tcg --tcg-h < $< > $@," GEN $(TARGET_DIR)trace-tcg-helper.h") + @cmp -s $@ trace-tcg-helper.h || cp $@ trace-tcg-helper.h + +trace-tcg-helper.h: trace-tcg-helper.h-timestamp + +###################################################################### # smartcard libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o card_7816.o diff --git a/def-helper.h b/def-helper.h index 8a822c7..c4fce2d 100644 --- a/def-helper.h +++ b/def-helper.h @@ -13,6 +13,11 @@ helper.c, defining: GEN_HELPER 1 to produce op generation functions (gen_helper_*) GEN_HELPER 2 to do runtime registration helper functions. + + After including this header the GEN_HELPER_MACRO will have the following + values: + 1 : op generation functions were produced (GEN_HELPER was 1) + -1 : otherwise */ #ifndef DEF_HELPER_H @@ -142,6 +147,7 @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \ #undef GEN_HELPER #define GEN_HELPER -1 +#define GEN_HELPER_CODE -1 #elif GEN_HELPER == 1 /* Gen functions. */ @@ -205,6 +211,7 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1 #undef GEN_HELPER #define GEN_HELPER -1 +#define GEN_HELPER_CODE 1 #elif GEN_HELPER == 2 /* Register helpers. */ @@ -226,6 +233,7 @@ DEF_HELPER_FLAGS_0(name, flags, ret) #undef GEN_HELPER #define GEN_HELPER -1 +#define GEN_HELPER_CODE -1 #elif GEN_HELPER == -1 /* Undefine macros. */ @@ -236,5 +244,6 @@ DEF_HELPER_FLAGS_0(name, flags, ret) #undef DEF_HELPER_FLAGS_3 #undef DEF_HELPER_FLAGS_4 #undef GEN_HELPER +#undef GEN_HELPER_CODE #endif diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index f55e5e6..3476d6c 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -20,7 +20,7 @@ dropped_event_id = 0xfffffffffffffffe trace_fmt = '=QQQQQQQQ' trace_len = struct.calcsize(trace_fmt) -event_re = re.compile(r'(disable\s+)?([a-zA-Z0-9_]+)\(([^)]*)\).*') +event_re = re.compile(r'(disable\s+|tcg\s+|tcg-vcpu\s+)*([a-zA-Z0-9_]+)\(([^)]*)\).*') def parse_events(fobj): """Parse a trace-events file into {event_num: (name, arg1, ...)}.""" diff --git a/scripts/tracetool b/scripts/tracetool index 1d8a637..5431f2d 100755 --- a/scripts/tracetool +++ b/scripts/tracetool @@ -13,7 +13,7 @@ set -f usage() { cat >&2 <<EOF -usage: $0 [--nop | --simple | --stderr | --ust | --dtrace] [-h | -c] +usage: $0 [--nop | --simple | --stderr | --ust | --dtrace | --tcg] [-h | -c] Generate tracing code for a file on stdin. Backends: @@ -22,12 +22,14 @@ Backends: --stderr Stderr built-in backend --ust LTTng User Space Tracing backend --dtrace DTrace/SystemTAP backend + --tcg Intermediate TCG helper to real backend proxy Output formats: - -h Generate .h file - -c Generate .c file - -d Generate .d file (DTrace only) - --stap Generate .stp file (DTrace with SystemTAP only) + -h Generate .h file + -c Generate .c file + -d Generate .d file (DTrace only) + --stap Generate .stp file (DTrace with SystemTAP only) + --tcg-h Generate trace-tcg-helper.h file (tcg only) Options: --binary [path] Full path to QEMU binary @@ -218,13 +220,57 @@ host_type() "TCGv_i32") echo "uint32_t" ;; "TCGv_i64") echo "uint64_t" ;; "TCGv_ptr") echo "void *" ;; - # force a fixed-size type in trace.{h,c} - # (ideally would use a host-specific type) - "TCGv") echo "uint64_t" ;; + "TCGv") + if [ "$backend" = "tcg" ]; then + echo "target_ulong" + else + # force a fixed-size type in trace.{h,c} + # (ideally would use a host-specific type) + echo "uint64_t" + fi + ;; *) echo "$1" ;; esac } +tcg_compat_type() +{ + case "$1" in + "uint8_t") echo "uint32_t" ;; + *) echo "$1" ;; + esac +} + +tcg_type() +{ + local tcg_compat_type + tcg_compat_type=`tcg_compat_type "$1"` + case "$tcg_compat_type" in + "uint32_t") echo "TCGv_i32" ;; + "uint64_t") echo "TCGv_i64" ;; + "void*") echo "TCGv_ptr" ;; + "TCGv"*) echo "$1" ;; + *) echo "Don't know how to translate type $1 into a TCG type" >&2 + exit 1 + ;; + esac +} + +tcg_helper_decl_type() +{ + local type + type=`tcg_type "$1"` + case "$type" in + "TCGv") echo "tl" ;; + "TCGv_ptr") echo "ptr" ;; + "TCGv_i32") echo "i32" ;; + "TCGv_i64") echo "i64" ;; + *) echo "Don't know how to translate type $1 into a TCG helper declaration type" >&2 + exit 1 + ;; + esac +} + # Get the argument name list of a trace event get_argnames() @@ -662,6 +708,127 @@ linetostap_end_dtrace() return } +linetotcg_h_nop() +{ + local has_tcg has_tcg_vcpu + has_property "$1" "tcg" && has_tcg=1 + has_property "$1" "tcg-vcpu" && has_tcg_vcpu=1 + if [ "$has_tcg" != "1" -a "$has_tcg_vcpu" != "1" ]; then + return + fi + + local api + api=$(get_api_name "$1") + + cat <<EOF +#if GEN_HELPER_CODE == 1 +static inline void gen_helper_${api}($(get_args "$1")) +{ +} +#endif +EOF +} + +tcg_temp_new_type() +{ + local compat_type + compat_type=`tcg_compat_type "$1"` + case "$compat_type" in + "uint32_t") echo "tcg_const_i32" ;; + "uint64_t") echo "tcg_const_i64" ;; + "void *") echo "tcg_cont_ptr" ;; + *) echo "" ;; + esac +} + +tcg_temp_free_type() +{ + local compat_type + compat_type=`tcg_compat_type "$1"` + case "$compat_type" in + "uint32_t") echo "tcg_temp_free_i32" ;; + "uint64_t") echo "tcg_temp_free_i64" ;; + "void *") echo "tcg_temp_free_ptr" ;; + # do nothing on non-temp values + *) echo "tcg_temp_noop" ;; + esac +} + +linetotcg_h_tcg() +{ + local has_tcg has_tcg_vcpu + has_property "$1" "tcg" && has_tcg=1 + has_property "$1" "tcg-vcpu" && has_tcg_vcpu=1 + if [ "$has_tcg" != "1" -a "$has_tcg_vcpu" != "1" ]; then + return + fi + + local api argc + api=$(get_api_name "$1") + argc=$(get_argc "$1") + + # TCG helper proxy declaration + local proxy_argtypes + if [ $argc -ne 0 ]; then + proxy_argtypes=$(get_argtypes "$1" tcg_helper_decl_type) + proxy_argtypes=", $proxy_argtypes" + fi + if [ "$has_tcg_vcpu" = "1" ]; then + if [ "$has_tcg" = "1" ]; then + echo "Cannot have both \"tcg\" and \"tcg-vcpu\" properties" >&2 + exit 1 + fi + echo "DEF_HELPER_$argc(${api}_proxy, void$proxy_argtypes)" + else + echo "DEF_HELPER_FLAGS_$argc(${api}_proxy, TCG_CALL_CONST, void$proxy_argtypes)" + fi + + # mixed-type to TCG helper bridge + local argnames argname temps_names + local temps_tcg_new temps_argtypes temps_new + local temps_tcg_free temps_free + if [ $argc -ne 0 ]; then + argnames=$(get_argnames "$1" ",") + temps_names="" + for argname in $argnames; do + temps_names="${temps_names} __${argname}" + done + + temps_tcg_new=$(get_argtypes "$1" tcg_temp_new_type) + temps_new=$(zip_lists "$temps_tcg_new" "$argnames" "%s(%s), ") + temps_new=$(zip_lists "$temps_names" "$temps_new" "%s =%s, ") + temps_argtypes=$(get_argtypes "$1" tcg_type) + temps_new=$(zip_lists "$temps_argtypes" "$temps_new" "%s %s;") + + tcg_temp_free=$(get_argtypes "$1" tcg_temp_free_type) + temps_free=$(zip_lists "$tcg_temp_free" "$temps_names" "%s(%s);") + fi + cat <<EOF +#if GEN_HELPER_CODE == 1 +static inline void gen_helper_${api}($(get_args "$1")) +{ + $temps_new + gen_helper_${api}_proxy($temps_names); + $temps_free +} +#endif +EOF +} + +linetotcg_h_begin_tcg() +{ + cat <<EOF +/* This file is autogenerated by tracetool, do not edit. */ + +#define tcg_temp_noop(v) +EOF +} + +linetotcg_h_end_tcg() +{ + return +} + # Process stdin by calling begin, line, and end functions for the backend convert() { @@ -744,6 +911,20 @@ tracetostap() convert stap } +tracetotcg_h() +{ + if [ $backend != "tcg" ]; then + echo "TCG helper generator not applicable to $backend backend" >&2 + exit 1 + fi + convert tcg_h + cat <<EOF +#if GEN_HELPER_CODE == 1 +#include "trace.h" +#endif +EOF +} + backend= output= @@ -756,7 +937,9 @@ probeprefix= until [ -z "$1" ] do case "$1" in - "--nop" | "--simple" | "--stderr" | "--ust" | "--dtrace") backend="${1#--}" ;; + "--nop" | "--simple" | "--stderr" | "--ust" | "--dtrace" | "--tcg") + backend="${1#--}" + ;; "--binary") shift ; binary="$1" ;; "--target-arch") shift ; targetarch="$1" ;; @@ -765,6 +948,7 @@ do "-h" | "-c" | "-d") output="${1#-}" ;; "--stap") output="${1#--}" ;; + "--tcg-h") output="tcg_h" ;; "--check-backend") exit 0 ;; # used by ./configure to test for backend