plugins: conditional callbacks

Extend plugins API to support callback called with a given criteria
(evaluated inline).

Added functions:
- qemu_plugin_register_vcpu_tb_exec_cond_cb
- qemu_plugin_register_vcpu_insn_exec_cond_cb

They expect as parameter a condition, a qemu_plugin_u64_t (op1) and an
immediate (op2). Callback is called if op1 |cond| op2 is true.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Message-Id: <20240502211522.346467-6-pierrick.bouvier@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
[AJB: fix re-base conflict with tb_is_mem_only()]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Message-Id: <20240514174253.694591-8-alex.bennee@linaro.org>
This commit is contained in:
Pierrick Bouvier 2024-05-14 18:42:49 +01:00 committed by Alex Bennée
parent a1c9bf2514
commit 7de77d3788
7 changed files with 213 additions and 0 deletions

View file

@ -132,6 +132,51 @@ static TCGv_ptr gen_plugin_u64_ptr(qemu_plugin_u64 entry)
return ptr;
}
static TCGCond plugin_cond_to_tcgcond(enum qemu_plugin_cond cond)
{
switch (cond) {
case QEMU_PLUGIN_COND_EQ:
return TCG_COND_EQ;
case QEMU_PLUGIN_COND_NE:
return TCG_COND_NE;
case QEMU_PLUGIN_COND_LT:
return TCG_COND_LTU;
case QEMU_PLUGIN_COND_LE:
return TCG_COND_LEU;
case QEMU_PLUGIN_COND_GT:
return TCG_COND_GTU;
case QEMU_PLUGIN_COND_GE:
return TCG_COND_GEU;
default:
/* ALWAYS and NEVER conditions should never reach */
g_assert_not_reached();
}
}
static void gen_udata_cond_cb(struct qemu_plugin_dyn_cb *cb)
{
TCGv_ptr ptr = gen_plugin_u64_ptr(cb->cond.entry);
TCGv_i32 cpu_index = tcg_temp_ebb_new_i32();
TCGv_i64 val = tcg_temp_ebb_new_i64();
TCGLabel *after_cb = gen_new_label();
/* Condition should be negated, as calling the cb is the "else" path */
TCGCond cond = tcg_invert_cond(plugin_cond_to_tcgcond(cb->cond.cond));
tcg_gen_ld_i64(val, ptr, 0);
tcg_gen_brcondi_i64(cond, val, cb->cond.imm, after_cb);
tcg_gen_ld_i32(cpu_index, tcg_env,
-offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
tcg_gen_call2(cb->cond.f.vcpu_udata, cb->cond.info, NULL,
tcgv_i32_temp(cpu_index),
tcgv_ptr_temp(tcg_constant_ptr(cb->userp)));
gen_set_label(after_cb);
tcg_temp_free_i64(val);
tcg_temp_free_i32(cpu_index);
tcg_temp_free_ptr(ptr);
}
static void gen_inline_add_u64_cb(struct qemu_plugin_dyn_cb *cb)
{
TCGv_ptr ptr = gen_plugin_u64_ptr(cb->inline_insn.entry);
@ -177,6 +222,9 @@ static void inject_cb(struct qemu_plugin_dyn_cb *cb)
case PLUGIN_CB_REGULAR:
gen_udata_cb(cb);
break;
case PLUGIN_CB_COND:
gen_udata_cond_cb(cb);
break;
case PLUGIN_CB_INLINE_ADD_U64:
gen_inline_add_u64_cb(cb);
break;