mirror of
https://github.com/qemu/qemu.git
synced 2026-04-05 21:46:25 +00:00
plugins: add flag to specify whether PC is rw
In addition to the flags specifying whether general-purpose registers are read-write (rw) during a plugin callback, we add an additional flag explicitly stating whether the PC is writable. This is in preparation of a patch that allows to explicitly set the PC to divert control flow from within a plugin callback, which is currently not possible. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Florian Hofhammer <florian.hofhammer@epfl.ch> Link: https://lore.kernel.org/qemu-devel/20260305-setpc-v5-v7-2-4c3adba52403@epfl.ch Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
This commit is contained in:
committed by
Pierrick Bouvier
parent
2cc35f14ba
commit
d16ffa4244
@@ -325,11 +325,14 @@ typedef struct {
|
||||
* @QEMU_PLUGIN_CB_NO_REGS: callback does not access the CPU's regs
|
||||
* @QEMU_PLUGIN_CB_R_REGS: callback reads the CPU's regs
|
||||
* @QEMU_PLUGIN_CB_RW_REGS: callback reads and writes the CPU's regs
|
||||
* @QEMU_PLUGIN_CB_RW_REGS_PC: callback reads and writes the CPU's
|
||||
* regs and updates the PC
|
||||
*/
|
||||
enum qemu_plugin_cb_flags {
|
||||
QEMU_PLUGIN_CB_NO_REGS,
|
||||
QEMU_PLUGIN_CB_R_REGS,
|
||||
QEMU_PLUGIN_CB_RW_REGS,
|
||||
QEMU_PLUGIN_CB_RW_REGS_PC,
|
||||
};
|
||||
|
||||
enum qemu_plugin_mem_rw {
|
||||
|
||||
@@ -458,7 +458,9 @@ bool qemu_plugin_write_register(struct qemu_plugin_register *reg,
|
||||
{
|
||||
g_assert(current_cpu);
|
||||
|
||||
if (buf->len == 0 || qemu_plugin_get_cb_flags() != QEMU_PLUGIN_CB_RW_REGS) {
|
||||
if (buf->len == 0 ||
|
||||
(qemu_plugin_get_cb_flags() != QEMU_PLUGIN_CB_RW_REGS &&
|
||||
qemu_plugin_get_cb_flags() != QEMU_PLUGIN_CB_RW_REGS_PC)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ static void plugin_vcpu_cb__discon(CPUState *cpu,
|
||||
struct qemu_plugin_cb *cb, *next;
|
||||
uint64_t to = cpu->cc->get_pc(cpu);
|
||||
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_RW_REGS);
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_RW_REGS_PC);
|
||||
if (cpu->cpu_index < plugin.num_vcpus) {
|
||||
/* iterate safely; plugins might uninstall themselves at any time */
|
||||
QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) {
|
||||
@@ -395,15 +395,16 @@ void plugin_register_dyn_cb__udata(GArray **arr,
|
||||
enum qemu_plugin_cb_flags flags,
|
||||
void *udata)
|
||||
{
|
||||
static TCGHelperInfo info[3] = {
|
||||
static TCGHelperInfo info[4] = {
|
||||
[QEMU_PLUGIN_CB_NO_REGS].flags = TCG_CALL_NO_RWG,
|
||||
[QEMU_PLUGIN_CB_R_REGS].flags = TCG_CALL_NO_WG,
|
||||
[QEMU_PLUGIN_CB_RW_REGS].flags = 0,
|
||||
[QEMU_PLUGIN_CB_RW_REGS_PC].flags = 0,
|
||||
/*
|
||||
* Match qemu_plugin_vcpu_udata_cb_t:
|
||||
* void (*)(uint32_t, void *)
|
||||
*/
|
||||
[0 ... 2].typemask = (dh_typemask(void, 0) |
|
||||
[0 ... 3].typemask = (dh_typemask(void, 0) |
|
||||
dh_typemask(i32, 1) |
|
||||
dh_typemask(ptr, 2))
|
||||
};
|
||||
@@ -425,15 +426,16 @@ void plugin_register_dyn_cond_cb__udata(GArray **arr,
|
||||
uint64_t imm,
|
||||
void *udata)
|
||||
{
|
||||
static TCGHelperInfo info[3] = {
|
||||
static TCGHelperInfo info[4] = {
|
||||
[QEMU_PLUGIN_CB_NO_REGS].flags = TCG_CALL_NO_RWG,
|
||||
[QEMU_PLUGIN_CB_R_REGS].flags = TCG_CALL_NO_WG,
|
||||
[QEMU_PLUGIN_CB_RW_REGS].flags = 0,
|
||||
[QEMU_PLUGIN_CB_RW_REGS_PC].flags = 0,
|
||||
/*
|
||||
* Match qemu_plugin_vcpu_udata_cb_t:
|
||||
* void (*)(uint32_t, void *)
|
||||
*/
|
||||
[0 ... 2].typemask = (dh_typemask(void, 0) |
|
||||
[0 ... 3].typemask = (dh_typemask(void, 0) |
|
||||
dh_typemask(i32, 1) |
|
||||
dh_typemask(ptr, 2))
|
||||
};
|
||||
@@ -464,15 +466,16 @@ void plugin_register_vcpu_mem_cb(GArray **arr,
|
||||
!__builtin_types_compatible_p(qemu_plugin_meminfo_t, uint32_t) &&
|
||||
!__builtin_types_compatible_p(qemu_plugin_meminfo_t, int32_t));
|
||||
|
||||
static TCGHelperInfo info[3] = {
|
||||
static TCGHelperInfo info[4] = {
|
||||
[QEMU_PLUGIN_CB_NO_REGS].flags = TCG_CALL_NO_RWG,
|
||||
[QEMU_PLUGIN_CB_R_REGS].flags = TCG_CALL_NO_WG,
|
||||
[QEMU_PLUGIN_CB_RW_REGS].flags = 0,
|
||||
[QEMU_PLUGIN_CB_RW_REGS_PC].flags = 0,
|
||||
/*
|
||||
* Match qemu_plugin_vcpu_mem_cb_t:
|
||||
* void (*)(uint32_t, qemu_plugin_meminfo_t, uint64_t, void *)
|
||||
*/
|
||||
[0 ... 2].typemask =
|
||||
[0 ... 3].typemask =
|
||||
(dh_typemask(void, 0) |
|
||||
dh_typemask(i32, 1) |
|
||||
(__builtin_types_compatible_p(qemu_plugin_meminfo_t, uint32_t)
|
||||
@@ -553,7 +556,7 @@ qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1, uint64_t a2,
|
||||
QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) {
|
||||
qemu_plugin_vcpu_syscall_cb_t func = cb->f.vcpu_syscall;
|
||||
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_RW_REGS);
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_RW_REGS_PC);
|
||||
func(cb->ctx->id, cpu->cpu_index, num, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_NO_REGS);
|
||||
}
|
||||
@@ -577,7 +580,7 @@ void qemu_plugin_vcpu_syscall_ret(CPUState *cpu, int64_t num, int64_t ret)
|
||||
QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) {
|
||||
qemu_plugin_vcpu_syscall_ret_cb_t func = cb->f.vcpu_syscall_ret;
|
||||
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_RW_REGS);
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_RW_REGS_PC);
|
||||
func(cb->ctx->id, cpu->cpu_index, num, ret);
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_NO_REGS);
|
||||
}
|
||||
@@ -605,7 +608,7 @@ qemu_plugin_vcpu_syscall_filter(CPUState *cpu, int64_t num, uint64_t a1,
|
||||
|
||||
clamp_syscall_arguments(&a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8);
|
||||
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_RW_REGS);
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_RW_REGS_PC);
|
||||
|
||||
QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) {
|
||||
qemu_plugin_vcpu_syscall_filter_cb_t func = cb->f.vcpu_syscall_filter;
|
||||
@@ -626,7 +629,7 @@ void qemu_plugin_vcpu_idle_cb(CPUState *cpu)
|
||||
{
|
||||
/* idle and resume cb may be called before init, ignore in this case */
|
||||
if (cpu->cpu_index < plugin.num_vcpus) {
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_RW_REGS);
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_RW_REGS_PC);
|
||||
plugin_vcpu_cb__simple(cpu, QEMU_PLUGIN_EV_VCPU_IDLE);
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_NO_REGS);
|
||||
}
|
||||
@@ -635,7 +638,7 @@ void qemu_plugin_vcpu_idle_cb(CPUState *cpu)
|
||||
void qemu_plugin_vcpu_resume_cb(CPUState *cpu)
|
||||
{
|
||||
if (cpu->cpu_index < plugin.num_vcpus) {
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_RW_REGS);
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_RW_REGS_PC);
|
||||
plugin_vcpu_cb__simple(cpu, QEMU_PLUGIN_EV_VCPU_RESUME);
|
||||
qemu_plugin_set_cb_flags(cpu, QEMU_PLUGIN_CB_NO_REGS);
|
||||
}
|
||||
@@ -906,6 +909,6 @@ enum qemu_plugin_cb_flags tcg_call_to_qemu_plugin_cb_flags(int flags)
|
||||
} else if (flags & TCG_CALL_NO_WG) {
|
||||
return QEMU_PLUGIN_CB_R_REGS;
|
||||
} else {
|
||||
return QEMU_PLUGIN_CB_RW_REGS;
|
||||
return QEMU_PLUGIN_CB_RW_REGS_PC;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user