All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 1/6] memory: change dirty getting API to take a size
@ 2012-01-29 19:13 Blue Swirl
  2012-02-08  7:19 ` Evgeny Voevodin
  0 siblings, 1 reply; 4+ messages in thread
From: Blue Swirl @ 2012-01-29 19:13 UTC (permalink / raw)
  To: Avi Kivity, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 10631 bytes --]

Instead of each device knowing or guessing the guest page size,
just pass the desired size of dirtied memory area.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
---
 arch_init.c      |    7 ++++---
 exec-obsolete.h  |   15 +++++++++++++--
 hw/framebuffer.c |    9 +--------
 hw/g364fb.c      |    3 ++-
 hw/sm501.c       |   11 ++++-------
 hw/tcx.c         |   19 +++++++++----------
 hw/vga.c         |   17 +++++------------
 memory.c         |    5 +++--
 memory.h         |    9 +++++----
 9 files changed, 46 insertions(+), 49 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 2366511..699bdd1 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -141,7 +141,8 @@ static int ram_save_block(QEMUFile *f)

     do {
         mr = block->mr;
-        if (memory_region_get_dirty(mr, offset, DIRTY_MEMORY_MIGRATION)) {
+        if (memory_region_get_dirty(mr, offset, TARGET_PAGE_SIZE,
+                                    DIRTY_MEMORY_MIGRATION)) {
             uint8_t *p;
             int cont = (block == last_block) ? RAM_SAVE_FLAG_CONTINUE : 0;

@@ -198,7 +199,7 @@ static ram_addr_t ram_save_remaining(void)
     QLIST_FOREACH(block, &ram_list.blocks, next) {
         ram_addr_t addr;
         for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {
-            if (memory_region_get_dirty(block->mr, addr,
+            if (memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE,
                                         DIRTY_MEMORY_MIGRATION)) {
                 count++;
             }
@@ -283,7 +284,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int
stage, void *opaque)
         /* Make sure all dirty bits are set */
         QLIST_FOREACH(block, &ram_list.blocks, next) {
             for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {
-                if (!memory_region_get_dirty(block->mr, addr,
+                if (!memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE,
                                              DIRTY_MEMORY_MIGRATION)) {
                     memory_region_set_dirty(block->mr, addr, TARGET_PAGE_SIZE);
                 }
diff --git a/exec-obsolete.h b/exec-obsolete.h
index d2749d3..94c23d0 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -59,10 +59,21 @@ static inline int
cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
     return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS];
 }

-static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
+static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
+                                                ram_addr_t length,
                                                 int dirty_flags)
 {
-    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
+    int ret = 0;
+    uint8_t *p;
+    ram_addr_t addr, end;
+
+    end = TARGET_PAGE_ALIGN(start + length);
+    start &= TARGET_PAGE_MASK;
+    p = ram_list.phys_dirty + (start >> TARGET_PAGE_BITS);
+    for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
+        ret |= *p++ & dirty_flags;
+    }
+    return ret;
 }

 static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
diff --git a/hw/framebuffer.c b/hw/framebuffer.c
index 6bf48dc..ea122fb 100644
--- a/hw/framebuffer.c
+++ b/hw/framebuffer.c
@@ -87,15 +87,8 @@ void framebuffer_update_display(
     dest += i * dest_row_pitch;

     for (; i < rows; i++) {
-        target_phys_addr_t dirty_offset;
-        dirty = 0;
-        dirty_offset = 0;
-        while (addr + dirty_offset < TARGET_PAGE_ALIGN(addr + src_width)) {
-            dirty |= memory_region_get_dirty(mem, addr + dirty_offset,
+        dirty = memory_region_get_dirty(mem, addr, addr + src_width,
                                              DIRTY_MEMORY_VGA);
-            dirty_offset += TARGET_PAGE_SIZE;
-        }
-
         if (dirty || invalidate) {
             fn(opaque, dest, src, cols, dest_col_pitch);
             if (first == -1)
diff --git a/hw/g364fb.c b/hw/g364fb.c
index 82b31f7..fa25033 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -62,7 +62,8 @@ typedef struct G364State {

 static inline int check_dirty(G364State *s, ram_addr_t page)
 {
-    return memory_region_get_dirty(&s->mem_vram, page, DIRTY_MEMORY_VGA);
+    return memory_region_get_dirty(&s->mem_vram, page, G364_PAGE_SIZE,
+                                   DIRTY_MEMORY_VGA);
 }

 static inline void reset_dirty(G364State *s,
diff --git a/hw/sm501.c b/hw/sm501.c
index 09c5894..94c0abf 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -1323,15 +1323,12 @@ static void sm501_draw_crt(SM501State * s)
     for (y = 0; y < height; y++) {
 	int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0;
 	int update = full_update || update_hwc;
-	ram_addr_t page0 = offset & TARGET_PAGE_MASK;
-	ram_addr_t page1 = (offset + width * src_bpp - 1) & TARGET_PAGE_MASK;
-	ram_addr_t page;
+        ram_addr_t page0 = offset;
+        ram_addr_t page1 = offset + width * src_bpp - 1;

 	/* check dirty flags for each line */
-	for (page = page0; page <= page1; page += TARGET_PAGE_SIZE)
-            if (memory_region_get_dirty(&s->local_mem_region, page,
-                                        DIRTY_MEMORY_VGA))
-		update = 1;
+        update = memory_region_get_dirty(&s->local_mem_region, page0, page1,
+                                         DIRTY_MEMORY_VGA);

 	/* draw line and change status */
 	if (update) {
diff --git a/hw/tcx.c b/hw/tcx.c
index 7743c05..6054779 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -178,15 +178,13 @@ static inline int check_dirty(TCXState *s,
ram_addr_t page, ram_addr_t page24,
                               ram_addr_t cpage)
 {
     int ret;
-    unsigned int off;
-
-    ret = memory_region_get_dirty(&s->vram_mem, page, DIRTY_MEMORY_VGA);
-    for (off = 0; off < TARGET_PAGE_SIZE * 4; off += TARGET_PAGE_SIZE) {
-        ret |= memory_region_get_dirty(&s->vram_mem, page24 + off,
-                                       DIRTY_MEMORY_VGA);
-        ret |= memory_region_get_dirty(&s->vram_mem, cpage + off,
-                                       DIRTY_MEMORY_VGA);
-    }
+
+    ret = memory_region_get_dirty(&s->vram_mem, page, TARGET_PAGE_SIZE,
+                                  DIRTY_MEMORY_VGA);
+    ret |= memory_region_get_dirty(&s->vram_mem, page24, TARGET_PAGE_SIZE * 4,
+                                   DIRTY_MEMORY_VGA);
+    ret |= memory_region_get_dirty(&s->vram_mem, cpage, TARGET_PAGE_SIZE * 4,
+                                   DIRTY_MEMORY_VGA);
     return ret;
 }

@@ -245,7 +243,8 @@ static void tcx_update_display(void *opaque)
     }

     for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
-        if (memory_region_get_dirty(&ts->vram_mem, page, DIRTY_MEMORY_VGA)) {
+        if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE,
+                                    DIRTY_MEMORY_VGA)) {
             if (y_start < 0)
                 y_start = y;
             if (page < page_min)
diff --git a/hw/vga.c b/hw/vga.c
index 4dc2610..cf9b39f 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1742,17 +1742,10 @@ static void vga_draw_graphic(VGACommonState
*s, int full_update)
         if (!(s->cr[0x17] & 2)) {
             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
         }
-        page0 = addr & TARGET_PAGE_MASK;
-        page1 = (addr + bwidth - 1) & TARGET_PAGE_MASK;
-        update = full_update |
-            memory_region_get_dirty(&s->vram, page0, DIRTY_MEMORY_VGA) |
-            memory_region_get_dirty(&s->vram, page1, DIRTY_MEMORY_VGA);
-        if ((page1 - page0) > TARGET_PAGE_SIZE) {
-            /* if wide line, can use another page */
-            update |= memory_region_get_dirty(&s->vram,
-                                              page0 + TARGET_PAGE_SIZE,
-                                              DIRTY_MEMORY_VGA);
-        }
+        page0 = addr;
+        page1 = addr + bwidth - 1;
+        update = memory_region_get_dirty(&s->vram, page0, page1,
+                                         DIRTY_MEMORY_VGA);
         /* explicit invalidation for the hardware cursor */
         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
         if (update) {
@@ -1798,7 +1791,7 @@ static void vga_draw_graphic(VGACommonState *s,
int full_update)
     if (page_max >= page_min) {
         memory_region_reset_dirty(&s->vram,
                                   page_min,
-                                  page_max + TARGET_PAGE_SIZE - page_min,
+                                  page_max - page_min,
                                   DIRTY_MEMORY_VGA);
     }
     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
diff --git a/memory.c b/memory.c
index ee4c98a..5e77d8a 100644
--- a/memory.c
+++ b/memory.c
@@ -1136,10 +1136,11 @@ void memory_region_set_log(MemoryRegion *mr,
bool log, unsigned client)
 }

 bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
-                             unsigned client)
+                             target_phys_addr_t size, unsigned client)
 {
     assert(mr->terminates);
-    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1 << client);
+    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, size,
+                                         1 << client);
 }

 void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr,
diff --git a/memory.h b/memory.h
index fa45b99..4cf8d2f 100644
--- a/memory.h
+++ b/memory.h
@@ -380,20 +380,21 @@ void memory_region_set_offset(MemoryRegion *mr,
target_phys_addr_t offset);
 void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client);

 /**
- * memory_region_get_dirty: Check whether a page is dirty for a specified
- *                          client.
+ * memory_region_get_dirty: Check whether a range of bytes is dirty
+ *                          for a specified client.
  *
- * Checks whether a page has been written to since the last
+ * 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_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
-                             unsigned client);
+                             target_phys_addr_t size, unsigned client);

 /**
  * memory_region_set_dirty: Mark a range of bytes as dirty in a memory region.
-- 
1.7.9.rc0

[-- Attachment #2: 0001-memory-change-dirty-getting-API-to-take-a-size.patch --]
[-- Type: text/x-patch, Size: 10953 bytes --]

From 423f585cc5456c32fd49cf649825fa061dd898bd Mon Sep 17 00:00:00 2001
Message-Id: <423f585cc5456c32fd49cf649825fa061dd898bd.1327864041.git.blauwirbel@gmail.com>
From: Blue Swirl <blauwirbel@gmail.com>
Date: Sun, 22 Jan 2012 16:38:21 +0000
Subject: [PATCH 1/6] memory: change dirty getting API to take a size

Instead of each device knowing or guessing the guest page size,
just pass the desired size of dirtied memory area.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
---
 arch_init.c      |    7 ++++---
 exec-obsolete.h  |   15 +++++++++++++--
 hw/framebuffer.c |    9 +--------
 hw/g364fb.c      |    3 ++-
 hw/sm501.c       |   11 ++++-------
 hw/tcx.c         |   17 ++++++++---------
 hw/vga.c         |   17 +++++------------
 memory.c         |    5 +++--
 memory.h         |    9 +++++----
 9 files changed, 45 insertions(+), 48 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 2366511..699bdd1 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -141,7 +141,8 @@ static int ram_save_block(QEMUFile *f)
 
     do {
         mr = block->mr;
-        if (memory_region_get_dirty(mr, offset, DIRTY_MEMORY_MIGRATION)) {
+        if (memory_region_get_dirty(mr, offset, TARGET_PAGE_SIZE,
+                                    DIRTY_MEMORY_MIGRATION)) {
             uint8_t *p;
             int cont = (block == last_block) ? RAM_SAVE_FLAG_CONTINUE : 0;
 
@@ -198,7 +199,7 @@ static ram_addr_t ram_save_remaining(void)
     QLIST_FOREACH(block, &ram_list.blocks, next) {
         ram_addr_t addr;
         for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {
-            if (memory_region_get_dirty(block->mr, addr,
+            if (memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE,
                                         DIRTY_MEMORY_MIGRATION)) {
                 count++;
             }
@@ -283,7 +284,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         /* Make sure all dirty bits are set */
         QLIST_FOREACH(block, &ram_list.blocks, next) {
             for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {
-                if (!memory_region_get_dirty(block->mr, addr,
+                if (!memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE,
                                              DIRTY_MEMORY_MIGRATION)) {
                     memory_region_set_dirty(block->mr, addr, TARGET_PAGE_SIZE);
                 }
diff --git a/exec-obsolete.h b/exec-obsolete.h
index d2749d3..94c23d0 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -59,10 +59,21 @@ static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
     return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS];
 }
 
-static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
+static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
+                                                ram_addr_t length,
                                                 int dirty_flags)
 {
-    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
+    int ret = 0;
+    uint8_t *p;
+    ram_addr_t addr, end;
+
+    end = TARGET_PAGE_ALIGN(start + length);
+    start &= TARGET_PAGE_MASK;
+    p = ram_list.phys_dirty + (start >> TARGET_PAGE_BITS);
+    for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
+        ret |= *p++ & dirty_flags;
+    }
+    return ret;
 }
 
 static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
diff --git a/hw/framebuffer.c b/hw/framebuffer.c
index 6bf48dc..ea122fb 100644
--- a/hw/framebuffer.c
+++ b/hw/framebuffer.c
@@ -87,15 +87,8 @@ void framebuffer_update_display(
     dest += i * dest_row_pitch;
 
     for (; i < rows; i++) {
-        target_phys_addr_t dirty_offset;
-        dirty = 0;
-        dirty_offset = 0;
-        while (addr + dirty_offset < TARGET_PAGE_ALIGN(addr + src_width)) {
-            dirty |= memory_region_get_dirty(mem, addr + dirty_offset,
+        dirty = memory_region_get_dirty(mem, addr, addr + src_width,
                                              DIRTY_MEMORY_VGA);
-            dirty_offset += TARGET_PAGE_SIZE;
-        }
-
         if (dirty || invalidate) {
             fn(opaque, dest, src, cols, dest_col_pitch);
             if (first == -1)
diff --git a/hw/g364fb.c b/hw/g364fb.c
index 82b31f7..fa25033 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -62,7 +62,8 @@ typedef struct G364State {
 
 static inline int check_dirty(G364State *s, ram_addr_t page)
 {
-    return memory_region_get_dirty(&s->mem_vram, page, DIRTY_MEMORY_VGA);
+    return memory_region_get_dirty(&s->mem_vram, page, G364_PAGE_SIZE,
+                                   DIRTY_MEMORY_VGA);
 }
 
 static inline void reset_dirty(G364State *s,
diff --git a/hw/sm501.c b/hw/sm501.c
index 09c5894..94c0abf 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -1323,15 +1323,12 @@ static void sm501_draw_crt(SM501State * s)
     for (y = 0; y < height; y++) {
 	int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0;
 	int update = full_update || update_hwc;
-	ram_addr_t page0 = offset & TARGET_PAGE_MASK;
-	ram_addr_t page1 = (offset + width * src_bpp - 1) & TARGET_PAGE_MASK;
-	ram_addr_t page;
+        ram_addr_t page0 = offset;
+        ram_addr_t page1 = offset + width * src_bpp - 1;
 
 	/* check dirty flags for each line */
-	for (page = page0; page <= page1; page += TARGET_PAGE_SIZE)
-            if (memory_region_get_dirty(&s->local_mem_region, page,
-                                        DIRTY_MEMORY_VGA))
-		update = 1;
+        update = memory_region_get_dirty(&s->local_mem_region, page0, page1,
+                                         DIRTY_MEMORY_VGA);
 
 	/* draw line and change status */
 	if (update) {
diff --git a/hw/tcx.c b/hw/tcx.c
index 7743c05..6054779 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -178,15 +178,13 @@ static inline int check_dirty(TCXState *s, ram_addr_t page, ram_addr_t page24,
                               ram_addr_t cpage)
 {
     int ret;
-    unsigned int off;
-
-    ret = memory_region_get_dirty(&s->vram_mem, page, DIRTY_MEMORY_VGA);
-    for (off = 0; off < TARGET_PAGE_SIZE * 4; off += TARGET_PAGE_SIZE) {
-        ret |= memory_region_get_dirty(&s->vram_mem, page24 + off,
-                                       DIRTY_MEMORY_VGA);
-        ret |= memory_region_get_dirty(&s->vram_mem, cpage + off,
-                                       DIRTY_MEMORY_VGA);
-    }
+
+    ret = memory_region_get_dirty(&s->vram_mem, page, TARGET_PAGE_SIZE,
+                                  DIRTY_MEMORY_VGA);
+    ret |= memory_region_get_dirty(&s->vram_mem, page24, TARGET_PAGE_SIZE * 4,
+                                   DIRTY_MEMORY_VGA);
+    ret |= memory_region_get_dirty(&s->vram_mem, cpage, TARGET_PAGE_SIZE * 4,
+                                   DIRTY_MEMORY_VGA);
     return ret;
 }
 
@@ -245,7 +243,8 @@ static void tcx_update_display(void *opaque)
     }
 
     for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
-        if (memory_region_get_dirty(&ts->vram_mem, page, DIRTY_MEMORY_VGA)) {
+        if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE,
+                                    DIRTY_MEMORY_VGA)) {
             if (y_start < 0)
                 y_start = y;
             if (page < page_min)
diff --git a/hw/vga.c b/hw/vga.c
index 4dc2610..cf9b39f 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1742,17 +1742,10 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
         if (!(s->cr[0x17] & 2)) {
             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
         }
-        page0 = addr & TARGET_PAGE_MASK;
-        page1 = (addr + bwidth - 1) & TARGET_PAGE_MASK;
-        update = full_update |
-            memory_region_get_dirty(&s->vram, page0, DIRTY_MEMORY_VGA) |
-            memory_region_get_dirty(&s->vram, page1, DIRTY_MEMORY_VGA);
-        if ((page1 - page0) > TARGET_PAGE_SIZE) {
-            /* if wide line, can use another page */
-            update |= memory_region_get_dirty(&s->vram,
-                                              page0 + TARGET_PAGE_SIZE,
-                                              DIRTY_MEMORY_VGA);
-        }
+        page0 = addr;
+        page1 = addr + bwidth - 1;
+        update = memory_region_get_dirty(&s->vram, page0, page1,
+                                         DIRTY_MEMORY_VGA);
         /* explicit invalidation for the hardware cursor */
         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
         if (update) {
@@ -1798,7 +1791,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
     if (page_max >= page_min) {
         memory_region_reset_dirty(&s->vram,
                                   page_min,
-                                  page_max + TARGET_PAGE_SIZE - page_min,
+                                  page_max - page_min,
                                   DIRTY_MEMORY_VGA);
     }
     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
diff --git a/memory.c b/memory.c
index ee4c98a..5e77d8a 100644
--- a/memory.c
+++ b/memory.c
@@ -1136,10 +1136,11 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
 }
 
 bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
-                             unsigned client)
+                             target_phys_addr_t size, unsigned client)
 {
     assert(mr->terminates);
-    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1 << client);
+    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, size,
+                                         1 << client);
 }
 
 void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr,
diff --git a/memory.h b/memory.h
index fa45b99..4cf8d2f 100644
--- a/memory.h
+++ b/memory.h
@@ -380,20 +380,21 @@ void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset);
 void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client);
 
 /**
- * memory_region_get_dirty: Check whether a page is dirty for a specified
- *                          client.
+ * memory_region_get_dirty: Check whether a range of bytes is dirty
+ *                          for a specified client.
  *
- * Checks whether a page has been written to since the last
+ * 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_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
-                             unsigned client);
+                             target_phys_addr_t size, unsigned client);
 
 /**
  * memory_region_set_dirty: Mark a range of bytes as dirty in a memory region.
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [PATCH 1/6] memory: change dirty getting API to take a size
  2012-01-29 19:13 [Qemu-devel] [PATCH 1/6] memory: change dirty getting API to take a size Blue Swirl
@ 2012-02-08  7:19 ` Evgeny Voevodin
  2012-02-08  7:42   ` Jan Kiszka
  0 siblings, 1 reply; 4+ messages in thread
From: Evgeny Voevodin @ 2012-02-08  7:19 UTC (permalink / raw)
  To: Blue Swirl; +Cc: Dmitry Solodkiy, Avi Kivity, qemu-devel

On 01/29/2012 11:13 PM, Blue Swirl wrote:
> Instead of each device knowing or guessing the guest page size,
> just pass the desired size of dirtied memory area.
>
> Signed-off-by: Blue Swirl<blauwirbel@gmail.com>
> ---
>   arch_init.c      |    7 ++++---
>   exec-obsolete.h  |   15 +++++++++++++--
>   hw/framebuffer.c |    9 +--------
>   hw/g364fb.c      |    3 ++-
>   hw/sm501.c       |   11 ++++-------
>   hw/tcx.c         |   19 +++++++++----------
>   hw/vga.c         |   17 +++++------------
>   memory.c         |    5 +++--
>   memory.h         |    9 +++++----
>   9 files changed, 46 insertions(+), 49 deletions(-)
>
> diff --git a/arch_init.c b/arch_init.c
> index 2366511..699bdd1 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -141,7 +141,8 @@ static int ram_save_block(QEMUFile *f)
>
>       do {
>           mr = block->mr;
> -        if (memory_region_get_dirty(mr, offset, DIRTY_MEMORY_MIGRATION)) {
> +        if (memory_region_get_dirty(mr, offset, TARGET_PAGE_SIZE,
> +                                    DIRTY_MEMORY_MIGRATION)) {
>               uint8_t *p;
>               int cont = (block == last_block) ? RAM_SAVE_FLAG_CONTINUE : 0;
>
> @@ -198,7 +199,7 @@ static ram_addr_t ram_save_remaining(void)
>       QLIST_FOREACH(block,&ram_list.blocks, next) {
>           ram_addr_t addr;
>           for (addr = 0; addr<  block->length; addr += TARGET_PAGE_SIZE) {
> -            if (memory_region_get_dirty(block->mr, addr,
> +            if (memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE,
>                                           DIRTY_MEMORY_MIGRATION)) {
>                   count++;
>               }
> @@ -283,7 +284,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int
> stage, void *opaque)
>           /* Make sure all dirty bits are set */
>           QLIST_FOREACH(block,&ram_list.blocks, next) {
>               for (addr = 0; addr<  block->length; addr += TARGET_PAGE_SIZE) {
> -                if (!memory_region_get_dirty(block->mr, addr,
> +                if (!memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE,
>                                                DIRTY_MEMORY_MIGRATION)) {
>                       memory_region_set_dirty(block->mr, addr, TARGET_PAGE_SIZE);
>                   }
> diff --git a/exec-obsolete.h b/exec-obsolete.h
> index d2749d3..94c23d0 100644
> --- a/exec-obsolete.h
> +++ b/exec-obsolete.h
> @@ -59,10 +59,21 @@ static inline int
> cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
>       return ram_list.phys_dirty[addr>>  TARGET_PAGE_BITS];
>   }
>
> -static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
> +static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
> +                                                ram_addr_t length,
>                                                   int dirty_flags)
>   {
> -    return ram_list.phys_dirty[addr>>  TARGET_PAGE_BITS]&  dirty_flags;
> +    int ret = 0;
> +    uint8_t *p;
> +    ram_addr_t addr, end;
> +
> +    end = TARGET_PAGE_ALIGN(start + length);
> +    start&= TARGET_PAGE_MASK;
> +    p = ram_list.phys_dirty + (start>>  TARGET_PAGE_BITS);
> +    for (addr = start; addr<  end; addr += TARGET_PAGE_SIZE) {
> +        ret |= *p++&  dirty_flags;
> +    }
> +    return ret;
>   }
>
>   static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
> diff --git a/hw/framebuffer.c b/hw/framebuffer.c
> index 6bf48dc..ea122fb 100644
> --- a/hw/framebuffer.c
> +++ b/hw/framebuffer.c
> @@ -87,15 +87,8 @@ void framebuffer_update_display(
>       dest += i * dest_row_pitch;
>
>       for (; i<  rows; i++) {
> -        target_phys_addr_t dirty_offset;
> -        dirty = 0;
> -        dirty_offset = 0;
> -        while (addr + dirty_offset<  TARGET_PAGE_ALIGN(addr + src_width)) {
> -            dirty |= memory_region_get_dirty(mem, addr + dirty_offset,
> +        dirty = memory_region_get_dirty(mem, addr, addr + src_width,
>                                                DIRTY_MEMORY_VGA);
> -            dirty_offset += TARGET_PAGE_SIZE;
> -        }
> -
>           if (dirty || invalidate) {
>               fn(opaque, dest, src, cols, dest_col_pitch);
>               if (first == -1)
> diff --git a/hw/g364fb.c b/hw/g364fb.c
> index 82b31f7..fa25033 100644
> --- a/hw/g364fb.c
> +++ b/hw/g364fb.c
> @@ -62,7 +62,8 @@ typedef struct G364State {
>
>   static inline int check_dirty(G364State *s, ram_addr_t page)
>   {
> -    return memory_region_get_dirty(&s->mem_vram, page, DIRTY_MEMORY_VGA);
> +    return memory_region_get_dirty(&s->mem_vram, page, G364_PAGE_SIZE,
> +                                   DIRTY_MEMORY_VGA);
>   }
>
>   static inline void reset_dirty(G364State *s,
> diff --git a/hw/sm501.c b/hw/sm501.c
> index 09c5894..94c0abf 100644
> --- a/hw/sm501.c
> +++ b/hw/sm501.c
> @@ -1323,15 +1323,12 @@ static void sm501_draw_crt(SM501State * s)
>       for (y = 0; y<  height; y++) {
>   	int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0;
>   	int update = full_update || update_hwc;
> -	ram_addr_t page0 = offset&  TARGET_PAGE_MASK;
> -	ram_addr_t page1 = (offset + width * src_bpp - 1)&  TARGET_PAGE_MASK;
> -	ram_addr_t page;
> +        ram_addr_t page0 = offset;
> +        ram_addr_t page1 = offset + width * src_bpp - 1;
>
>   	/* check dirty flags for each line */
> -	for (page = page0; page<= page1; page += TARGET_PAGE_SIZE)
> -            if (memory_region_get_dirty(&s->local_mem_region, page,
> -                                        DIRTY_MEMORY_VGA))
> -		update = 1;
> +        update = memory_region_get_dirty(&s->local_mem_region, page0, page1,
> +                                         DIRTY_MEMORY_VGA);
>
>   	/* draw line and change status */
>   	if (update) {
> diff --git a/hw/tcx.c b/hw/tcx.c
> index 7743c05..6054779 100644
> --- a/hw/tcx.c
> +++ b/hw/tcx.c
> @@ -178,15 +178,13 @@ static inline int check_dirty(TCXState *s,
> ram_addr_t page, ram_addr_t page24,
>                                 ram_addr_t cpage)
>   {
>       int ret;
> -    unsigned int off;
> -
> -    ret = memory_region_get_dirty(&s->vram_mem, page, DIRTY_MEMORY_VGA);
> -    for (off = 0; off<  TARGET_PAGE_SIZE * 4; off += TARGET_PAGE_SIZE) {
> -        ret |= memory_region_get_dirty(&s->vram_mem, page24 + off,
> -                                       DIRTY_MEMORY_VGA);
> -        ret |= memory_region_get_dirty(&s->vram_mem, cpage + off,
> -                                       DIRTY_MEMORY_VGA);
> -    }
> +
> +    ret = memory_region_get_dirty(&s->vram_mem, page, TARGET_PAGE_SIZE,
> +                                  DIRTY_MEMORY_VGA);
> +    ret |= memory_region_get_dirty(&s->vram_mem, page24, TARGET_PAGE_SIZE * 4,
> +                                   DIRTY_MEMORY_VGA);
> +    ret |= memory_region_get_dirty(&s->vram_mem, cpage, TARGET_PAGE_SIZE * 4,
> +                                   DIRTY_MEMORY_VGA);
>       return ret;
>   }
>
> @@ -245,7 +243,8 @@ static void tcx_update_display(void *opaque)
>       }
>
>       for(y = 0; y<  ts->height; y += 4, page += TARGET_PAGE_SIZE) {
> -        if (memory_region_get_dirty(&ts->vram_mem, page, DIRTY_MEMORY_VGA)) {
> +        if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE,
> +                                    DIRTY_MEMORY_VGA)) {
>               if (y_start<  0)
>                   y_start = y;
>               if (page<  page_min)
> diff --git a/hw/vga.c b/hw/vga.c
> index 4dc2610..cf9b39f 100644
> --- a/hw/vga.c
> +++ b/hw/vga.c
> @@ -1742,17 +1742,10 @@ static void vga_draw_graphic(VGACommonState
> *s, int full_update)
>           if (!(s->cr[0x17]&  2)) {
>               addr = (addr&  ~0x8000) | ((y1&  2)<<  14);
>           }
> -        page0 = addr&  TARGET_PAGE_MASK;
> -        page1 = (addr + bwidth - 1)&  TARGET_PAGE_MASK;
> -        update = full_update |
> -            memory_region_get_dirty(&s->vram, page0, DIRTY_MEMORY_VGA) |
> -            memory_region_get_dirty(&s->vram, page1, DIRTY_MEMORY_VGA);
> -        if ((page1 - page0)>  TARGET_PAGE_SIZE) {
> -            /* if wide line, can use another page */
> -            update |= memory_region_get_dirty(&s->vram,
> -                                              page0 + TARGET_PAGE_SIZE,
> -                                              DIRTY_MEMORY_VGA);
> -        }
> +        page0 = addr;
> +        page1 = addr + bwidth - 1;
> +        update = memory_region_get_dirty(&s->vram, page0, page1,
> +                                         DIRTY_MEMORY_VGA);
>           /* explicit invalidation for the hardware cursor */
>           update |= (s->invalidated_y_table[y>>  5]>>  (y&  0x1f))&  1;
>           if (update) {
> @@ -1798,7 +1791,7 @@ static void vga_draw_graphic(VGACommonState *s,
> int full_update)
>       if (page_max>= page_min) {
>           memory_region_reset_dirty(&s->vram,
>                                     page_min,
> -                                  page_max + TARGET_PAGE_SIZE - page_min,
> +                                  page_max - page_min,
>                                     DIRTY_MEMORY_VGA);
>       }
>       memset(s->invalidated_y_table, 0, ((height + 31)>>  5) * 4);
> diff --git a/memory.c b/memory.c
> index ee4c98a..5e77d8a 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -1136,10 +1136,11 @@ void memory_region_set_log(MemoryRegion *mr,
> bool log, unsigned client)
>   }
>
>   bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
> -                             unsigned client)
> +                             target_phys_addr_t size, unsigned client)
>   {
>       assert(mr->terminates);
> -    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1<<  client);
> +    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, size,
> +                                         1<<  client);
>   }
>
>   void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr,
> diff --git a/memory.h b/memory.h
> index fa45b99..4cf8d2f 100644
> --- a/memory.h
> +++ b/memory.h
> @@ -380,20 +380,21 @@ void memory_region_set_offset(MemoryRegion *mr,
> target_phys_addr_t offset);
>   void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client);
>
>   /**
> - * memory_region_get_dirty: Check whether a page is dirty for a specified
> - *                          client.
> + * memory_region_get_dirty: Check whether a range of bytes is dirty
> + *                          for a specified client.
>    *
> - * Checks whether a page has been written to since the last
> + * 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_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
> -                             unsigned client);
> +                             target_phys_addr_t size, unsigned client);
>
>   /**
>    * memory_region_set_dirty: Mark a range of bytes as dirty in a memory region.

Since this patch was applied to master, my realview-pbx board emulation 
with graphics support started to work about 10 times  slower (or even 
more, didn't make measures, but I can see it with the naked eye). This 
happens as soon as Linux kernel found an XVGA display and started to use 
frame buffer.

-- 
Kind regards,
Evgeny Voevodin,
Leading Software Engineer,
ASWG, Moscow R&D center, Samsung Electronics
e-mail: e.voevodin@samsung.com

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [PATCH 1/6] memory: change dirty getting API to take a size
  2012-02-08  7:19 ` Evgeny Voevodin
