qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 1/6] memory: change dirty getting API to take a


From: Evgeny Voevodin
Subject: Re: [Qemu-devel] [PATCH 1/6] memory: change dirty getting API to take a size
Date: Wed, 08 Feb 2012 11:19:32 +0400
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.24) Gecko/20111108 Thunderbird/3.1.16

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<address@hidden>
---
  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: address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]