Blame SOURCES/kvm-dump-rebase-from-host-private-RAMBlock-offsets-to-guest-physical-addresses.patch

218e99
From c67daf48e19c0a73c933d09a4c748cfda8d6d3f2 Mon Sep 17 00:00:00 2001
218e99
From: Laszlo Ersek <lersek@redhat.com>
218e99
Date: Mon, 12 Aug 2013 15:59:40 +0200
218e99
Subject: dump: rebase from host-private RAMBlock offsets to guest-physical addresses
218e99
218e99
RH-Author: Laszlo Ersek <lersek@redhat.com>
218e99
Message-id: <1376323180-12863-11-git-send-email-lersek@redhat.com>
218e99
Patchwork-id: 53168
218e99
O-Subject: [RHEL-7 qemu-kvm PATCH 10/10] dump: rebase from host-private RAMBlock offsets to guest-physical addresses
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
RAMBlock.offset                   --> GuestPhysBlock.target_start
218e99
RAMBlock.offset + RAMBlock.length --> GuestPhysBlock.target_end
218e99
RAMBlock.length                   --> GuestPhysBlock.target_end -
218e99
                                      GuestPhysBlock.target_start
218e99
218e99
"GuestPhysBlock.host_addr" is only used when writing the dump contents.
218e99
218e99
This patch enables "crash" to work with the vmcore by rebasing the vmcore
218e99
from the left side of the following diagram to the right side:
218e99
218e99
host-private
218e99
offset
218e99
relative
218e99
to ram_addr   RAMBlock                  guest-visible paddrs
218e99
            0 +-------------------+.....+-------------------+ 0
218e99
              |         ^         |     |        ^          |
218e99
              |       640 KB      |     |      640 KB       |
218e99
              |         v         |     |        v          |
218e99
  0x0000a0000 +-------------------+.....+-------------------+ 0x0000a0000
218e99
              |         ^         |     |XXXXXXXXXXXXXXXXXXX|
218e99
              |       384 KB      |     |XXXXXXXXXXXXXXXXXXX|
218e99
              |         v         |     |XXXXXXXXXXXXXXXXXXX|
218e99
  0x000100000 +-------------------+.....+-------------------+ 0x000100000
218e99
              |         ^         |     |        ^          |
218e99
              |       3583 MB     |     |      3583 MB      |
218e99
              |         v         |     |        v          |
218e99
  0x0e0000000 +-------------------+.....+-------------------+ 0x0e0000000
218e99
              |         ^         |.    |XXXXXXXXXXXXXXXXXXX|
218e99
              | above_4g_mem_size | .   |XXXX PCI hole XXXXX|
218e99
              |         v         |  .  |XXXX          XXXXX|
218e99
     ram_size +-------------------+   . |XXXX  512 MB  XXXXX|
218e99
                                   .   .|XXXXXXXXXXXXXXXXXXX|
218e99
                                    .   +-------------------+ 0x100000000
218e99
                                     .  |         ^         |
218e99
                                      . | above_4g_mem_size |
218e99
                                       .|         v         |
218e99
                                        +-------------------+ ram_size
218e99
                                                              + 512 MB
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 56c4bfb3f07f3107894c00281276aea4f5e8834d)
218e99
218e99
Conflicts:
218e99
218e99
	memory_mapping.c
218e99
	stubs/dump.c
218e99
	target-s390x/arch_dump.c
218e99
218e99
The conflicts are due to RHEL-7 not having
218e99
- upstream commit 182735ef ("cpu: Make first_cpu and next_cpu CPUState"),
218e99
  whose backport I rejected due to its many dependencies,