@ 2012-02-08  7:42   ` Jan Kiszka
  2012-02-08  8:00     ` Evgeny Voevodin
  0 siblings, 1 reply; 4+ messages in thread
From: Jan Kiszka @ 2012-02-08  7:42 UTC (permalink / raw)
  To: Evgeny Voevodin; +Cc: Blue Swirl, qemu-devel, Dmitry Solodkiy, Avi Kivity

[-- Attachment #1: Type: text/plain, Size: 12443 bytes --]

On 2012-02-08 08:19, Evgeny Voevodin wrote:
> On 01/29/2012 11:13 PM, Blue Swirl wrote:
>> Instead of each device knowing or guessing the guest page size,
>> just pass the desired size of dirtied memory area.
>>
>> Signed-off-by: Blue Swirl<blauwirbel@gmail.com>
>> ---
>>   arch_init.c      |    7 ++++---
>>   exec-obsolete.h  |   15 +++++++++++++--
>>   hw/framebuffer.c |    9 +--------
>>   hw/g364fb.c      |    3 ++-
>>   hw/sm501.c       |   11 ++++-------
>>   hw/tcx.c         |   19 +++++++++----------
>>   hw/vga.c         |   17 +++++------------
>>   memory.c         |    5 +++--
>>   memory.h         |    9 +++++----
>>   9 files changed, 46 insertions(+), 49 deletions(-)
>>
>> diff --git a/arch_init.c b/arch_init.c
>> index 2366511..699bdd1 100644
>> --- a/arch_init.c
>> +++ b/arch_init.c
>> @@ -141,7 +141,8 @@ static int ram_save_block(QEMUFile *f)
>>
>>       do {
>>           mr = block->mr;
>> -        if (memory_region_get_dirty(mr, offset,
>> DIRTY_MEMORY_MIGRATION)) {
>> +        if (memory_region_get_dirty(mr, offset, TARGET_PAGE_SIZE,
>> +                                    DIRTY_MEMORY_MIGRATION)) {
>>               uint8_t *p;
>>               int cont = (block == last_block) ?
>> RAM_SAVE_FLAG_CONTINUE : 0;
>>
>> @@ -198,7 +199,7 @@ static ram_addr_t ram_save_remaining(void)
>>       QLIST_FOREACH(block,&ram_list.blocks, next) {
>>           ram_addr_t addr;
>>           for (addr = 0; addr<  block->length; addr +=
>> TARGET_PAGE_SIZE) {
>> -            if (memory_region_get_dirty(block->mr, addr,
>> +            if (memory_region_get_dirty(block->mr, addr,
>> TARGET_PAGE_SIZE,
>>                                           DIRTY_MEMORY_MIGRATION)) {
>>                   count++;
>>               }
>> @@ -283,7 +284,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int
>> stage, void *opaque)
>>           /* Make sure all dirty bits are set */
>>           QLIST_FOREACH(block,&ram_list.blocks, next) {
>>               for (addr = 0; addr<  block->length; addr +=
>> TARGET_PAGE_SIZE) {
>> -                if (!memory_region_get_dirty(block->mr, addr,
>> +                if (!memory_region_get_dirty(block->mr, addr,
>> TARGET_PAGE_SIZE,
>>                                                DIRTY_MEMORY_MIGRATION)) {
>>                       memory_region_set_dirty(block->mr, addr,
>> TARGET_PAGE_SIZE);
>>                   }
>> diff --git a/exec-obsolete.h b/exec-obsolete.h
>> index d2749d3..94c23d0 100644
>> --- a/exec-obsolete.h
>> +++ b/exec-obsolete.h
>> @@ -59,10 +59,21 @@ static inline int
>> cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
>>       return ram_list.phys_dirty[addr>>  TARGET_PAGE_BITS];
>>   }
>>
>> -static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
>> +static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
>> +                                                ram_addr_t length,
>>                                                   int dirty_flags)
>>   {
>> -    return ram_list.phys_dirty[addr>>  TARGET_PAGE_BITS]&  dirty_flags;
>> +    int ret = 0;
>> +    uint8_t *p;
>> +    ram_addr_t addr, end;
>> +
>> +    end = TARGET_PAGE_ALIGN(start + length);
>> +    start&= TARGET_PAGE_MASK;
>> +    p = ram_list.phys_dirty + (start>>  TARGET_PAGE_BITS);
>> +    for (addr = start; addr<  end; addr += TARGET_PAGE_SIZE) {
>> +        ret |= *p++&  dirty_flags;
>> +    }
>> +    return ret;
>>   }
>>
>>   static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
>> diff --git a/hw/framebuffer.c b/hw/framebuffer.c
>> index 6bf48dc..ea122fb 100644
>> --- a/hw/framebuffer.c
>> +++ b/hw/framebuffer.c
>> @@ -87,15 +87,8 @@ void framebuffer_update_display(
>>       dest += i * dest_row_pitch;
>>
>>       for (; i<  rows; i++) {
>> -        target_phys_addr_t dirty_offset;
>> -        dirty = 0;
>> -        dirty_offset = 0;
>> -        while (addr + dirty_offset<  TARGET_PAGE_ALIGN(addr +
>> src_width)) {
>> -            dirty |= memory_region_get_dirty(mem, addr + dirty_offset,
>> +        dirty = memory_region_get_dirty(mem, addr, addr + src_width,
>>                                                DIRTY_MEMORY_VGA);
>> -            dirty_offset += TARGET_PAGE_SIZE;
>> -        }
>> -
>>           if (dirty || invalidate) {
>>               fn(opaque, dest, src, cols, dest_col_pitch);
>>               if (first == -1)
>> diff --git a/hw/g364fb.c b/hw/g364fb.c
>> index 82b31f7..fa25033 100644
>> --- a/hw/g364fb.c
>> +++ b/hw/g364fb.c
>> @@ -62,7 +62,8 @@ typedef struct G364State {
>>
>>   static inline int check_dirty(G364State *s, ram_addr_t page)
>>   {
>> -    return memory_region_get_dirty(&s->mem_vram, page,
>> DIRTY_MEMORY_VGA);
>> +    return memory_region_get_dirty(&s->mem_vram, page, G364_PAGE_SIZE,
>> +                                   DIRTY_MEMORY_VGA);
>>   }
>>
>>   static inline void reset_dirty(G364State *s,
>> diff --git a/hw/sm501.c b/hw/sm501.c
>> index 09c5894..94c0abf 100644
>> --- a/hw/sm501.c
>> +++ b/hw/sm501.c
>> @@ -1323,15 +1323,12 @@ static void sm501_draw_crt(SM501State * s)
>>       for (y = 0; y<  height; y++) {
>>       int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0;
>>       int update = full_update || update_hwc;
>> -    ram_addr_t page0 = offset&  TARGET_PAGE_MASK;
>> -    ram_addr_t page1 = (offset + width * src_bpp - 1)& 
>> TARGET_PAGE_MASK;
>> -    ram_addr_t page;
>> +        ram_addr_t page0 = offset;
>> +        ram_addr_t page1 = offset + width * src_bpp - 1;
>>
>>       /* check dirty flags for each line */
>> -    for (page = page0; page<= page1; page += TARGET_PAGE_SIZE)
>> -            if (memory_region_get_dirty(&s->local_mem_region, page,
>> -                                        DIRTY_MEMORY_VGA))
>> -        update = 1;
>> +        update = memory_region_get_dirty(&s->local_mem_region, page0,
>> page1,
>> +                                         DIRTY_MEMORY_VGA);
>>
>>       /* draw line and change status */
>>       if (update) {
>> diff --git a/hw/tcx.c b/hw/tcx.c
>> index 7743c05..6054779 100644
>> --- a/hw/tcx.c
>> +++ b/hw/tcx.c
>> @@ -178,15 +178,13 @@ static inline int check_dirty(TCXState *s,
>> ram_addr_t page, ram_addr_t page24,
>>                                 ram_addr_t cpage)
>>   {
>>       int ret;
>> -    unsigned int off;
>> -
>> -    ret = memory_region_get_dirty(&s->vram_mem, page, DIRTY_MEMORY_VGA);
>> -    for (off = 0; off<  TARGET_PAGE_SIZE * 4; off += TARGET_PAGE_SIZE) {
>> -        ret |= memory_region_get_dirty(&s->vram_mem, page24 + off,
>> -                                       DIRTY_MEMORY_VGA);
>> -        ret |= memory_region_get_dirty(&s->vram_mem, cpage + off,
>> -                                       DIRTY_MEMORY_VGA);
>> -    }
>> +
>> +    ret = memory_region_get_dirty(&s->vram_mem, page, TARGET_PAGE_SIZE,
>> +                                  DIRTY_MEMORY_VGA);
>> +    ret |= memory_region_get_dirty(&s->vram_mem, page24,
>> TARGET_PAGE_SIZE * 4,
>> +                                   DIRTY_MEMORY_VGA);
>> +    ret |= memory_region_get_dirty(&s->vram_mem, cpage,
>> TARGET_PAGE_SIZE * 4,
>> +                                   DIRTY_MEMORY_VGA);
>>       return ret;
>>   }
>>
>> @@ -245,7 +243,8 @@ static void tcx_update_display(void *opaque)
>>       }
>>
>>       for(y = 0; y<  ts->height; y += 4, page += TARGET_PAGE_SIZE) {
>> -        if (memory_region_get_dirty(&ts->vram_mem, page,
>> DIRTY_MEMORY_VGA)) {
>> +        if (memory_region_get_dirty(&ts->vram_mem, page,
>> TARGET_PAGE_SIZE,
>> +                                    DIRTY_MEMORY_VGA)) {
>>               if (y_start<  0)
>>                   y_start = y;
>>               if (page<  page_min)
>> diff --git a/hw/vga.c b/hw/vga.c
>> index 4dc2610..cf9b39f 100644
>> --- a/hw/vga.c
>> +++ b/hw/vga.c
>> @@ -1742,17 +1742,10 @@ static void vga_draw_graphic(VGACommonState
>> *s, int full_update)
>>           if (!(s->cr[0x17]&  2)) {
>>               addr = (addr&  ~0x8000) | ((y1&  2)<<  14);
>>           }
>> -        page0 = addr&  TARGET_PAGE_MASK;
>> -        page1 = (addr + bwidth - 1)&  TARGET_PAGE_MASK;
>> -        update = full_update |
>> -            memory_region_get_dirty(&s->vram, page0, DIRTY_MEMORY_VGA) |
>> -            memory_region_get_dirty(&s->vram, page1, DIRTY_MEMORY_VGA);
>> -        if ((page1 - page0)>  TARGET_PAGE_SIZE) {
>> -            /* if wide line, can use another page */
>> -            update |= memory_region_get_dirty(&s->vram,
>> -                                              page0 + TARGET_PAGE_SIZE,
>> -                                              DIRTY_MEMORY_VGA);
>> -        }
>> +        page0 = addr;
>> +        page1 = addr + bwidth - 1;
>> +        update = memory_region_get_dirty(&s->vram, page0, page1,
>> +                                         DIRTY_MEMORY_VGA);
>>           /* explicit invalidation for the hardware cursor */
>>           update |= (s->invalidated_y_table[y>>  5]>>  (y&  0x1f))&  1;
>>           if (update) {
>> @@ -1798,7 +1791,7 @@ static void vga_draw_graphic(VGACommonState *s,
>> int full_update)
>>       if (page_max>= page_min) {
>>           memory_region_reset_dirty(&s->vram,
>>                                     page_min,
>> -                                  page_max + TARGET_PAGE_SIZE -
>> page_min,
>> +                                  page_max - page_min,
>>                                     DIRTY_MEMORY_VGA);
>>       }
>>       memset(s->invalidated_y_table, 0, ((height + 31)>>  5) * 4);
>> diff --git a/memory.c b/memory.c
>> index ee4c98a..5e77d8a 100644
>> --- a/memory.c
>> +++ b/memory.c
>> @@ -1136,10 +1136,11 @@ void memory_region_set_log(MemoryRegion *mr,
>> bool log, unsigned client)
>>   }
>>
>>   bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
>> -                             unsigned client)
>> +                             target_phys_addr_t size, unsigned client)
>>   {
>>       assert(mr->terminates);
>> -    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1<< 
>> client);
>> +    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, size,
>> +                                         1<<  client);
>>   }
>>
>>   void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr,
>> diff --git a/memory.h b/memory.h
>> index fa45b99..4cf8d2f 100644
>> --- a/memory.h
>> +++ b/memory.h
>> @@ -380,20 +380,21 @@ void memory_region_set_offset(MemoryRegion *mr,
>> target_phys_addr_t offset);
>>   void memory_region_set_log(MemoryRegion *mr, bool log, unsigned
>> client);
>>
>>   /**
>> - * memory_region_get_dirty: Check whether a page is dirty for a
>> specified
>> - *                          client.
>> + * memory_region_get_dirty: Check whether a range of bytes is dirty
>> + *                          for a specified client.
>>    *
>> - * Checks whether a page has been written to since the last
>> + * 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_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
>> -                             unsigned client);
>> +                             target_phys_addr_t size, unsigned client);
>>
>>   /**
>>    * memory_region_set_dirty: Mark a range of bytes as dirty in a
>> memory region.
> 
> Since this patch was applied to master, my realview-pbx board emulation
> with graphics support started to work about 10 times  slower (or even
> more, didn't make measures, but I can see it with the naked eye). This
> happens as soon as Linux kernel found an XVGA display and started to use
> frame buffer.
> 

Do [1] or [2] make a difference?

Jan

[1] http://thread.gmane.org/gmane.comp.emulators.qemu/134958
[2] http://thread.gmane.org/gmane.comp.emulators.qemu/135244



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [PATCH 1/6] memory: change dirty getting API to take a size
  2012-02-08  7:42   ` Jan Kiszka
@ 2012-02-08  8:00     ` Evgeny Voevodin
  0 siblings, 0 replies; 4+ messages in thread
From: Evgeny Voevodin @ 2012-02-08  8:00 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Blue Swirl, qemu-devel, Dmitry Solodkiy, Avi Kivity

On 02/08/2012 11:42 AM, Jan Kiszka wrote:
> On 2012-02-08 08:19, Evgeny Voevodin wrote:
>> On 01/29/2012 11:13 PM, Blue Swirl wrote:
>>> Instead of each device knowing or guessing the guest page size,
>>> just pass the desired size of dirtied memory area.
>>>
>>> Signed-off-by: Blue Swirl<blauwirbel@gmail.com>
>>> ---
>>>    arch_init.c      |    7 ++++---
>>>    exec-obsolete.h  |   15 +++++++++++++--
>>>    hw/framebuffer.c |    9 +--------
>>>    hw/g364fb.c      |    3 ++-
>>>    hw/sm501.c       |   11 ++++-------
>>>    hw/tcx.c         |   19 +++++++++----------
>>>    hw/vga.c         |   17 +++++------------
>>>    memory.c         |    5 +++--
>>>    memory.h         |    9 +++++----
>>>    9 files changed, 46 insertions(+), 49 deletions(-)
>>>
>>> diff --git a/arch_init.c b/arch_init.c
>>> index 2366511..699bdd1 100644
>>> --- a/arch_init.c
>>> +++ b/arch_init.c
>>> @@ -141,7 +141,8 @@ static int ram_save_block(QEMUFile *f)
>>>
>>>        do {
>>>            mr = block->mr;
>>> -        if (memory_region_get_dirty(mr, offset,
>>> DIRTY_MEMORY_MIGRATION)) {
>>> +        if (memory_region_get_dirty(mr, offset, TARGET_PAGE_SIZE,
>>> +                                    DIRTY_MEMORY_MIGRATION)) {
>>>                uint8_t *p;
>>>                int cont = (block == last_block) ?
>>> RAM_SAVE_FLAG_CONTINUE : 0;
>>>
>>> @@ -198,7 +199,7 @@ static ram_addr_t ram_save_remaining(void)
>>>        QLIST_FOREACH(block,&ram_list.blocks, next) {
>>>            ram_addr_t addr;
>>>            for (addr = 0; addr<   block->length; addr +=
>>> TARGET_PAGE_SIZE) {
>>> -            if (memory_region_get_dirty(block->mr, addr,
>>> +            if (memory_region_get_dirty(block->mr, addr,
>>> TARGET_PAGE_SIZE,
>>>                                            DIRTY_MEMORY_MIGRATION)) {
>>>                    count++;
>>>                }
>>> @@ -283,7 +284,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int
>>> stage, void *opaque)
>>>            /* Make sure all dirty bits are set */
>>>            QLIST_FOREACH(block,&ram_list.blocks, next) {
>>>                for (addr = 0; addr<   block->length; addr +=
>>> TARGET_PAGE_SIZE) {
>>> -                if (!memory_region_get_dirty(block->mr, addr,
>>> +                if (!memory_region_get_dirty(block->mr, addr,
>>> TARGET_PAGE_SIZE,
>>>                                                 DIRTY_MEMORY_MIGRATION)) {
>>>                        memory_region_set_dirty(block->mr, addr,
>>> TARGET_PAGE_SIZE);
>>>                    }
>>> diff --git a/exec-obsolete.h b/exec-obsolete.h
>>> index d2749d3..94c23d0 100644
>>> --- a/exec-obsolete.h
>>> +++ b/exec-obsolete.h
>>> @@ -59,10 +59,21 @@ static inline int
>>> cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
>>>        return ram_list.phys_dirty[addr>>   TARGET_PAGE_BITS];
>>>    }
>>>
>>> -static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
>>> +static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
>>> +                                                ram_addr_t length,
>>>                                                    int dirty_flags)
>>>    {
>>> -    return ram_list.phys_dirty[addr>>   TARGET_PAGE_BITS]&   dirty_flags;
>>> +    int ret = 0;
>>> +    uint8_t *p;
>>> +    ram_addr_t addr, end;
>>> +
>>> +    end = TARGET_PAGE_ALIGN(start + length);
>>> +    start&= TARGET_PAGE_MASK;
>>> +    p = ram_list.phys_dirty + (start>>   TARGET_PAGE_BITS);
>>> +    for (addr = start; addr<   end; addr += TARGET_PAGE_SIZE) {
>>> +        ret |= *p++&   dirty_flags;
>>> +    }
>>> +    return ret;
>>>    }
>>>
>>>    static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
>>> diff --git a/hw/framebuffer.c b/hw/framebuffer.c
>>> index 6bf48dc..ea122fb 100644
>>> --- a/hw/framebuffer.c
>>> +++ b/hw/framebuffer.c
>>> @@ -87,15 +87,8 @@ void framebuffer_update_display(
>>>        dest += i * dest_row_pitch;
>>>
>>>        for (; i<   rows; i++) {
>>> -        target_phys_addr_t dirty_offset;
>>> -        dirty = 0;
>>> -        dirty_offset = 0;
>>> -        while (addr + dirty_offset<   TARGET_PAGE_ALIGN(addr +
>>> src_width)) {
>>> -            dirty |= memory_region_get_dirty(mem, addr + dirty_offset,
>>> +        dirty = memory_region_get_dirty(mem, addr, addr + src_width,
>>>                                                 DIRTY_MEMORY_VGA);
>>> -            dirty_offset += TARGET_PAGE_SIZE;
>>> -        }
>>> -
>>>            if (dirty || invalidate) {
>>>                fn(opaque, dest, src, cols, dest_col_pitch);
>>>                if (first == -1)
>>> diff --git a/hw/g364fb.c b/hw/g364fb.c
>>> index 82b31f7..fa25033 100644
>>> --- a/hw/g364fb.c
>>> +++ b/hw/g364fb.c
>>> @@ -62,7 +62,8 @@ typedef struct G364State {
>>>
>>>    static inline int check_dirty(G364State *s, ram_addr_t page)
>>>    {
>>> -    return memory_region_get_dirty(&s->mem_vram, page,
>>> DIRTY_MEMORY_VGA);
>>> +    return memory_region_get_dirty(&s->mem_vram, page, G364_PAGE_SIZE,
>>> +                                   DIRTY_MEMORY_VGA);
>>>    }
>>>
>>>    static inline void reset_dirty(G364State *s,
>>> diff --git a/hw/sm501.c b/hw/sm501.c
>>> index 09c5894..94c0abf 100644
>>> --- a/hw/sm501.c
>>> +++ b/hw/sm501.c
>>> @@ -1323,15 +1323,12 @@ static void sm501_draw_crt(SM501State * s)
>>>        for (y = 0; y<   height; y++) {
>>>        int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0;
>>>        int update = full_update || update_hwc;
>>> -    ram_addr_t page0 = offset&   TARGET_PAGE_MASK;
>>> -    ram_addr_t page1 = (offset + width * src_bpp - 1)&
>>> TARGET_PAGE_MASK;
>>> -    ram_addr_t page;
>>> +        ram_addr_t page0 = offset;
>>> +        ram_addr_t page1 = offset + width * src_bpp - 1;
>>>
>>>        /* check dirty flags for each line */
>>> -    for (page = page0; page<= page1; page += TARGET_PAGE_SIZE)
>>> -            if (memory_region_get_dirty(&s->local_mem_region, page,
>>> -                                        DIRTY_MEMORY_VGA))
>>> -        update = 1;
>>> +        update = memory_region_get_dirty(&s->local_mem_region, page0,
>>> page1,
>>> +                                         DIRTY_MEMORY_VGA);
>>>
>>>        /* draw line and change status */
>>>        if (update) {
>>> diff --git a/hw/tcx.c b/hw/tcx.c
>>> index 7743c05..6054779 100644
>>> --- a/hw/tcx.c
>>> +++ b/hw/tcx.c
>>> @@ -178,15 +178,13 @@ static inline int check_dirty(TCXState *s,
>>> ram_addr_t page, ram_addr_t page24,
>>>                                  ram_addr_t cpage)
>>>    {
>>>        int ret;
>>> -    unsigned int off;
>>> -
>>> -    ret = memory_region_get_dirty(&s->vram_mem, page, DIRTY_MEMORY_VGA);
>>> -    for (off = 0; off<   TARGET_PAGE_SIZE * 4; off += TARGET_PAGE_SIZE) {
>>> -        ret |= memory_region_get_dirty(&s->vram_mem, page24 + off,
>>> -                                       DIRTY_MEMORY_VGA);
>>> -        ret |= memory_region_get_dirty(&s->vram_mem, cpage + off,
>>> -                                       DIRTY_MEMORY_VGA);
>>> -    }
>>> +
>>> +    ret = memory_region_get_dirty(&s->vram_mem, page, TARGET_PAGE_SIZE,
>>> +                                  DIRTY_MEMORY_VGA);
>>> +    ret |= memory_region_get_dirty(&s->vram_mem, page24,
>>> TARGET_PAGE_SIZE * 4,
>>> +                                   DIRTY_MEMORY_VGA);
>>> +    ret |= memory_region_get_dirty(&s->vram_mem, cpage,
>>> TARGET_PAGE_SIZE * 4,
>>> +                                   DIRTY_MEMORY_VGA);
>>>        return ret;
>>>    }
>>>
>>> @@ -245,7 +243,8 @@ static void tcx_update_display(void *opaque)
>>>        }
>>>
>>>        for(y = 0; y<   ts->height; y += 4, page += TARGET_PAGE_SIZE) {
>>> -        if (memory_region_get_dirty(&ts->vram_mem, page,
>>> DIRTY_MEMORY_VGA)) {
>>> +        if (memory_region_get_dirty(&ts->vram_mem, page,
>>> TARGET_PAGE_SIZE,
>>> +                                    DIRTY_MEMORY_VGA)) {
>>>                if (y_start<   0)
>>>                    y_start = y;
>>>                if (page<   page_min)
>>> diff --git a/hw/vga.c b/hw/vga.c
>>> index 4dc2610..cf9b39f 100644
>>> --- a/hw/vga.c
>>> +++ b/hw/vga.c
>>> @@ -1742,17 +1742,10 @@ static void vga_draw_graphic(VGACommonState
>>> *s, int full_update)
>>>            if (!(s->cr[0x17]&   2)) {
>>>                addr = (addr&   ~0x8000) | ((y1&   2)<<   14);
>>>            }
>>> -        page0 = addr&   TARGET_PAGE_MASK;
>>> -        page1 = (addr + bwidth - 1)&   TARGET_PAGE_MASK;
>>> -        update = full_update |
>>> -            memory_region_get_dirty(&s->vram, page0, DIRTY_MEMORY_VGA) |
>>> -            memory_region_get_dirty(&s->vram, page1, DIRTY_MEMORY_VGA);
>>> -        if ((page1 - page0)>   TARGET_PAGE_SIZE) {
>>> -            /* if wide line, can use another page */
>>> -            update |= memory_region_get_dirty(&s->vram,
>>> -                                              page0 + TARGET_PAGE_SIZE,
>>> -                                              DIRTY_MEMORY_VGA);
>>> -        }
>>> +        page0 = addr;
>>> +        page1 = addr + bwidth - 1;
>>> +        update = memory_region_get_dirty(&s->vram, page0, page1,
>>> +                                         DIRTY_MEMORY_VGA);
>>>            /* explicit invalidation for the hardware cursor */
>>>            update |= (s->invalidated_y_table[y>>   5]>>   (y&   0x1f))&   1;
>>>            if (update) {
>>> @@ -1798,7 +1791,7 @@ static void vga_draw_graphic(VGACommonState *s,
>>> int full_update)
>>>        if (page_max>= page_min) {
>>>            memory_region_reset_dirty(&s->vram,
>>>                                      page_min,
>>> -                                  page_max + TARGET_PAGE_SIZE -
>>> page_min,
>>> +                                  page_max - page_min,
>>>                                      DIRTY_MEMORY_VGA);
>>>        }
>>>        memset(s->invalidated_y_table, 0, ((height + 31)>>   5) * 4);
>>> diff --git a/memory.c b/memory.c
>>> index ee4c98a..5e77d8a 100644
>>> --- a/memory.c
>>> +++ b/memory.c
>>> @@ -1136,10 +1136,11 @@ void memory_region_set_log(MemoryRegion *mr,
>>> bool log, unsigned client)
>>>    }
>>>
>>>    bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
>>> -                             unsigned client)
>>> +                             target_phys_addr_t size, unsigned client)
>>>    {
>>>        assert(mr->terminates);
>>> -    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1<<
>>> client);
>>> +    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, size,
>>> +                                         1<<   client);
>>>    }
>>>
>>>    void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr,
>>> diff --git a/memory.h b/memory.h
>>> index fa45b99..4cf8d2f 100644
>>> --- a/memory.h
>>> +++ b/memory.h
>>> @@ -380,20 +380,21 @@ void memory_region_set_offset(MemoryRegion *mr,
>>> target_phys_addr_t offset);
>>>    void memory_region_set_log(MemoryRegion *mr, bool log, unsigned
>>> client);
>>>
>>>    /**
>>> - * memory_region_get_dirty: Check whether a page is dirty for a
>>> specified
>>> - *                          client.
>>> + * memory_region_get_dirty: Check whether a range of bytes is dirty
>>> + *                          for a specified client.
>>>     *
>>> - * Checks whether a page has been written to since the last
>>> + * 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_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
>>> -                             unsigned client);
>>> +                             target_phys_addr_t size, unsigned client);
>>>
>>>    /**
>>>     * memory_region_set_dirty: Mark a range of bytes as dirty in a
>>> memory region.
>> Since this patch was applied to master, my realview-pbx board emulation
>> with graphics support started to work about 10 times  slower (or even
>> more, didn't make measures, but I can see it with the naked eye). This
>> happens as soon as Linux kernel found an XVGA display and started to use
>> frame buffer.
>>
> Do [1] or [2] make a difference?
>
> Jan
>
> [1] http://thread.gmane.org/gmane.comp.emulators.qemu/134958

Helped.

> [2] http://thread.gmane.org/gmane.comp.emulators.qemu/135244
>
>


-- 
Kind regards,
Evgeny Voevodin,
Leading Software Engineer,
ASWG, Moscow R&D center, Samsung Electronics
e-mail: e.voevodin@samsung.com

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-02-08  8:00 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-29 19:13 [Qemu-devel] [PATCH 1/6] memory: change dirty getting API to take a size Blue Swirl
2012-02-08  7:19 ` Evgeny Voevodin
2012-02-08  7:42   ` Jan Kiszka
2012-02-08  8:00     ` Evgeny Voevodin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.