We think access phys_ram_dirty through inline functions is better than directly for encoupseling reason. We devided the ram in a 64 pages block. Each block has a counter, which is stored in phys_ram_dirty_by_word. It shows the number of dirty pages. We will find the 64 pages block is dirty or non-dirty using phys_ram_dirty_by_word. Signed-off-by: OHMURA Kei <ohmura.kei@xxxxxxxxxxxxx> --- cpu-all.h | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cpu-defs.h | 1 + 2 files changed, 75 insertions(+), 0 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index 8ed76c7..2251f14 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -168,6 +168,33 @@ typedef union { } CPU_QuadU; #endif +static inline unsigned long unroll_flags_to_ul(int flags) +{ + unsigned long ret = 0, flags_ul = (unsigned long)flags; + +#if TARGET_LONG_SIZE == 4 + ret |= flags_ul << 0; + ret |= flags_ul << 8; + ret |= flags_ul << 16; + ret |= flags_ul << 24; +#elif TARGET_LONG_SIZE == 8 + ret |= flags_ul << 0; + ret |= flags_ul << 8; + ret |= flags_ul << 16; + ret |= flags_ul << 24; + ret |= flags_ul << 32; + ret |= flags_ul << 40; + ret |= flags_ul << 48; + ret |= flags_ul << 56; +#else + int i; + for (i = 0; i < sizeof(unsigned long); i++) + ret |= flags_ul << (i * 8); +#endif + + return ret; +} + /* CPU memory access without any memory or io remapping */ /* @@ -847,6 +874,7 @@ int cpu_str_to_log_mask(const char *str); extern int phys_ram_fd; extern uint8_t *phys_ram_dirty; +extern int *phys_ram_dirty_by_word; extern ram_addr_t ram_size; extern ram_addr_t last_ram_offset; extern uint8_t *bios_mem; @@ -882,6 +910,11 @@ static inline int cpu_physical_memory_is_dirty(ram_addr_t addr) return phys_ram_dirty[addr >> TARGET_PAGE_BITS] == 0xff; } +static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr) +{ + return phys_ram_dirty[addr >> TARGET_PAGE_BITS]; +} + static inline int cpu_physical_memory_get_dirty(ram_addr_t addr, int dirty_flags) { @@ -890,9 +923,50 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t addr, static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) { + if (phys_ram_dirty[addr >> TARGET_PAGE_BITS] != 0xff) + ++phys_ram_dirty_by_word[(addr >> TARGET_PAGE_BITS) / + TARGET_LONG_BITS]; + phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 0xff; } +static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr, + int dirty_flags) +{ + if ((phys_ram_dirty[addr >> TARGET_PAGE_BITS] != 0xff) && + ((phys_ram_dirty[addr >> TARGET_PAGE_BITS] | dirty_flags) == 0xff)) + ++phys_ram_dirty_by_word[(addr >> TARGET_PAGE_BITS) / + TARGET_LONG_BITS]; + + return phys_ram_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags; +} + +static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start, + int length, + int dirty_flags) +{ + int i, mask, len, *pw; + uint8_t *p; + + len = length >> TARGET_PAGE_BITS; + mask = ~dirty_flags; + p = phys_ram_dirty + (start >> TARGET_PAGE_BITS); + pw = phys_ram_dirty_by_word + (start >> TARGET_PAGE_BITS) / + TARGET_LONG_BITS; + + for (i = 0; i < len; i++) { + if (p[i] == 0xff) + --pw[i / TARGET_LONG_BITS]; + p[i] &= mask; + } +} + +int cpu_physical_memory_get_dirty_range(ram_addr_t start, ram_addr_t end, + int dirty_flags); + +int cpu_physical_memory_get_non_dirty_range(ram_addr_t start, ram_addr_t end, + int dirty_flags); + void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, int dirty_flags); void cpu_tlb_update_dirty(CPUState *env); diff --git a/cpu-defs.h b/cpu-defs.h index cf502e9..8e89e96 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -37,6 +37,7 @@ #endif #define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8) +#define TARGET_LONG_ALIGN(addr) (((addr) + TARGET_LONG_BITS - 1) / TARGET_LONG_BITS) /* target_ulong is the type of a virtual address */ #if TARGET_LONG_SIZE == 4 -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html