static void handle_hva_to_gpa(struct kvm *kvm, unsigned long start, unsigned long end, void (*handler)(struct kvm *kvm, gpa_t gpa, void *data), void *data) { struct kvm_memslots *slots; struct kvm_memory_slot *memslot; slots = kvm_memslots(kvm); /* we only care about the pages that the guest sees */ kvm_for_each_memslot(memslot, slots) { unsigned long hva_start, hva_end; gfn_t gfn, gfn_end; hva_start = max(start, memslot->userspace_addr); hva_end = min(end, memslot->userspace_addr + (memslot->npages << PAGE_SHIFT)); if (hva_start >= hva_end) continue; /* * {gfn(page) | page intersects with [hva_start, hva_end)} = * {gfn_start, gfn_start+1, ..., gfn_end-1}. */ gfn = hva_to_gfn_memslot(hva_start, memslot); gfn_end = hva_to_gfn_memslot(hva_end + PAGE_SIZE - 1, memslot); for (; gfn < gfn_end; ++gfn) { gpa_t gpa = gfn << PAGE_SHIFT; handler(kvm, gpa, data); } }
/************* MMU Notifiers *************/ static void do_kvm_unmap_hva(struct kvm *kvm, unsigned long start, unsigned long end) { long i; struct kvm_vcpu *vcpu; struct kvm_memslots *slots; struct kvm_memory_slot *memslot; slots = kvm_memslots(kvm); kvm_for_each_memslot(memslot, slots) { unsigned long hva_start, hva_end; gfn_t gfn, gfn_end; hva_start = max(start, memslot->userspace_addr); hva_end = min(end, memslot->userspace_addr + (memslot->npages << PAGE_SHIFT)); if (hva_start >= hva_end) continue; /* * {gfn(page) | page intersects with [hva_start, hva_end)} = * {gfn, gfn+1, ..., gfn_end-1}. */ gfn = hva_to_gfn_memslot(hva_start, memslot); gfn_end = hva_to_gfn_memslot(hva_end + PAGE_SIZE - 1, memslot); kvm_for_each_vcpu(i, vcpu, kvm) kvmppc_mmu_pte_pflush(vcpu, gfn << PAGE_SHIFT, gfn_end << PAGE_SHIFT); }