218e99
From 0c26814e42d1090b3ad3a20ca97b5a74accee7e9 Mon Sep 17 00:00:00 2001
218e99
From: Laszlo Ersek <lersek@redhat.com>
218e99
Date: Mon, 12 Aug 2013 15:59:38 +0200
218e99
Subject: dump: introduce GuestPhysBlockList
218e99
218e99
RH-Author: Laszlo Ersek <lersek@redhat.com>
218e99
Message-id: <1376323180-12863-9-git-send-email-lersek@redhat.com>
218e99
Patchwork-id: 53166
218e99
O-Subject: [RHEL-7 qemu-kvm PATCH 08/10] dump: introduce GuestPhysBlockList
218e99
Bugzilla: 981582
218e99
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
218e99
RH-Acked-by: Radim Krcmar <rkrcmar@redhat.com>
218e99
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
218e99
218e99
The vmcore must use physical addresses that are visible to the guest, not
218e99
addresses that point into linear RAMBlocks. As first step, introduce the
218e99
list type into which we'll collect the physical mappings in effect at the
218e99
time of the dump.
218e99
218e99
Related RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=981582
218e99
218e99
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
218e99
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
218e99
(cherry picked from commit 5ee163e8ea2fb6610339f494e039159e08a69066)
218e99
218e99
Conflicts:
218e99
218e99
	dump.c
218e99
	memory_mapping.c
218e99
218e99
The conflicts are due to RHEL-7 not having upstream commit 182735ef ("cpu:
218e99
Make first_cpu and next_cpu CPUState"), whose backport I rejected due to
218e99
its many dependencies.
218e99
218e99
diff --git a/dump.c b/dump.c
218e99
index cbfad1c..351233b 100644
218e99
--- a/dump.c
218e99
+++ b/dump.c
218e99
@@ -59,6 +59,7 @@ static uint64_t cpu_convert_to_target64(uint64_t val, int endian)
218e99
 }
218e99
 
218e99
 typedef struct DumpState {
218e99
+    GuestPhysBlockList guest_phys_blocks;
218e99
     ArchDumpInfo dump_info;
218e99
     MemoryMappingList list;
218e99
     uint16_t phdr_num;
218e99
@@ -81,6 +82,7 @@ static int dump_cleanup(DumpState *s)
218e99
 {
218e99
     int ret = 0;
218e99
 
218e99
+    guest_phys_blocks_free(&s->guest_phys_blocks);
218e99
     memory_mapping_list_free(&s->list);
218e99
     if (s->fd != -1) {
218e99
         close(s->fd);
218e99
@@ -732,31 +734,34 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
218e99
         s->resume = false;
218e99
     }
218e99
 
218e99
+    /* If we use KVM, we should synchronize the registers before we get dump
218e99
+     * info or physmap info.
218e99
+     */
218e99
+    cpu_synchronize_all_states();
218e99
+    nr_cpus = 0;
218e99
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
218e99
+        nr_cpus++;
218e99
+    }
218e99
+
218e99
     s->errp = errp;
218e99
     s->fd = fd;
218e99
     s->has_filter = has_filter;
218e99
     s->begin = begin;
218e99
     s->length = length;
218e99
+
218e99
+    guest_phys_blocks_init(&s->guest_phys_blocks);
218e99
+    /* FILL LIST */
218e99
+
218e99
     s->start = get_start_block(s);
218e99
     if (s->start == -1) {
218e99
         error_set(errp, QERR_INVALID_PARAMETER, "begin");
218e99
         goto cleanup;
218e99
     }
218e99
 
218e99
-    /*
218e99
-     * get dump info: endian, class and architecture.
218e99
+    /* get dump info: endian, class and architecture.
218e99
      * If the target architecture is not supported, cpu_get_dump_info() will
218e99
      * return -1.
218e99
-     *
218e99
-     * If we use KVM, we should synchronize the registers before we get dump
218e99
-     * info.
218e99
      */
218e99
-    cpu_synchronize_all_states();
218e99
-    nr_cpus = 0;
218e99
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
218e99
-        nr_cpus++;
218e99
-    }
218e99
-
218e99
     ret = cpu_get_dump_info(&s->dump_info);
