Re: [Qemu-devel] [RFC PATCH v2 3/3] Per memslot dirty bitmap

2011-08-02 Thread Marcelo Tosatti
On Fri, Jul 29, 2011 at 04:57:26PM -0400, Umesh Deshpande wrote:
 This patch creates a separate dirty bitmap for each slot. Currently dirty 
 bitmap
 is created for addresses ranging from 0 to the end address of the last memory
 slot. Since the memslots are not necessarily contiguous, current bitmap might
 contain empty region or holes that doesn't represent any VM pages. This patch
 reduces the size of the dirty bitmap by allocating per memslot dirty bitmaps.
 
 Signed-off-by: Umesh Deshpande udesh...@redhat.com
 ---
  cpu-all.h |   40 +---
  exec.c|   38 +++---
  xen-all.c |6 ++
  3 files changed, 58 insertions(+), 26 deletions(-)
 
 diff --git a/cpu-all.h b/cpu-all.h
 index e839100..9517a9b 100644
 --- a/cpu-all.h
 +++ b/cpu-all.h
 @@ -920,6 +920,7 @@ extern ram_addr_t ram_size;
  
  typedef struct RAMBlock {
  uint8_t *host;
 +uint8_t *phys_dirty;
  ram_addr_t offset;
  ram_addr_t length;
  uint32_t flags;
 @@ -931,7 +932,6 @@ typedef struct RAMBlock {
  } RAMBlock;
  
  typedef struct RAMList {
 -uint8_t *phys_dirty;
  QLIST_HEAD(ram, RAMBlock) blocks;
  } RAMList;
  extern RAMList ram_list;
 @@ -961,32 +961,55 @@ extern int mem_prealloc;
  #define CODE_DIRTY_FLAG  0x02
  #define MIGRATION_DIRTY_FLAG 0x08
  
 +RAMBlock *qemu_addr_to_ramblock(ram_addr_t);
 +
 +static inline int get_page_nr(ram_addr_t addr, RAMBlock **block)
 +{
 +int page_nr;
 +*block = qemu_addr_to_ramblock(addr);
 +
 +page_nr = addr - (*block)-offset;
 +page_nr = page_nr  TARGET_PAGE_BITS;
 +
 +return page_nr;
 +}
 +
  /* read dirty bit (return 0 or 1) */
  static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
  {
 -return ram_list.phys_dirty[addr  TARGET_PAGE_BITS] == 0xff;
 +RAMBlock *block;
 +int page_nr = get_page_nr(addr, block);
 +return block-phys_dirty[page_nr] == 0xff;
  }
  
  static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
  {
 -return ram_list.phys_dirty[addr  TARGET_PAGE_BITS];
 +RAMBlock *block;
 +int page_nr = get_page_nr(addr, block);
 +return block-phys_dirty[page_nr];
  }
  
  static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
  int dirty_flags)
  {
 -return ram_list.phys_dirty[addr  TARGET_PAGE_BITS]  dirty_flags;
 +RAMBlock *block;
 +int page_nr = get_page_nr(addr, block);
 +return block-phys_dirty[page_nr]  dirty_flags;
  }
  
  static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
  {
 -ram_list.phys_dirty[addr  TARGET_PAGE_BITS] = 0xff;
 +RAMBlock *block;
 +int page_nr = get_page_nr(addr, block);
 +block-phys_dirty[page_nr] = 0xff;
  }
  
  static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr,
int dirty_flags)
  {
 -return ram_list.phys_dirty[addr  TARGET_PAGE_BITS] |= dirty_flags;
 +RAMBlock *block;
 +int page_nr = get_page_nr(addr, block);
 +return block-phys_dirty[page_nr] |= dirty_flags;
  }
  
  static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
 @@ -995,10 +1018,13 @@ static inline void 
 cpu_physical_memory_mask_dirty_range(ram_addr_t start,
  {
  int i, mask, len;
  uint8_t *p;
 +RAMBlock *block;
 +int page_nr = get_page_nr(start, block);
  
  len = length  TARGET_PAGE_BITS;
  mask = ~dirty_flags;
 -p = ram_list.phys_dirty + (start  TARGET_PAGE_BITS);
 +
 +p = block-phys_dirty + page_nr;
  p[i] = mask;
  }
 diff --git a/exec.c b/exec.c
 index 0e2ce57..6312550 100644
 --- a/exec.c
 +++ b/exec.c
 @@ -2106,6 +2106,10 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, 
 ram_addr_t end,
  abort();
  }
  
 +if (kvm_enabled()) {
 +return;
 +}
 +

This belongs to a separate patch.




[Qemu-devel] [RFC PATCH v2 3/3] Per memslot dirty bitmap

2011-07-29 Thread Umesh Deshpande
This patch creates a separate dirty bitmap for each slot. Currently dirty bitmap
is created for addresses ranging from 0 to the end address of the last memory
slot. Since the memslots are not necessarily contiguous, current bitmap might
contain empty region or holes that doesn't represent any VM pages. This patch
reduces the size of the dirty bitmap by allocating per memslot dirty bitmaps.

