Message ID | 18b8687e6310a68283b8b3ed72ad38479114bc51.1733063076.git.neither@nut.email (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | tcg-plugins: add hooks for discontinuities | expand |
On 12/2/24 11:26, Julian Ganz wrote: > The plugin API allows registration of callbacks for a variety of VCPU > related events, such as VCPU reset, idle and resume. In addition, we > recently introduced API for registering callbacks for discontinuity > events, specifically for interrupts, exceptions and host calls. > > This change introduces the corresponding hooks called from target > specific code inside qemu. > --- > include/qemu/plugin.h | 12 ++++++++++ > plugins/core.c | 52 +++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 64 insertions(+) > > diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h > index 27a176b631..3de9cb3fe4 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, uint64_t to); > +void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from, uint64_t to); > +void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from, uint64_t to); > 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, > @@ -243,6 +246,15 @@ static inline void qemu_plugin_vcpu_idle_cb(CPUState *cpu) > static inline void qemu_plugin_vcpu_resume_cb(CPUState *cpu) > { } > > +void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from, uint64_t to) > +{ } > + > +void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from, uint64_t to) > +{ } > + > +void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from, uint64_t to) > +{ } > + > 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 a89a4a0315..2c9637334f 100644 > --- a/plugins/core.c > +++ b/plugins/core.c > @@ -112,6 +112,43 @@ 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_discon_type type, > + uint64_t from, uint64_t to) > +{ > + struct qemu_plugin_cb *cb, *next; > + enum qemu_plugin_event ev; > + > + if (cpu->cpu_index < plugin.num_vcpus) { > + switch (type) { > + case QEMU_PLUGIN_DISCON_INTERRUPT: > + ev = QEMU_PLUGIN_EV_VCPU_INTERRUPT; > + break; > + case QEMU_PLUGIN_DISCON_EXCEPTION: > + ev = QEMU_PLUGIN_EV_VCPU_EXCEPTION; > + break; > + case QEMU_PLUGIN_DISCON_HOSTCALL: > + ev = QEMU_PLUGIN_EV_VCPU_HOSTCALL; > + break; > + default: > + g_assert_not_reached(); > + } > + > + /* 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 > @@ -547,6 +584,21 @@ void qemu_plugin_vcpu_resume_cb(CPUState *cpu) > } > } > > +void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from, uint64_t to) > +{ > + plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_DISCON_INTERRUPT, from, to); > +} > + > +void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from, uint64_t to) > +{ > + plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_DISCON_EXCEPTION, from, to); > +} > + > +void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from, uint64_t to) > +{ > + plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_DISCON_HOSTCALL, from, to); > +} > + > void qemu_plugin_register_vcpu_idle_cb(qemu_plugin_id_t id, > qemu_plugin_vcpu_simple_cb_t cb) > { Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h index 27a176b631..3de9cb3fe4 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, uint64_t to); +void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from, uint64_t to); +void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from, uint64_t to); 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, @@ -243,6 +246,15 @@ static inline void qemu_plugin_vcpu_idle_cb(CPUState *cpu) static inline void qemu_plugin_vcpu_resume_cb(CPUState *cpu) { } +void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from, uint64_t to) +{ } + +void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from, uint64_t to) +{ } + +void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from, uint64_t to) +{ } + 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 a89a4a0315..2c9637334f 100644 --- a/plugins/core.c +++ b/plugins/core.c @@ -112,6 +112,43 @@ 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_discon_type type, + uint64_t from, uint64_t to) +{ + struct qemu_plugin_cb *cb, *next; + enum qemu_plugin_event ev; + + if (cpu->cpu_index < plugin.num_vcpus) { + switch (type) { + case QEMU_PLUGIN_DISCON_INTERRUPT: + ev = QEMU_PLUGIN_EV_VCPU_INTERRUPT; + break; + case QEMU_PLUGIN_DISCON_EXCEPTION: + ev = QEMU_PLUGIN_EV_VCPU_EXCEPTION; + break; + case QEMU_PLUGIN_DISCON_HOSTCALL: + ev = QEMU_PLUGIN_EV_VCPU_HOSTCALL; + break; + default: + g_assert_not_reached(); + } + + /* 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 @@ -547,6 +584,21 @@ void qemu_plugin_vcpu_resume_cb(CPUState *cpu) } } +void qemu_plugin_vcpu_interrupt_cb(CPUState *cpu, uint64_t from, uint64_t to) +{ + plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_DISCON_INTERRUPT, from, to); +} + +void qemu_plugin_vcpu_exception_cb(CPUState *cpu, uint64_t from, uint64_t to) +{ + plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_DISCON_EXCEPTION, from, to); +} + +void qemu_plugin_vcpu_hostcall_cb(CPUState *cpu, uint64_t from, uint64_t to) +{ + plugin_vcpu_cb__discon(cpu, QEMU_PLUGIN_DISCON_HOSTCALL, from, to); +} + void qemu_plugin_register_vcpu_idle_cb(qemu_plugin_id_t id, qemu_plugin_vcpu_simple_cb_t cb) {