diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h index 8cf20cd96f..cea0a68858 100644 --- a/include/qemu/plugin.h +++ b/include/qemu/plugin.h @@ -161,6 +161,9 @@ void qemu_plugin_vcpu_exit_hook(CPUState *cpu); void qemu_plugin_tb_trans_cb(CPUState *cpu, struct qemu_plugin_tb *tb); void qemu_plugin_vcpu_idle_cb(CPUState *cpu); void qemu_plugin_vcpu_resume_cb(CPUState *cpu); +void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from); +void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from); +void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from); void qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, @@ -258,6 +261,15 @@ static inline void qemu_plugin_vcpu_idle_cb(CPUState *cpu) static inline void qemu_plugin_vcpu_resume_cb(CPUState *cpu) { } +static inline void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from) +{ } + +static inline void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from) +{ } + +static inline void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from) +{ } + static inline void qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6, diff --git a/plugins/core.c b/plugins/core.c index 40d001d39a..35a252d272 100644 --- a/plugins/core.c +++ b/plugins/core.c @@ -105,6 +105,30 @@ static void plugin_vcpu_cb__simple(CPUState *cpu, enum qemu_plugin_event ev) } } +/* + * Disable CFI checks. + * The callback function has been loaded from an external library so we do not + * have type information + */ +QEMU_DISABLE_CFI +static void plugin_vcpu_cb__discon(CPUState *cpu, + enum qemu_plugin_event ev, + enum qemu_plugin_discon_type type, + uint64_t from) +{ + struct qemu_plugin_cb *cb, *next; + uint64_t to = cpu->cc->get_pc(cpu); + + 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) { + qemu_plugin_vcpu_discon_cb_t func = cb->f.vcpu_discon; + + func(cb->ctx->id, cpu->cpu_index, type, from, to); + } + } +} + /* * Disable CFI checks. * The callback function has been loaded from an external library so we do not @@ -557,6 +581,24 @@ void qemu_plugin_vcpu_resume_cb(CPUState *cpu) } } +void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from) +{ + plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_EV_VCPU_INTERRUPT, + QEMU_PLUGIN_DISCON_INTERRUPT, from); +} + +void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from) +{ + plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_EV_VCPU_EXCEPTION, + QEMU_PLUGIN_DISCON_EXCEPTION, from); +} + +void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from) +{ + plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_EV_VCPU_HOSTCALL, + QEMU_PLUGIN_DISCON_HOSTCALL, from); +} + void qemu_plugin_register_vcpu_idle_cb(qemu_plugin_id_t id, qemu_plugin_vcpu_simple_cb_t cb) {