+static unsigned long *migration_bitmap;
+static uint64_t migration_dirty_pages;
+static uint32_t last_version;
+static bool ram_bulk_stage;
+
+static inline
+ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
+ ram_addr_t start)
+{
+ unsigned long base = mr->ram_addr >> TARGET_PAGE_BITS;
+ unsigned long nr = base + (start >> TARGET_PAGE_BITS);
+ unsigned long size = base + (int128_get64(mr->size) >> TARGET_PAGE_BITS);
+
+ unsigned long next;
+
+ if (ram_bulk_stage && nr > base) {
+ next = nr + 1;
+ } else {
+ next = find_next_bit(migration_bitmap, size, nr);
+ }
+
+ if (next < size) {
+ clear_bit(next, migration_bitmap);
+ migration_dirty_pages--;
+ }
+ return (next - base) << TARGET_PAGE_BITS;
+}
+
+static inline bool migration_bitmap_set_dirty(MemoryRegion *mr,
+ ram_addr_t offset)
+{
+ bool ret;
+ int nr = (mr->ram_addr + offset) >> TARGET_PAGE_BITS;
+
+ ret = test_and_set_bit(nr, migration_bitmap);
+
+ if (!ret) {
+ migration_dirty_pages++;
+ }
+ return ret;
+}
+
+/* Needs iothread lock! */