diff options
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/api.c | 2 | ||||
| -rw-r--r-- | plugins/core.c | 39 |
2 files changed, 40 insertions, 1 deletions
diff --git a/plugins/api.c b/plugins/api.c index 78b563c5c5..2d521e6ba8 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -319,7 +319,7 @@ uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr) return block->offset + offset + block->mr->addr; } else { MemoryRegionSection *mrs = haddr->v.io.section; - return haddr->v.io.offset + mrs->mr->addr; + return mrs->offset_within_address_space + haddr->v.io.offset; } } #endif diff --git a/plugins/core.c b/plugins/core.c index 474db287cb..6b2490f973 100644 --- a/plugins/core.c +++ b/plugins/core.c @@ -488,6 +488,45 @@ void qemu_plugin_register_atexit_cb(qemu_plugin_id_t id, } /* + * Handle exit from linux-user. Unlike the normal atexit() mechanism + * we need to handle the clean-up manually as it's possible threads + * are still running. We need to remove all callbacks from code + * generation, flush the current translations and then we can safely + * trigger the exit callbacks. + */ + +void qemu_plugin_user_exit(void) +{ + enum qemu_plugin_event ev; + CPUState *cpu; + + QEMU_LOCK_GUARD(&plugin.lock); + + start_exclusive(); + + /* un-register all callbacks except the final AT_EXIT one */ + for (ev = 0; ev < QEMU_PLUGIN_EV_MAX; ev++) { + if (ev != QEMU_PLUGIN_EV_ATEXIT) { + struct qemu_plugin_ctx *ctx; + QTAILQ_FOREACH(ctx, &plugin.ctxs, entry) { + plugin_unregister_cb__locked(ctx, ev); + } + } + } + + tb_flush(current_cpu); + + CPU_FOREACH(cpu) { + qemu_plugin_disable_mem_helpers(cpu); + } + + end_exclusive(); + + /* now it's safe to handle the exit case */ + qemu_plugin_atexit_cb(); +} + +/* * Call this function after longjmp'ing to the main loop. It's possible that the * last instruction of a TB might have used helpers, and therefore the * "disable" instruction will never execute because it ended up as dead code. |