From 4500da18bc6bbd0715c26deeb693f45241f58bbd Mon Sep 17 00:00:00 2001 Message-Id: <4500da18bc6bbd0715c26deeb693f45241f58bbd.1376572530.git.minovotn@redhat.com> In-Reply-To: <1ab1cadd348058496d2f900c3d4ac4b7c325d3e6.1376572530.git.minovotn@redhat.com> References: <1ab1cadd348058496d2f900c3d4ac4b7c325d3e6.1376572530.git.minovotn@redhat.com> From: Laszlo Ersek Date: Mon, 12 Aug 2013 15:17:06 +0200 Subject: [PATCH 02/11] dump: introduce GuestPhysBlockList RH-Author: Laszlo Ersek Message-id: <1376320628-11255-3-git-send-email-lersek@redhat.com> Patchwork-id: 53155 O-Subject: [RHEL-6.5 qemu-kvm PATCH 2/4] dump: introduce GuestPhysBlockList Bugzilla: 989585 RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Radim Krcmar RH-Acked-by: Miroslav Rezanina The vmcore must use physical addresses that are visible to the guest, not addresses that point into linear RAMBlocks. As first step, introduce the list type into which we'll collect the physical mappings in effect at the time of the dump. Manual port of upstream commit 5ee163e8ea2fb6610339f494e039159e08a69066. Signed-off-by: Laszlo Ersek --- memory_mapping.h | 22 ++++++++++++++++++++++ dump.c | 31 +++++++++++++++++++------------ memory_mapping.c | 18 ++++++++++++++++++ 3 files changed, 59 insertions(+), 12 deletions(-) Signed-off-by: Michal Novotny --- dump.c | 31 +++++++++++++++++++------------ memory_mapping.c | 18 ++++++++++++++++++ memory_mapping.h | 22 ++++++++++++++++++++++ 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/dump.c b/dump.c index 61c9b23..42d8ebb 100644 --- a/dump.c +++ b/dump.c @@ -64,6 +64,7 @@ static uint64_t cpu_convert_to_target64(uint64_t val, int endian) } typedef struct DumpState { + GuestPhysBlockList guest_phys_blocks; ArchDumpInfo dump_info; MemoryMappingList list; uint16_t phdr_num; @@ -86,6 +87,7 @@ static int dump_cleanup(DumpState *s) { int ret = 0; + guest_phys_blocks_free(&s->guest_phys_blocks); memory_mapping_list_free(&s->list); if (s->fd != -1) { close(s->fd); @@ -727,31 +729,34 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, s->resume = false; } + /* If we use kvm, we should synchronize the register before we get dump + * info or physmap info. + */ + nr_cpus = 0; + for (env = first_cpu; env != NULL; env = env->next_cpu) { + cpu_synchronize_state(env); + nr_cpus++; + } + s->errp = errp; s->fd = fd; s->has_filter = has_filter; s->begin = begin; s->length = length; + + guest_phys_blocks_init(&s->guest_phys_blocks); + /* FILL LIST */ + s->start = get_start_block(s); if (s->start == -1) { error_set(errp, QERR_INVALID_PARAMETER, "begin"); goto cleanup; } - /* - * get dump info: endian, class and architecture. + /* get dump info: endian, class and architecture. * If the target architecture is not supported, cpu_get_dump_info() will * return -1. - * - * if we use kvm, we should synchronize the register before we get dump - * info. */ - nr_cpus = 0; - for (env = first_cpu; env != NULL; env = env->next_cpu) { - cpu_synchronize_state(env); - nr_cpus++; - } - ret = cpu_get_dump_info(&s->dump_info); if (ret < 0) { error_set(errp, QERR_UNSUPPORTED); @@ -817,6 +822,8 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, return 0; cleanup: + guest_phys_blocks_free(&s->guest_phys_blocks); + if (s->resume) { vm_start(); } @@ -865,7 +872,7 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin, return; } - s = g_malloc(sizeof(DumpState)); + s = g_malloc0(sizeof(DumpState)); ret = dump_init(s, fd, paging, has_begin, begin, length, errp); if (ret < 0) { diff --git a/memory_mapping.c b/memory_mapping.c index 8810bb0..9b55746 100644 --- a/memory_mapping.c +++ b/memory_mapping.c @@ -165,6 +165,24 @@ void memory_mapping_list_init(MemoryMappingList *list) QTAILQ_INIT(&list->head); } +void guest_phys_blocks_free(GuestPhysBlockList *list) +{ + GuestPhysBlock *p, *q; + + QTAILQ_FOREACH_SAFE(p, &list->head, next, q) { + QTAILQ_REMOVE(&list->head, p, next); + g_free(p); + } + list->num = 0; +} + +void guest_phys_blocks_init(GuestPhysBlockList *list) +{ + list->num = 0; + QTAILQ_INIT(&list->head); +} + + #if defined(CONFIG_HAVE_GET_MEMORY_MAPPING) static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu) diff --git a/memory_mapping.h b/memory_mapping.h index a1aa64f..36d82e9 100644 --- a/memory_mapping.h +++ b/memory_mapping.h @@ -17,6 +17,25 @@ #include "qemu-queue.h" #ifndef CONFIG_USER_ONLY +typedef struct GuestPhysBlock { + /* visible to guest, reflects PCI hole, etc */ + target_phys_addr_t target_start; + + /* implies size */ + target_phys_addr_t target_end; + + /* points into host memory */ + uint8_t *host_addr; + + QTAILQ_ENTRY(GuestPhysBlock) next; +} GuestPhysBlock; + +/* point-in-time snapshot of guest-visible physical mappings */ +typedef struct GuestPhysBlockList { + unsigned num; + QTAILQ_HEAD(GuestPhysBlockHead, GuestPhysBlock) head; +} GuestPhysBlockList; + /* The physical and virtual address in the memory mapping are contiguous. */ typedef struct MemoryMapping { target_phys_addr_t phys_addr; @@ -45,6 +64,9 @@ void memory_mapping_list_free(MemoryMappingList *list); void memory_mapping_list_init(MemoryMappingList *list); +void guest_phys_blocks_free(GuestPhysBlockList *list); +void guest_phys_blocks_init(GuestPhysBlockList *list); + /* * Return value: * 0: success -- 1.7.11.7