memory: replace cpu_physical_memory_reset_dirty() with test-and-clear

The cpu_physical_memory_reset_dirty() function is sometimes used
together with cpu_physical_memory_get_dirty(). This is not atomic since
two separate accesses to the dirty memory bitmap are made.

Turn cpu_physical_memory_reset_dirty() and
cpu_physical_memory_clear_dirty_range_type() into the atomic
cpu_physical_memory_test_and_clear_dirty().

Backports commit 03eebc9e3246b9b3f5925aa41f7dfd7c1e467875 from qemu
This commit is contained in:
Stefan Hajnoczi 2018-02-13 11:23:17 -05:00 committed by Lioncash
parent 18ccd4b5be
commit fc7b95d06a
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
19 changed files with 78 additions and 17 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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',

View file

@ -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)
*

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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