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);