#define DIRTY_CLIENTS_ALL ((1 << DIRTY_MEMORY_NUM) - 1)
#define DIRTY_CLIENTS_NOCODE (DIRTY_CLIENTS_ALL & ~(1 << DIRTY_MEMORY_CODE))
-static inline bool cpu_physical_memory_all_dirty(ram_addr_t start,
- ram_addr_t length,
- unsigned client)
-{
- DirtyMemoryBlocks *blocks;
- unsigned long end, page;
- unsigned long idx, offset, base;
- bool dirty = true;
-
- assert(client < DIRTY_MEMORY_NUM);
-
- end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
- page = start >> TARGET_PAGE_BITS;
-
- RCU_READ_LOCK_GUARD();
-
- blocks = qatomic_rcu_read(&ram_list.dirty_memory[client]);
-
- idx = page / DIRTY_MEMORY_BLOCK_SIZE;
- offset = page % DIRTY_MEMORY_BLOCK_SIZE;
- base = page - offset;
- while (page < end) {
- unsigned long next = MIN(end, base + DIRTY_MEMORY_BLOCK_SIZE);
- unsigned long num = next - base;
- unsigned long found = find_next_zero_bit(blocks->blocks[idx], num, offset);
- if (found < num) {
- dirty = false;
- break;
- }
-
- page = next;
- idx++;
- offset = 0;
- base += DIRTY_MEMORY_BLOCK_SIZE;
- }
-
- return dirty;
-}
-
bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr, unsigned client);
bool cpu_physical_memory_is_clean(ram_addr_t addr);
-static inline uint8_t cpu_physical_memory_range_includes_clean(ram_addr_t start,
- ram_addr_t length,
- uint8_t mask)
-{
- uint8_t ret = 0;
-
- if (mask & (1 << DIRTY_MEMORY_VGA) &&
- !cpu_physical_memory_all_dirty(start, length, DIRTY_MEMORY_VGA)) {
- ret |= (1 << DIRTY_MEMORY_VGA);
- }
- if (mask & (1 << DIRTY_MEMORY_CODE) &&
- !cpu_physical_memory_all_dirty(start, length, DIRTY_MEMORY_CODE)) {
- ret |= (1 << DIRTY_MEMORY_CODE);
- }
- if (mask & (1 << DIRTY_MEMORY_MIGRATION) &&
- !cpu_physical_memory_all_dirty(start, length, DIRTY_MEMORY_MIGRATION)) {
- ret |= (1 << DIRTY_MEMORY_MIGRATION);
- }
- return ret;
-}
+uint8_t cpu_physical_memory_range_includes_clean(ram_addr_t start,
+ ram_addr_t length,
+ uint8_t mask);
static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
unsigned client)
return !(vga && code && migration);
}
+static bool physical_memory_all_dirty(ram_addr_t start, ram_addr_t length,
+ unsigned client)
+{
+ DirtyMemoryBlocks *blocks;
+ unsigned long end, page;
+ unsigned long idx, offset, base;
+ bool dirty = true;
+
+ assert(client < DIRTY_MEMORY_NUM);
+
+ end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
+ page = start >> TARGET_PAGE_BITS;
+
+ RCU_READ_LOCK_GUARD();
+
+ blocks = qatomic_rcu_read(&ram_list.dirty_memory[client]);
+
+ idx = page / DIRTY_MEMORY_BLOCK_SIZE;
+ offset = page % DIRTY_MEMORY_BLOCK_SIZE;
+ base = page - offset;
+ while (page < end) {
+ unsigned long next = MIN(end, base + DIRTY_MEMORY_BLOCK_SIZE);
+ unsigned long num = next - base;
+ unsigned long found = find_next_zero_bit(blocks->blocks[idx],
+ num, offset);
+ if (found < num) {
+ dirty = false;
+ break;
+ }
+
+ page = next;
+ idx++;
+ offset = 0;
+ base += DIRTY_MEMORY_BLOCK_SIZE;
+ }
+
+ return dirty;
+}
+
+uint8_t cpu_physical_memory_range_includes_clean(ram_addr_t start,
+ ram_addr_t length,
+ uint8_t mask)
+{
+ uint8_t ret = 0;
+
+ if (mask & (1 << DIRTY_MEMORY_VGA) &&
+ !physical_memory_all_dirty(start, length, DIRTY_MEMORY_VGA)) {
+ ret |= (1 << DIRTY_MEMORY_VGA);
+ }
+ if (mask & (1 << DIRTY_MEMORY_CODE) &&
+ !physical_memory_all_dirty(start, length, DIRTY_MEMORY_CODE)) {
+ ret |= (1 << DIRTY_MEMORY_CODE);
+ }
+ if (mask & (1 << DIRTY_MEMORY_MIGRATION) &&
+ !physical_memory_all_dirty(start, length, DIRTY_MEMORY_MIGRATION)) {
+ ret |= (1 << DIRTY_MEMORY_MIGRATION);
+ }
+ return ret;
+}
+
/* Note: start and end must be within the same ram block. */
bool cpu_physical_memory_test_and_clear_dirty(ram_addr_t start,
ram_addr_t length,