[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v15 17/19] plugins: Use different helpers when reading registers
From: |
Akihiko Odaki |
Subject: |
[PATCH v15 17/19] plugins: Use different helpers when reading registers |
Date: |
Wed, 25 Oct 2023 14:27:39 +0900 |
This avoids optimizations incompatible when reading registers.
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
accel/tcg/plugin-helpers.h | 3 ++-
include/exec/plugin-gen.h | 4 ++--
include/qemu/plugin.h | 2 ++
plugins/plugin.h | 2 +-
accel/tcg/plugin-gen.c | 39 ++++++++++++++++++++++++++++----------
accel/tcg/translator.c | 2 +-
plugins/api.c | 14 ++++++++++++--
plugins/core.c | 10 ++++++++--
8 files changed, 57 insertions(+), 19 deletions(-)
diff --git a/accel/tcg/plugin-helpers.h b/accel/tcg/plugin-helpers.h
index 8e685e0654..11796436f3 100644
--- a/accel/tcg/plugin-helpers.h
+++ b/accel/tcg/plugin-helpers.h
@@ -1,4 +1,5 @@
#ifdef CONFIG_PLUGIN
-DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb, TCG_CALL_NO_RWG | TCG_CALL_PLUGIN,
void, i32, ptr)
+DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb_no_wg, TCG_CALL_NO_WG |
TCG_CALL_PLUGIN, void, i32, ptr)
+DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb_no_rwg, TCG_CALL_NO_RWG |
TCG_CALL_PLUGIN, void, i32, ptr)
DEF_HELPER_FLAGS_4(plugin_vcpu_mem_cb, TCG_CALL_NO_RWG | TCG_CALL_PLUGIN,
void, i32, i32, i64, ptr)
#endif
diff --git a/include/exec/plugin-gen.h b/include/exec/plugin-gen.h
index c4552b5061..b964e1eb5c 100644
--- a/include/exec/plugin-gen.h
+++ b/include/exec/plugin-gen.h
@@ -22,7 +22,7 @@ bool plugin_gen_tb_start(CPUState *cpu, const struct
DisasContextBase *db,
bool supress);
void plugin_gen_tb_end(CPUState *cpu, size_t num_insns);
void plugin_gen_insn_start(CPUState *cpu, const struct DisasContextBase *db);
-void plugin_gen_insn_end(void);
+void plugin_gen_insn_end(CPUState *cpu);
void plugin_gen_disable_mem_helpers(void);
void plugin_gen_empty_mem_callback(TCGv_i64 addr, uint32_t info);
@@ -39,7 +39,7 @@ static inline
void plugin_gen_insn_start(CPUState *cpu, const struct DisasContextBase *db)
{ }
-static inline void plugin_gen_insn_end(void)
+static inline void plugin_gen_insn_end(CPUState *cpu)
{ }
static inline void plugin_gen_tb_end(CPUState *cpu, size_t num_insns)
diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
index b15fee39fd..1228562fa7 100644
--- a/include/qemu/plugin.h
+++ b/include/qemu/plugin.h
@@ -17,6 +17,8 @@
#include "hw/core/cpu.h"
#define QEMU_PLUGIN_CPU_FLAG_CB_TB_TRANS BIT(0)
+#define QEMU_PLUGIN_CPU_FLAG_CB_TB_READ BIT(1)
+#define QEMU_PLUGIN_CPU_FLAG_CB_INSN_READ BIT(2)
/*
* Option parsing/processing.
diff --git a/plugins/plugin.h b/plugins/plugin.h
index db25e2650d..c9f602316c 100644
--- a/plugins/plugin.h
+++ b/plugins/plugin.h
@@ -87,7 +87,7 @@ plugin_register_cb_udata(qemu_plugin_id_t id, enum
qemu_plugin_event ev,
void
plugin_register_dyn_cb__udata(GArray **arr,
qemu_plugin_vcpu_udata_cb_t cb,
- enum qemu_plugin_cb_flags flags, void *udata);
+ unsigned int flags, void *udata);
void plugin_register_vcpu_mem_cb(GArray **arr,
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
index 4870433f3a..6d33b2bf24 100644
--- a/accel/tcg/plugin-gen.c
+++ b/accel/tcg/plugin-gen.c
@@ -90,7 +90,10 @@ enum plugin_gen_cb {
* These helpers are stubs that get dynamically switched out for calls
* direct to the plugin if they are subscribed to.
*/
-void HELPER(plugin_vcpu_udata_cb)(uint32_t cpu_index, void *udata)
+void HELPER(plugin_vcpu_udata_cb_no_wg)(uint32_t cpu_index, void *udata)
+{ }
+
+void HELPER(plugin_vcpu_udata_cb_no_rwg)(uint32_t cpu_index, void *udata)
{ }
void HELPER(plugin_vcpu_mem_cb)(unsigned int vcpu_index,
@@ -98,7 +101,7 @@ void HELPER(plugin_vcpu_mem_cb)(unsigned int vcpu_index,
void *userdata)
{ }
-static void gen_empty_udata_cb(void)
+static void gen_empty_udata_cb(void (*gen_helper)(TCGv_i32, TCGv_ptr))
{
TCGv_i32 cpu_index = tcg_temp_ebb_new_i32();
TCGv_ptr udata = tcg_temp_ebb_new_ptr();
@@ -106,12 +109,22 @@ static void gen_empty_udata_cb(void)
tcg_gen_movi_ptr(udata, 0);
tcg_gen_ld_i32(cpu_index, tcg_env,
-offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
- gen_helper_plugin_vcpu_udata_cb(cpu_index, udata);
+ gen_helper(cpu_index, udata);
tcg_temp_free_ptr(udata);
tcg_temp_free_i32(cpu_index);
}
+static void gen_empty_udata_cb_no_wg(void)
+{
+ gen_empty_udata_cb(gen_helper_plugin_vcpu_udata_cb_no_wg);
+}
+
+static void gen_empty_udata_cb_no_rwg(void)
+{
+ gen_empty_udata_cb(gen_helper_plugin_vcpu_udata_cb_no_rwg);
+}
+
/*
* For now we only support addi_i64.
* When we support more ops, we can generate one empty inline cb for each.
@@ -176,7 +189,7 @@ static void gen_wrapped(enum plugin_gen_from from,
tcg_gen_plugin_cb_end();
}
-static void plugin_gen_empty_callback(enum plugin_gen_from from)
+static void plugin_gen_empty_callback(CPUState *cpu, enum plugin_gen_from from)
{
switch (from) {
case PLUGIN_GEN_AFTER_INSN:
@@ -190,9 +203,15 @@ static void plugin_gen_empty_callback(enum plugin_gen_from
from)
*/
gen_wrapped(from, PLUGIN_GEN_ENABLE_MEM_HELPER,
gen_empty_mem_helper);
- /* fall through */
+ gen_wrapped(from, PLUGIN_GEN_CB_UDATA,
+ cpu->plugin_flags & QEMU_PLUGIN_CPU_FLAG_CB_INSN_READ ?
+ gen_empty_udata_cb_no_wg : gen_empty_udata_cb_no_rwg);
+ gen_wrapped(from, PLUGIN_GEN_CB_INLINE, gen_empty_inline_cb);
+ break;
case PLUGIN_GEN_FROM_TB:
- gen_wrapped(from, PLUGIN_GEN_CB_UDATA, gen_empty_udata_cb);
+ gen_wrapped(from, PLUGIN_GEN_CB_UDATA,
+ cpu->plugin_flags & QEMU_PLUGIN_CPU_FLAG_CB_TB_READ ?
+ gen_empty_udata_cb_no_wg : gen_empty_udata_cb_no_rwg);
gen_wrapped(from, PLUGIN_GEN_CB_INLINE, gen_empty_inline_cb);
break;
default:
@@ -817,7 +836,7 @@ bool plugin_gen_tb_start(CPUState *cpu, const
DisasContextBase *db,
ptb->mem_only = mem_only;
ptb->mem_helper = false;
- plugin_gen_empty_callback(PLUGIN_GEN_FROM_TB);
+ plugin_gen_empty_callback(cpu, PLUGIN_GEN_FROM_TB);
}
tcg_ctx->plugin_insn = NULL;
@@ -832,7 +851,7 @@ void plugin_gen_insn_start(CPUState *cpu, const
DisasContextBase *db)
pinsn = qemu_plugin_tb_insn_get(ptb, db->pc_next);
tcg_ctx->plugin_insn = pinsn;
- plugin_gen_empty_callback(PLUGIN_GEN_FROM_INSN);
+ plugin_gen_empty_callback(cpu, PLUGIN_GEN_FROM_INSN);
/*
* Detect page crossing to get the new host address.
@@ -852,9 +871,9 @@ void plugin_gen_insn_start(CPUState *cpu, const
DisasContextBase *db)
}
}
-void plugin_gen_insn_end(void)
+void plugin_gen_insn_end(CPUState *cpu)
{
- plugin_gen_empty_callback(PLUGIN_GEN_AFTER_INSN);
+ plugin_gen_empty_callback(cpu, PLUGIN_GEN_AFTER_INSN);
}
/*
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index 575b9812ad..bec58dd93f 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -189,7 +189,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb,
int *max_insns,
* to accurately track instrumented helpers that might access memory.
*/
if (plugin_enabled) {
- plugin_gen_insn_end();
+ plugin_gen_insn_end(cpu);
}
/* Stop translation if translate_insn so indicated. */
diff --git a/plugins/api.c b/plugins/api.c
index 5521b0ad36..29c6fc788f 100644
--- a/plugins/api.c
+++ b/plugins/api.c
@@ -89,8 +89,13 @@ void qemu_plugin_register_vcpu_tb_exec_cb(struct
qemu_plugin_tb *tb,
void *udata)
{
if (!tb->mem_only) {
+ bool read = flags == QEMU_PLUGIN_CB_R_REGS ||
+ flags == QEMU_PLUGIN_CB_RW_REGS;
+
plugin_register_dyn_cb__udata(&tb->cbs[PLUGIN_CB_REGULAR],
- cb, flags, udata);
+ cb,
+ read ? QEMU_PLUGIN_CPU_FLAG_CB_TB_READ :
0,
+ udata);
}
}
@@ -109,8 +114,13 @@ void qemu_plugin_register_vcpu_insn_exec_cb(struct
qemu_plugin_insn *insn,
void *udata)
{
if (!insn->mem_only) {
+ bool read = flags == QEMU_PLUGIN_CB_R_REGS ||
+ flags == QEMU_PLUGIN_CB_RW_REGS;
+
plugin_register_dyn_cb__udata(&insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_REGULAR],
- cb, flags, udata);
+ cb,
+ read ? QEMU_PLUGIN_CPU_FLAG_CB_INSN_READ
: 0,
+ udata);
}
}
diff --git a/plugins/core.c b/plugins/core.c
index 368e2d1f54..8e436a424b 100644
--- a/plugins/core.c
+++ b/plugins/core.c
@@ -302,15 +302,20 @@ void plugin_register_inline_op(GArray **arr,
void plugin_register_dyn_cb__udata(GArray **arr,
qemu_plugin_vcpu_udata_cb_t cb,
- enum qemu_plugin_cb_flags flags,
+ unsigned int flags,
void *udata)
{
struct qemu_plugin_dyn_cb *dyn_cb = plugin_get_dyn_cb(arr);
dyn_cb->userp = udata;
- /* Note flags are discarded as unused. */
dyn_cb->f.vcpu_udata = cb;
dyn_cb->type = PLUGIN_CB_REGULAR;
+
+ if (flags) {
+ QEMU_LOCK_GUARD(&plugin.lock);
+ plugin.cpu_flags |= flags;
+ g_hash_table_foreach(plugin.cpu_ht, plugin_cpu_update__locked, NULL);
+ }
}
void plugin_register_vcpu_mem_cb(GArray **arr,
@@ -434,6 +439,7 @@ void qemu_plugin_flush_cb(void)
{
qht_iter_remove(&plugin.dyn_cb_arr_ht, free_dyn_cb_arr, NULL);
qht_reset(&plugin.dyn_cb_arr_ht);
+ plugin.cpu_flags &= ~QEMU_PLUGIN_CPU_FLAG_CB_INSN_READ;
plugin_cb__simple(QEMU_PLUGIN_EV_FLUSH);
}
--
2.42.0
- [PATCH v15 08/19] gdbstub: Use GDBFeature for GDBRegisterState, (continued)
- [PATCH v15 08/19] gdbstub: Use GDBFeature for GDBRegisterState, Akihiko Odaki, 2023/10/25
- [PATCH v15 10/19] gdbstub: Simplify XML lookup, Akihiko Odaki, 2023/10/25
- [PATCH v15 09/19] gdbstub: Change gdb_get_reg_cb and gdb_set_reg_cb, Akihiko Odaki, 2023/10/25
- [PATCH v15 11/19] gdbstub: Infer number of core registers from XML, Akihiko Odaki, 2023/10/25
- [PATCH v15 12/19] hw/core/cpu: Remove gdb_get_dynamic_xml member, Akihiko Odaki, 2023/10/25
- [PATCH v15 13/19] gdbstub: Add members to identify registers to GDBFeature, Akihiko Odaki, 2023/10/25
- [PATCH v15 14/19] gdbstub: Expose functions to read registers, Akihiko Odaki, 2023/10/25
- [PATCH v15 15/19] cpu: Call plugin hooks only when ready, Akihiko Odaki, 2023/10/25
- [PATCH v15 16/19] plugins: Introduce CPU flags, Akihiko Odaki, 2023/10/25
- [PATCH v15 18/19] plugins: Allow to read registers, Akihiko Odaki, 2023/10/25
- [PATCH v15 17/19] plugins: Use different helpers when reading registers,
Akihiko Odaki <=
- [PATCH v15 19/19] contrib/plugins: Allow to log registers, Akihiko Odaki, 2023/10/25