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);


Reply via email to