@@ -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
@@ -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);
@@ -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"
@@ -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"
@@ -40,6 +40,7 @@
| dh_sizemask(t5, 5) },
#include "helper.h"
+#include "instrument/helpers.h"
#include "trace/generated-helpers.h"
#include "tcg-runtime.h"
@@ -15,6 +15,8 @@
#include "qemu/compiler.h"
#include "qemu/main-loop.h"
#include "qom/cpu.h"
+#include "exec/helper-proto.h"
+#include "exec/helper-gen.h"
__thread InstrInfo instr_cur_info;
@@ -156,3 +158,38 @@ SYM_PUBLIC void qi_event_set_guest_mem_before_trans(
ERROR_IF(!tcg_enabled(), "called without TCG");
instr_set_event(guest_mem_before_trans, fn);
}
+
+
+SYM_PUBLIC 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");
+ ERROR_IF(!tcg_enabled(), "called without TCG");
+ InstrInfo *iinfo = &instr_cur_info;
+ TCGv_env vcpu_ = instr_tcg_from_qitcg(iinfo, vcpu);
+ TCGv vaddr_ = instr_tcg_from_qitcg(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);
+
+SYM_PUBLIC 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");
+ ERROR_IF(!tcg_enabled(), "called without TCG");
+ instr_set_event(guest_mem_before_exec, fn);
+}
@@ -84,6 +84,7 @@ void instr_cpu_stop_all_end(InstrCPUStop *info);
typedef enum {
INSTR_STATE_DISABLE,
INSTR_STATE_ENABLE,
+ INSTR_STATE_ENABLE_TCG,
} InstrState;
#define INSTR_MAX_TCG_REGS 16
@@ -123,6 +124,20 @@ static inline InstrState instr_get_state(void);
(void *)num; \
})
+/**
+ * instr_tcg_from_qitcg:
+ * @info: Pointer to #InstrInfo.
+ * @arg: QITCG register.
+ *
+ * Get a suitable TCGv* from a QITCGv* value.
+ */
+#define instr_tcg_from_qitcg(info, arg) \
+ ({ \
+ unsigned int idx = (uintptr_t)arg; \
+ ERROR_IF(info->max <= idx, "invalid QITCGv register"); \
+ info->tcg_regs[idx]; \
+ })
+
/**
* instr_tcg_count:
* @info: Pointer to #InstrInfo.
@@ -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"
@@ -51,7 +51,7 @@ static inline void instr_guest_mem_before_trans(
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_to_qicpu(vcpu_trans);
QITCGv_cpu vcpu_exec_ = instr_tcg_to_qitcg(iinfo, 0, vcpu_exec);
QITCGv vaddr_ = instr_tcg_to_qitcg(iinfo, 1, vaddr);
@@ -62,3 +62,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_to_qicpu(vcpu);
+ QIMemInfo info_;
+ info_.raw = info.raw;
+ instr_tcg_count(iinfo, 2);
+ (*cb)(vcpu_, vaddr, info_);
+ instr_set_state(INSTR_STATE_DISABLE);
+ }
+}
new file mode 100644
@@ -0,0 +1,2 @@
+DEF_HELPER_FLAGS_3(instr_guest_mem_before_exec, TCG_CALL_NO_RWG,
+ void, env, tl, i32)
@@ -163,6 +163,7 @@ InstrUnloadError instr_unload(const char *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);
instr_cpu_stop_all_end(&info);
cpu_list_unlock();
@@ -121,6 +121,27 @@ 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
@@ -7,6 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+/* Unpoison missing types */
+#define HW_POISON_H
+
#include "qemu/osdep.h"
#include "instrument/cmdline.h"
@@ -15,6 +18,11 @@
#include "qapi/qmp/qerror.h"
+/* Declare missing types */
+typedef struct CPUArchState CPUArchState;
+typedef int target_ulong;
+
+
void instr_init(const char *path, int argc, const char **argv)
{
}
@@ -46,4 +54,15 @@ void (*instr_event__guest_cpu_enter)(QICPU *vcpu);
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);
+ QICPU vcpu_trans, QITCGv_cpu vcpu_exec,
+ QITCGv vaddr, QIMemInfo info);
+void helper_instr_guest_mem_before_exec(
+ CPUArchState *vcpu, target_ulong vaddr, uint32_t info);
+void helper_instr_guest_mem_before_exec(
+ CPUArchState *vcpu, target_ulong vaddr, uint32_t info)
+{
+ assert(false);
+}
+void (*instr_event__guest_mem_before_exec)(
+ QICPU vcpu_trans, QITCGv_cpu vcpu_exec,
+ QITCGv vaddr, QIMemInfo info);
Signed-off-by: Lluís Vilanova <vilanova@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 | 37 +++++++++++++++++++++++++++++ instrument/control.h | 15 ++++++++++++ instrument/events.h | 5 ++++ instrument/events.inc.h | 18 +++++++++++++- instrument/helpers.h | 2 ++ instrument/load.c | 1 + instrument/qemu-instr/control.h | 21 ++++++++++++++++ stubs/instrument.c | 21 ++++++++++++++++ 13 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 instrument/helpers.h