summaryrefslogtreecommitdiff
path: root/dump.c
diff options
context:
space:
mode:
authorLaszlo Ersek <lersek@redhat.com>2013-08-06 12:37:11 +0200
committerLuiz Capitulino <lcapitulino@redhat.com>2013-08-08 11:01:46 -0400
commit56c4bfb3f07f3107894c00281276aea4f5e8834d (patch)
treeabcdfab8c89a19415971046b9449019dab6d677c /dump.c
parentc5d7f60f0614250bd925071e25220ce5958f75d0 (diff)
dump: rebase from host-private RAMBlock offsets to guest-physical addresses
RAMBlock.offset --> GuestPhysBlock.target_start RAMBlock.offset + RAMBlock.length --> GuestPhysBlock.target_end RAMBlock.length --> GuestPhysBlock.target_end - GuestPhysBlock.target_start "GuestPhysBlock.host_addr" is only used when writing the dump contents. This patch enables "crash" to work with the vmcore by rebasing the vmcore from the left side of the following diagram to the right side: host-private offset relative to ram_addr RAMBlock guest-visible paddrs 0 +-------------------+.....+-------------------+ 0 | ^ | | ^ | | 640 KB | | 640 KB | | v | | v | 0x0000a0000 +-------------------+.....+-------------------+ 0x0000a0000 | ^ | |XXXXXXXXXXXXXXXXXXX| | 384 KB | |XXXXXXXXXXXXXXXXXXX| | v | |XXXXXXXXXXXXXXXXXXX| 0x000100000 +-------------------+.....+-------------------+ 0x000100000 | ^ | | ^ | | 3583 MB | | 3583 MB | | v | | v | 0x0e0000000 +-------------------+.....+-------------------+ 0x0e0000000 | ^ |. |XXXXXXXXXXXXXXXXXXX| | above_4g_mem_size | . |XXXX PCI hole XXXXX| | v | . |XXXX XXXXX| ram_size +-------------------+ . |XXXX 512 MB XXXXX| . .|XXXXXXXXXXXXXXXXXXX| . +-------------------+ 0x100000000 . | ^ | . | above_4g_mem_size | .| v | +-------------------+ ram_size + 512 MB Related RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=981582 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Diffstat (limited to 'dump.c')
-rw-r--r--dump.c77
1 files changed, 38 insertions, 39 deletions
diff --git a/dump.c b/dump.c
index 3fa33fccf0..c0dae2c3ff 100644
--- a/dump.c
+++ b/dump.c
@@ -70,7 +70,7 @@ typedef struct DumpState {
hwaddr memory_offset;
int fd;
- RAMBlock *block;
+ GuestPhysBlock *next_block;
ram_addr_t start;
bool has_filter;
int64_t begin;
@@ -391,14 +391,14 @@ static int write_data(DumpState *s, void *buf, int length)
}
/* write the memroy to vmcore. 1 page per I/O. */
-static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start,
+static int write_memory(DumpState *s, GuestPhysBlock *block, ram_addr_t start,
int64_t size)
{
int64_t i;
int ret;
for (i = 0; i < size / TARGET_PAGE_SIZE; i++) {
- ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
+ ret = write_data(s, block->host_addr + start + i * TARGET_PAGE_SIZE,
TARGET_PAGE_SIZE);
if (ret < 0) {
return ret;
@@ -406,7 +406,7 @@ static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start,
}
if ((size % TARGET_PAGE_SIZE) != 0) {
- ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
+ ret = write_data(s, block->host_addr + start + i * TARGET_PAGE_SIZE,
size % TARGET_PAGE_SIZE);
if (ret < 0) {
return ret;
@@ -423,7 +423,7 @@ static void get_offset_range(hwaddr phys_addr,
hwaddr *p_offset,
hwaddr *p_filesz)
{
- RAMBlock *block;
+ GuestPhysBlock *block;
hwaddr offset = s->memory_offset;
int64_t size_in_block, start;
@@ -437,35 +437,34 @@ static void get_offset_range(hwaddr phys_addr,
}
}
- QTAILQ_FOREACH(block, &ram_list.blocks, next) {
+ QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
if (s->has_filter) {
- if (block->offset >= s->begin + s->length ||
- block->offset + block->length <= s->begin) {
+ if (block->target_start >= s->begin + s->length ||
+ block->target_end <= s->begin) {
/* This block is out of the range */
continue;
}
- if (s->begin <= block->offset) {
- start = block->offset;
+ if (s->begin <= block->target_start) {
+ start = block->target_start;
} else {
start = s->begin;
}
- size_in_block = block->length - (start - block->offset);
- if (s->begin + s->length < block->offset + block->length) {
- size_in_block -= block->offset + block->length -
- (s->begin + s->length);
+ size_in_block = block->target_end - start;
+ if (s->begin + s->length < block->target_end) {
+ size_in_block -= block->target_end - (s->begin + s->length);
}
} else {
- start = block->offset;
- size_in_block = block->length;
+ start = block->target_start;
+ size_in_block = block->target_end - block->target_start;
}
if (phys_addr >= start && phys_addr < start + size_in_block) {
*p_offset = phys_addr - start + offset;
/* The offset range mapped from the vmcore file must not spill over
- * the RAMBlock, clamp it. The rest of the mapping will be
+ * the GuestPhysBlock, clamp it. The rest of the mapping will be
* zero-filled in memory at load time; see
* <http://refspecs.linuxbase.org/elf/gabi4+/ch5.pheader.html>.
*/
@@ -613,7 +612,7 @@ static int dump_completed(DumpState *s)
return 0;
}
-static int get_next_block(DumpState *s, RAMBlock *block)
+static int get_next_block(DumpState *s, GuestPhysBlock *block)
{
while (1) {
block = QTAILQ_NEXT(block, next);
@@ -623,16 +622,16 @@ static int get_next_block(DumpState *s, RAMBlock *block)
}
s->start = 0;
- s->block = block;
+ s->next_block = block;
if (s->has_filter) {
- if (block->offset >= s->begin + s->length ||
- block->offset + block->length <= s->begin) {
+ if (block->target_start >= s->begin + s->length ||
+ block->target_end <= s->begin) {
/* This block is out of the range */
continue;
}
- if (s->begin > block->offset) {
- s->start = s->begin - block->offset;
+ if (s->begin > block->target_start) {
+ s->start = s->begin - block->target_start;
}
}
@@ -643,18 +642,18 @@ static int get_next_block(DumpState *s, RAMBlock *block)
/* write all memory to vmcore */
static int dump_iterate(DumpState *s)
{
- RAMBlock *block;
+ GuestPhysBlock *block;
int64_t size;
int ret;
while (1) {
- block = s->block;
+ block = s->next_block;
- size = block->length;
+ size = block->target_end - block->target_start;
if (s->has_filter) {
size -= s->start;
- if (s->begin + s->length < block->offset + block->length) {
- size -= block->offset + block->length - (s->begin + s->length);
+ if (s->begin + s->length < block->target_end) {
+ size -= block->target_end - (s->begin + s->length);
}
}
ret = write_memory(s, block, s->start, size);
@@ -689,23 +688,23 @@ static int create_vmcore(DumpState *s)
static ram_addr_t get_start_block(DumpState *s)
{
- RAMBlock *block;
+ GuestPhysBlock *block;
if (!s->has_filter) {
- s->block = QTAILQ_FIRST(&ram_list.blocks);
+ s->next_block = QTAILQ_FIRST(&s->guest_phys_blocks.head);
return 0;
}
- QTAILQ_FOREACH(block, &ram_list.blocks, next) {
- if (block->offset >= s->begin + s->length ||
- block->offset + block->length <= s->begin) {
+ QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
+ if (block->target_start >= s->begin + s->length ||
+ block->target_end <= s->begin) {
/* This block is out of the range */
continue;
}
- s->block = block;
- if (s->begin > block->offset) {
- s->start = s->begin - block->offset;
+ s->next_block = block;
+ if (s->begin > block->target_start) {
+ s->start = s->begin - block->target_start;
} else {
s->start = 0;
}
@@ -758,7 +757,7 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
* If the target architecture is not supported, cpu_get_dump_info() will
* return -1.
*/
- ret = cpu_get_dump_info(&s->dump_info);
+ ret = cpu_get_dump_info(&s->dump_info, &s->guest_phys_blocks);
if (ret < 0) {
error_set(errp, QERR_UNSUPPORTED);
goto cleanup;
@@ -774,13 +773,13 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
/* get memory mapping */
memory_mapping_list_init(&s->list);
if (paging) {
- qemu_get_guest_memory_mapping(&s->list, &err);
+ qemu_get_guest_memory_mapping(&s->list, &s->guest_phys_blocks, &err);
if (err != NULL) {
error_propagate(errp, err);
goto cleanup;
}
} else {
- qemu_get_guest_simple_memory_mapping(&s->list);
+ qemu_get_guest_simple_memory_mapping(&s->list, &s->guest_phys_blocks);
}
if (s->has_filter) {