aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2015-03-25 15:21:39 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2015-06-05 17:10:00 +0200
commite87f7778b64d4a6a78e16c288c7fdc6c15317d5f (patch)
treed246cf453fbddd2831d628f4217a34e65f9274fc
parent72b47e79cef36ed6ffc718f10e21001d7ec2a66f (diff)
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. Reviewed-by: Fam Zheng <famz@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--exec.c22
-rw-r--r--include/exec/ram_addr.h25
2 files changed, 31 insertions, 16 deletions
diff --git a/exec.c b/exec.c
index fe137bd725..162c57908e 100644
--- a/exec.c
+++ b/exec.c
@@ -2259,16 +2259,20 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
static void invalidate_and_set_dirty(MemoryRegion *mr, hwaddr addr,
hwaddr length)
{
- if (cpu_physical_memory_range_includes_clean(addr, length)) {
- uint8_t dirty_log_mask = memory_region_get_dirty_log_mask(mr);
- if (dirty_log_mask & (1 << DIRTY_MEMORY_CODE)) {
- tb_invalidate_phys_range(addr, addr + length);
- dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE);
- }
- cpu_physical_memory_set_dirty_range(addr, length, dirty_log_mask);
- } else {
- xen_modified_memory(addr, length);
+ uint8_t dirty_log_mask = memory_region_get_dirty_log_mask(mr);
+ /* No early return if dirty_log_mask is or becomes 0, because
+ * cpu_physical_memory_set_dirty_range will still call
+ * xen_modified_memory.
+ */
+ if (dirty_log_mask) {
+ dirty_log_mask =
+ cpu_physical_memory_range_includes_clean(addr, length, dirty_log_mask);
+ }
+ if (dirty_log_mask & (1 << DIRTY_MEMORY_CODE)) {
+ tb_invalidate_phys_range(addr, addr + length);
+ dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE);
}
+ cpu_physical_memory_set_dirty_range(addr, length, dirty_log_mask);
}
static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr)
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index c221bd7dd0..3e42b4f602 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -89,14 +89,25 @@ static inline bool cpu_physical_memory_is_clean(ram_addr_t addr)
return !(vga && code && migration);
}
-static inline bool cpu_physical_memory_range_includes_clean(ram_addr_t start,
- ram_addr_t length)
+static inline uint8_t cpu_physical_memory_range_includes_clean(ram_addr_t start,
+ ram_addr_t length,
+ uint8_t mask)
{
- bool vga = !cpu_physical_memory_all_dirty(start, length, DIRTY_MEMORY_VGA);
- bool code = !cpu_physical_memory_all_dirty(start, length, DIRTY_MEMORY_CODE);
- bool migration =
- !cpu_physical_memory_all_dirty(start, length, DIRTY_MEMORY_MIGRATION);
- return vga || code || migration;
+ uint8_t ret = 0;
+
+ if (mask & (1 << DIRTY_MEMORY_VGA) &&
+ !cpu_physical_memory_all_dirty(start, length, DIRTY_MEMORY_VGA)) {
+ ret |= (1 << DIRTY_MEMORY_VGA);
+ }
+ if (mask & (1 << DIRTY_MEMORY_CODE) &&
+ !cpu_physical_memory_all_dirty(start, length, DIRTY_MEMORY_CODE)) {
+ ret |= (1 << DIRTY_MEMORY_CODE);
+ }
+ if (mask & (1 << DIRTY_MEMORY_MIGRATION) &&
+ !cpu_physical_memory_all_dirty(start, length, DIRTY_MEMORY_MIGRATION)) {
+ ret |= (1 << DIRTY_MEMORY_MIGRATION);
+ }
+ return ret;
}
static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,