From a8ae486bb6c00ddd7d7d51329e9810829f23c0bf Mon Sep 17 00:00:00 2001
Message-Id: <a8ae486bb6c00ddd7d7d51329e9810829f23c0bf.1318783737.git.blauwirbel@gmail.com>
In-Reply-To: <b23f87c42ce7a6a5078ebb969bdb0dd8046f9578.1318783737.git.blauwirbel@gmail.com>
References: <b23f87c42ce7a6a5078ebb969bdb0dd8046f9578.1318783737.git.blauwirbel@gmail.com>
From: Blue Swirl <blauwirbel@gmail.com>
Date: Sun, 16 Oct 2011 16:04:59 +0000
Subject: [PATCH 3/4] memory: change dirtying APIs to take a size

Instead of each target knowing or guessing the guest page size,
just pass the desired size of dirtied memory area. This should also
improve performance due to memset() optimizations.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
---
 arch_init.c     |    3 ++-
 cpu-all.h       |    9 +++++++--
 hw/cirrus_vga.c |   18 ++++++++----------
 hw/g364fb.c     |   11 +++--------
 hw/qxl.c        |    5 +----
 hw/tcx.c        |   14 +++-----------
 hw/vga.c        |    6 +++---
 hw/vhost.c      |    2 +-
 kvm-all.c       |    8 +++++---
 memory.c        |    5 +++--
 memory.h        |    6 ++++--
 xen-all.c       |    4 +++-
 12 files changed, 43 insertions(+), 48 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index a6c69c7..8b3b414 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -280,7 +280,8 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
                  addr += TARGET_PAGE_SIZE) {
                 if (!cpu_physical_memory_get_dirty(addr,
                                                    MIGRATION_DIRTY_FLAG)) {
-                    cpu_physical_memory_set_dirty(addr);
+                    cpu_physical_memory_range_set_dirty(addr,
+                                                        TARGET_PAGE_SIZE);
                 }
             }
         }
diff --git a/cpu-all.h b/cpu-all.h
index 42a5fa0..4ed84a1 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -533,9 +533,14 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
     return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
 }
 
-static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
+static inline void cpu_physical_memory_range_set_dirty(ram_addr_t start,
+                                                       ram_addr_t size)
 {
-    ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
+    start >>= TARGET_PAGE_BITS;
+    size = (size | (TARGET_PAGE_SIZE - 1)) + 1;
+    size >>= TARGET_PAGE_BITS;
+
+    memset(&ram_list.phys_dirty[start], 0xff, size);
 }
 
 static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr,
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index aa8a0e6..846c8f5 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -619,10 +619,7 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
 	off_cur = off_begin;
 	off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
 	off_cur &= TARGET_PAGE_MASK;
-	while (off_cur < off_cur_end) {
-	    memory_region_set_dirty(&s->vga.vram, off_cur);
-	    off_cur += TARGET_PAGE_SIZE;
-	}
+        memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur);
 	off_begin += off_pitch;
     }
 }
@@ -1923,8 +1920,8 @@ static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
 	val <<= 1;
 	dst++;
     }
-    memory_region_set_dirty(&s->vga.vram, offset);
-    memory_region_set_dirty(&s->vga.vram, offset + 7);
+    memory_region_set_dirty(&s->vga.vram, offset, 1);
+    memory_region_set_dirty(&s->vga.vram, offset + 7, 1);
 }
 
 static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
@@ -1948,8 +1945,8 @@ static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
 	val <<= 1;
 	dst += 2;
     }
