Add qemu_ram_remap
qemu_ram_remap() unmaps the specified RAM pages, then re-maps these pages again. This is used by KVM HWPoison support to clear HWPoisoned page tables across guest rebooting, so that a new page may be allocated later to recover the memory error. [ Jan: style fixlets, WIN32 fix ] Signed-off-by: Huang Ying <ying.huang@intel.com> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
This commit is contained in:
parent
75d4949733
commit
cd19cfa236
@ -863,10 +863,14 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
|
||||
extern int phys_ram_fd;
|
||||
extern ram_addr_t ram_size;
|
||||
|
||||
/* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */
|
||||
#define RAM_PREALLOC_MASK (1 << 0)
|
||||
|
||||
typedef struct RAMBlock {
|
||||
uint8_t *host;
|
||||
ram_addr_t offset;
|
||||
ram_addr_t length;
|
||||
uint32_t flags;
|
||||
char idstr[256];
|
||||
QLIST_ENTRY(RAMBlock) next;
|
||||
#if defined(__linux__) && !defined(TARGET_S390X)
|
||||
|
@ -50,6 +50,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
|
||||
ram_addr_t size, void *host);
|
||||
ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size);
|
||||
void qemu_ram_free(ram_addr_t addr);
|
||||
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
|
||||
/* This should only be used for ram local to a device. */
|
||||
void *qemu_get_ram_ptr(ram_addr_t addr);
|
||||
/* Same but slower, to use for migration, where the order of
|
||||
|
63
exec.c
63
exec.c
@ -2867,6 +2867,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
|
||||
|
||||
if (host) {
|
||||
new_block->host = host;
|
||||
new_block->flags |= RAM_PREALLOC_MASK;
|
||||
} else {
|
||||
if (mem_path) {
|
||||
#if defined (__linux__) && !defined(TARGET_S390X)
|
||||
@ -2920,7 +2921,9 @@ void qemu_ram_free(ram_addr_t addr)
|
||||
QLIST_FOREACH(block, &ram_list.blocks, next) {
|
||||
if (addr == block->offset) {
|
||||
QLIST_REMOVE(block, next);
|
||||
if (mem_path) {
|
||||
if (block->flags & RAM_PREALLOC_MASK) {
|
||||
;
|
||||
} else if (mem_path) {
|
||||
#if defined (__linux__) && !defined(TARGET_S390X)
|
||||
if (block->fd) {
|
||||
munmap(block->host, block->length);
|
||||
@ -2943,6 +2946,64 @@ void qemu_ram_free(ram_addr_t addr)
|
||||
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
|
||||
{
|
||||
RAMBlock *block;
|
||||
ram_addr_t offset;
|
||||
int flags;
|
||||
void *area, *vaddr;
|
||||
|
||||
QLIST_FOREACH(block, &ram_list.blocks, next) {
|
||||
offset = addr - block->offset;
|
||||
if (offset < block->length) {
|
||||
vaddr = block->host + offset;
|
||||
if (block->flags & RAM_PREALLOC_MASK) {
|
||||
;
|
||||
} else {
|
||||
flags = MAP_FIXED;
|
||||
munmap(vaddr, length);
|
||||
if (mem_path) {
|
||||
#if defined(__linux__) && !defined(TARGET_S390X)
|
||||
if (block->fd) {
|
||||
#ifdef MAP_POPULATE
|
||||
flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
|
||||
MAP_PRIVATE;
|
||||
#else
|
||||
flags |= MAP_PRIVATE;
|
||||
#endif
|
||||
area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
|
||||
flags, block->fd, offset);
|
||||
} else {
|
||||
flags |= MAP_PRIVATE | MAP_ANONYMOUS;
|
||||
area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
|
||||
flags, -1, 0);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if defined(TARGET_S390X) && defined(CONFIG_KVM)
|
||||
flags |= MAP_SHARED | MAP_ANONYMOUS;
|
||||
area = mmap(vaddr, length, PROT_EXEC|PROT_READ|PROT_WRITE,
|
||||
flags, -1, 0);
|
||||
#else
|
||||
flags |= MAP_PRIVATE | MAP_ANONYMOUS;
|
||||
area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
|
||||
flags, -1, 0);
|
||||
#endif
|
||||
}
|
||||
if (area != vaddr) {
|
||||
fprintf(stderr, "Could not remap addr: %lx@%lx\n",
|
||||
length, addr);
|
||||
exit(1);
|
||||
}
|
||||
qemu_madvise(vaddr, length, QEMU_MADV_MERGEABLE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
/* Return a host pointer to ram allocated with qemu_ram_alloc.
|
||||
With the exception of the softmmu code in this file, this should
|
||||
only be used for local memory (e.g. video ram) that the device owns,
|
||||
|
Loading…
Reference in New Issue
Block a user