From c44834c7d3f1996c7e2f80085580561bbbe31b83 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 4 Feb 2011 12:20:02 -0200 Subject: [RHEL6 qemu-kvm PATCH 26/27] Maintaing number of dirty pages RH-Author: Juan Quintela Message-id: <67252eb0e1a87c5de7337a6c0e0dfeea87104c39.1296800500.git.quintela@redhat.com> Patchwork-id: 17740 O-Subject: [PATCH 7/8] Maintaing number of dirty pages Bugzilla: 643970 RH-Acked-by: Alex Williamson RH-Acked-by: Jes Sorensen RH-Acked-by: Amit Shah Calculate the number of dirty pages takes a lot on hosts with lots of memory. Just maintain how many pages are dirty. Only sync bitmaps if number is small enough. Signed-off-by: Juan Quintela --- cpu-all.h | 4 ++++ exec.c | 27 ++++++++++++++++++++++++++- vl.c | 14 +------------- 3 files changed, 31 insertions(+), 14 deletions(-) Signed-off-by: Eduardo Habkost --- cpu-all.h | 4 ++++ exec.c | 27 ++++++++++++++++++++++++++- vl.c | 14 +------------- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index 854c63d..07ada32 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -862,6 +862,7 @@ typedef struct RAMBlock { typedef struct RAMList { uint8_t *phys_dirty; + uint64_t dirty_pages; QLIST_HEAD(ram, RAMBlock) blocks; } RAMList; extern RAMList ram_list; @@ -905,6 +906,9 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t addr, static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) { + if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) + ram_list.dirty_pages++; + ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] = 0xff; } diff --git a/exec.c b/exec.c index d6c773d..b992016 100644 --- a/exec.c +++ b/exec.c @@ -1958,8 +1958,12 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, len = length >> TARGET_PAGE_BITS; mask = ~dirty_flags; p = ram_list.phys_dirty + (start >> TARGET_PAGE_BITS); - for(i = 0; i < len; i++) + for(i = 0; i < len; i++) { + if (cpu_physical_memory_get_dirty(start + i * TARGET_PAGE_SIZE, + MIGRATION_DIRTY_FLAG & dirty_flags)) + ram_list.dirty_pages--; p[i] &= mask; + } if (kvm_enabled()) return; @@ -2752,6 +2756,8 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size) memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS), 0xff, size >> TARGET_PAGE_BITS); + ram_list.dirty_pages += size >> TARGET_PAGE_BITS; + if (kvm_enabled()) kvm_setup_guest_memory(new_block->host, size); @@ -2930,6 +2936,9 @@ static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr, } stb_p(qemu_get_ram_ptr(ram_addr), val); dirty_flags |= (0xff & ~CODE_DIRTY_FLAG); + if (!cpu_physical_memory_get_dirty(ram_addr, + MIGRATION_DIRTY_FLAG & dirty_flags)) + ram_list.dirty_pages++; ram_list.phys_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags; /* we remove the notdirty callback only if the code has been flushed */ @@ -2950,6 +2959,9 @@ static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr, } stw_p(qemu_get_ram_ptr(ram_addr), val); dirty_flags |= (0xff & ~CODE_DIRTY_FLAG); + if (!cpu_physical_memory_get_dirty(ram_addr, + MIGRATION_DIRTY_FLAG & dirty_flags)) + ram_list.dirty_pages++; ram_list.phys_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags; /* we remove the notdirty callback only if the code has been flushed */ @@ -2970,6 +2982,9 @@ static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr, } stl_p(qemu_get_ram_ptr(ram_addr), val); dirty_flags |= (0xff & ~CODE_DIRTY_FLAG); + if (!cpu_physical_memory_get_dirty(ram_addr, + MIGRATION_DIRTY_FLAG & dirty_flags)) + ram_list.dirty_pages++; ram_list.phys_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags; /* we remove the notdirty callback only if the code has been flushed */ @@ -3424,6 +3439,8 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, /* invalidate code */ tb_invalidate_phys_page_range(addr1, addr1 + l, 0); /* set dirty bit */ + if (!cpu_physical_memory_get_dirty(addr1, MIGRATION_DIRTY_FLAG)) + ram_list.dirty_pages++; ram_list.phys_dirty[addr1 >> TARGET_PAGE_BITS] |= (0xff & ~CODE_DIRTY_FLAG); } @@ -3638,6 +3655,8 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, /* invalidate code */ tb_invalidate_phys_page_range(addr1, addr1 + l, 0); /* set dirty bit */ + if (!cpu_physical_memory_get_dirty(addr1, MIGRATION_DIRTY_FLAG)) + ram_list.dirty_pages++; ram_list.phys_dirty[addr1 >> TARGET_PAGE_BITS] |= (0xff & ~CODE_DIRTY_FLAG); } @@ -3799,6 +3818,8 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val) /* invalidate code */ tb_invalidate_phys_page_range(addr1, addr1 + 4, 0); /* set dirty bit */ + if (!cpu_physical_memory_get_dirty(addr1, MIGRATION_DIRTY_FLAG)) + ram_list.dirty_pages++; ram_list.phys_dirty[addr1 >> TARGET_PAGE_BITS] |= (0xff & ~CODE_DIRTY_FLAG); } @@ -3868,6 +3889,8 @@ void stl_phys(target_phys_addr_t addr, uint32_t val) /* invalidate code */ tb_invalidate_phys_page_range(addr1, addr1 + 4, 0); /* set dirty bit */ + if (!cpu_physical_memory_get_dirty(addr1, MIGRATION_DIRTY_FLAG)) + ram_list.dirty_pages++; ram_list.phys_dirty[addr1 >> TARGET_PAGE_BITS] |= (0xff & ~CODE_DIRTY_FLAG); } @@ -3911,6 +3934,8 @@ void stw_phys(target_phys_addr_t addr, uint32_t val) /* invalidate code */ tb_invalidate_phys_page_range(addr1, addr1 + 2, 0); /* set dirty bit */ + if (!cpu_physical_memory_get_dirty(addr1, MIGRATION_DIRTY_FLAG)) + ram_list.dirty_pages++; ram_list.phys_dirty[addr1 >> TARGET_PAGE_BITS] |= (0xff & ~CODE_DIRTY_FLAG); } diff --git a/vl.c b/vl.c index 733139c..d899c9c 100644 --- a/vl.c +++ b/vl.c @@ -3306,19 +3306,7 @@ static uint64_t bytes_transferred; static ram_addr_t ram_save_remaining(void) { - RAMBlock *block; - ram_addr_t count = 0; - - QLIST_FOREACH(block, &ram_list.blocks, next) { - ram_addr_t addr; - for (addr = block->offset; addr < block->offset + block->length; - addr += TARGET_PAGE_SIZE) { - if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) - count++; - } - } - - return count; + return ram_list.dirty_pages; } uint64_t ram_bytes_remaining(void) -- 1.7.3.2