272 |
272 |
* @start_add: start of logged region.
|
273 |
273 |
* @end_addr: end of logged region.
|
274 |
274 |
*/
|
275 |
|
void kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
|
276 |
|
target_phys_addr_t end_addr)
|
|
275 |
int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
|
|
276 |
target_phys_addr_t end_addr)
|
277 |
277 |
{
|
278 |
278 |
KVMState *s = kvm_state;
|
279 |
|
KVMDirtyLog d;
|
280 |
|
KVMSlot *mem = kvm_lookup_matching_slot(s, start_addr, end_addr);
|
281 |
|
unsigned long alloc_size;
|
|
279 |
unsigned long size, allocated_size = 0;
|
|
280 |
target_phys_addr_t phys_addr;
|
282 |
281 |
ram_addr_t addr;
|
283 |
|
target_phys_addr_t phys_addr = start_addr;
|
|
282 |
KVMDirtyLog d;
|
|
283 |
KVMSlot *mem;
|
|
284 |
int ret = 0;
|
284 |
285 |
|
285 |
|
dprintf("sync addr: " TARGET_FMT_lx " into %lx\n", start_addr,
|
286 |
|
mem->phys_offset);
|
287 |
|
if (mem == NULL) {
|
288 |
|
fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-"
|
289 |
|
TARGET_FMT_plx "\n", __func__, phys_addr, end_addr - 1);
|
290 |
|
return;
|
291 |
|
}
|
|
286 |
d.dirty_bitmap = NULL;
|
|
287 |
while (start_addr < end_addr) {
|
|
288 |
mem = kvm_lookup_overlapping_slot(s, start_addr, end_addr);
|
|
289 |
if (mem == NULL) {
|
|
290 |
break;
|
|
291 |
}
|
292 |
292 |
|
293 |
|
alloc_size = ((mem->memory_size >> TARGET_PAGE_BITS) + 7) / 8;
|
294 |
|
d.dirty_bitmap = qemu_mallocz(alloc_size);
|
|
293 |
size = ((mem->memory_size >> TARGET_PAGE_BITS) + 7) / 8;
|
|
294 |
if (!d.dirty_bitmap) {
|
|
295 |
d.dirty_bitmap = qemu_malloc(size);
|
|
296 |
} else if (size > allocated_size) {
|
|
297 |
d.dirty_bitmap = qemu_realloc(d.dirty_bitmap, size);
|
|
298 |
}
|
|
299 |
allocated_size = size;
|
|
300 |
memset(d.dirty_bitmap, 0, allocated_size);
|
295 |
301 |
|
296 |
|
d.slot = mem->slot;
|
297 |
|
dprintf("slot %d, phys_addr %llx, uaddr: %llx\n",
|
298 |
|
d.slot, mem->start_addr, mem->phys_offset);
|
|
302 |
d.slot = mem->slot;
|
299 |
303 |
|
300 |
|
if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) {
|
301 |
|
dprintf("ioctl failed %d\n", errno);
|
302 |
|
goto out;
|
303 |
|
}
|
|
304 |
if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) {
|
|
305 |
dprintf("ioctl failed %d\n", errno);
|
|
306 |
ret = -1;
|
|
307 |
break;
|
|
308 |
}
|
|
309 |
|
|
310 |
for (phys_addr = mem->start_addr, addr = mem->phys_offset;
|
|
311 |
phys_addr < mem->start_addr + mem->memory_size;
|
|
312 |
phys_addr += TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
|
|
313 |
unsigned long *bitmap = (unsigned long *)d.dirty_bitmap;
|
|
314 |
unsigned nr = (phys_addr - mem->start_addr) >> TARGET_PAGE_BITS;
|
|
315 |
unsigned word = nr / (sizeof(*bitmap) * 8);
|
|
316 |
unsigned bit = nr % (sizeof(*bitmap) * 8);
|
304 |
317 |
|
305 |
|
phys_addr = start_addr;
|
306 |
|
for (addr = mem->phys_offset; phys_addr < end_addr; phys_addr+= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
|
307 |
|
unsigned long *bitmap = (unsigned long *)d.dirty_bitmap;
|
308 |
|
unsigned nr = (phys_addr - start_addr) >> TARGET_PAGE_BITS;
|
309 |
|
unsigned word = nr / (sizeof(*bitmap) * 8);
|
310 |
|
unsigned bit = nr % (sizeof(*bitmap) * 8);
|
311 |
|
if ((bitmap[word] >> bit) & 1)
|
312 |
|
cpu_physical_memory_set_dirty(addr);
|
|
318 |
if ((bitmap[word] >> bit) & 1) {
|
|
319 |
cpu_physical_memory_set_dirty(addr);
|
|
320 |
}
|
|
321 |
}
|
|
322 |
start_addr = phys_addr;
|
313 |
323 |
}
|
314 |
|
out:
|
315 |
324 |
qemu_free(d.dirty_bitmap);
|
|
325 |
|
|
326 |
return ret;
|
316 |
327 |
}
|
317 |
328 |
|
318 |
329 |
int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
|