|
@@ -2275,17 +2275,35 @@ void qemu_ram_free(RAMBlock *block)
|
|
|
}
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
-void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
|
|
|
+/*
|
|
|
+ * qemu_ram_remap - remap a single RAM page
|
|
|
+ *
|
|
|
+ * @addr: address in ram_addr_t address space.
|
|
|
+ *
|
|
|
+ * This function will try remapping a single page of guest RAM identified by
|
|
|
+ * @addr, essentially discarding memory to recover from previously poisoned
|
|
|
+ * memory (MCE). The page size depends on the RAMBlock (i.e., hugetlb). @addr
|
|
|
+ * does not have to point at the start of the page.
|
|
|
+ *
|
|
|
+ * This function is only to be used during system resets; it will kill the
|
|
|
+ * VM if remapping failed.
|
|
|
+ */
|
|
|
+void qemu_ram_remap(ram_addr_t addr)
|
|
|
{
|
|
|
RAMBlock *block;
|
|
|
- ram_addr_t offset;
|
|
|
+ uint64_t offset;
|
|
|
int flags;
|
|
|
void *area, *vaddr;
|
|
|
int prot;
|
|
|
+ size_t page_size;
|
|
|
|
|
|
RAMBLOCK_FOREACH(block) {
|
|
|
offset = addr - block->offset;
|
|
|
if (offset < block->max_length) {
|
|
|
+ /* Respect the pagesize of our RAMBlock */
|
|
|
+ page_size = qemu_ram_pagesize(block);
|
|
|
+ offset = QEMU_ALIGN_DOWN(offset, page_size);
|
|
|
+
|
|
|
vaddr = ramblock_ptr(block, offset);
|
|
|
if (block->flags & RAM_PREALLOC) {
|
|
|
;
|
|
@@ -2299,21 +2317,23 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
|
|
|
prot = PROT_READ;
|
|
|
prot |= block->flags & RAM_READONLY ? 0 : PROT_WRITE;
|
|
|
if (block->fd >= 0) {
|
|
|
- area = mmap(vaddr, length, prot, flags, block->fd,
|
|
|
+ area = mmap(vaddr, page_size, prot, flags, block->fd,
|
|
|
offset + block->fd_offset);
|
|
|
} else {
|
|
|
flags |= MAP_ANONYMOUS;
|
|
|
- area = mmap(vaddr, length, prot, flags, -1, 0);
|
|
|
+ area = mmap(vaddr, page_size, prot, flags, -1, 0);
|
|
|
}
|
|
|
if (area != vaddr) {
|
|
|
- error_report("Could not remap addr: "
|
|
|
- RAM_ADDR_FMT "@" RAM_ADDR_FMT "",
|
|
|
- length, addr);
|
|
|
+ error_report("Could not remap RAM %s:%" PRIx64 "+%" PRIx64
|
|
|
+ " +%zx", block->idstr, offset,
|
|
|
+ block->fd_offset, page_size);
|
|
|
exit(1);
|
|
|
}
|
|
|
- memory_try_enable_merging(vaddr, length);
|
|
|
- qemu_ram_setup_dump(vaddr, length);
|
|
|
+ memory_try_enable_merging(vaddr, page_size);
|
|
|
+ qemu_ram_setup_dump(vaddr, page_size);
|
|
|
}
|
|
|
+
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
}
|