From: Harry van Haaren <[email protected]> Executed instructions are cached in string format inside the execlog plugin. These strings are flushed on exit of a TB, improving performance. This causes executed instructions to be lost when an 'ecall' (riscv system call) occurs that causes the thread to terminate.
The fix in this patch registers a 'vcpu_exit' callback, and flushes any content in the c->last_exec buffer, to ensure all instructions are present in the final instruction log. Reviewed-by: Pierrick Bouvier <[email protected]> Tested-by: Pierrick Bouvier <[email protected]> Signed-off-by: Harry van Haaren <[email protected]> Link: https://lore.kernel.org/qemu-devel/[email protected] Signed-off-by: Pierrick Bouvier <[email protected]> --- contrib/plugins/execlog.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c index dfe00bf836c..cb0bd399d88 100644 --- a/contrib/plugins/execlog.c +++ b/contrib/plugins/execlog.c @@ -380,6 +380,25 @@ static void vcpu_init(unsigned int vcpu_index, void *userdata) c->registers = registers_init(vcpu_index); } +/** + * On vCPU exit, flush the last cached instruction for this vCPU. + * + * The one-instruction-delay pattern stores each instruction in last_exec and + * only prints it when the *next* callback fires. When a thread exits via + * syscall (e.g. ecall/exit), no subsequent callback fires for that vCPU and + * the final instruction is silently dropped. Flushing here guarantees it is + * written before the vCPU is torn down. + */ +static void vcpu_exit(unsigned int vcpu_index, void *udata) +{ + CPU *c = qemu_plugin_scoreboard_find(cpus, vcpu_index); + if (c->last_exec && c->last_exec->len) { + g_string_append_c(c->last_exec, '\n'); + qemu_plugin_outs(c->last_exec->str); + g_string_truncate(c->last_exec, 0); + } +} + /** * On plugin exit, flush any remaining cached instructions and free state. */ @@ -461,6 +480,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, /* Register init, translation block and exit callbacks */ qemu_plugin_register_vcpu_init_cb(id, vcpu_init, NULL); qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans, NULL); + qemu_plugin_register_vcpu_exit_cb(id, vcpu_exit, NULL); qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); return 0; -- 2.47.3