Signed-off-by: Umesh Deshpande udesh...@redhat.com
---
 cpu-all.h |   40 +---
 exec.c|   38 +++---
 xen-all.c |6 ++
 3 files changed, 58 insertions(+), 26 deletions(-)

diff --git a/cpu-all.h b/cpu-all.h
index e839100..9517a9b 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -920,6 +920,7 @@ extern ram_addr_t ram_size;
 
 typedef struct RAMBlock {
 uint8_t *host;
+uint8_t *phys_dirty;
 ram_addr_t offset;
 ram_addr_t length;
 uint32_t flags;
@@ -931,7 +932,6 @@ typedef struct RAMBlock {
 } RAMBlock;
 
 typedef struct RAMList {
-uint8_t *phys_dirty;
 QLIST_HEAD(ram, RAMBlock) blocks;
 } RAMList;
 extern RAMList ram_list;
@@ -961,32 +961,55 @@ extern int mem_prealloc;
 #define CODE_DIRTY_FLAG  0x02
 #define MIGRATION_DIRTY_FLAG 0x08
 
+RAMBlock *qemu_addr_to_ramblock(ram_addr_t);
+
+static inline int get_page_nr(ram_addr_t addr, RAMBlock **block)
+{
+int page_nr;
+*block = qemu_addr_to_ramblock(addr);
+
+page_nr = addr - (*block)-offset;
+page_nr = page_nr  TARGET_PAGE_BITS;
+
+return page_nr;
+}
+
 /* read dirty bit (return 0 or 1) */
 static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
 {
-return ram_list.phys_dirty[addr  TARGET_PAGE_BITS] == 0xff;
+RAMBlock *block;
+int page_nr = get_page_nr(addr, block);
+return block-phys_dirty[page_nr] == 0xff;
 }
 
 static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
 {
-return ram_list.phys_dirty[addr  TARGET_PAGE_BITS];
+RAMBlock *block;
+int page_nr = get_page_nr(addr, block);
+return block-phys_dirty[page_nr];
 }
 
 static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
 int dirty_flags)
 {
-return ram_list.phys_dirty[addr  TARGET_PAGE_BITS]  dirty_flags;
+RAMBlock *block;
+int page_nr = get_page_nr(addr, block);
+return block-phys_dirty[page_nr]  dirty_flags;
 }
 
 static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
 {
-ram_list.phys_dirty[addr  TARGET_PAGE_BITS] = 0xff;
+RAMBlock *block;
+int page_nr = get_page_nr(addr, block);
+block-phys_dirty[page_nr] = 0xff;
 }
 
 static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr,
   int dirty_flags)
 {
-return ram_list.phys_dirty[addr  TARGET_PAGE_BITS] |= dirty_flags;
+RAMBlock *block;
+int page_nr = get_page_nr(addr, block);
+return block-phys_dirty[page_nr] |= dirty_flags;
 }
 
 static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
@@ -995,10 +1018,13 @@ static inline void 
cpu_physical_memory_mask_dirty_range(ram_addr_t start,
 {
 int i, mask, len;
 uint8_t *p;
+RAMBlock *block;
+int page_nr = get_page_nr(start, block);
 
 len = length  TARGET_PAGE_BITS;
 mask = ~dirty_flags;
-p = ram_list.phys_dirty + (start  TARGET_PAGE_BITS);
+
+p = block-phys_dirty + page_nr;
 for (i = 0; i  len; i++) {
 p[i] = mask;
 }
diff --git a/exec.c b/exec.c
index 0e2ce57..6312550 100644
--- a/exec.c
+++ b/exec.c
@@ -2106,6 +2106,10 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, 
ram_addr_t end,
 abort();
 }
 
+if (kvm_enabled()) {
+return;
+}
+
 for(env = first_cpu; env != NULL; env = env-next_cpu) {
 int mmu_idx;
 for (mmu_idx = 0; mmu_idx  NB_MMU_MODES; mmu_idx++) {
@@ -2894,17 +2898,6 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
 return offset;
 }
 
-static ram_addr_t last_ram_offset(void)
-{
-RAMBlock *block;
-ram_addr_t last = 0;
-
-QLIST_FOREACH(block, ram_list.blocks, next)
-last = MAX(last, block-offset + block-length);
-
-return last;
-}
-
 ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
ram_addr_t size, void *host)
 {
@@ -2974,10 +2967,8 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, 
const char *name,
 
 QLIST_INSERT_HEAD(ram_list.blocks, new_block, next);
 
-ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,
-   last_ram_offset()  TARGET_PAGE_BITS);
-memset(ram_list.phys_dirty + (new_block-offset  TARGET_PAGE_BITS),
-   0xff, size  TARGET_PAGE_BITS);
+new_block-phys_dirty = qemu_mallocz(new_block-length  
TARGET_PAGE_BITS);
+memset(new_block-phys_dirty, 0xff, new_block-length  TARGET_PAGE_BITS);
 
 if (kvm_enabled())
 kvm_setup_guest_memory(new_block-host, size);