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