@@ -407,6 +407,7 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
#endif
if (do_strace)
print_freebsd_syscall_ret(num, ret);
+ instr_guest_user_syscall_ret(cpu, num, ret);
trace_guest_user_syscall_ret(cpu, num, ret);
return ret;
efault:
@@ -485,6 +486,7 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
#endif
if (do_strace)
print_netbsd_syscall_ret(num, ret);
+ instr_guest_user_syscall_ret(cpu, num, ret);
trace_guest_user_syscall_ret(cpu, num, ret);
return ret;
efault:
@@ -563,6 +565,7 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
#endif
if (do_strace)
print_openbsd_syscall_ret(num, ret);
+ instr_guest_user_syscall_ret(cpu, num, ret);
trace_guest_user_syscall_ret(cpu, num, ret);
return ret;
efault:
@@ -210,3 +210,18 @@ SYM_PUBLIC void qi_event_set_guest_user_syscall(
#endif
instr_set_event(guest_user_syscall, fn);
}
+
+
+void (*instr_event__guest_user_syscall_ret)(
+ QICPU vcpu, uint64_t num, uint64_t ret);
+
+SYM_PUBLIC void qi_event_set_guest_user_syscall_ret(
+ void (*fn)(QICPU vcpu, uint64_t num, uint64_t ret))
+{
+ ERROR_IF(!instr_get_state(), "called outside instrumentation");
+ ERROR_IF(!tcg_enabled(), "called without TCG");
+#if !defined(CONFIG_USER_ONLY)
+ ERROR_IF(true, "called in full-system mode");
+#endif
+ instr_set_event(guest_user_syscall_ret, fn);
+}
@@ -75,6 +75,11 @@ static inline void instr_guest_user_syscall(
CPUState *vcpu, uint64_t num, uint64_t arg1, uint64_t arg2, uint64_t arg3,
uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t arg7, uint64_t arg8);
+extern void (*instr_event__guest_user_syscall_ret)(
+ QICPU vcpu, uint64_t num, uint64_t ret);
+static inline void instr_guest_user_syscall_ret(
+ CPUState *vcpu, uint64_t num, uint64_t ret);
+
#include "instrument/events.inc.h"
@@ -94,3 +94,16 @@ static inline void instr_guest_user_syscall(
instr_set_state(INSTR_STATE_DISABLE);
}
}
+
+static inline void instr_guest_user_syscall_ret(
+ CPUState *vcpu, uint64_t num, uint64_t ret)
+{
+ void (*cb)(QICPU vcpu, uint64_t num, uint64_t ret)
+ = instr_get_event(guest_user_syscall_ret);
+ if (cb) {
+ instr_set_state(INSTR_STATE_ENABLE);
+ QICPU vcpu_ = instr_cpu_to_qicpu(vcpu);
+ (*cb)(vcpu_, num, ret);
+ instr_set_state(INSTR_STATE_DISABLE);
+ }
+}
@@ -165,6 +165,7 @@ InstrUnloadError instr_unload(const char *id)
instr_set_event(guest_mem_before_trans, NULL);
instr_set_event(guest_mem_before_exec, NULL);
instr_set_event(guest_user_syscall, NULL);
+ instr_set_event(guest_user_syscall_ret, NULL);
instr_cpu_stop_all_end(&info);
cpu_list_unlock();
@@ -157,6 +157,19 @@ void qi_event_set_guest_user_syscall(
uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6,
uint64_t arg7, uint64_t arg8));
+/*
+ * Finish executing a guest system call in syscall emulation mode.
+ *
+ * @num: System call number.
+ * @ret: System call result value.
+ *
+ * Mode: user
+ * Targets: TCG(all)
+ * Time: exec
+ */
+void qi_event_set_guest_user_syscall_ret(
+ void (*fn)(QICPU vcpu, uint64_t num, uint64_t ret));
+
#ifdef __cplusplus
}
#endif
@@ -12398,6 +12398,7 @@ fail:
#endif
if(do_strace)
print_syscall_ret(num, ret);
+ instr_guest_user_syscall_ret(cpu, num, ret);
trace_guest_user_syscall_ret(cpu, num, ret);
return ret;
efault:
@@ -71,3 +71,5 @@ void (*instr_event__guest_mem_before_exec)(
void (*instr_event__guest_user_syscall)(
QICPU vcpu, uint64_t num, uint64_t arg1, uint64_t arg2, uint64_t arg3,
uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t arg7, uint64_t arg8);
+void (*instr_event__guest_user_syscall_ret)(
+ QICPU vcpu, uint64_t num, uint64_t ret);
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> --- bsd-user/syscall.c | 3 +++ instrument/control.c | 15 +++++++++++++++ instrument/events.h | 5 +++++ instrument/events.inc.h | 13 +++++++++++++ instrument/load.c | 1 + instrument/qemu-instr/control.h | 13 +++++++++++++ linux-user/syscall.c | 1 + stubs/instrument.c | 2 ++ 8 files changed, 53 insertions(+)