-    memory_region_set_dirty(&s->vga.vram, offset);
-    memory_region_set_dirty(&s->vga.vram, offset + 15);
+    memory_region_set_dirty(&s->vga.vram, offset, 1);
+    memory_region_set_dirty(&s->vga.vram, offset + 15, 1);
 }
 
 /***************************************
@@ -2039,7 +2036,8 @@ static void cirrus_vga_mem_write(void *opaque,
 		mode = s->vga.gr[0x05] & 0x7;
 		if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
 		    *(s->vga.vram_ptr + bank_offset) = mem_value;
-		    memory_region_set_dirty(&s->vga.vram, bank_offset);
+                    memory_region_set_dirty(&s->vga.vram, bank_offset,
+                                            sizeof(mem_value));
 		} else {
 		    if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
 			cirrus_mem_writeb_mode4and5_8bpp(s, mode,
@@ -2311,7 +2309,7 @@ static void cirrus_linear_write(void *opaque, target_phys_addr_t addr,
 	mode = s->vga.gr[0x05] & 0x7;
 	if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
 	    *(s->vga.vram_ptr + addr) = (uint8_t) val;
-	    memory_region_set_dirty(&s->vga.vram, addr);
+            memory_region_set_dirty(&s->vga.vram, addr, 1);
 	} else {
 	    if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
 		cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
diff --git a/hw/g364fb.c b/hw/g364fb.c
index f00ee27..166839b 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -268,12 +268,9 @@ static void g364fb_update_display(void *opaque)
 static inline void g364fb_invalidate_display(void *opaque)
 {
     G364State *s = opaque;
-    int i;
 
     s->blanked = 0;
-    for (i = 0; i < s->vram_size; i += G364_PAGE_SIZE) {
-        memory_region_set_dirty(&s->mem_vram, i);
-    }
+    memory_region_set_dirty(&s->mem_vram, 0, s->vram_size);
 }
 
 static void g364fb_reset(G364State *s)
@@ -385,7 +382,7 @@ static void g364fb_update_depth(G364State *s)
 
 static void g364_invalidate_cursor_position(G364State *s)
 {
-    int ymin, ymax, start, end, i;
+    int ymin, ymax, start, end;
 
     /* invalidate only near the cursor */
     ymin = s->cursor_position & 0xfff;
@@ -393,9 +390,7 @@ static void g364_invalidate_cursor_position(G364State *s)
     start = ymin * ds_get_linesize(s->ds);
     end = (ymax + 1) * ds_get_linesize(s->ds);
 
-    for (i = start; i < end; i += G364_PAGE_SIZE) {
-        memory_region_set_dirty(&s->mem_vram, i);
-    }
+    memory_region_set_dirty(&s->mem_vram, start, end - start);
 }
 
 static void g364fb_ctrl_write(void *opaque,
diff --git a/hw/qxl.c b/hw/qxl.c
index 03848ed..b1e0d80 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -341,10 +341,7 @@ static void init_qxl_ram(PCIQXLDevice *d)
 /* can be called from spice server thread context */
 static void qxl_set_dirty(MemoryRegion *mr, ram_addr_t addr, ram_addr_t end)
 {
-    while (addr < end) {
-        memory_region_set_dirty(mr, addr);
-        addr += TARGET_PAGE_SIZE;
-    }
+    memory_region_set_dirty(mr, addr, end - addr);
 }
 
 static void qxl_rom_set_dirty(PCIQXLDevice *qxl)
diff --git a/hw/tcx.c b/hw/tcx.c
index 309600d..e48c564 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -53,21 +53,13 @@ static void tcx24_screen_dump(void *opaque, const char *filename);
 
 static void tcx_set_dirty(TCXState *s)
 {
-    unsigned int i;
-
-    for (i = 0; i < MAXX * MAXY; i += TARGET_PAGE_SIZE) {
-        cpu_physical_memory_set_dirty(s->vram_offset + i);
-    }
+    cpu_physical_memory_range_set_dirty(s->vram_offset, MAXX * MAXY);
 }
 
 static void tcx24_set_dirty(TCXState *s)
 {
-    unsigned int i;
-
-    for (i = 0; i < MAXX * MAXY * 4; i += TARGET_PAGE_SIZE) {
-        cpu_physical_memory_set_dirty(s->vram24_offset + i);
-        cpu_physical_memory_set_dirty(s->cplane_offset + i);
-    }
+    cpu_physical_memory_range_set_dirty(s->vram24_offset, MAXX * MAXY * 4);
+    cpu_physical_memory_range_set_dirty(s->cplane_offset, MAXX * MAXY * 4);
 }
 
 static void update_palette_entries(TCXState *s, int start, int end)
diff --git a/hw/vga.c b/hw/vga.c
index ca79aa1..85176a6 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -853,7 +853,7 @@ void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
             printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
 #endif
             s->plane_updated |= mask; /* only used to detect font change */
-            memory_region_set_dirty(&s->vram, addr);
+            memory_region_set_dirty(&s->vram, addr, 1);
         }
     } else if (s->gr[5] & 0x10) {
         /* odd/even mode (aka text mode mapping) */
@@ -866,7 +866,7 @@ void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
             printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
 #endif
             s->plane_updated |= mask; /* only used to detect font change */
-            memory_region_set_dirty(&s->vram, addr);
+            memory_region_set_dirty(&s->vram, addr, 1);
         }
     } else {
         /* standard VGA latched access */
@@ -940,7 +940,7 @@ void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
         printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
                addr * 4, write_mask, val);
 #endif
