diff --git a/dump.c b/dump.c index 923e3a5756c4..9210a72d614a 100644 --- a/dump.c +++ b/dump.c @@ -1643,6 +1643,20 @@ static void dump_process(DumpState *s, Error **errp) dump_cleanup(s); } +static void *dump_thread(void *data) +{ + Error *err = NULL; + DumpState *s = (DumpState *)data; + + dump_process(s, &err); + + if (err) { + /* TODO: notify user the error */ + error_free(err); + } + return NULL; +} + void qmp_dump_guest_memory(bool paging, const char *file, bool has_detach, bool detach, bool has_begin, int64_t begin, bool has_length, @@ -1653,6 +1667,7 @@ void qmp_dump_guest_memory(bool paging, const char *file, int fd = -1; DumpState *s; Error *local_err = NULL; + bool detach_p = false; if (runstate_check(RUN_STATE_INMIGRATE)) { error_setg(errp, "Dump not allowed during incoming migration."); @@ -1684,6 +1699,9 @@ void qmp_dump_guest_memory(bool paging, const char *file, error_setg(errp, QERR_MISSING_PARAMETER, "begin"); return; } + if (has_detach) { + detach_p = detach; + } /* check whether lzo/snappy is supported */ #ifndef CONFIG_LZO @@ -1733,7 +1751,14 @@ void qmp_dump_guest_memory(bool paging, const char *file, return; } - dump_process(s, errp); + if (detach_p) { + /* detached dump */ + qemu_thread_create(&s->dump_thread, "dump_thread", dump_thread, + s, QEMU_THREAD_DETACHED); + } else { + /* sync dump */ + dump_process(s, errp); + } } DumpGuestMemoryCapability *qmp_query_dump_guest_memory_capability(Error **errp) diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h index 1da3ddb61766..06393c3f8f55 100644 --- a/include/sysemu/dump.h +++ b/include/sysemu/dump.h @@ -181,6 +181,7 @@ typedef struct DumpState { bool has_format; /* whether format is provided */ DumpGuestMemoryFormat format; /* valid only if has_format == true */ + QemuThread dump_thread; /* thread for detached dump */ } DumpState; uint16_t cpu_to_dump16(DumpState *s, uint16_t val); diff --git a/include/sysemu/memory_mapping.h b/include/sysemu/memory_mapping.h index a75d59a55db2..d46d879b9461 100644 --- a/include/sysemu/memory_mapping.h +++ b/include/sysemu/memory_mapping.h @@ -16,6 +16,7 @@ #include "qemu/queue.h" #include "qemu/typedefs.h" +#include "exec/memory.h" typedef struct GuestPhysBlock { /* visible to guest, reflects PCI hole, etc */ @@ -27,6 +28,9 @@ typedef struct GuestPhysBlock { /* points into host memory */ uint8_t *host_addr; + /* points to the MemoryRegion that this block belongs to */ + MemoryRegion *mr; + QTAILQ_ENTRY(GuestPhysBlock) next; } GuestPhysBlock; diff --git a/memory_mapping.c b/memory_mapping.c index 04db3ac7faf2..c8855de92b10 100644 --- a/memory_mapping.c +++ b/memory_mapping.c @@ -178,6 +178,7 @@ void guest_phys_blocks_free(GuestPhysBlockList *list) QTAILQ_FOREACH_SAFE(p, &list->head, next, q) { QTAILQ_REMOVE(&list->head, p, next); + memory_region_unref(p->mr); g_free(p); } list->num = 0; @@ -241,6 +242,8 @@ static void guest_phys_blocks_region_add(MemoryListener *listener, block->target_start = target_start; block->target_end = target_end; block->host_addr = host_addr; + block->mr = section->mr; + memory_region_ref(section->mr); QTAILQ_INSERT_TAIL(&g->list->head, block, next); ++g->list->num;