218e99
     if (ret < 0) {
218e99
         error_set(errp, QERR_UNSUPPORTED);
218e99
@@ -831,6 +836,8 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
218e99
     return 0;
218e99
 
218e99
 cleanup:
218e99
+    guest_phys_blocks_free(&s->guest_phys_blocks);
218e99
+
218e99
     if (s->resume) {
218e99
         vm_start();
218e99
     }
218e99
@@ -878,7 +885,7 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
218e99
         return;
218e99
     }
218e99
 
218e99
-    s = g_malloc(sizeof(DumpState));
218e99
+    s = g_malloc0(sizeof(DumpState));
218e99
 
218e99
     ret = dump_init(s, fd, paging, has_begin, begin, length, errp);
218e99
     if (ret < 0) {
218e99
diff --git a/include/sysemu/memory_mapping.h b/include/sysemu/memory_mapping.h
218e99
index 6dfb68d..d2d06cd 100644
218e99
--- a/include/sysemu/memory_mapping.h
218e99
+++ b/include/sysemu/memory_mapping.h
218e99
@@ -17,6 +17,25 @@
218e99
 #include "qemu/queue.h"
218e99
 #include "qemu/typedefs.h"
218e99
 
218e99
+typedef struct GuestPhysBlock {
218e99
+    /* visible to guest, reflects PCI hole, etc */
218e99
+    hwaddr target_start;
218e99
+
218e99
+    /* implies size */
218e99
+    hwaddr target_end;
218e99
+
218e99
+    /* points into host memory */
218e99
+    uint8_t *host_addr;
218e99
+
218e99
+    QTAILQ_ENTRY(GuestPhysBlock) next;
218e99
+} GuestPhysBlock;
218e99
+
218e99
+/* point-in-time snapshot of guest-visible physical mappings */
218e99
+typedef struct GuestPhysBlockList {
218e99
+    unsigned num;
218e99
+    QTAILQ_HEAD(GuestPhysBlockHead, GuestPhysBlock) head;
218e99
+} GuestPhysBlockList;
218e99
+
218e99
 /* The physical and virtual address in the memory mapping are contiguous. */
218e99
 typedef struct MemoryMapping {
218e99
     hwaddr phys_addr;
218e99
@@ -45,6 +64,9 @@ void memory_mapping_list_free(MemoryMappingList *list);
218e99
 
218e99
 void memory_mapping_list_init(MemoryMappingList *list);
218e99
 
218e99
+void guest_phys_blocks_free(GuestPhysBlockList *list);
218e99
+void guest_phys_blocks_init(GuestPhysBlockList *list);
218e99
+
218e99
 void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp);
218e99
 
218e99
 /* get guest's memory mapping without do paging(virtual address is 0). */
218e99
diff --git a/memory_mapping.c b/memory_mapping.c
218e99
index 5634f81..78a9829 100644
218e99
--- a/memory_mapping.c
218e99
+++ b/memory_mapping.c
218e99
@@ -165,6 +165,23 @@ void memory_mapping_list_init(MemoryMappingList *list)
218e99
     QTAILQ_INIT(&list->head);
218e99
 }
218e99
 
218e99
+void guest_phys_blocks_free(GuestPhysBlockList *list)
218e99
+{
218e99
+    GuestPhysBlock *p, *q;
218e99
+
218e99
+    QTAILQ_FOREACH_SAFE(p, &list->head, next, q) {
218e99
+        QTAILQ_REMOVE(&list->head, p, next);
218e99
+        g_free(p);
218e99
+    }
218e99
+    list->num = 0;
218e99
+}
218e99
+
218e99
+void guest_phys_blocks_init(GuestPhysBlockList *list)
218e99
+{
218e99
+    list->num = 0;
218e99
+    QTAILQ_INIT(&list->head);
218e99
+}
218e99
+
218e99
 static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu)
218e99
 {
218e99
     CPUArchState *env;