From: William Roche <william.roche@xxxxxxxxxx> When a memory page is added to the hwpoison_page_list, include the page size information. This size is the backend real page size. To better deal with hugepages, we create a single entry for the entire page. Signed-off-by: William Roche <william.roche@xxxxxxxxxx> --- accel/kvm/kvm-all.c | 8 +++++++- include/exec/cpu-common.h | 1 + system/physmem.c | 13 +++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 801cff16a5..6dd06f5edf 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -1266,6 +1266,7 @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension) */ typedef struct HWPoisonPage { ram_addr_t ram_addr; + size_t page_size; QLIST_ENTRY(HWPoisonPage) list; } HWPoisonPage; @@ -1278,7 +1279,7 @@ static void kvm_unpoison_all(void *param) QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) { QLIST_REMOVE(page, list); - qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE); + qemu_ram_remap(page->ram_addr, page->page_size); g_free(page); } } @@ -1286,6 +1287,10 @@ static void kvm_unpoison_all(void *param) void kvm_hwpoison_page_add(ram_addr_t ram_addr) { HWPoisonPage *page; + size_t sz = qemu_ram_pagesize_from_addr(ram_addr); + + if (sz > TARGET_PAGE_SIZE) + ram_addr = ROUND_DOWN(ram_addr, sz); QLIST_FOREACH(page, &hwpoison_page_list, list) { if (page->ram_addr == ram_addr) { @@ -1294,6 +1299,7 @@ void kvm_hwpoison_page_add(ram_addr_t ram_addr) } page = g_new(HWPoisonPage, 1); page->ram_addr = ram_addr; + page->page_size = sz; QLIST_INSERT_HEAD(&hwpoison_page_list, page, list); } diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 638dc806a5..8f8f7ad567 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -108,6 +108,7 @@ bool qemu_ram_is_named_file(RAMBlock *rb); int qemu_ram_get_fd(RAMBlock *rb); size_t qemu_ram_pagesize(RAMBlock *block); +size_t qemu_ram_pagesize_from_addr(ram_addr_t addr); size_t qemu_ram_pagesize_largest(void); /** diff --git a/system/physmem.c b/system/physmem.c index dc1db3a384..750604d47d 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -1665,6 +1665,19 @@ size_t qemu_ram_pagesize(RAMBlock *rb) return rb->page_size; } +/* Return backend real page size used for the given ram_addr. */ +size_t qemu_ram_pagesize_from_addr(ram_addr_t addr) +{ + RAMBlock *rb; + + RCU_READ_LOCK_GUARD(); + rb = qemu_get_ram_block(addr); + if (!rb) { + return TARGET_PAGE_SIZE; + } + return qemu_ram_pagesize(rb); +} + /* Returns the largest size of page in use */ size_t qemu_ram_pagesize_largest(void) { -- 2.43.5