218e99
- upstream commit 9b4f38e1 ("s390: Implement dump-guest-memory support for
218e99
  target s390x") -- we don't support the s390x target.
218e99
218e99
diff --git a/dump.c b/dump.c
218e99
index e6b7a00..0523ad4 100644
218e99
--- a/dump.c
218e99
+++ b/dump.c
218e99
@@ -70,7 +70,7 @@ typedef struct DumpState {
218e99
     hwaddr memory_offset;
218e99
     int fd;
218e99
 
218e99
-    RAMBlock *block;
218e99
+    GuestPhysBlock *next_block;
218e99
     ram_addr_t start;
218e99
     bool has_filter;
218e99
     int64_t begin;
218e99
@@ -395,14 +395,14 @@ static int write_data(DumpState *s, void *buf, int length)
218e99
 }
218e99
 
218e99
 /* write the memroy to vmcore. 1 page per I/O. */
218e99
-static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start,
218e99
+static int write_memory(DumpState *s, GuestPhysBlock *block, ram_addr_t start,
218e99
                         int64_t size)
218e99
 {
218e99
     int64_t i;
218e99
     int ret;
218e99
 
218e99
     for (i = 0; i < size / TARGET_PAGE_SIZE; i++) {
218e99
-        ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
218e99
+        ret = write_data(s, block->host_addr + start + i * TARGET_PAGE_SIZE,
218e99
                          TARGET_PAGE_SIZE);
218e99
         if (ret < 0) {
218e99
             return ret;
218e99
@@ -410,7 +410,7 @@ static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start,
218e99
     }
218e99
 
218e99
     if ((size % TARGET_PAGE_SIZE) != 0) {
218e99
-        ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
218e99
+        ret = write_data(s, block->host_addr + start + i * TARGET_PAGE_SIZE,
218e99
                          size % TARGET_PAGE_SIZE);
218e99
         if (ret < 0) {
218e99
             return ret;
218e99
@@ -427,7 +427,7 @@ static void get_offset_range(hwaddr phys_addr,
218e99
                              hwaddr *p_offset,
218e99
                              hwaddr *p_filesz)
218e99
 {
218e99
-    RAMBlock *block;
218e99
+    GuestPhysBlock *block;
218e99
     hwaddr offset = s->memory_offset;
218e99
     int64_t size_in_block, start;
218e99
 
218e99
@@ -441,35 +441,34 @@ static void get_offset_range(hwaddr phys_addr,
218e99
         }
218e99
     }
218e99
 
218e99
-    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
218e99
+    QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
218e99
         if (s->has_filter) {
218e99
-            if (block->offset >= s->begin + s->length ||
218e99
-                block->offset + block->length <= s->begin) {
218e99
+            if (block->target_start >= s->begin + s->length ||
218e99
+                block->target_end <= s->begin) {
218e99
                 /* This block is out of the range */
218e99
                 continue;
218e99
             }
218e99
 
218e99
-            if (s->begin <= block->offset) {
218e99
-                start = block->offset;
218e99
+            if (s->begin <= block->target_start) {
218e99
+                start = block->target_start;
218e99
             } else {
218e99
                 start = s->begin;
218e99
             }
218e99
 
218e99
-            size_in_block = block->length - (start - block->offset);
218e99
-            if (s->begin + s->length < block->offset + block->length) {
218e99
-                size_in_block -= block->offset + block->length -
218e99
-                                 (s->begin + s->length);
218e99
+            size_in_block = block->target_end - start;
218e99
+            if (s->begin + s->length < block->target_end) {
218e99
+                size_in_block -= block->target_end - (s->begin + s->length);
218e99
             }
218e99
         } else {
218e99
-            start = block->offset;
218e99
-            size_in_block = block->length;
218e99
+            start = block->target_start;
218e99
+            size_in_block = block->target_end - block->target_start;
218e99
         }
218e99
 
218e99
         if (phys_addr >= start && phys_addr < start + size_in_block) {
218e99
             *p_offset = phys_addr - start + offset;
218e99
 
218e99
             /* The offset range mapped from the vmcore file must not spill over
218e99
-             * the RAMBlock, clamp it. The rest of the mapping will be
218e99
+             * the GuestPhysBlock, clamp it. The rest of the mapping will be
218e99
              * zero-filled in memory at load time; see
218e99
              * <http: refspecs.linuxbase.org="" elf="" gabi4+="" ch5.pheader.html="">.
218e99
              */
218e99
@@ -617,7 +616,7 @@ static int dump_completed(DumpState *s)
218e99
     return 0;
218e99
 }
218e99
 
218e99
-static int get_next_block(DumpState *s, RAMBlock *block)
218e99
+static int get_next_block(DumpState *s, GuestPhysBlock *block)
218e99
 {
218e99
     while (1) {
218e99
         block = QTAILQ_NEXT(block, next);
218e99
@@ -627,16 +626,16 @@ static int get_next_block(DumpState *s, RAMBlock *block)
218e99
         }
218e99
 
218e99
         s->start = 0;
218e99
-        s->block = block;
218e99
+        s->next_block = block;
218e99
         if (s->has_filter) {
218e99
-            if (block->offset >= s->begin + s->length ||
218e99
-                block->offset + block->length <= s->begin) {
218e99
+            if (block->target_start >= s->begin + s->length ||
218e99
+                block->target_end <= s->begin) {
218e99
                 /* This block is out of the range */
218e99
                 continue;
218e99
             }
218e99
 
218e99
-            if (s->begin > block->offset) {
218e99
-                s->start = s->begin - block->offset;
218e99
+            if (s->begin > block->target_start) {
218e99
+                s->start = s->begin - block->target_start;
218e99
             }
218e99
         }
218e99
 
218e99
@@ -647,18 +646,18 @@ static int get_next_block(DumpState *s, RAMBlock *block)
218e99
 /* write all memory to vmcore */
218e99
 static int dump_iterate(DumpState *s)
218e99
 {
218e99
-    RAMBlock *block;
218e99
+    GuestPhysBlock *block;
218e99
     int64_t size;
218e99
     int ret;
218e99
 
218e99
     while (1) {
218e99
-        block = s->block;
218e99
+        block = s->next_block;
218e99
 
218e99
-        size = block->length;
218e99
+        size = block->target_end - block->target_start;
218e99
         if (s->has_filter) {
218e99
             size -= s->start;
218e99
-            if (s->begin + s->length < block->offset + block->length) {
218e99
-                size -= block->offset + block->length - (s->begin + s->length);
218e99
+            if (s->begin + s->length < block->target_end) {
218e99
+                size -= block->target_end - (s->begin + s->length);
218e99
             }
218e99
         }
218e99
         ret = write_memory(s, block, s->start, size);
218e99
@@ -693,23 +692,23 @@ static int create_vmcore(DumpState *s)
218e99
 
218e99
 static ram_addr_t get_start_block(DumpState *s)
218e99
 {
218e99
-    RAMBlock *block;
218e99
+    GuestPhysBlock *block;
218e99
 
218e99
     if (!s->has_filter) {
218e99
-        s->block = QTAILQ_FIRST(&ram_list.blocks);
218e99
+        s->next_block = QTAILQ_FIRST(&s->guest_phys_blocks.head);
218e99
         return 0;
218e99
     }
218e99
 
218e99
-    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
218e99
-        if (block->offset >= s->begin + s->length ||
218e99
-            block->offset + block->length <= s->begin) {
218e99
+    QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
218e99
+        if (block->target_start >= s->begin + s->length ||
218e99
+            block->target_end <= s->begin) {
218e99
             /* This block is out of the range */
218e99
             continue;
218e99
         }
218e99
 
218e99
-        s->block = block;
218e99
-        if (s->begin > block->offset) {
218e99
-            s->start = s->begin - block->offset;
218e99
+        s->next_block = block;
218e99
+        if (s->begin > block->target_start) {
218e99
+            s->start = s->begin - block->target_start;
218e99
         } else {
218e99
             s->start = 0;
218e99
         }
218e99
@@ -762,7 +761,7 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
218e99
      * If the target architecture is not supported, cpu_get_dump_info() will
218e99
      * return -1.
218e99
      */
218e99
-    ret = cpu_get_dump_info(&s->dump_info);
218e99
+    ret = cpu_get_dump_info(&s->dump_info, &s->guest_phys_blocks);
218e99
     if (ret < 0) {
218e99
         error_set(errp, QERR_UNSUPPORTED);
218e99
         goto cleanup;
218e99
@@ -778,13 +777,13 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
218e99
     /* get memory mapping */
218e99
     memory_mapping_list_init(&s->list);
218e99
     if (paging) {
218e99
-        qemu_get_guest_memory_mapping(&s->list, &err);
218e99
+        qemu_get_guest_memory_mapping(&s->list, &s->guest_phys_blocks, &err);
218e99
         if (err != NULL) {
218e99
             error_propagate(errp, err);
218e99
             goto cleanup;
218e99
         }
218e99
     } else {
218e99
-        qemu_get_guest_simple_memory_mapping(&s->list);
218e99
+        qemu_get_guest_simple_memory_mapping(&s->list, &s->guest_phys_blocks);
218e99
     }
218e99
 
218e99
     if (s->has_filter) {
218e99
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
218e99
index b8c770f..19fafb2 100644
218e99
--- a/include/sysemu/dump.h
218e99
+++ b/include/sysemu/dump.h
218e99
@@ -20,7 +20,9 @@ typedef struct ArchDumpInfo {
218e99
     int d_class;    /* ELFCLASS32 or ELFCLASS64 */
218e99
 } ArchDumpInfo;
218e99
 
218e99
-int cpu_get_dump_info(ArchDumpInfo *info);
218e99
+struct GuestPhysBlockList; /* memory_mapping.h */
218e99
+int cpu_get_dump_info(ArchDumpInfo *info,
218e99
+                      const struct GuestPhysBlockList *guest_phys_blocks);
218e99
 ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
218e99
 
218e99
 #endif
218e99
diff --git a/include/sysemu/memory_mapping.h b/include/sysemu/memory_mapping.h
218e99
index b2d7d85..a75d59a 100644
218e99
--- a/include/sysemu/memory_mapping.h
218e99
+++ b/include/sysemu/memory_mapping.h
218e99
@@ -68,10 +68,13 @@ void guest_phys_blocks_free(GuestPhysBlockList *list);
218e99
 void guest_phys_blocks_init(GuestPhysBlockList *list);
218e99
 void guest_phys_blocks_append(GuestPhysBlockList *list);
218e99
 
218e99
-void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp);
218e99
+void qemu_get_guest_memory_mapping(MemoryMappingList *list,
218e99
+                                   const GuestPhysBlockList *guest_phys_blocks,
218e99
+                                   Error **errp);
218e99
 
218e99
 /* get guest's memory mapping without do paging(virtual address is 0). */
218e99
-void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list);
218e99
+void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list,
218e99
+                                  const GuestPhysBlockList *guest_phys_blocks);
218e99
 
218e99
 void memory_mapping_filter(MemoryMappingList *list, int64_t begin,
218e99
                            int64_t length);
218e99
diff --git a/memory_mapping.c b/memory_mapping.c
218e99
index 411aba6..65082d8 100644
218e99
--- a/memory_mapping.c
218e99
+++ b/memory_mapping.c
218e99
@@ -279,10 +279,12 @@ static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu)
218e99
     return NULL;
218e99
 }
218e99
 
218e99
-void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp)
218e99
+void qemu_get_guest_memory_mapping(MemoryMappingList *list,
218e99
+                                   const GuestPhysBlockList *guest_phys_blocks,
218e99
+                                   Error **errp)
218e99
 {
218e99
     CPUArchState *env, *first_paging_enabled_cpu;
218e99
-    RAMBlock *block;
218e99
+    GuestPhysBlock *block;
218e99
     ram_addr_t offset, length;
218e99
 
218e99
     first_paging_enabled_cpu = find_paging_enabled_cpu(first_cpu);
218e99
@@ -302,19 +304,21 @@ void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp)
218e99
      * If the guest doesn't use paging, the virtual address is equal to physical
218e99
      * address.
218e99
      */
218e99
-    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
218e99
-        offset = block->offset;
218e99
-        length = block->length;
218e99
+    QTAILQ_FOREACH(block, &guest_phys_blocks->head, next) {
218e99
+        offset = block->target_start;
218e99
+        length = block->target_end - block->target_start;
218e99
         create_new_memory_mapping(list, offset, offset, length);
218e99
     }
218e99
 }
218e99
 
218e99
-void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list)
218e99
+void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list,
218e99
+                                   const GuestPhysBlockList *guest_phys_blocks)
218e99
 {
218e99
-    RAMBlock *block;
218e99
+    GuestPhysBlock *block;
218e99
 
218e99
-    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
218e99
-        create_new_memory_mapping(list, block->offset, 0, block->length);
218e99
+    QTAILQ_FOREACH(block, &guest_phys_blocks->head, next) {
218e99
+        create_new_memory_mapping(list, block->target_start, 0,
218e99
+                                  block->target_end - block->target_start);
218e99
     }
218e99
 }
218e99
 
218e99
diff --git a/stubs/dump.c b/stubs/dump.c
218e99
index b3f42cb..5749e2c 100644
218e99
--- a/stubs/dump.c
218e99
+++ b/stubs/dump.c
218e99
@@ -24,7 +24,8 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
218e99
     error_set(errp, QERR_UNSUPPORTED);
218e99
 }
218e99
 
218e99
-int cpu_get_dump_info(ArchDumpInfo *info)
218e99
+int cpu_get_dump_info(ArchDumpInfo *info,
218e99
+                      const struct GuestPhysBlockList *guest_phys_blocks)
218e99
 {
218e99
     return -1;
218e99
 }
218e99
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
218e99
index 83898cd..a99ef8c 100644
218e99
--- a/target-i386/arch_dump.c
218e99
+++ b/target-i386/arch_dump.c
218e99
@@ -15,6 +15,7 @@
218e99
 #include "exec/cpu-all.h"
218e99
 #include "sysemu/dump.h"
218e99
 #include "elf.h"
218e99
+#include "sysemu/memory_mapping.h"
218e99
 
218e99
 #ifdef TARGET_X86_64
218e99
 typedef struct {
218e99
@@ -388,10 +389,11 @@ int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cs,
218e99
     return cpu_write_qemu_note(f, &cpu->env, opaque, 0);
218e99
 }
218e99
 
218e99
-int cpu_get_dump_info(ArchDumpInfo *info)
218e99
+int cpu_get_dump_info(ArchDumpInfo *info,
218e99
+                      const GuestPhysBlockList *guest_phys_blocks)
218e99
 {
218e99
     bool lma = false;
218e99
-    RAMBlock *block;
218e99
+    GuestPhysBlock *block;
218e99
 
218e99
 #ifdef TARGET_X86_64
218e99
     lma = !!(first_cpu->hflags & HF_LMA_MASK);
218e99
@@ -409,8 +411,8 @@ int cpu_get_dump_info(ArchDumpInfo *info)
218e99
     } else {
218e99
         info->d_class = ELFCLASS32;
218e99
 
218e99
-        QTAILQ_FOREACH(block, &ram_list.blocks, next) {
218e99
-            if (block->offset + block->length > UINT_MAX) {
218e99
+        QTAILQ_FOREACH(block, &guest_phys_blocks->head, next) {
218e99
+            if (block->target_end > UINT_MAX) {
218e99
                 /* The memory size is greater than 4G */
218e99
                 info->d_class = ELFCLASS64;
218e99
                 break;