/* get kvm's dirty pages bitmap and update qemu's */ static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section, unsigned long *bitmap) { unsigned int i, j; unsigned long page_number, c; target_phys_addr_t addr, addr1; unsigned int len = ((section->size / TARGET_PAGE_SIZE) + HOST_LONG_BITS - 1) / HOST_LONG_BITS; /* * bitmap-traveling is faster than memory-traveling (for addr...) * especially when most of the memory is not dirty. */ for (i = 0; i < len; i++) { if (bitmap[i] != 0) { c = leul_to_cpu(bitmap[i]); do { j = ffsl(c) - 1; c &= ~(1ul << j); page_number = i * HOST_LONG_BITS + j; addr1 = page_number * TARGET_PAGE_SIZE; addr = section->offset_within_region + addr1; memory_region_set_dirty(section->mr, addr, TARGET_PAGE_SIZE); } while (c != 0); } } return 0; }
static void acpi_ram_update(MemoryRegion *mr, GArray *data) { uint32_t size = acpi_data_len(data); /* Make sure RAM size is correct - in case it got changed * e.g. by migration */ memory_region_ram_resize(mr, size, &error_abort); memcpy(memory_region_get_ram_ptr(mr), data->data, size); memory_region_set_dirty(mr, 0, size); }
static void whpx_log_sync(MemoryListener *listener, MemoryRegionSection *section) { MemoryRegion *mr = section->mr; if (!memory_region_is_ram(mr)) { return; } memory_region_set_dirty(mr, 0, int128_get64(section->size)); }
static void nvdimm_write_label_data(NVDIMMDevice *nvdimm, const void *buf, uint64_t size, uint64_t offset) { MemoryRegion *mr; PCDIMMDevice *dimm = PC_DIMM(nvdimm); uint64_t backend_offset; nvdimm_validate_rw_label_data(nvdimm, size, offset); memcpy(nvdimm->label_data + offset, buf, size); mr = host_memory_backend_get_memory(dimm->hostmem, &error_abort); backend_offset = memory_region_size(mr) - nvdimm->label_size + offset; memory_region_set_dirty(mr, backend_offset, size); }
static void vhost_dev_sync_region(struct vhost_dev *dev, MemoryRegionSection *section, uint64_t mfirst, uint64_t mlast, uint64_t rfirst, uint64_t rlast) { uint64_t start = MAX(mfirst, rfirst); uint64_t end = MIN(mlast, rlast); vhost_log_chunk_t *from = dev->log + start / VHOST_LOG_CHUNK; vhost_log_chunk_t *to = dev->log + end / VHOST_LOG_CHUNK + 1; uint64_t addr = (start / VHOST_LOG_CHUNK) * VHOST_LOG_CHUNK; if (end < start) { return; } assert(end / VHOST_LOG_CHUNK < dev->log_size); assert(start / VHOST_LOG_CHUNK < dev->log_size); for (;from < to; ++from) { vhost_log_chunk_t log; int bit; /* We first check with non-atomic: much cheaper, * and we expect non-dirty to be the common case. */ if (!*from) { addr += VHOST_LOG_CHUNK; continue; } /* Data must be read atomically. We don't really * need the barrier semantics of __sync * builtins, but it's easier to use them than * roll our own. */ log = __sync_fetch_and_and(from, 0); while ((bit = sizeof(log) > sizeof(int) ? ffsll(log) : ffs(log))) { ram_addr_t ram_addr; bit -= 1; ram_addr = section->offset_within_region + bit * VHOST_LOG_PAGE; memory_region_set_dirty(section->mr, ram_addr, VHOST_LOG_PAGE); log &= ~(0x1ull << bit); } addr += VHOST_LOG_CHUNK; } }
static void cg3_invalidate_display(void *opaque) { CG3State *s = opaque; memory_region_set_dirty(&s->vram_mem, 0, CG3_VRAM_SIZE); }
static void tcx24_set_dirty(TCXState *s) { memory_region_set_dirty(&s->vram_mem, s->vram24_offset, MAXX * MAXY * 4); memory_region_set_dirty(&s->vram_mem, s->cplane_offset, MAXX * MAXY * 4); }
static void tcx_set_dirty(TCXState *s) { memory_region_set_dirty(&s->vram_mem, 0, MAXX * MAXY); }