exec: only check relevant bitmaps for cleanliness

Most of the time, not all bitmaps have to be marked as dirty;
do not do anything if the interesting ones are already dirty.
Previously, any clean bitmap would have cause all the bitmaps to be
marked dirty.

In fact, unless running TCG most of the time bitmap operations need
not be done at all, because memory_region_is_logging returns zero.
In this case, skip the call to cpu_physical_memory_range_includes_clean
altogether as well.

With this patch, cpu_physical_memory_set_dirty_range is called
unconditionally, so there need not be anymore a separate call to
xen_modified_memory.

Backports commit e87f7778b64d4a6a78e16c288c7fdc6c15317d5f from qemu
This commit is contained in:
Paolo Bonzini 2018-02-13 11:00:32 -05:00 committed by Lioncash
parent 6bbfcf65e8
commit 6d509f7333
No known key found for this signature in database
GPG Key ID: 4E3C3CC1031BA9C7
2 changed files with 25 additions and 11 deletions

View File

@ -1609,12 +1609,20 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
#else
static void invalidate_and_set_dirty(struct uc_struct *uc, hwaddr addr,
static void invalidate_and_set_dirty(MemoryRegion *mr, hwaddr addr,
hwaddr length)
{
if (cpu_physical_memory_range_includes_clean(uc, addr, length)) {
tb_invalidate_phys_range(uc, addr, addr + length);
uint8_t dirty_log_mask = memory_region_get_dirty_log_mask(mr);
if (dirty_log_mask) {
dirty_log_mask =
cpu_physical_memory_range_includes_clean(mr->uc, addr, length, dirty_log_mask);
}
if (dirty_log_mask & (1 << DIRTY_MEMORY_CODE)) {
tb_invalidate_phys_range(mr->uc, addr, addr + length);
dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE);
}
cpu_physical_memory_set_dirty_range(mr->uc, addr, length, dirty_log_mask);
}
static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr)
@ -1703,7 +1711,7 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
/* RAM case */
ptr = qemu_get_ram_ptr(as->uc, addr1);
memcpy(ptr, buf, l);
invalidate_and_set_dirty(as->uc, addr1, l);
invalidate_and_set_dirty(mr, addr1, l);
}
} else {
if (!memory_access_is_direct(mr, is_write)) {
@ -1803,7 +1811,7 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
switch (type) {
case WRITE_DATA:
memcpy(ptr, buf, l);
invalidate_and_set_dirty(as->uc, addr1, l);
invalidate_and_set_dirty(mr, addr1, l);
break;
case FLUSH_CACHE:
flush_icache_range((uintptr_t)ptr, (uintptr_t)ptr + l);
@ -1944,7 +1952,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
mr = qemu_ram_addr_from_host(as->uc, buffer, &addr1);
assert(mr != NULL);
if (is_write) {
invalidate_and_set_dirty(as->uc, addr1, access_len);
invalidate_and_set_dirty(mr, addr1, access_len);
}
memory_region_unref(mr);
return;
@ -2325,7 +2333,7 @@ static inline void address_space_stl_internal(AddressSpace *as,
stl_p(ptr, val);
break;
}
invalidate_and_set_dirty(mr->uc, addr1, 4);
invalidate_and_set_dirty(mr, addr1, 4);
r = MEMTX_OK;
}
if (result) {
@ -2427,7 +2435,7 @@ static inline void address_space_stw_internal(AddressSpace *as,
stw_p(ptr, val);
break;
}
invalidate_and_set_dirty(as->uc, addr1, 2);
invalidate_and_set_dirty(mr, addr1, 2);
r = MEMTX_OK;
}
if (result) {

View File

@ -77,9 +77,15 @@ static inline bool cpu_physical_memory_is_clean(struct uc_struct *uc, ram_addr_t
}
static inline bool cpu_physical_memory_range_includes_clean(struct uc_struct *uc, ram_addr_t start,
ram_addr_t length)
ram_addr_t length, uint8_t mask)
{
return !cpu_physical_memory_all_dirty(uc, start, length, DIRTY_MEMORY_CODE);
uint8_t ret = 0;
if (mask & (1 << DIRTY_MEMORY_CODE) &&
!cpu_physical_memory_all_dirty(uc, start, length, DIRTY_MEMORY_CODE)) {
ret |= (1 << DIRTY_MEMORY_CODE);
}
return ret;
}
static inline void cpu_physical_memory_set_dirty_flag(struct uc_struct *uc, ram_addr_t addr,