|
|
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;
|