From e2da99d582300bb8deecb25d26a179ef5b92e066 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 2 Oct 2013 14:04:19 +0200 Subject: memory: cpu_physical_memory_set_dirty_flags() result is never used So return void. Signed-off-by: Juan Quintela Reviewed-by: Orit Wasserman Reviewed-by: Eric Blake --- include/exec/memory-internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/exec') diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index d0e063392a..c71a5e62f6 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -70,10 +70,10 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t start, return ret; } -static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr, +static inline void cpu_physical_memory_set_dirty_flags(ram_addr_t addr, int dirty_flags) { - return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags; + ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags; } static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) -- cgit v1.2.3-55-g7522 From a1390db4df32ad95bf7854944180d2343f7f6368 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 11:53:46 +0200 Subject: memory: create function to set a single dirty bit Signed-off-by: Juan Quintela Reviewed-by: Orit Wasserman Reviewed-by: Eric Blake --- cputlb.c | 2 +- include/exec/memory-internal.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'include/exec') diff --git a/cputlb.c b/cputlb.c index 9270055b83..c545e4c1cf 100644 --- a/cputlb.c +++ b/cputlb.c @@ -122,7 +122,7 @@ void tlb_protect_code(ram_addr_t ram_addr) void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr, target_ulong vaddr) { - cpu_physical_memory_set_dirty_flags(ram_addr, CODE_DIRTY_FLAG); + cpu_physical_memory_set_dirty_flag(ram_addr, CODE_DIRTY_FLAG); } static bool tlb_is_dirty_ram(CPUTLBEntry *tlbe) diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index c71a5e62f6..4ebab8066a 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -76,6 +76,12 @@ static inline void cpu_physical_memory_set_dirty_flags(ram_addr_t addr, ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags; } +static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr, + int dirty_flag) +{ + ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flag; +} + static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) { cpu_physical_memory_set_dirty_flags(addr, 0xff); -- cgit v1.2.3-55-g7522 From 7e5609a85e3f35965af5e4c7b1480254642cf2dd Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 11:57:21 +0200 Subject: exec: create function to get a single dirty bit Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- exec.c | 2 +- include/exec/memory-internal.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'include/exec') diff --git a/exec.c b/exec.c index c42a2f9794..ea78d82023 100644 --- a/exec.c +++ b/exec.c @@ -1487,7 +1487,7 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr, { int dirty_flags; dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr); - if (!(dirty_flags & CODE_DIRTY_FLAG)) { + if (!cpu_physical_memory_get_dirty_flag(ram_addr, CODE_DIRTY_FLAG)) { tb_invalidate_phys_page_fast(ram_addr, size); dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr); } diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 4ebab8066a..136198c001 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -49,6 +49,12 @@ static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr) return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS]; } +static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr, + int dirty_flag) +{ + return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flag; +} + /* read dirty bit (return 0 or 1) */ static inline int cpu_physical_memory_is_dirty(ram_addr_t addr) { -- cgit v1.2.3-55-g7522 From 4f08cabe9e6efe8a50abc30cfa59e8470ad434d7 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 12:01:01 +0200 Subject: memory: make cpu_physical_memory_is_dirty return bool Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- exec.c | 7 ++----- include/exec/memory-internal.h | 8 ++++++-- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'include/exec') diff --git a/exec.c b/exec.c index ea78d82023..a8c79e5fda 100644 --- a/exec.c +++ b/exec.c @@ -1485,11 +1485,8 @@ found: static void notdirty_mem_write(void *opaque, hwaddr ram_addr, uint64_t val, unsigned size) { - int dirty_flags; - dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr); if (!cpu_physical_memory_get_dirty_flag(ram_addr, CODE_DIRTY_FLAG)) { tb_invalidate_phys_page_fast(ram_addr, size); - dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr); } switch (size) { case 1: @@ -1504,8 +1501,8 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr, default: abort(); } - dirty_flags |= (0xff & ~CODE_DIRTY_FLAG); - cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags); + cpu_physical_memory_set_dirty_flag(ram_addr, MIGRATION_DIRTY_FLAG); + cpu_physical_memory_set_dirty_flag(ram_addr, VGA_DIRTY_FLAG); /* we remove the notdirty callback only if the code has been flushed */ if (cpu_physical_memory_is_dirty(ram_addr)) { diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 136198c001..0b25c3f9c3 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -56,9 +56,13 @@ static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr, } /* read dirty bit (return 0 or 1) */ -static inline int cpu_physical_memory_is_dirty(ram_addr_t addr) +static inline bool cpu_physical_memory_is_dirty(ram_addr_t addr) { - return cpu_physical_memory_get_dirty_flags(addr) == 0xff; + bool vga = cpu_physical_memory_get_dirty_flag(addr, VGA_DIRTY_FLAG); + bool code = cpu_physical_memory_get_dirty_flag(addr, CODE_DIRTY_FLAG); + bool migration = + cpu_physical_memory_get_dirty_flag(addr, MIGRATION_DIRTY_FLAG); + return vga && code && migration; } static inline int cpu_physical_memory_get_dirty(ram_addr_t start, -- cgit v1.2.3-55-g7522 From 36187e2ca0295364dcb9a3f256a6fcd77e983c02 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 12:17:12 +0200 Subject: memory: all users of cpu_physical_memory_get_dirty used only one flag So cpu_physical_memory_get_dirty_flags is not needed anymore Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- include/exec/memory-internal.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'include/exec') diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 0b25c3f9c3..53cfe83d2f 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -44,11 +44,6 @@ void qemu_ram_free_from_ptr(ram_addr_t addr); #define CODE_DIRTY_FLAG 0x02 #define MIGRATION_DIRTY_FLAG 0x08 -static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr) -{ - return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS]; -} - static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr, int dirty_flag) { @@ -67,7 +62,7 @@ static inline bool cpu_physical_memory_is_dirty(ram_addr_t addr) static inline int cpu_physical_memory_get_dirty(ram_addr_t start, ram_addr_t length, - int dirty_flags) + int dirty_flag) { int ret = 0; ram_addr_t addr, end; @@ -75,7 +70,7 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t start, end = TARGET_PAGE_ALIGN(start + length); start &= TARGET_PAGE_MASK; for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { - ret |= cpu_physical_memory_get_dirty_flags(addr) & dirty_flags; + ret |= cpu_physical_memory_get_dirty_flag(addr, dirty_flag); } return ret; } -- cgit v1.2.3-55-g7522 From 63995cebfaa283586682ea6236c9686b2a49ece7 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 12:25:25 +0200 Subject: memory: set single dirty flags when possible Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- exec.c | 7 ++++--- include/exec/memory-internal.h | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'include/exec') diff --git a/exec.c b/exec.c index a8c79e5fda..ffda8be436 100644 --- a/exec.c +++ b/exec.c @@ -1912,7 +1912,8 @@ static void invalidate_and_set_dirty(hwaddr addr, /* invalidate code */ tb_invalidate_phys_page_range(addr, addr + length, 0); /* set dirty bit */ - cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG)); + cpu_physical_memory_set_dirty_flag(addr, VGA_DIRTY_FLAG); + cpu_physical_memory_set_dirty_flag(addr, MIGRATION_DIRTY_FLAG); } xen_modified_memory(addr, length); } @@ -2527,8 +2528,8 @@ void stl_phys_notdirty(hwaddr addr, uint32_t val) /* invalidate code */ tb_invalidate_phys_page_range(addr1, addr1 + 4, 0); /* set dirty bit */ - cpu_physical_memory_set_dirty_flags( - addr1, (0xff & ~CODE_DIRTY_FLAG)); + cpu_physical_memory_set_dirty_flag(addr1, MIGRATION_DIRTY_FLAG); + cpu_physical_memory_set_dirty_flag(addr1, VGA_DIRTY_FLAG); } } } diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 53cfe83d2f..9f4ad697b3 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -89,7 +89,9 @@ static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr, static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) { - cpu_physical_memory_set_dirty_flags(addr, 0xff); + cpu_physical_memory_set_dirty_flag(addr, MIGRATION_DIRTY_FLAG); + cpu_physical_memory_set_dirty_flag(addr, VGA_DIRTY_FLAG); + cpu_physical_memory_set_dirty_flag(addr, CODE_DIRTY_FLAG); } static inline int cpu_physical_memory_clear_dirty_flags(ram_addr_t addr, -- cgit v1.2.3-55-g7522 From 75218e7f2b7f052c6f44489afaf45b3ea4369f45 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 12:31:54 +0200 Subject: memory: cpu_physical_memory_set_dirty_range() always dirty all flags So remove the flag argument and do it directly. After this change, there is nothing else using cpu_physical_memory_set_dirty_flags() so remove it. Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- exec.c | 2 +- include/exec/memory-internal.h | 11 ++--------- memory.c | 2 +- 3 files changed, 4 insertions(+), 11 deletions(-) (limited to 'include/exec') diff --git a/exec.c b/exec.c index ffda8be436..f21596040d 100644 --- a/exec.c +++ b/exec.c @@ -1275,7 +1275,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, last_ram_offset() >> TARGET_PAGE_BITS); memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS), 0, size >> TARGET_PAGE_BITS); - cpu_physical_memory_set_dirty_range(new_block->offset, size, 0xff); + cpu_physical_memory_set_dirty_range(new_block->offset, size); qemu_ram_setup_dump(new_block->host, size); qemu_madvise(new_block->host, size, QEMU_MADV_HUGEPAGE); diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 9f4ad697b3..681d63b7ba 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -75,12 +75,6 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t start, return ret; } -static inline void cpu_physical_memory_set_dirty_flags(ram_addr_t addr, - int dirty_flags) -{ - ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags; -} - static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr, int dirty_flag) { @@ -103,15 +97,14 @@ static inline int cpu_physical_memory_clear_dirty_flags(ram_addr_t addr, } static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, - ram_addr_t length, - int dirty_flags) + ram_addr_t length) { ram_addr_t addr, end; end = TARGET_PAGE_ALIGN(start + length); start &= TARGET_PAGE_MASK; for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { - cpu_physical_memory_set_dirty_flags(addr, dirty_flags); + cpu_physical_memory_set_dirty(addr); } xen_modified_memory(addr, length); } diff --git a/memory.c b/memory.c index e497f998cd..fb52e1cdb2 100644 --- a/memory.c +++ b/memory.c @@ -1182,7 +1182,7 @@ void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr, hwaddr size) { assert(mr->terminates); - cpu_physical_memory_set_dirty_range(mr->ram_addr + addr, size, -1); + cpu_physical_memory_set_dirty_range(mr->ram_addr + addr, size); } bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr, -- cgit v1.2.3-55-g7522 From 52159192919469b424b54c167312e53d5a62d233 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 12:44:04 +0200 Subject: memory: cpu_physical_memory_mask_dirty_range() always clears a single flag Document it Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- cputlb.c | 4 ++-- exec.c | 19 ++++++++++--------- include/exec/memory-internal.h | 40 ++++++++++++++++++---------------------- include/exec/memory.h | 3 --- memory.c | 10 ++++------ 5 files changed, 34 insertions(+), 42 deletions(-) (limited to 'include/exec') diff --git a/cputlb.c b/cputlb.c index c545e4c1cf..ec2140580b 100644 --- a/cputlb.c +++ b/cputlb.c @@ -114,7 +114,7 @@ void tlb_protect_code(ram_addr_t ram_addr) { cpu_physical_memory_reset_dirty(ram_addr, ram_addr + TARGET_PAGE_SIZE, - CODE_DIRTY_FLAG); + DIRTY_MEMORY_CODE); } /* update the TLB so that writes in physical page 'phys_addr' are no longer @@ -122,7 +122,7 @@ void tlb_protect_code(ram_addr_t ram_addr) void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr, target_ulong vaddr) { - cpu_physical_memory_set_dirty_flag(ram_addr, CODE_DIRTY_FLAG); + cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_CODE); } static bool tlb_is_dirty_ram(CPUTLBEntry *tlbe) diff --git a/exec.c b/exec.c index f21596040d..82aca4ad37 100644 --- a/exec.c +++ b/exec.c @@ -738,7 +738,7 @@ static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t end, /* Note: start and end must be within the same ram block. */ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, - int dirty_flags) + unsigned client) { uintptr_t length; @@ -748,7 +748,7 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, length = end - start; if (length == 0) return; - cpu_physical_memory_mask_dirty_range(start, length, dirty_flags); + cpu_physical_memory_mask_dirty_range(start, length, client); if (tcg_enabled()) { tlb_reset_dirty_range_all(start, end, length); @@ -1485,7 +1485,7 @@ found: static void notdirty_mem_write(void *opaque, hwaddr ram_addr, uint64_t val, unsigned size) { - if (!cpu_physical_memory_get_dirty_flag(ram_addr, CODE_DIRTY_FLAG)) { + if (!cpu_physical_memory_get_dirty_flag(ram_addr, DIRTY_MEMORY_CODE)) { tb_invalidate_phys_page_fast(ram_addr, size); } switch (size) { @@ -1501,8 +1501,8 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr, default: abort(); } - cpu_physical_memory_set_dirty_flag(ram_addr, MIGRATION_DIRTY_FLAG); - cpu_physical_memory_set_dirty_flag(ram_addr, VGA_DIRTY_FLAG); + cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_MIGRATION); + cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_VGA); /* we remove the notdirty callback only if the code has been flushed */ if (cpu_physical_memory_is_dirty(ram_addr)) { @@ -1912,8 +1912,8 @@ static void invalidate_and_set_dirty(hwaddr addr, /* invalidate code */ tb_invalidate_phys_page_range(addr, addr + length, 0); /* set dirty bit */ - cpu_physical_memory_set_dirty_flag(addr, VGA_DIRTY_FLAG); - cpu_physical_memory_set_dirty_flag(addr, MIGRATION_DIRTY_FLAG); + cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_VGA); + cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_MIGRATION); } xen_modified_memory(addr, length); } @@ -2528,8 +2528,9 @@ void stl_phys_notdirty(hwaddr addr, uint32_t val) /* invalidate code */ tb_invalidate_phys_page_range(addr1, addr1 + 4, 0); /* set dirty bit */ - cpu_physical_memory_set_dirty_flag(addr1, MIGRATION_DIRTY_FLAG); - cpu_physical_memory_set_dirty_flag(addr1, VGA_DIRTY_FLAG); + cpu_physical_memory_set_dirty_flag(addr1, + DIRTY_MEMORY_MIGRATION); + cpu_physical_memory_set_dirty_flag(addr1, DIRTY_MEMORY_VGA); } } } diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 681d63b7ba..b58010f1d0 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -40,29 +40,25 @@ void *qemu_get_ram_ptr(ram_addr_t addr); void qemu_ram_free(ram_addr_t addr); void qemu_ram_free_from_ptr(ram_addr_t addr); -#define VGA_DIRTY_FLAG 0x01 -#define CODE_DIRTY_FLAG 0x02 -#define MIGRATION_DIRTY_FLAG 0x08 - static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr, - int dirty_flag) + unsigned client) { - return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flag; + return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & (1 << client); } /* read dirty bit (return 0 or 1) */ static inline bool cpu_physical_memory_is_dirty(ram_addr_t addr) { - bool vga = cpu_physical_memory_get_dirty_flag(addr, VGA_DIRTY_FLAG); - bool code = cpu_physical_memory_get_dirty_flag(addr, CODE_DIRTY_FLAG); + bool vga = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_VGA); + bool code = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_CODE); bool migration = - cpu_physical_memory_get_dirty_flag(addr, MIGRATION_DIRTY_FLAG); + cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_MIGRATION); return vga && code && migration; } static inline int cpu_physical_memory_get_dirty(ram_addr_t start, ram_addr_t length, - int dirty_flag) + unsigned client) { int ret = 0; ram_addr_t addr, end; @@ -70,28 +66,28 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t start, end = TARGET_PAGE_ALIGN(start + length); start &= TARGET_PAGE_MASK; for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { - ret |= cpu_physical_memory_get_dirty_flag(addr, dirty_flag); + ret |= cpu_physical_memory_get_dirty_flag(addr, client); } return ret; } static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr, - int dirty_flag) + unsigned client) { - ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flag; + ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= (1 << client); } static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) { - cpu_physical_memory_set_dirty_flag(addr, MIGRATION_DIRTY_FLAG); - cpu_physical_memory_set_dirty_flag(addr, VGA_DIRTY_FLAG); - cpu_physical_memory_set_dirty_flag(addr, CODE_DIRTY_FLAG); + cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_MIGRATION); + cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_VGA); + cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_CODE); } -static inline int cpu_physical_memory_clear_dirty_flags(ram_addr_t addr, - int dirty_flags) +static inline int cpu_physical_memory_clear_dirty_flag(ram_addr_t addr, + unsigned client) { - int mask = ~dirty_flags; + int mask = ~(1 << client); return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] &= mask; } @@ -111,19 +107,19 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start, ram_addr_t length, - int dirty_flags) + unsigned client) { ram_addr_t addr, end; end = TARGET_PAGE_ALIGN(start + length); start &= TARGET_PAGE_MASK; for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { - cpu_physical_memory_clear_dirty_flags(addr, dirty_flags); + cpu_physical_memory_clear_dirty_flag(addr, client); } } void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, - int dirty_flags); + unsigned client); #endif diff --git a/include/exec/memory.h b/include/exec/memory.h index 480dfbf9da..b8e76f44b3 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -33,9 +33,6 @@ typedef struct MemoryRegionOps MemoryRegionOps; typedef struct MemoryRegionMmio MemoryRegionMmio; -/* Must match *_DIRTY_FLAGS in cpu-all.h. To be replaced with dynamic - * registration. - */ #define DIRTY_MEMORY_VGA 0 #define DIRTY_MEMORY_CODE 1 #define DIRTY_MEMORY_MIGRATION 3 diff --git a/memory.c b/memory.c index fb52e1cdb2..a490cbd667 100644 --- a/memory.c +++ b/memory.c @@ -1174,8 +1174,7 @@ bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr, hwaddr size, unsigned client) { assert(mr->terminates); - return cpu_physical_memory_get_dirty(mr->ram_addr + addr, size, - 1 << client); + return cpu_physical_memory_get_dirty(mr->ram_addr + addr, size, client); } void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr, @@ -1190,12 +1189,11 @@ bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr, { bool ret; assert(mr->terminates); - ret = cpu_physical_memory_get_dirty(mr->ram_addr + addr, size, - 1 << client); + ret = cpu_physical_memory_get_dirty(mr->ram_addr + addr, size, client); if (ret) { cpu_physical_memory_reset_dirty(mr->ram_addr + addr, mr->ram_addr + addr + size, - 1 << client); + client); } return ret; } @@ -1243,7 +1241,7 @@ void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr, assert(mr->terminates); cpu_physical_memory_reset_dirty(mr->ram_addr + addr, mr->ram_addr + addr + size, - 1 << client); + client); } void *memory_region_get_ram_ptr(MemoryRegion *mr) -- cgit v1.2.3-55-g7522 From 5adca7ace9b80bf594e4c52c0d5b23573cba3639 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 13:26:29 +0200 Subject: memory: use bit 2 for migration For historical reasons it was bit 3. Once there, create a constant to know the number of clients. Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- include/exec/memory.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/exec') diff --git a/include/exec/memory.h b/include/exec/memory.h index b8e76f44b3..d5e9d58102 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -35,7 +35,8 @@ typedef struct MemoryRegionMmio MemoryRegionMmio; #define DIRTY_MEMORY_VGA 0 #define DIRTY_MEMORY_CODE 1 -#define DIRTY_MEMORY_MIGRATION 3 +#define DIRTY_MEMORY_MIGRATION 2 +#define DIRTY_MEMORY_NUM 3 /* num of dirty bits */ struct MemoryRegionMmio { CPUReadMemoryFunc *read[3]; -- cgit v1.2.3-55-g7522 From 7a5b558c9d061814f34d9b95d70d17ef75037937 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 13:29:11 +0200 Subject: memory: make sure that client is always inside range Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- include/exec/memory-internal.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/exec') diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index b58010f1d0..d09d6d8355 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -43,6 +43,7 @@ void qemu_ram_free_from_ptr(ram_addr_t addr); static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr, unsigned client) { + assert(client < DIRTY_MEMORY_NUM); return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & (1 << client); } @@ -74,6 +75,7 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t start, static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr, unsigned client) { + assert(client < DIRTY_MEMORY_NUM); ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= (1 << client); } @@ -89,6 +91,8 @@ static inline int cpu_physical_memory_clear_dirty_flag(ram_addr_t addr, { int mask = ~(1 << client); + assert(client < DIRTY_MEMORY_NUM); + return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] &= mask; } -- cgit v1.2.3-55-g7522 From e8a97cafc4108fa964807eb9cbce7eda698f99bb Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 15:50:55 +0200 Subject: memory: cpu_physical_memory_clear_dirty_flag() result is never used Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- include/exec/memory-internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/exec') diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index d09d6d8355..666490cc1c 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -86,14 +86,14 @@ static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_CODE); } -static inline int cpu_physical_memory_clear_dirty_flag(ram_addr_t addr, +static inline void cpu_physical_memory_clear_dirty_flag(ram_addr_t addr, unsigned client) { int mask = ~(1 << client); assert(client < DIRTY_MEMORY_NUM); - return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] &= mask; + ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] &= mask; } static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, -- cgit v1.2.3-55-g7522 From 1ab4c8ceaa5ec55af9bb25e88e46d461a8550280 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 16:14:39 +0200 Subject: memory: split dirty bitmap into three After all the previous patches, spliting the bitmap gets direct. Note: For some reason, I have to move DIRTY_MEMORY_* definitions to the beginning of memory.h to make compilation work. Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- exec.c | 9 ++++++--- include/exec/cpu-all.h | 3 ++- include/exec/memory-internal.h | 9 +++------ include/exec/memory.h | 10 +++++----- 4 files changed, 16 insertions(+), 15 deletions(-) (limited to 'include/exec') diff --git a/exec.c b/exec.c index db369dc42f..028eee4f59 100644 --- a/exec.c +++ b/exec.c @@ -1277,9 +1277,12 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, new_ram_size = last_ram_offset() >> TARGET_PAGE_BITS; if (new_ram_size > old_ram_size) { - ram_list.phys_dirty = g_realloc(ram_list.phys_dirty, new_ram_size); - memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS), - 0, size >> TARGET_PAGE_BITS); + int i; + for (i = 0; i < DIRTY_MEMORY_NUM; i++) { + ram_list.dirty_memory[i] = + bitmap_zero_extend(ram_list.dirty_memory[i], + old_ram_size, new_ram_size); + } } cpu_physical_memory_set_dirty_range(new_block->offset, size); diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index b6998f055a..4cb4b4a53a 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -21,6 +21,7 @@ #include "qemu-common.h" #include "exec/cpu-common.h" +#include "exec/memory.h" #include "qemu/thread.h" #include "qom/cpu.h" @@ -459,7 +460,7 @@ typedef struct RAMBlock { typedef struct RAMList { QemuMutex mutex; /* Protected by the iothread lock. */ - uint8_t *phys_dirty; + unsigned long *dirty_memory[DIRTY_MEMORY_NUM]; RAMBlock *mru_block; /* Protected by the ramlist lock. */ QTAILQ_HEAD(, RAMBlock) blocks; diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 666490cc1c..6fb1b64410 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -44,7 +44,7 @@ static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr, unsigned client) { assert(client < DIRTY_MEMORY_NUM); - return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & (1 << client); + return test_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]); } /* read dirty bit (return 0 or 1) */ @@ -76,7 +76,7 @@ static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr, unsigned client) { assert(client < DIRTY_MEMORY_NUM); - ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= (1 << client); + set_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]); } static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) @@ -89,11 +89,8 @@ static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) static inline void cpu_physical_memory_clear_dirty_flag(ram_addr_t addr, unsigned client) { - int mask = ~(1 << client); - assert(client < DIRTY_MEMORY_NUM); - - ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] &= mask; + clear_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]); } static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, diff --git a/include/exec/memory.h b/include/exec/memory.h index d5e9d58102..296d6ab2f4 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -16,6 +16,11 @@ #ifndef CONFIG_USER_ONLY +#define DIRTY_MEMORY_VGA 0 +#define DIRTY_MEMORY_CODE 1 +#define DIRTY_MEMORY_MIGRATION 2 +#define DIRTY_MEMORY_NUM 3 /* num of dirty bits */ + #include #include #include "qemu-common.h" @@ -33,11 +38,6 @@ typedef struct MemoryRegionOps MemoryRegionOps; typedef struct MemoryRegionMmio MemoryRegionMmio; -#define DIRTY_MEMORY_VGA 0 -#define DIRTY_MEMORY_CODE 1 -#define DIRTY_MEMORY_MIGRATION 2 -#define DIRTY_MEMORY_NUM 3 /* num of dirty bits */ - struct MemoryRegionMmio { CPUReadMemoryFunc *read[3]; CPUWriteMemoryFunc *write[3]; -- cgit v1.2.3-55-g7522 From 86a49582dbe66d59a9366d2f002f0d6af965ecb8 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 20:21:10 +0200 Subject: memory: unfold cpu_physical_memory_clear_dirty_flag() in its only user Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- include/exec/memory-internal.h | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'include/exec') diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 6fb1b64410..2f6610a464 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -86,13 +86,6 @@ static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_CODE); } -static inline void cpu_physical_memory_clear_dirty_flag(ram_addr_t addr, - unsigned client) -{ - assert(client < DIRTY_MEMORY_NUM); - clear_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]); -} - static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, ram_addr_t length) { @@ -112,10 +105,11 @@ static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start, { ram_addr_t addr, end; + assert(client < DIRTY_MEMORY_NUM); end = TARGET_PAGE_ALIGN(start + length); start &= TARGET_PAGE_MASK; for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { - cpu_physical_memory_clear_dirty_flag(addr, client); + clear_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]); } } -- cgit v1.2.3-55-g7522 From 4f13bb80a2dc1bb851b43da6dd9117473772b197 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 20:25:16 +0200 Subject: memory: unfold cpu_physical_memory_set_dirty() in its only user Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- include/exec/memory-internal.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'include/exec') diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 2f6610a464..9d344342e4 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -79,13 +79,6 @@ static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr, set_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]); } -static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) -{ - cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_MIGRATION); - cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_VGA); - cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_CODE); -} - static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, ram_addr_t length) { @@ -94,7 +87,9 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, end = TARGET_PAGE_ALIGN(start + length); start &= TARGET_PAGE_MASK; for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { - cpu_physical_memory_set_dirty(addr); + cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_MIGRATION); + cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_VGA); + cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_CODE); } xen_modified_memory(addr, length); } -- cgit v1.2.3-55-g7522 From c1427a3f84c42d5159d10927700eafc9b653d68f Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 20:27:58 +0200 Subject: memory: unfold cpu_physical_memory_set_dirty_flag() Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- include/exec/memory-internal.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'include/exec') diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 9d344342e4..b99617a500 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -87,9 +87,12 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, end = TARGET_PAGE_ALIGN(start + length); start &= TARGET_PAGE_MASK; for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { - cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_MIGRATION); - cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_VGA); - cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_CODE); + set_bit(addr >> TARGET_PAGE_BITS, + ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION]); + set_bit(addr >> TARGET_PAGE_BITS, + ram_list.dirty_memory[DIRTY_MEMORY_VGA]); + set_bit(addr >> TARGET_PAGE_BITS, + ram_list.dirty_memory[DIRTY_MEMORY_CODE]); } xen_modified_memory(addr, length); } -- cgit v1.2.3-55-g7522 From 9f2c43e41a13605d3ab1e37ba433aa669652fb6b Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 20:35:39 +0200 Subject: memory: make cpu_physical_memory_get_dirty() the main function And make cpu_physical_memory_get_dirty_flag() to use it. It used to be the other way around. Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- include/exec/memory-internal.h | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'include/exec') diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index b99617a500..edca8a87ce 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -40,11 +40,28 @@ void *qemu_get_ram_ptr(ram_addr_t addr); void qemu_ram_free(ram_addr_t addr); void qemu_ram_free_from_ptr(ram_addr_t addr); +static inline int cpu_physical_memory_get_dirty(ram_addr_t start, + ram_addr_t length, + unsigned client) +{ + int ret = 0; + ram_addr_t addr, end; + + assert(client < DIRTY_MEMORY_NUM); + + end = TARGET_PAGE_ALIGN(start + length); + start &= TARGET_PAGE_MASK; + for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { + ret |= test_bit(addr >> TARGET_PAGE_BITS, + ram_list.dirty_memory[client]); + } + return ret; +} + static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr, unsigned client) { - assert(client < DIRTY_MEMORY_NUM); - return test_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]); + return cpu_physical_memory_get_dirty(addr, 1, client); } /* read dirty bit (return 0 or 1) */ @@ -57,21 +74,6 @@ static inline bool cpu_physical_memory_is_dirty(ram_addr_t addr) return vga && code && migration; } -static inline int cpu_physical_memory_get_dirty(ram_addr_t start, - ram_addr_t length, - unsigned client) -{ - int ret = 0; - ram_addr_t addr, end; - - end = TARGET_PAGE_ALIGN(start + length); - start &= TARGET_PAGE_MASK; - for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { - ret |= cpu_physical_memory_get_dirty_flag(addr, client); - } - return ret; -} - static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr, unsigned client) { -- cgit v1.2.3-55-g7522 From 94833c896d2d339571a66542f2715b1897d70fa7 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 8 Oct 2013 20:40:55 +0200 Subject: memory: cpu_physical_memory_get_dirty() is used as returning a bool Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- include/exec/memory-internal.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'include/exec') diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index edca8a87ce..fa28fc677d 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -40,11 +40,10 @@ void *qemu_get_ram_ptr(ram_addr_t addr); void qemu_ram_free(ram_addr_t addr); void qemu_ram_free_from_ptr(ram_addr_t addr); -static inline int cpu_physical_memory_get_dirty(ram_addr_t start, - ram_addr_t length, - unsigned client) +static inline bool cpu_physical_memory_get_dirty(ram_addr_t start, + ram_addr_t length, + unsigned client) { - int ret = 0; ram_addr_t addr, end; assert(client < DIRTY_MEMORY_NUM); @@ -52,10 +51,12 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t start, end = TARGET_PAGE_ALIGN(start + length); start &= TARGET_PAGE_MASK; for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { - ret |= test_bit(addr >> TARGET_PAGE_BITS, - ram_list.dirty_memory[client]); + if (test_bit(addr >> TARGET_PAGE_BITS, + ram_list.dirty_memory[client])) { + return true; + } } - return ret; + return false; } static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr, -- cgit v1.2.3-55-g7522 From ace694cccccf343852d9f0b34171ad475e248bbf Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 9 Oct 2013 10:36:56 +0200 Subject: memory: s/mask/clear/ cpu_physical_memory_mask_dirty_range Now all functions use the same wording that bitops/bitmap operations Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- exec.c | 2 +- include/exec/memory-internal.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include/exec') diff --git a/exec.c b/exec.c index 028eee4f59..9267596c05 100644 --- a/exec.c +++ b/exec.c @@ -748,7 +748,7 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, length = end - start; if (length == 0) return; - cpu_physical_memory_mask_dirty_range(start, length, client); + cpu_physical_memory_clear_dirty_range(start, length, client); if (tcg_enabled()) { tlb_reset_dirty_range_all(start, end, length); diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index fa28fc677d..c04a92a2d9 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -100,9 +100,9 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, xen_modified_memory(addr, length); } -static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start, - ram_addr_t length, - unsigned client) +static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, + ram_addr_t length, + unsigned client) { ram_addr_t addr, end; -- cgit v1.2.3-55-g7522 From 1bafff0c7cb99972fd243464632eca0780c6a8f1 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 9 Oct 2013 12:15:06 +0200 Subject: memory: use find_next_bit() to find dirty bits This operation is way faster than doing it bit by bit. Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- include/exec/memory-internal.h | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'include/exec') diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index c04a92a2d9..b017c2ec98 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -44,19 +44,15 @@ static inline bool cpu_physical_memory_get_dirty(ram_addr_t start, ram_addr_t length, unsigned client) { - ram_addr_t addr, end; + unsigned long end, page, next; assert(client < DIRTY_MEMORY_NUM); - end = TARGET_PAGE_ALIGN(start + length); - start &= TARGET_PAGE_MASK; - for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { - if (test_bit(addr >> TARGET_PAGE_BITS, - ram_list.dirty_memory[client])) { - return true; - } - } - return false; + end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; + page = start >> TARGET_PAGE_BITS; + next = find_next_bit(ram_list.dirty_memory[client], end, page); + + return next < end; } static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr, -- cgit v1.2.3-55-g7522 From 5b9a3a5f77e3458af6c1bb0654ee0f32936a5594 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 9 Oct 2013 12:26:23 +0200 Subject: memory: cpu_physical_memory_set_dirty_range() now uses bitmap operations We were setting a range of bits, so use bitmap_set(). Note: xen has always been wrong, and should have used start instead of addr from the beginning. Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- include/exec/memory-internal.h | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'include/exec') diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index b017c2ec98..4906cdf0ea 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -81,19 +81,14 @@ static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr, static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, ram_addr_t length) { - ram_addr_t addr, end; + unsigned long end, page; - end = TARGET_PAGE_ALIGN(start + length); - start &= TARGET_PAGE_MASK; - for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { - set_bit(addr >> TARGET_PAGE_BITS, - ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION]); - set_bit(addr >> TARGET_PAGE_BITS, - ram_list.dirty_memory[DIRTY_MEMORY_VGA]); - set_bit(addr >> TARGET_PAGE_BITS, - ram_list.dirty_memory[DIRTY_MEMORY_CODE]); - } - xen_modified_memory(addr, length); + end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; + page = start >> TARGET_PAGE_BITS; + bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION], page, end - page); + bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_VGA], page, end - page); + bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_CODE], page, end - page); + xen_modified_memory(start, length); } static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, -- cgit v1.2.3-55-g7522 From a461e389f489e72cdc770ff887512c2c9109bc43 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 9 Oct 2013 12:30:35 +0200 Subject: memory: cpu_physical_memory_clear_dirty_range() now uses bitmap operations We were clearing a range of bits, so use bitmap_clear(). Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- include/exec/memory-internal.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'include/exec') diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 4906cdf0ea..e2f55eaeb1 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -95,14 +95,12 @@ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, ram_addr_t length, unsigned client) { - ram_addr_t addr, end; + unsigned long end, page; assert(client < DIRTY_MEMORY_NUM); - end = TARGET_PAGE_ALIGN(start + length); - start &= TARGET_PAGE_MASK; - for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { - clear_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]); - } + end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; + page = start >> TARGET_PAGE_BITS; + bitmap_clear(ram_list.dirty_memory[client], page, end - page); } void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, -- cgit v1.2.3-55-g7522 From a2cd8c852d2d8c2a084b68b2470f214d6726f6d2 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Thu, 10 Oct 2013 11:20:22 +0200 Subject: memory: s/dirty/clean/ in cpu_physical_memory_is_dirty() All uses except one really want the other meaning. Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- cputlb.c | 3 ++- exec.c | 6 +++--- include/exec/memory-internal.h | 5 ++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'include/exec') diff --git a/cputlb.c b/cputlb.c index ec2140580b..eab91d7b5e 100644 --- a/cputlb.c +++ b/cputlb.c @@ -284,7 +284,8 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr, /* Write access calls the I/O callback. */ te->addr_write = address | TLB_MMIO; } else if (memory_region_is_ram(section->mr) - && !cpu_physical_memory_is_dirty(section->mr->ram_addr + xlat)) { + && cpu_physical_memory_is_clean(section->mr->ram_addr + + xlat)) { te->addr_write = address | TLB_NOTDIRTY; } else { te->addr_write = address; diff --git a/exec.c b/exec.c index 9267596c05..47add21303 100644 --- a/exec.c +++ b/exec.c @@ -1514,7 +1514,7 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr, cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_VGA); /* we remove the notdirty callback only if the code has been flushed */ - if (cpu_physical_memory_is_dirty(ram_addr)) { + if (!cpu_physical_memory_is_clean(ram_addr)) { CPUArchState *env = current_cpu->env_ptr; tlb_set_dirty(env, env->mem_io_vaddr); } @@ -1917,7 +1917,7 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr, static void invalidate_and_set_dirty(hwaddr addr, hwaddr length) { - if (!cpu_physical_memory_is_dirty(addr)) { + if (cpu_physical_memory_is_clean(addr)) { /* invalidate code */ tb_invalidate_phys_page_range(addr, addr + length, 0); /* set dirty bit */ @@ -2533,7 +2533,7 @@ void stl_phys_notdirty(hwaddr addr, uint32_t val) stl_p(ptr, val); if (unlikely(in_migration)) { - if (!cpu_physical_memory_is_dirty(addr1)) { + if (cpu_physical_memory_is_clean(addr1)) { /* invalidate code */ tb_invalidate_phys_page_range(addr1, addr1 + 4, 0); /* set dirty bit */ diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index e2f55eaeb1..771b23f321 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -61,14 +61,13 @@ static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr, return cpu_physical_memory_get_dirty(addr, 1, client); } -/* read dirty bit (return 0 or 1) */ -static inline bool cpu_physical_memory_is_dirty(ram_addr_t addr) +static inline bool cpu_physical_memory_is_clean(ram_addr_t addr) { bool vga = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_VGA); bool code = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_CODE); bool migration = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_MIGRATION); - return vga && code && migration; + return !(vga && code && migration); } static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr, -- cgit v1.2.3-55-g7522 From a2f4d5bef2cfde557d76fc45a40d2c89b6bed4e4 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Thu, 10 Oct 2013 11:49:53 +0200 Subject: memory: make cpu_physical_memory_reset_dirty() take a length parameter We have an end parameter in all the callers, and this make it coherent with the rest of cpu_physical_memory_* functions, that also take a length parameter. Once here, move the start/end calculation to tlb_reset_dirty_range_all() as we don't need it here anymore. Signed-off-by: Juan Quintela Reviewed-by: Eric Blake Reviewed-by: Orit Wasserman --- cputlb.c | 3 +-- exec.c | 19 ++++++++----------- include/exec/memory-internal.h | 2 +- memory.c | 8 ++------ 4 files changed, 12 insertions(+), 20 deletions(-) (limited to 'include/exec') diff --git a/cputlb.c b/cputlb.c index eab91d7b5e..0ac8d90a48 100644 --- a/cputlb.c +++ b/cputlb.c @@ -112,8 +112,7 @@ void tlb_flush_page(CPUArchState *env, target_ulong addr) can be detected */ void tlb_protect_code(ram_addr_t ram_addr) { - cpu_physical_memory_reset_dirty(ram_addr, - ram_addr + TARGET_PAGE_SIZE, + cpu_physical_memory_reset_dirty(ram_addr, TARGET_PAGE_SIZE, DIRTY_MEMORY_CODE); } diff --git a/exec.c b/exec.c index 47add21303..c71f2d558a 100644 --- a/exec.c +++ b/exec.c @@ -724,11 +724,14 @@ found: return block; } -static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t end, - uintptr_t length) +static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t length) { - RAMBlock *block; ram_addr_t start1; + RAMBlock *block; + ram_addr_t end; + + end = TARGET_PAGE_ALIGN(start + length); + start &= TARGET_PAGE_MASK; block = qemu_get_ram_block(start); assert(block == qemu_get_ram_block(end - 1)); @@ -737,21 +740,15 @@ static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t end, } /* Note: start and end must be within the same ram block. */ -void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, +void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t length, unsigned client) { - uintptr_t length; - - start &= TARGET_PAGE_MASK; - end = TARGET_PAGE_ALIGN(end); - - length = end - start; if (length == 0) return; cpu_physical_memory_clear_dirty_range(start, length, client); if (tcg_enabled()) { - tlb_reset_dirty_range_all(start, end, length); + tlb_reset_dirty_range_all(start, length); } } diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 771b23f321..cb2249fd0b 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -102,7 +102,7 @@ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, bitmap_clear(ram_list.dirty_memory[client], page, end - page); } -void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, +void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t length, unsigned client); #endif diff --git a/memory.c b/memory.c index a490cbd667..c01029633e 100644 --- a/memory.c +++ b/memory.c @@ -1191,9 +1191,7 @@ bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr, assert(mr->terminates); ret = cpu_physical_memory_get_dirty(mr->ram_addr + addr, size, client); if (ret) { - cpu_physical_memory_reset_dirty(mr->ram_addr + addr, - mr->ram_addr + addr + size, - client); + cpu_physical_memory_reset_dirty(mr->ram_addr + addr, size, client); } return ret; } @@ -1239,9 +1237,7 @@ void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr, hwaddr size, unsigned client) { assert(mr->terminates); - cpu_physical_memory_reset_dirty(mr->ram_addr + addr, - mr->ram_addr + addr + size, - client); + cpu_physical_memory_reset_dirty(mr->ram_addr + addr, size, client); } void *memory_region_get_ram_ptr(MemoryRegion *mr) -- cgit v1.2.3-55-g7522 From 220c3ebddbd1ac289ae7fc64733c9501b3921d94 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Mon, 14 Oct 2013 17:13:59 +0200 Subject: memory: split cpu_physical_memory_* functions to its own include All the functions that use ram_addr_t should be here. Signed-off-by: Juan Quintela Reviewed-by: Orit Wasserman --- cputlb.c | 1 + exec.c | 1 + include/exec/memory-internal.h | 76 -------------------------------- include/exec/ram_addr.h | 98 ++++++++++++++++++++++++++++++++++++++++++ memory.c | 1 + 5 files changed, 101 insertions(+), 76 deletions(-) create mode 100644 include/exec/ram_addr.h (limited to 'include/exec') diff --git a/cputlb.c b/cputlb.c index 0ac8d90a48..b533f3f372 100644 --- a/cputlb.c +++ b/cputlb.c @@ -26,6 +26,7 @@ #include "exec/cputlb.h" #include "exec/memory-internal.h" +#include "exec/ram_addr.h" //#define DEBUG_TLB //#define DEBUG_TLB_CHECK diff --git a/exec.c b/exec.c index 514d6a08cc..b387d2856d 100644 --- a/exec.c +++ b/exec.c @@ -50,6 +50,7 @@ #include "translate-all.h" #include "exec/memory-internal.h" +#include "exec/ram_addr.h" #include "qemu/cache-utils.h" #include "qemu/range.h" diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index cb2249fd0b..25c43c06e9 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -20,9 +20,6 @@ #define MEMORY_INTERNAL_H #ifndef CONFIG_USER_ONLY -#include "hw/xen/xen.h" - - typedef struct AddressSpaceDispatch AddressSpaceDispatch; void address_space_init_dispatch(AddressSpace *as); @@ -33,78 +30,5 @@ extern const MemoryRegionOps unassigned_mem_ops; bool memory_region_access_valid(MemoryRegion *mr, hwaddr addr, unsigned size, bool is_write); -ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, - MemoryRegion *mr); -ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr); -void *qemu_get_ram_ptr(ram_addr_t addr); -void qemu_ram_free(ram_addr_t addr); -void qemu_ram_free_from_ptr(ram_addr_t addr); - -static inline bool cpu_physical_memory_get_dirty(ram_addr_t start, - ram_addr_t length, - unsigned client) -{ - unsigned long end, page, next; - - assert(client < DIRTY_MEMORY_NUM); - - end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; - page = start >> TARGET_PAGE_BITS; - next = find_next_bit(ram_list.dirty_memory[client], end, page); - - return next < end; -} - -static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr, - unsigned client) -{ - return cpu_physical_memory_get_dirty(addr, 1, client); -} - -static inline bool cpu_physical_memory_is_clean(ram_addr_t addr) -{ - bool vga = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_VGA); - bool code = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_CODE); - bool migration = - cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_MIGRATION); - return !(vga && code && migration); -} - -static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr, - unsigned client) -{ - assert(client < DIRTY_MEMORY_NUM); - set_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]); -} - -static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, - ram_addr_t length) -{ - unsigned long end, page; - - end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; - page = start >> TARGET_PAGE_BITS; - bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION], page, end - page); - bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_VGA], page, end - page); - bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_CODE], page, end - page); - xen_modified_memory(start, length); -} - -static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, - ram_addr_t length, - unsigned client) -{ - unsigned long end, page; - - assert(client < DIRTY_MEMORY_NUM); - end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; - page = start >> TARGET_PAGE_BITS; - bitmap_clear(ram_list.dirty_memory[client], page, end - page); -} - -void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t length, - unsigned client); - #endif - #endif diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h new file mode 100644 index 0000000000..db977fbdae --- /dev/null +++ b/include/exec/ram_addr.h @@ -0,0 +1,98 @@ +/* + * Declarations for cpu physical memory functions + * + * Copyright 2011 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Avi Kivity + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + * + */ + +/* + * This header is for use by exec.c and memory.c ONLY. Do not include it. + * The functions declared here will be removed soon. + */ + +#ifndef RAM_ADDR_H +#define RAM_ADDR_H + +#ifndef CONFIG_USER_ONLY +#include "hw/xen/xen.h" + +ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, + MemoryRegion *mr); +ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr); +void *qemu_get_ram_ptr(ram_addr_t addr); +void qemu_ram_free(ram_addr_t addr); +void qemu_ram_free_from_ptr(ram_addr_t addr); + +static inline bool cpu_physical_memory_get_dirty(ram_addr_t start, + ram_addr_t length, + unsigned client) +{ + unsigned long end, page, next; + + assert(client < DIRTY_MEMORY_NUM); + + end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; + page = start >> TARGET_PAGE_BITS; + next = find_next_bit(ram_list.dirty_memory[client], end, page); + + return next < end; +} + +static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr, + unsigned client) +{ + return cpu_physical_memory_get_dirty(addr, 1, client); +} + +static inline bool cpu_physical_memory_is_clean(ram_addr_t addr) +{ + bool vga = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_VGA); + bool code = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_CODE); + bool migration = + cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_MIGRATION); + return !(vga && code && migration); +} + +static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr, + unsigned client) +{ + assert(client < DIRTY_MEMORY_NUM); + set_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]); +} + +static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, + ram_addr_t length) +{ + unsigned long end, page; + + end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; + page = start >> TARGET_PAGE_BITS; + bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION], page, end - page); + bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_VGA], page, end - page); + bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_CODE], page, end - page); + xen_modified_memory(start, length); +} + +static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, + ram_addr_t length, + unsigned client) +{ + unsigned long end, page; + + assert(client < DIRTY_MEMORY_NUM); + end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; + page = start >> TARGET_PAGE_BITS; + bitmap_clear(ram_list.dirty_memory[client], page, end - page); +} + +void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t length, + unsigned client); + +#endif +#endif diff --git a/memory.c b/memory.c index c01029633e..59ecc28401 100644 --- a/memory.c +++ b/memory.c @@ -22,6 +22,7 @@ #include #include "exec/memory-internal.h" +#include "exec/ram_addr.h" //#define DEBUG_UNASSIGNED -- cgit v1.2.3-55-g7522 From 5ff7fb77b3cee8e26648e4fdccb23a77c2a6d3c6 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 5 Nov 2013 15:52:54 +0100 Subject: memory: move bitmap synchronization to its own function We want to have all the functions that handle directly the dirty bitmap near. We will change it later. Signed-off-by: Juan Quintela Reviewed-by: Orit Wasserman --- include/exec/ram_addr.h | 31 +++++++++++++++++++++++++++++++ kvm-all.c | 27 ++------------------------- 2 files changed, 33 insertions(+), 25 deletions(-) (limited to 'include/exec') diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index db977fbdae..c6736ed04f 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -79,6 +79,37 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, xen_modified_memory(start, length); } +static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap, + ram_addr_t start, + ram_addr_t pages) +{ + unsigned int i, j; + unsigned long page_number, c; + hwaddr addr; + ram_addr_t ram_addr; + unsigned int len = (pages + HOST_LONG_BITS - 1) / HOST_LONG_BITS; + unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE; + + /* + * bitmap-traveling is faster than memory-traveling (for addr...) + * especially when most of the memory is not dirty. + */ + for (i = 0; i < len; i++) { + if (bitmap[i] != 0) { + c = leul_to_cpu(bitmap[i]); + do { + j = ffsl(c) - 1; + c &= ~(1ul << j); + page_number = (i * HOST_LONG_BITS + j) * hpratio; + addr = page_number * TARGET_PAGE_SIZE; + ram_addr = start + addr; + cpu_physical_memory_set_dirty_range(ram_addr, + TARGET_PAGE_SIZE * hpratio); + } while (c != 0); + } + } +} + static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, ram_addr_t length, unsigned client) diff --git a/kvm-all.c b/kvm-all.c index cb62ba4333..0bfb060fa7 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -380,33 +380,10 @@ static int kvm_set_migration_log(int enable) static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section, unsigned long *bitmap) { - unsigned int i, j; - unsigned long page_number, c; - hwaddr addr; ram_addr_t start = section->offset_within_region + section->mr->ram_addr; - ram_addr_t ram_addr; - unsigned int pages = int128_get64(section->size) / getpagesize(); - unsigned int len = (pages + HOST_LONG_BITS - 1) / HOST_LONG_BITS; - unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE; + ram_addr_t pages = int128_get64(section->size) / getpagesize(); - /* - * bitmap-traveling is faster than memory-traveling (for addr...) - * especially when most of the memory is not dirty. - */ - for (i = 0; i < len; i++) { - if (bitmap[i] != 0) { - c = leul_to_cpu(bitmap[i]); - do { - j = ffsl(c) - 1; - c &= ~(1ul << j); - page_number = (i * HOST_LONG_BITS + j) * hpratio; - addr = page_number * TARGET_PAGE_SIZE; - ram_addr = start + addr; - cpu_physical_memory_set_dirty_range(ram_addr, - TARGET_PAGE_SIZE * hpratio); - } while (c != 0); - } - } + cpu_physical_memory_set_dirty_lebitmap(bitmap, start, pages); return 0; } -- cgit v1.2.3-55-g7522 From ae2810c4bb3b383176e8e1b33931b16c01483aab Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 5 Nov 2013 16:46:26 +0100 Subject: memory: syncronize kvm bitmap using bitmaps operations If bitmaps are aligned properly, use bitmap operations. If they are not, just use old bit at a time code. Signed-off-by: Juan Quintela Reviewed-by: Orit Wasserman --- include/exec/ram_addr.h | 54 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 18 deletions(-) (limited to 'include/exec') diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index c6736ed04f..33c8acc02e 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -83,29 +83,47 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap, ram_addr_t start, ram_addr_t pages) { - unsigned int i, j; + unsigned long i, j; unsigned long page_number, c; hwaddr addr; ram_addr_t ram_addr; - unsigned int len = (pages + HOST_LONG_BITS - 1) / HOST_LONG_BITS; + unsigned long len = (pages + HOST_LONG_BITS - 1) / HOST_LONG_BITS; unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE; + unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS); - /* - * bitmap-traveling is faster than memory-traveling (for addr...) - * especially when most of the memory is not dirty. - */ - for (i = 0; i < len; i++) { - if (bitmap[i] != 0) { - c = leul_to_cpu(bitmap[i]); - do { - j = ffsl(c) - 1; - c &= ~(1ul << j); - page_number = (i * HOST_LONG_BITS + j) * hpratio; - addr = page_number * TARGET_PAGE_SIZE; - ram_addr = start + addr; - cpu_physical_memory_set_dirty_range(ram_addr, - TARGET_PAGE_SIZE * hpratio); - } while (c != 0); + /* start address is aligned at the start of a word? */ + if (((page * BITS_PER_LONG) << TARGET_PAGE_BITS) == start) { + long k; + long nr = BITS_TO_LONGS(pages); + + for (k = 0; k < nr; k++) { + if (bitmap[k]) { + unsigned long temp = leul_to_cpu(bitmap[k]); + + ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION][page + k] |= temp; + ram_list.dirty_memory[DIRTY_MEMORY_VGA][page + k] |= temp; + ram_list.dirty_memory[DIRTY_MEMORY_CODE][page + k] |= temp; + } + } + xen_modified_memory(start, pages); + } else { + /* + * bitmap-traveling is faster than memory-traveling (for addr...) + * especially when most of the memory is not dirty. + */ + for (i = 0; i < len; i++) { + if (bitmap[i] != 0) { + c = leul_to_cpu(bitmap[i]); + do { + j = ffsl(c) - 1; + c &= ~(1ul << j); + page_number = (i * HOST_LONG_BITS + j) * hpratio; + addr = page_number * TARGET_PAGE_SIZE; + ram_addr = start + addr; + cpu_physical_memory_set_dirty_range(ram_addr, + TARGET_PAGE_SIZE * hpratio); + } while (c != 0); + } } } } -- cgit v1.2.3-55-g7522