diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 9850e831..eacde623 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -296,6 +296,7 @@ #define cpu_physical_memory_rw cpu_physical_memory_rw_aarch64 #define cpu_physical_memory_set_dirty_flag cpu_physical_memory_set_dirty_flag_aarch64 #define cpu_physical_memory_set_dirty_range cpu_physical_memory_set_dirty_range_aarch64 +#define cpu_physical_memory_test_and_clear_dirty cpu_physical_memory_test_and_clear_dirty_aarch64 #define cpu_physical_memory_unmap cpu_physical_memory_unmap_aarch64 #define cpu_physical_memory_write_rom cpu_physical_memory_write_rom_aarch64 #define cpu_physical_memory_write_rom_internal cpu_physical_memory_write_rom_internal_aarch64 @@ -2095,6 +2096,7 @@ #define memory_region_set_readonly memory_region_set_readonly_aarch64 #define memory_region_set_skip_dump memory_region_set_skip_dump_aarch64 #define memory_region_size memory_region_size_aarch64 +#define memory_region_test_and_clear_dirty memory_region_test_and_clear_dirty_aarch64 #define memory_region_to_address_space memory_region_to_address_space_aarch64 #define memory_region_transaction_begin memory_region_transaction_begin_aarch64 #define memory_region_transaction_commit memory_region_transaction_commit_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index 63a1b4d5..364cbbc9 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -296,6 +296,7 @@ #define cpu_physical_memory_rw cpu_physical_memory_rw_aarch64eb #define cpu_physical_memory_set_dirty_flag cpu_physical_memory_set_dirty_flag_aarch64eb #define cpu_physical_memory_set_dirty_range cpu_physical_memory_set_dirty_range_aarch64eb +#define cpu_physical_memory_test_and_clear_dirty cpu_physical_memory_test_and_clear_dirty_aarch64eb #define cpu_physical_memory_unmap cpu_physical_memory_unmap_aarch64eb #define cpu_physical_memory_write_rom cpu_physical_memory_write_rom_aarch64eb #define cpu_physical_memory_write_rom_internal cpu_physical_memory_write_rom_internal_aarch64eb @@ -2095,6 +2096,7 @@ #define memory_region_set_readonly memory_region_set_readonly_aarch64eb #define memory_region_set_skip_dump memory_region_set_skip_dump_aarch64eb #define memory_region_size memory_region_size_aarch64eb +#define memory_region_test_and_clear_dirty memory_region_test_and_clear_dirty_aarch64eb #define memory_region_to_address_space memory_region_to_address_space_aarch64eb #define memory_region_transaction_begin memory_region_transaction_begin_aarch64eb #define memory_region_transaction_commit memory_region_transaction_commit_aarch64eb diff --git a/qemu/arm.h b/qemu/arm.h index 44f0b212..d789bfa3 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -296,6 +296,7 @@ #define cpu_physical_memory_rw cpu_physical_memory_rw_arm #define cpu_physical_memory_set_dirty_flag cpu_physical_memory_set_dirty_flag_arm #define cpu_physical_memory_set_dirty_range cpu_physical_memory_set_dirty_range_arm +#define cpu_physical_memory_test_and_clear_dirty cpu_physical_memory_test_and_clear_dirty_arm #define cpu_physical_memory_unmap cpu_physical_memory_unmap_arm #define cpu_physical_memory_write_rom cpu_physical_memory_write_rom_arm #define cpu_physical_memory_write_rom_internal cpu_physical_memory_write_rom_internal_arm @@ -2095,6 +2096,7 @@ #define memory_region_set_readonly memory_region_set_readonly_arm #define memory_region_set_skip_dump memory_region_set_skip_dump_arm #define memory_region_size memory_region_size_arm +#define memory_region_test_and_clear_dirty memory_region_test_and_clear_dirty_arm #define memory_region_to_address_space memory_region_to_address_space_arm #define memory_region_transaction_begin memory_region_transaction_begin_arm #define memory_region_transaction_commit memory_region_transaction_commit_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index d242a51f..4ee595ac 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -296,6 +296,7 @@ #define cpu_physical_memory_rw cpu_physical_memory_rw_armeb #define cpu_physical_memory_set_dirty_flag cpu_physical_memory_set_dirty_flag_armeb #define cpu_physical_memory_set_dirty_range cpu_physical_memory_set_dirty_range_armeb +#define cpu_physical_memory_test_and_clear_dirty cpu_physical_memory_test_and_clear_dirty_armeb #define cpu_physical_memory_unmap cpu_physical_memory_unmap_armeb #define cpu_physical_memory_write_rom cpu_physical_memory_write_rom_armeb #define cpu_physical_memory_write_rom_internal cpu_physical_memory_write_rom_internal_armeb @@ -2095,6 +2096,7 @@ #define memory_region_set_readonly memory_region_set_readonly_armeb #define memory_region_set_skip_dump memory_region_set_skip_dump_armeb #define memory_region_size memory_region_size_armeb +#define memory_region_test_and_clear_dirty memory_region_test_and_clear_dirty_armeb #define memory_region_to_address_space memory_region_to_address_space_armeb #define memory_region_transaction_begin memory_region_transaction_begin_armeb #define memory_region_transaction_commit memory_region_transaction_commit_armeb diff --git a/qemu/cputlb.c b/qemu/cputlb.c index 6ce0fbc7..f01ba51e 100644 --- a/qemu/cputlb.c +++ b/qemu/cputlb.c @@ -124,8 +124,8 @@ void tlb_flush_page(CPUState *cpu, target_ulong addr) can be detected */ void tlb_protect_code(struct uc_struct *uc, ram_addr_t ram_addr) { - cpu_physical_memory_reset_dirty(uc, ram_addr, TARGET_PAGE_SIZE, - DIRTY_MEMORY_CODE); + cpu_physical_memory_test_and_clear_dirty(uc, ram_addr, TARGET_PAGE_SIZE, + DIRTY_MEMORY_CODE); } /* update the TLB so that writes in physical page 'phys_addr' are no longer diff --git a/qemu/exec.c b/qemu/exec.c index 49bde70d..274c8b88 100644 --- a/qemu/exec.c +++ b/qemu/exec.c @@ -714,16 +714,28 @@ static void tlb_reset_dirty_range_all(struct uc_struct* uc, } /* Note: start and end must be within the same ram block. */ -void cpu_physical_memory_reset_dirty(struct uc_struct* uc, - ram_addr_t start, ram_addr_t length, unsigned client) +bool cpu_physical_memory_test_and_clear_dirty(struct uc_struct *uc, + ram_addr_t start, + ram_addr_t length, + unsigned client) { - if (length == 0) - return; - cpu_physical_memory_clear_dirty_range(uc, start, length, client); + unsigned long end, page; + bool dirty; - if (tcg_enabled(uc)) { + if (length == 0) { + return false; + } + + end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; + page = start >> TARGET_PAGE_BITS; + dirty = bitmap_test_and_clear_atomic(uc->ram_list.dirty_memory[client], + page, end - page); + + if (dirty && tcg_enabled(uc)) { tlb_reset_dirty_range_all(uc, start, length); } + + return dirty; } hwaddr memory_region_section_get_iotlb(CPUState *cpu, diff --git a/qemu/header_gen.py b/qemu/header_gen.py index a06d06a8..0bbc5ff6 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -302,6 +302,7 @@ symbols = ( 'cpu_physical_memory_rw', 'cpu_physical_memory_set_dirty_flag', 'cpu_physical_memory_set_dirty_range', + 'cpu_physical_memory_test_and_clear_dirty', 'cpu_physical_memory_unmap', 'cpu_physical_memory_write_rom', 'cpu_physical_memory_write_rom_internal', @@ -2101,6 +2102,7 @@ symbols = ( 'memory_region_set_readonly', 'memory_region_set_skip_dump', 'memory_region_size', + 'memory_region_test_and_clear_dirty', 'memory_region_to_address_space', 'memory_region_transaction_begin', 'memory_region_transaction_commit', diff --git a/qemu/include/exec/memory.h b/qemu/include/exec/memory.h index f7c32f16..954a7f20 100644 --- a/qemu/include/exec/memory.h +++ b/qemu/include/exec/memory.h @@ -559,6 +559,23 @@ int memory_region_get_fd(MemoryRegion *mr); */ void *memory_region_get_ram_ptr(MemoryRegion *mr); +/** + * memory_region_test_and_clear_dirty: Check whether a range of bytes is dirty + * for a specified client. It clears them. + * + * Checks whether a range of bytes has been written to since the last + * call to memory_region_reset_dirty() with the same @client. Dirty logging + * must be enabled. + * + * @mr: the memory region being queried. + * @addr: the address (relative to the start of the region) being queried. + * @size: the size of the range being queried. + * @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or + * %DIRTY_MEMORY_VGA. + */ +bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr, + hwaddr size, unsigned client); + /** * memory_region_set_readonly: Turn a memory region read-only (or read-write) * diff --git a/qemu/include/exec/ram_addr.h b/qemu/include/exec/ram_addr.h index 2fa763ca..5453aa35 100644 --- a/qemu/include/exec/ram_addr.h +++ b/qemu/include/exec/ram_addr.h @@ -163,20 +163,17 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(struct uc_struct *uc, } #endif /* not _WIN32 */ +bool cpu_physical_memory_test_and_clear_dirty(struct uc_struct *uc, + ram_addr_t start, + ram_addr_t length, + unsigned client); + static inline void cpu_physical_memory_clear_dirty_range(struct uc_struct *uc, 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(uc->ram_list.dirty_memory[client], page, end - page); + cpu_physical_memory_test_and_clear_dirty(uc, start, length, DIRTY_MEMORY_CODE); } -void cpu_physical_memory_reset_dirty(struct uc_struct *uc, - ram_addr_t start, ram_addr_t length, unsigned client); - #endif #endif diff --git a/qemu/m68k.h b/qemu/m68k.h index 715a4595..c37348bd 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -296,6 +296,7 @@ #define cpu_physical_memory_rw cpu_physical_memory_rw_m68k #define cpu_physical_memory_set_dirty_flag cpu_physical_memory_set_dirty_flag_m68k #define cpu_physical_memory_set_dirty_range cpu_physical_memory_set_dirty_range_m68k +#define cpu_physical_memory_test_and_clear_dirty cpu_physical_memory_test_and_clear_dirty_m68k #define cpu_physical_memory_unmap cpu_physical_memory_unmap_m68k #define cpu_physical_memory_write_rom cpu_physical_memory_write_rom_m68k #define cpu_physical_memory_write_rom_internal cpu_physical_memory_write_rom_internal_m68k @@ -2095,6 +2096,7 @@ #define memory_region_set_readonly memory_region_set_readonly_m68k #define memory_region_set_skip_dump memory_region_set_skip_dump_m68k #define memory_region_size memory_region_size_m68k +#define memory_region_test_and_clear_dirty memory_region_test_and_clear_dirty_m68k #define memory_region_to_address_space memory_region_to_address_space_m68k #define memory_region_transaction_begin memory_region_transaction_begin_m68k #define memory_region_transaction_commit memory_region_transaction_commit_m68k diff --git a/qemu/memory.c b/qemu/memory.c index 75917302..b9dfbc23 100644 --- a/qemu/memory.c +++ b/qemu/memory.c @@ -1344,6 +1344,13 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr) return qemu_get_ram_ptr(mr->uc, mr->ram_addr & TARGET_PAGE_MASK); } +bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr, + hwaddr size, unsigned client) +{ + return cpu_physical_memory_test_and_clear_dirty(mr->uc, mr->ram_addr + addr, + size, client); +} + static void memory_region_update_container_subregions(MemoryRegion *subregion) { hwaddr offset = subregion->addr; diff --git a/qemu/mips.h b/qemu/mips.h index 9171bbbc..2e2a511c 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -296,6 +296,7 @@ #define cpu_physical_memory_rw cpu_physical_memory_rw_mips #define cpu_physical_memory_set_dirty_flag cpu_physical_memory_set_dirty_flag_mips #define cpu_physical_memory_set_dirty_range cpu_physical_memory_set_dirty_range_mips +#define cpu_physical_memory_test_and_clear_dirty cpu_physical_memory_test_and_clear_dirty_mips #define cpu_physical_memory_unmap cpu_physical_memory_unmap_mips #define cpu_physical_memory_write_rom cpu_physical_memory_write_rom_mips #define cpu_physical_memory_write_rom_internal cpu_physical_memory_write_rom_internal_mips @@ -2095,6 +2096,7 @@ #define memory_region_set_readonly memory_region_set_readonly_mips #define memory_region_set_skip_dump memory_region_set_skip_dump_mips #define memory_region_size memory_region_size_mips +#define memory_region_test_and_clear_dirty memory_region_test_and_clear_dirty_mips #define memory_region_to_address_space memory_region_to_address_space_mips #define memory_region_transaction_begin memory_region_transaction_begin_mips #define memory_region_transaction_commit memory_region_transaction_commit_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 73181162..7671a51a 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -296,6 +296,7 @@ #define cpu_physical_memory_rw cpu_physical_memory_rw_mips64 #define cpu_physical_memory_set_dirty_flag cpu_physical_memory_set_dirty_flag_mips64 #define cpu_physical_memory_set_dirty_range cpu_physical_memory_set_dirty_range_mips64 +#define cpu_physical_memory_test_and_clear_dirty cpu_physical_memory_test_and_clear_dirty_mips64 #define cpu_physical_memory_unmap cpu_physical_memory_unmap_mips64 #define cpu_physical_memory_write_rom cpu_physical_memory_write_rom_mips64 #define cpu_physical_memory_write_rom_internal cpu_physical_memory_write_rom_internal_mips64 @@ -2095,6 +2096,7 @@ #define memory_region_set_readonly memory_region_set_readonly_mips64 #define memory_region_set_skip_dump memory_region_set_skip_dump_mips64 #define memory_region_size memory_region_size_mips64 +#define memory_region_test_and_clear_dirty memory_region_test_and_clear_dirty_mips64 #define memory_region_to_address_space memory_region_to_address_space_mips64 #define memory_region_transaction_begin memory_region_transaction_begin_mips64 #define memory_region_transaction_commit memory_region_transaction_commit_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 36248cf9..851342bb 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -296,6 +296,7 @@ #define cpu_physical_memory_rw cpu_physical_memory_rw_mips64el #define cpu_physical_memory_set_dirty_flag cpu_physical_memory_set_dirty_flag_mips64el #define cpu_physical_memory_set_dirty_range cpu_physical_memory_set_dirty_range_mips64el +#define cpu_physical_memory_test_and_clear_dirty cpu_physical_memory_test_and_clear_dirty_mips64el #define cpu_physical_memory_unmap cpu_physical_memory_unmap_mips64el #define cpu_physical_memory_write_rom cpu_physical_memory_write_rom_mips64el #define cpu_physical_memory_write_rom_internal cpu_physical_memory_write_rom_internal_mips64el @@ -2095,6 +2096,7 @@ #define memory_region_set_readonly memory_region_set_readonly_mips64el #define memory_region_set_skip_dump memory_region_set_skip_dump_mips64el #define memory_region_size memory_region_size_mips64el +#define memory_region_test_and_clear_dirty memory_region_test_and_clear_dirty_mips64el #define memory_region_to_address_space memory_region_to_address_space_mips64el #define memory_region_transaction_begin memory_region_transaction_begin_mips64el #define memory_region_transaction_commit memory_region_transaction_commit_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 15281dc0..0c949e1e 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -296,6 +296,7 @@ #define cpu_physical_memory_rw cpu_physical_memory_rw_mipsel #define cpu_physical_memory_set_dirty_flag cpu_physical_memory_set_dirty_flag_mipsel #define cpu_physical_memory_set_dirty_range cpu_physical_memory_set_dirty_range_mipsel +#define cpu_physical_memory_test_and_clear_dirty cpu_physical_memory_test_and_clear_dirty_mipsel #define cpu_physical_memory_unmap cpu_physical_memory_unmap_mipsel #define cpu_physical_memory_write_rom cpu_physical_memory_write_rom_mipsel #define cpu_physical_memory_write_rom_internal cpu_physical_memory_write_rom_internal_mipsel @@ -2095,6 +2096,7 @@ #define memory_region_set_readonly memory_region_set_readonly_mipsel #define memory_region_set_skip_dump memory_region_set_skip_dump_mipsel #define memory_region_size memory_region_size_mipsel +#define memory_region_test_and_clear_dirty memory_region_test_and_clear_dirty_mipsel #define memory_region_to_address_space memory_region_to_address_space_mipsel #define memory_region_transaction_begin memory_region_transaction_begin_mipsel #define memory_region_transaction_commit memory_region_transaction_commit_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 733e61f1..fbb8ff43 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -296,6 +296,7 @@ #define cpu_physical_memory_rw cpu_physical_memory_rw_powerpc #define cpu_physical_memory_set_dirty_flag cpu_physical_memory_set_dirty_flag_powerpc #define cpu_physical_memory_set_dirty_range cpu_physical_memory_set_dirty_range_powerpc +#define cpu_physical_memory_test_and_clear_dirty cpu_physical_memory_test_and_clear_dirty_powerpc #define cpu_physical_memory_unmap cpu_physical_memory_unmap_powerpc #define cpu_physical_memory_write_rom cpu_physical_memory_write_rom_powerpc #define cpu_physical_memory_write_rom_internal cpu_physical_memory_write_rom_internal_powerpc @@ -2095,6 +2096,7 @@ #define memory_region_set_readonly memory_region_set_readonly_powerpc #define memory_region_set_skip_dump memory_region_set_skip_dump_powerpc #define memory_region_size memory_region_size_powerpc +#define memory_region_test_and_clear_dirty memory_region_test_and_clear_dirty_powerpc #define memory_region_to_address_space memory_region_to_address_space_powerpc #define memory_region_transaction_begin memory_region_transaction_begin_powerpc #define memory_region_transaction_commit memory_region_transaction_commit_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index a8f68908..d91d7258 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -296,6 +296,7 @@ #define cpu_physical_memory_rw cpu_physical_memory_rw_sparc #define cpu_physical_memory_set_dirty_flag cpu_physical_memory_set_dirty_flag_sparc #define cpu_physical_memory_set_dirty_range cpu_physical_memory_set_dirty_range_sparc +#define cpu_physical_memory_test_and_clear_dirty cpu_physical_memory_test_and_clear_dirty_sparc #define cpu_physical_memory_unmap cpu_physical_memory_unmap_sparc #define cpu_physical_memory_write_rom cpu_physical_memory_write_rom_sparc #define cpu_physical_memory_write_rom_internal cpu_physical_memory_write_rom_internal_sparc @@ -2095,6 +2096,7 @@ #define memory_region_set_readonly memory_region_set_readonly_sparc #define memory_region_set_skip_dump memory_region_set_skip_dump_sparc #define memory_region_size memory_region_size_sparc +#define memory_region_test_and_clear_dirty memory_region_test_and_clear_dirty_sparc #define memory_region_to_address_space memory_region_to_address_space_sparc #define memory_region_transaction_begin memory_region_transaction_begin_sparc #define memory_region_transaction_commit memory_region_transaction_commit_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index a149eabf..fc71cb87 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -296,6 +296,7 @@ #define cpu_physical_memory_rw cpu_physical_memory_rw_sparc64 #define cpu_physical_memory_set_dirty_flag cpu_physical_memory_set_dirty_flag_sparc64 #define cpu_physical_memory_set_dirty_range cpu_physical_memory_set_dirty_range_sparc64 +#define cpu_physical_memory_test_and_clear_dirty cpu_physical_memory_test_and_clear_dirty_sparc64 #define cpu_physical_memory_unmap cpu_physical_memory_unmap_sparc64 #define cpu_physical_memory_write_rom cpu_physical_memory_write_rom_sparc64 #define cpu_physical_memory_write_rom_internal cpu_physical_memory_write_rom_internal_sparc64 @@ -2095,6 +2096,7 @@ #define memory_region_set_readonly memory_region_set_readonly_sparc64 #define memory_region_set_skip_dump memory_region_set_skip_dump_sparc64 #define memory_region_size memory_region_size_sparc64 +#define memory_region_test_and_clear_dirty memory_region_test_and_clear_dirty_sparc64 #define memory_region_to_address_space memory_region_to_address_space_sparc64 #define memory_region_transaction_begin memory_region_transaction_begin_sparc64 #define memory_region_transaction_commit memory_region_transaction_commit_sparc64 diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 57afa7d2..9d4749d6 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -296,6 +296,7 @@ #define cpu_physical_memory_rw cpu_physical_memory_rw_x86_64 #define cpu_physical_memory_set_dirty_flag cpu_physical_memory_set_dirty_flag_x86_64 #define cpu_physical_memory_set_dirty_range cpu_physical_memory_set_dirty_range_x86_64 +#define cpu_physical_memory_test_and_clear_dirty cpu_physical_memory_test_and_clear_dirty_x86_64 #define cpu_physical_memory_unmap cpu_physical_memory_unmap_x86_64 #define cpu_physical_memory_write_rom cpu_physical_memory_write_rom_x86_64 #define cpu_physical_memory_write_rom_internal cpu_physical_memory_write_rom_internal_x86_64 @@ -2095,6 +2096,7 @@ #define memory_region_set_readonly memory_region_set_readonly_x86_64 #define memory_region_set_skip_dump memory_region_set_skip_dump_x86_64 #define memory_region_size memory_region_size_x86_64 +#define memory_region_test_and_clear_dirty memory_region_test_and_clear_dirty_x86_64 #define memory_region_to_address_space memory_region_to_address_space_x86_64 #define memory_region_transaction_begin memory_region_transaction_begin_x86_64 #define memory_region_transaction_commit memory_region_transaction_commit_x86_64