mirror of https://github.com/xemu-project/xemu.git
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 int phys_ram_fd;
|
||||||
extern ram_addr_t ram_size;
|
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 {
|
typedef struct RAMBlock {
|
||||||
uint8_t *host;
|
uint8_t *host;
|
||||||
ram_addr_t offset;
|
ram_addr_t offset;
|
||||||
ram_addr_t length;
|
ram_addr_t length;
|
||||||
|
uint32_t flags;
|
||||||
char idstr[256];
|
char idstr[256];
|
||||||
QLIST_ENTRY(RAMBlock) next;
|
QLIST_ENTRY(RAMBlock) next;
|
||||||
#if defined(__linux__) && !defined(TARGET_S390X)
|
#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 size, void *host);
|
||||||
ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size);
|
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_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. */
|
/* This should only be used for ram local to a device. */
|
||||||
void *qemu_get_ram_ptr(ram_addr_t addr);
|
void *qemu_get_ram_ptr(ram_addr_t addr);
|
||||||
/* Same but slower, to use for migration, where the order of
|
/* 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) {
|
if (host) {
|
||||||
new_block->host = host;
|
new_block->host = host;
|
||||||
|
new_block->flags |= RAM_PREALLOC_MASK;
|
||||||
} else {
|
} else {
|
||||||
if (mem_path) {
|
if (mem_path) {
|
||||||
#if defined (__linux__) && !defined(TARGET_S390X)
|
#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) {
|
QLIST_FOREACH(block, &ram_list.blocks, next) {
|
||||||
if (addr == block->offset) {
|
if (addr == block->offset) {
|
||||||
QLIST_REMOVE(block, next);
|
QLIST_REMOVE(block, next);
|
||||||
if (mem_path) {
|
if (block->flags & RAM_PREALLOC_MASK) {
|
||||||
|
;
|
||||||
|
} else if (mem_path) {
|
||||||
#if defined (__linux__) && !defined(TARGET_S390X)
|
#if defined (__linux__) && !defined(TARGET_S390X)
|
||||||
if (block->fd) {
|
if (block->fd) {
|
||||||
munmap(block->host, block->length);
|
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.
|
/* Return a host pointer to ram allocated with qemu_ram_alloc.
|
||||||
With the exception of the softmmu code in this file, this should
|
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,
|
only be used for local memory (e.g. video ram) that the device owns,
|
||||||
|
|
Loading…
Reference in New Issue