diff options
Diffstat (limited to 'accel/tcg/plugin-gen.c')
-rw-r--r-- | accel/tcg/plugin-gen.c | 59 |
1 files changed, 49 insertions, 10 deletions
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c index ec89a08..9920381 100644 --- a/accel/tcg/plugin-gen.c +++ b/accel/tcg/plugin-gen.c @@ -22,13 +22,12 @@ #include "qemu/osdep.h" #include "qemu/plugin.h" #include "qemu/log.h" -#include "cpu.h" #include "tcg/tcg.h" #include "tcg/tcg-temp-internal.h" -#include "tcg/tcg-op.h" -#include "exec/exec-all.h" +#include "tcg/tcg-op-common.h" #include "exec/plugin-gen.h" #include "exec/translator.h" +#include "exec/translation-block.h" enum plugin_gen_from { PLUGIN_GEN_FROM_TB, @@ -89,32 +88,49 @@ static void gen_enable_mem_helper(struct qemu_plugin_tb *ptb, qemu_plugin_add_dyn_cb_arr(arr); tcg_gen_st_ptr(tcg_constant_ptr((intptr_t)arr), tcg_env, - offsetof(CPUState, neg.plugin_mem_cbs) - - offsetof(ArchCPU, env)); + offsetof(CPUState, neg.plugin_mem_cbs) - sizeof(CPUState)); } static void gen_disable_mem_helper(void) { tcg_gen_st_ptr(tcg_constant_ptr(0), tcg_env, - offsetof(CPUState, neg.plugin_mem_cbs) - - offsetof(ArchCPU, env)); + offsetof(CPUState, neg.plugin_mem_cbs) - sizeof(CPUState)); } static TCGv_i32 gen_cpu_index(void) { + /* + * Optimize when we run with a single vcpu. All values using cpu_index, + * including scoreboard index, will be optimized out. + * User-mode calls tb_flush when setting this flag. In system-mode, all + * vcpus are created before generating code. + */ + if (!tcg_cflags_has(current_cpu, CF_PARALLEL)) { + return tcg_constant_i32(current_cpu->cpu_index); + } TCGv_i32 cpu_index = tcg_temp_ebb_new_i32(); tcg_gen_ld_i32(cpu_index, tcg_env, - -offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index)); + offsetof(CPUState, cpu_index) - sizeof(CPUState)); return cpu_index; } static void gen_udata_cb(struct qemu_plugin_regular_cb *cb) { TCGv_i32 cpu_index = gen_cpu_index(); + enum qemu_plugin_cb_flags cb_flags = + tcg_call_to_qemu_plugin_cb_flags(cb->info->flags); + TCGv_i32 flags = tcg_constant_i32(cb_flags); + TCGv_i32 clear_flags = tcg_constant_i32(QEMU_PLUGIN_CB_NO_REGS); + tcg_gen_st_i32(flags, tcg_env, + offsetof(CPUState, neg.plugin_cb_flags) - sizeof(CPUState)); tcg_gen_call2(cb->f.vcpu_udata, cb->info, NULL, tcgv_i32_temp(cpu_index), tcgv_ptr_temp(tcg_constant_ptr(cb->userp))); + tcg_gen_st_i32(clear_flags, tcg_env, + offsetof(CPUState, neg.plugin_cb_flags) - sizeof(CPUState)); tcg_temp_free_i32(cpu_index); + tcg_temp_free_i32(flags); + tcg_temp_free_i32(clear_flags); } static TCGv_ptr gen_plugin_u64_ptr(qemu_plugin_u64 entry) @@ -167,10 +183,20 @@ static void gen_udata_cond_cb(struct qemu_plugin_conditional_cb *cb) tcg_gen_ld_i64(val, ptr, 0); tcg_gen_brcondi_i64(cond, val, cb->imm, after_cb); TCGv_i32 cpu_index = gen_cpu_index(); + enum qemu_plugin_cb_flags cb_flags = + tcg_call_to_qemu_plugin_cb_flags(cb->info->flags); + TCGv_i32 flags = tcg_constant_i32(cb_flags); + TCGv_i32 clear_flags = tcg_constant_i32(QEMU_PLUGIN_CB_NO_REGS); + tcg_gen_st_i32(flags, tcg_env, + offsetof(CPUState, neg.plugin_cb_flags) - sizeof(CPUState)); tcg_gen_call2(cb->f.vcpu_udata, cb->info, NULL, tcgv_i32_temp(cpu_index), tcgv_ptr_temp(tcg_constant_ptr(cb->userp))); + tcg_gen_st_i32(clear_flags, tcg_env, + offsetof(CPUState, neg.plugin_cb_flags) - sizeof(CPUState)); tcg_temp_free_i32(cpu_index); + tcg_temp_free_i32(flags); + tcg_temp_free_i32(clear_flags); gen_set_label(after_cb); tcg_temp_free_i64(val); @@ -204,12 +230,22 @@ static void gen_mem_cb(struct qemu_plugin_regular_cb *cb, qemu_plugin_meminfo_t meminfo, TCGv_i64 addr) { TCGv_i32 cpu_index = gen_cpu_index(); + enum qemu_plugin_cb_flags cb_flags = + tcg_call_to_qemu_plugin_cb_flags(cb->info->flags); + TCGv_i32 flags = tcg_constant_i32(cb_flags); + TCGv_i32 clear_flags = tcg_constant_i32(QEMU_PLUGIN_CB_NO_REGS); + tcg_gen_st_i32(flags, tcg_env, + offsetof(CPUState, neg.plugin_cb_flags) - sizeof(CPUState)); tcg_gen_call4(cb->f.vcpu_mem, cb->info, NULL, tcgv_i32_temp(cpu_index), tcgv_i32_temp(tcg_constant_i32(meminfo)), tcgv_i64_temp(addr), tcgv_ptr_temp(tcg_constant_ptr(cb->userp))); + tcg_gen_st_i32(clear_flags, tcg_env, + offsetof(CPUState, neg.plugin_cb_flags) - sizeof(CPUState)); tcg_temp_free_i32(cpu_index); + tcg_temp_free_i32(flags); + tcg_temp_free_i32(clear_flags); } static void inject_cb(struct qemu_plugin_dyn_cb *cb) @@ -251,7 +287,6 @@ static void inject_mem_cb(struct qemu_plugin_dyn_cb *cb, break; default: g_assert_not_reached(); - break; } } @@ -276,7 +311,7 @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb) * that might be live within the existing opcode stream. * The simplest solution is to release them all and create new. */ - memset(tcg_ctx->free_temps, 0, sizeof(tcg_ctx->free_temps)); + tcg_temp_ebb_reset_freed(tcg_ctx); QTAILQ_FOREACH_SAFE(op, &tcg_ctx->ops, link, next) { switch (op->opc) { @@ -468,4 +503,8 @@ void plugin_gen_tb_end(CPUState *cpu, size_t num_insns) /* inject the instrumentation at the appropriate places */ plugin_gen_inject(ptb); + + /* reset plugin translation state (plugin_tb is reused between blocks) */ + tcg_ctx->plugin_db = NULL; + tcg_ctx->plugin_insn = NULL; } |