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.
*/
/* 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;