diff options
Diffstat (limited to 'plugins/core.c')
-rw-r--r-- | plugins/core.c | 109 |
1 files changed, 80 insertions, 29 deletions
diff --git a/plugins/core.c b/plugins/core.c index 1e58a57bf1..0726bc7f25 100644 --- a/plugins/core.c +++ b/plugins/core.c @@ -316,6 +316,18 @@ static struct qemu_plugin_dyn_cb *plugin_get_dyn_cb(GArray **arr) return &g_array_index(cbs, struct qemu_plugin_dyn_cb, cbs->len - 1); } +static enum plugin_dyn_cb_type op_to_cb_type(enum qemu_plugin_op op) +{ + switch (op) { + case QEMU_PLUGIN_INLINE_ADD_U64: + return PLUGIN_CB_INLINE_ADD_U64; + case QEMU_PLUGIN_INLINE_STORE_U64: + return PLUGIN_CB_INLINE_STORE_U64; + default: + g_assert_not_reached(); + } +} + void plugin_register_inline_op_on_entry(GArray **arr, enum qemu_plugin_mem_rw rw, enum qemu_plugin_op op, @@ -324,13 +336,12 @@ void plugin_register_inline_op_on_entry(GArray **arr, { struct qemu_plugin_dyn_cb *dyn_cb; + struct qemu_plugin_inline_cb inline_cb = { .rw = rw, + .entry = entry, + .imm = imm }; dyn_cb = plugin_get_dyn_cb(arr); - dyn_cb->userp = NULL; - dyn_cb->type = PLUGIN_CB_INLINE; - dyn_cb->rw = rw; - dyn_cb->inline_insn.entry = entry; - dyn_cb->inline_insn.op = op; - dyn_cb->inline_insn.imm = imm; + dyn_cb->type = op_to_cb_type(op); + dyn_cb->inline_insn = inline_cb; } void plugin_register_dyn_cb__udata(GArray **arr, @@ -349,14 +360,46 @@ void plugin_register_dyn_cb__udata(GArray **arr, dh_typemask(i32, 1) | dh_typemask(ptr, 2)) }; + assert((unsigned)flags < ARRAY_SIZE(info)); struct qemu_plugin_dyn_cb *dyn_cb = plugin_get_dyn_cb(arr); - dyn_cb->userp = udata; + struct qemu_plugin_regular_cb regular_cb = { .f.vcpu_udata = cb, + .userp = udata, + .info = &info[flags] }; dyn_cb->type = PLUGIN_CB_REGULAR; - dyn_cb->regular.f.vcpu_udata = cb; + dyn_cb->regular = regular_cb; +} +void plugin_register_dyn_cond_cb__udata(GArray **arr, + qemu_plugin_vcpu_udata_cb_t cb, + enum qemu_plugin_cb_flags flags, + enum qemu_plugin_cond cond, + qemu_plugin_u64 entry, + uint64_t imm, + void *udata) +{ + static TCGHelperInfo info[3] = { + [QEMU_PLUGIN_CB_NO_REGS].flags = TCG_CALL_NO_RWG, + [QEMU_PLUGIN_CB_R_REGS].flags = TCG_CALL_NO_WG, + /* + * Match qemu_plugin_vcpu_udata_cb_t: + * void (*)(uint32_t, void *) + */ + [0 ... 2].typemask = (dh_typemask(void, 0) | + dh_typemask(i32, 1) | + dh_typemask(ptr, 2)) + }; assert((unsigned)flags < ARRAY_SIZE(info)); - dyn_cb->regular.info = &info[flags]; + + struct qemu_plugin_dyn_cb *dyn_cb = plugin_get_dyn_cb(arr); + struct qemu_plugin_conditional_cb cond_cb = { .userp = udata, + .f.vcpu_udata = cb, + .cond = cond, + .entry = entry, + .imm = imm, + .info = &info[flags] }; + dyn_cb->type = PLUGIN_CB_COND; + dyn_cb->cond = cond_cb; } void plugin_register_vcpu_mem_cb(GArray **arr, @@ -388,15 +431,15 @@ void plugin_register_vcpu_mem_cb(GArray **arr, dh_typemask(i64, 3) | dh_typemask(ptr, 4)) }; + assert((unsigned)flags < ARRAY_SIZE(info)); struct qemu_plugin_dyn_cb *dyn_cb = plugin_get_dyn_cb(arr); - dyn_cb->userp = udata; + struct qemu_plugin_regular_cb regular_cb = { .userp = udata, + .rw = rw, + .f.vcpu_mem = cb, + .info = &info[flags] }; dyn_cb->type = PLUGIN_CB_MEM_REGULAR; - dyn_cb->rw = rw; - dyn_cb->regular.f.vcpu_mem = cb; - - assert((unsigned)flags < ARRAY_SIZE(info)); - dyn_cb->regular.info = &info[flags]; + dyn_cb->regular = regular_cb; } /* @@ -513,17 +556,22 @@ void qemu_plugin_flush_cb(void) plugin_cb__simple(QEMU_PLUGIN_EV_FLUSH); } -void exec_inline_op(struct qemu_plugin_dyn_cb *cb, int cpu_index) +void exec_inline_op(enum plugin_dyn_cb_type type, + struct qemu_plugin_inline_cb *cb, + int cpu_index) { - char *ptr = cb->inline_insn.entry.score->data->data; + char *ptr = cb->entry.score->data->data; size_t elem_size = g_array_get_element_size( - cb->inline_insn.entry.score->data); - size_t offset = cb->inline_insn.entry.offset; + cb->entry.score->data); + size_t offset = cb->entry.offset; uint64_t *val = (uint64_t *)(ptr + offset + cpu_index * elem_size); - switch (cb->inline_insn.op) { - case QEMU_PLUGIN_INLINE_ADD_U64: - *val += cb->inline_insn.imm; + switch (type) { + case PLUGIN_CB_INLINE_ADD_U64: + *val += cb->imm; + break; + case PLUGIN_CB_INLINE_STORE_U64: + *val = cb->imm; break; default: g_assert_not_reached(); @@ -543,16 +591,19 @@ void qemu_plugin_vcpu_mem_cb(CPUState *cpu, uint64_t vaddr, struct qemu_plugin_dyn_cb *cb = &g_array_index(arr, struct qemu_plugin_dyn_cb, i); - if (!(rw & cb->rw)) { - break; - } switch (cb->type) { case PLUGIN_CB_MEM_REGULAR: - cb->regular.f.vcpu_mem(cpu->cpu_index, make_plugin_meminfo(oi, rw), - vaddr, cb->userp); + if (rw && cb->regular.rw) { + cb->regular.f.vcpu_mem(cpu->cpu_index, + make_plugin_meminfo(oi, rw), + vaddr, cb->regular.userp); + } break; - case PLUGIN_CB_INLINE: - exec_inline_op(cb, cpu->cpu_index); + case PLUGIN_CB_INLINE_ADD_U64: + case PLUGIN_CB_INLINE_STORE_U64: + if (rw && cb->inline_insn.rw) { + exec_inline_op(cb->type, &cb->inline_insn, cpu->cpu_index); + } break; default: g_assert_not_reached(); |