Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/vmm/vmm.c
| Show First 20 Lines • Show All 2,979 Lines • ▼ Show 20 Lines | for (i = 0; i < maxcpus; i++) { | ||||
| error = vmmops_restore_tsc(vcpu->cookie, | error = vmmops_restore_tsc(vcpu->cookie, | ||||
| vcpu->tsc_offset - now); | vcpu->tsc_offset - now); | ||||
| if (error) | if (error) | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| #endif | |||||
| static int | |||||
| vm_search_dirty_pages_in_object(vm_object_t object, size_t start, size_t end, | |||||
| size_t offset, uint8_t *page_list, bool is_all_dirty) | |||||
| { | |||||
| vm_pindex_t pindex, swap_pindex; | |||||
| vm_page_t m; | |||||
| int error = 0; | |||||
| uint8_t result; | |||||
| VM_OBJECT_WLOCK(object); | |||||
| pindex = start / PAGE_SIZE; | |||||
| swap_pindex = swap_pager_find_least(object, pindex); | |||||
| for (; pindex < end / PAGE_SIZE; pindex++) { | |||||
| if (pindex == swap_pindex) { | |||||
| swap_pindex = swap_pager_find_least(object, pindex + 1); | |||||
| error = vm_page_grab_valid(&m, object, pindex, | |||||
| VM_ALLOC_NORMAL | VM_ALLOC_COUNT(VM_ALLOC_COUNT_MAX)); | |||||
| if (error != VM_PAGER_OK) { | |||||
| error = EINVAL; | |||||
| break; | |||||
| } | |||||
| } else { | |||||
| m = vm_page_grab(object, pindex, VM_ALLOC_NOCREAT); | |||||
| } | |||||
| if (m != NULL) { | |||||
| result = vm_page_test_vmm_dirty(m) || is_all_dirty; | |||||
| vm_page_xunbusy(m); | |||||
| subyte(page_list + pindex - offset, result); | |||||
| } | |||||
| } | |||||
| VM_OBJECT_WUNLOCK(object); | |||||
| return (error); | |||||
| } | |||||
| int | |||||
| vm_get_dirty_page_list(struct vm *vm, struct vm_get_dirty_page_list *list) | |||||
| { | |||||
| struct vmspace *vm_vmspace; | |||||
| struct vm_map *vmmap; | |||||
| struct vm_map_entry *entry; | |||||
| struct vm_object *object; | |||||
| int error = 0; | |||||
| uint8_t *page_list; | |||||
| size_t offset; | |||||
| page_list = list->page_list; | |||||
| if (page_list == NULL) | |||||
| return (EINVAL); | |||||
| vm_vmspace = vm->vmspace; | |||||
| if (vm_vmspace == NULL) { | |||||
| printf("%s: vm_vmspace is null\r\n", __func__); | |||||
| return (EINVAL); | |||||
| } | |||||
| vmmap = &vm_vmspace->vm_map; | |||||
| vm_map_lock(vmmap); | |||||
| if (vmmap->busy) | |||||
| vm_map_wait_busy(vmmap); | |||||
| for (entry = vmmap->header.right; entry != &vmmap->header; entry = entry->right) { | |||||
| object = entry->object.vm_object; | |||||
| /* if object is lowmem */ | |||||
| if (entry->start == list->lowmem_start && entry->end == list->lowmem_end) { | |||||
| if (object == NULL) | |||||
| continue; | |||||
| error = vm_search_dirty_pages_in_object(object, | |||||
| list->lowmem_start, | |||||
| list->lowmem_end, | |||||
| 0, | |||||
| page_list, | |||||
| list->is_all_dirty); | |||||
| if (error != 0) | |||||
| break; | |||||
| } | |||||
| /* if object is highmem */ | |||||
| if (entry->start == list->highmem_start && entry->end == list->highmem_end) { | |||||
| if (object == NULL) | |||||
| continue; | |||||
| offset = (list->highmem_start - list->lowmem_end) / PAGE_SIZE; | |||||
| error = vm_search_dirty_pages_in_object(object, | |||||
| list->highmem_start, | |||||
| list->highmem_end, | |||||
| offset, | |||||
| page_list, | |||||
| list->is_all_dirty); | |||||
| if (error != 0) | |||||
| break; | |||||
| } | |||||
| } | |||||
| vm_map_unlock(vmmap); | |||||
| return (error); | |||||
| } | |||||
| #endif /* BHYVE_SNAPSHOT */ | |||||