-        memory_region_set_dirty(&s->vram, addr << 2);
+        memory_region_set_dirty(&s->vram, addr << 2, sizeof(uint32_t));
     }
 }
 
diff --git a/hw/vhost.c b/hw/vhost.c
index 0870cb7..d96b186 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -50,7 +50,7 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
             ram_addr_t ram_addr;
             bit -= 1;
             ram_addr = cpu_get_physical_page_desc(addr + bit * VHOST_LOG_PAGE);
-            cpu_physical_memory_set_dirty(ram_addr);
+            cpu_physical_memory_range_set_dirty(ram_addr, VHOST_LOG_CHUNK);
             log &= ~(0x1ull << bit);
         }
         addr += VHOST_LOG_CHUNK;
diff --git a/kvm-all.c b/kvm-all.c
index e7faf5c..104b0d7 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -352,7 +352,8 @@ static int kvm_get_dirty_pages_log_range(unsigned long start_addr,
                 addr1 = page_number * TARGET_PAGE_SIZE;
                 addr = offset + addr1;
                 ram_addr = cpu_get_physical_page_desc(addr);
-                cpu_physical_memory_set_dirty(ram_addr);
+                cpu_physical_memory_range_set_dirty(ram_addr,
+                                                    TARGET_PAGE_SIZE);
             } while (c != 0);
         }
     }
@@ -363,8 +364,9 @@ static int kvm_get_dirty_pages_log_range(unsigned long start_addr,
 
 /**
  * kvm_physical_sync_dirty_bitmap - Grab dirty bitmap from kernel space
- * This function updates qemu's dirty bitmap using cpu_physical_memory_set_dirty().
- * This means all bits are set to dirty.
+ * This function updates qemu's dirty bitmap using
+ * cpu_physical_memory_range_set_dirty().  This means all bits are set
+ * to dirty.
  *
  * @start_add: start of logged region.
  * @end_addr: end of logged region.
diff --git a/memory.c b/memory.c
index dc5e35d..37a282b 100644
--- a/memory.c
+++ b/memory.c
@@ -1037,10 +1037,11 @@ bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
     return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1 << client);
 }
 
-void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
+void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                             target_phys_addr_t size)
 {
     assert(mr->terminates);
-    return cpu_physical_memory_set_dirty(mr->ram_addr + addr);
+    return cpu_physical_memory_range_set_dirty(mr->ram_addr + addr, size);
 }
 
 void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
diff --git a/memory.h b/memory.h
index d5b47da..fcd15b3 100644
--- a/memory.h
+++ b/memory.h
@@ -310,10 +310,12 @@ bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
  *
  * Marks a page as dirty, after it has been dirtied outside guest code.
  *
- * @mr: the memory region being queried.
+ * @mr: the memory region being dirtied.
  * @addr: the address (relative to the start of the region) being dirtied.
+ * @size: size of the range being dirtied.
  */
-void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr);
+void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                             target_phys_addr_t size);
 
 /**
  * memory_region_sync_dirty_bitmap: Synchronize a region's dirty bitmap with
diff --git a/xen-all.c b/xen-all.c
index b5e28ab..c07494b 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -422,7 +422,9 @@ static int xen_sync_dirty_bitmap(XenIOState *state,
         while (map != 0) {
             j = ffsl(map) - 1;
             map &= ~(1ul << j);
-            cpu_physical_memory_set_dirty(vram_offset + (i * width + j) * TARGET_PAGE_SIZE);
+            cpu_physical_memory_range_set_dirty(vram_offset + (i * width + j) *
+                                                TARGET_PAGE_SIZE,
+                                                TARGET_PAGE_SIZE);
         };
     }
 
-- 
1.7.2.5

