Signed-off-by: Lluís Vilanova <vilan...@ac.upc.edu> --- include/exec/cpu_ldst_template.h | 4 +++ include/exec/cpu_ldst_useronly_template.h | 4 +++ include/exec/helper-gen.h | 1 + include/exec/helper-proto.h | 1 + include/exec/helper-tcg.h | 1 + instrument/control.c | 35 +++++++++++++++++++++++++++++ instrument/control.h | 15 ++++++++++++ instrument/events.h | 5 ++++ instrument/events.inc.h | 18 ++++++++++++++- instrument/helpers.h | 1 + instrument/load.c | 1 + instrument/qemu-instr/control.h | 21 +++++++++++++++++ stubs/instrument.c | 2 ++ 13 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 instrument/helpers.h
diff --git a/include/exec/cpu_ldst_template.h b/include/exec/cpu_ldst_template.h index debbabcfb2..8018e8b16a 100644 --- a/include/exec/cpu_ldst_template.h +++ b/include/exec/cpu_ldst_template.h @@ -28,6 +28,7 @@ #include "trace-root.h" #endif +#include "instrument/events.h" #include "trace/mem.h" #if DATA_SIZE == 8 @@ -89,6 +90,7 @@ glue(glue(glue(cpu_ld, USUFFIX), MEMSUFFIX), _ra)(CPUArchState *env, #if !defined(SOFTMMU_CODE_ACCESS) TraceMemInfo meminfo = trace_mem_build_info(SHIFT, false, MO_TE, false); + instr_guest_mem_before_exec(ENV_GET_CPU(env), ptr, meminfo); trace_guest_mem_before_exec(ENV_GET_CPU(env), ptr, meminfo.raw); #endif @@ -126,6 +128,7 @@ glue(glue(glue(cpu_lds, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env, #if !defined(SOFTMMU_CODE_ACCESS) TraceMemInfo meminfo = trace_mem_build_info(SHIFT, true, MO_TE, false); + instr_guest_mem_before_exec(ENV_GET_CPU(env), ptr, meminfo); trace_guest_mem_before_exec(ENV_GET_CPU(env), ptr, meminfo.raw); #endif @@ -167,6 +170,7 @@ glue(glue(glue(cpu_st, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env, #if !defined(SOFTMMU_CODE_ACCESS) TraceMemInfo meminfo = trace_mem_build_info(SHIFT, false, MO_TE, true); + instr_guest_mem_before_exec(ENV_GET_CPU(env), ptr, meminfo); trace_guest_mem_before_exec(ENV_GET_CPU(env), ptr, meminfo.raw); #endif diff --git a/include/exec/cpu_ldst_useronly_template.h b/include/exec/cpu_ldst_useronly_template.h index b0b3fc1b8d..c36c50ae41 100644 --- a/include/exec/cpu_ldst_useronly_template.h +++ b/include/exec/cpu_ldst_useronly_template.h @@ -27,6 +27,7 @@ #include "trace-root.h" #endif +#include "instrument/events.h" #include "trace/mem.h" #if DATA_SIZE == 8 @@ -62,6 +63,7 @@ glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) { #if !defined(CODE_ACCESS) TraceMemInfo meminfo = trace_mem_build_info(DATA_SIZE, false, MO_TE, false); + instr_guest_mem_before_exec(ENV_GET_CPU(env), ptr, meminfo); trace_guest_mem_before_exec(ENV_GET_CPU(env), ptr, meminfo.raw); #endif return glue(glue(ld, USUFFIX), _p)(g2h(ptr)); @@ -81,6 +83,7 @@ glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) { #if !defined(CODE_ACCESS) TraceMemInfo meminfo = trace_mem_build_info(DATA_SIZE, true, MO_TE, false); + instr_guest_mem_before_exec(ENV_GET_CPU(env), ptr, meminfo); trace_guest_mem_before_exec(ENV_GET_CPU(env), ptr, meminfo.raw); #endif return glue(glue(lds, SUFFIX), _p)(g2h(ptr)); @@ -102,6 +105,7 @@ glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr, { #if !defined(CODE_ACCESS) TraceMemInfo meminfo = trace_mem_build_info(DATA_SIZE, false, MO_TE, true); + instr_guest_mem_before_exec(ENV_GET_CPU(env), ptr, meminfo); trace_guest_mem_before_exec(ENV_GET_CPU(env), ptr, meminfo.raw); #endif glue(glue(st, SUFFIX), _p)(g2h(ptr), v); diff --git a/include/exec/helper-gen.h b/include/exec/helper-gen.h index 8239ffc77c..f351c3d050 100644 --- a/include/exec/helper-gen.h +++ b/include/exec/helper-gen.h @@ -57,6 +57,7 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \ } #include "helper.h" +#include "instrument/helpers.h" #include "trace/generated-helpers.h" #include "trace/generated-helpers-wrappers.h" #include "tcg-runtime.h" diff --git a/include/exec/helper-proto.h b/include/exec/helper-proto.h index 954bef85ce..8fdd02c132 100644 --- a/include/exec/helper-proto.h +++ b/include/exec/helper-proto.h @@ -27,6 +27,7 @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \ dh_ctype(t4), dh_ctype(t5)); #include "helper.h" +#include "instrument/helpers.h" #include "trace/generated-helpers.h" #include "tcg-runtime.h" diff --git a/include/exec/helper-tcg.h b/include/exec/helper-tcg.h index b0c5bafa99..255e73c3e6 100644 --- a/include/exec/helper-tcg.h +++ b/include/exec/helper-tcg.h @@ -40,6 +40,7 @@ | dh_sizemask(t5, 5) }, #include "helper.h" +#include "instrument/helpers.h" #include "trace/generated-helpers.h" #include "tcg-runtime.h" diff --git a/instrument/control.c b/instrument/control.c index 3c3875dc99..f39e81d7c7 100644 --- a/instrument/control.c +++ b/instrument/control.c @@ -14,6 +14,8 @@ #include "instrument/qemu-instr/control.h" #include "instrument/qemu-instr/visibility.h" #include "qom/cpu.h" +#include "exec/helper-proto.h" +#include "exec/helper-gen.h" __thread InstrInfo instr_cur_info; @@ -86,3 +88,36 @@ QI_VPUBLIC void qi_event_set_guest_mem_before_trans( ERROR_IF(!instr_get_state(), "called outside instrumentation"); instr_set_event(guest_mem_before_trans, fn); } + + +QI_VPUBLIC void qi_event_gen_guest_mem_before_exec( + QITCGv_cpu vcpu, QITCGv vaddr, QIMemInfo info) +{ + ERROR_IF(instr_get_state() != INSTR_STATE_ENABLE_TCG, + "called outside instrumentation"); + InstrInfo *iinfo = &instr_cur_info; + TCGv_env vcpu_ = instr_tcg_get(iinfo, vcpu); + TCGv vaddr_ = instr_tcg_get(iinfo, vaddr); + TCGv_i32 info_ = tcg_const_i32(info.raw); + gen_helper_instr_guest_mem_before_exec(vcpu_, vaddr_, info_); + tcg_temp_free_i32(info_); +} + +void helper_instr_guest_mem_before_exec( + CPUArchState * vcpu, target_ulong vaddr, uint32_t info) +{ + TraceMemInfo info_; + info_.raw = info; + instr_guest_mem_before_exec(ENV_GET_CPU(vcpu), vaddr, info_); +} + + +void (*instr_event__guest_mem_before_exec)( + QICPU vcpu, uint64_t vaddr, QIMemInfo info); + +QI_VPUBLIC void qi_event_set_guest_mem_before_exec( + void (*fn)(QICPU vcpu, uint64_t vaddr, QIMemInfo info)) +{ + ERROR_IF(!instr_get_state(), "called outside instrumentation"); + instr_set_event(guest_mem_before_exec, fn); +} diff --git a/instrument/control.h b/instrument/control.h index d9e3dd3da6..19c9c9fb98 100644 --- a/instrument/control.h +++ b/instrument/control.h @@ -54,6 +54,7 @@ static inline QICPU instr_cpu_set(CPUState *vcpu); typedef enum { INSTR_STATE_DISABLE, INSTR_STATE_ENABLE, + INSTR_STATE_ENABLE_TCG, } InstrState; #define INSTR_MAX_TCG_REGS 16 @@ -102,6 +103,20 @@ static inline InstrState instr_get_state(void); */ static inline void instr_tcg_count(InstrInfo *info, unsigned int count); +/** + * instr_tcg_get: + * @info: Pointer to #InstrInfo. + * @arg: QITCG register. + * + * Get a suitable TCGv* from a QITCGv* value. + */ +#define instr_tcg_get(info, arg) \ + ({ \ + unsigned int idx = (uintptr_t)arg; \ + ERROR_IF(info->max <= idx, "invalid QITCGv register"); \ + info->tcg_regs[idx]; \ + }) + #include "instrument/control.inc.h" diff --git a/instrument/events.h b/instrument/events.h index 1cc4dbb052..6507b26867 100644 --- a/instrument/events.h +++ b/instrument/events.h @@ -63,6 +63,11 @@ extern void (*instr_event__guest_mem_before_trans)( static inline void instr_guest_mem_before_trans( CPUState *vcpu_trans, TCGv_env vcpu_exec, TCGv vaddr, TraceMemInfo info); +extern void (*instr_event__guest_mem_before_exec)( + QICPU vcpu, uint64_t vaddr, QIMemInfo info); +static inline void instr_guest_mem_before_exec( + CPUState *vcpu, uint64_t vaddr, TraceMemInfo info); + #include "instrument/events.inc.h" diff --git a/instrument/events.inc.h b/instrument/events.inc.h index 2cb17049f7..d7a3065ac1 100644 --- a/instrument/events.inc.h +++ b/instrument/events.inc.h @@ -50,7 +50,7 @@ static inline void instr_guest_mem_before_trans( void (*cb)(QICPU vcpu_trans, QITCGv_cpu vcpu_exec, QITCGv vaddr, QIMemInfo info) = instr_get_event(guest_mem_before_trans); if (cb) { - InstrInfo *iinfo = instr_set_state(INSTR_STATE_ENABLE); + InstrInfo *iinfo = instr_set_state(INSTR_STATE_ENABLE_TCG); QICPU vcpu_trans_ = instr_cpu_set(vcpu_trans); QITCGv_cpu vcpu_exec_ = instr_tcg_set(iinfo, 0, vcpu_exec); QITCGv vaddr_ = instr_tcg_set(iinfo, 1, vaddr); @@ -61,3 +61,19 @@ static inline void instr_guest_mem_before_trans( instr_set_state(INSTR_STATE_DISABLE); } } + +static inline void instr_guest_mem_before_exec( + CPUState *vcpu, uint64_t vaddr, TraceMemInfo info) +{ + void (*cb)(QICPU vcpu, uint64_t vaddr, QIMemInfo info) + = instr_get_event(guest_mem_before_exec); + if (cb) { + InstrInfo *iinfo = instr_set_state(INSTR_STATE_ENABLE); + QICPU vcpu_ = instr_cpu_set(vcpu); + QIMemInfo info_; + info_.raw = info.raw; + instr_tcg_count(iinfo, 2); + (*cb)(vcpu_, vaddr, info_); + instr_set_state(INSTR_STATE_DISABLE); + } +} diff --git a/instrument/helpers.h b/instrument/helpers.h new file mode 100644 index 0000000000..957cdc0993 --- /dev/null +++ b/instrument/helpers.h @@ -0,0 +1 @@ +DEF_HELPER_FLAGS_3(instr_guest_mem_before_exec, TCG_CALL_NO_RWG, void, env, tl, i32) diff --git a/instrument/load.c b/instrument/load.c index d5612af452..1df660d5d1 100644 --- a/instrument/load.c +++ b/instrument/load.c @@ -152,6 +152,7 @@ InstrUnloadError instr_unload(int64_t handle_id) instr_set_event(guest_cpu_exit, NULL); instr_set_event(guest_cpu_reset, NULL); instr_set_event(guest_mem_before_trans, NULL); + instr_set_event(guest_mem_before_exec, NULL); /* this should never fail */ if (dlclose(handle->dlhandle) < 0) { diff --git a/instrument/qemu-instr/control.h b/instrument/qemu-instr/control.h index af4fda138e..4fa99a968d 100644 --- a/instrument/qemu-instr/control.h +++ b/instrument/qemu-instr/control.h @@ -113,6 +113,27 @@ void qi_event_set_guest_cpu_reset(void (*fn)(QICPU vcpu)); void qi_event_set_guest_mem_before_trans( void (*fn)(QICPU vcpu_trans, QITCGv_cpu vcpu_exec, QITCGv vaddr, QIMemInfo info)); +/* + * Generate code to trigger a 'guest_mem_before_exec' from + * 'guest_mem_before_trans'. + * + * Mode: user, softmmu + * Targets: TCG(all) + * Time: trans + */ +void qi_event_gen_guest_mem_before_exec( + QITCGv_cpu vcpu, QITCGv vaddr, QIMemInfo info); + +/* + * Execution-time equivalent of 'guest_mem_before_trans'. + * + * Mode: user, softmmu + * Targets: TCG(all) + * Time: exec + */ +void qi_event_set_guest_mem_before_exec( + void (*fn)(QICPU vcpu, uint64_t vaddr, QIMemInfo info)); + #ifdef __cplusplus } #endif diff --git a/stubs/instrument.c b/stubs/instrument.c index 5e0d5150b5..c6c279c85e 100644 --- a/stubs/instrument.c +++ b/stubs/instrument.c @@ -16,3 +16,5 @@ void (*instr_event__guest_cpu_exit)(QICPU *vcpu); void (*instr_event__guest_cpu_reset)(QICPU *vcpu); void (*instr_event__guest_mem_before_trans)( QICPU vcpu_trans, QITCGv_cpu vcpu_exec, QITCGv vaddr, QIMemInfo info); +void (*instr_event__guest_mem_before_exec)( + QICPU vcpu_trans, QITCGv_cpu vcpu_exec, QITCGv vaddr, QIMemInfo info);