diff options
-rw-r--r-- | arch/powerpc/kvm/book3s_64_mmu_hv.c | 36 | ||||
-rw-r--r-- | arch/x86/kvm/mmu.c | 42 |
2 files changed, 60 insertions, 18 deletions
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index 37037553fe60..1a470bc28763 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c | |||
@@ -756,9 +756,12 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
756 | goto out_put; | 756 | goto out_put; |
757 | } | 757 | } |
758 | 758 | ||
759 | static int kvm_handle_hva(struct kvm *kvm, unsigned long hva, | 759 | static int kvm_handle_hva_range(struct kvm *kvm, |
760 | int (*handler)(struct kvm *kvm, unsigned long *rmapp, | 760 | unsigned long start, |
761 | unsigned long gfn)) | 761 | unsigned long end, |
762 | int (*handler)(struct kvm *kvm, | ||
763 | unsigned long *rmapp, | ||
764 | unsigned long gfn)) | ||
762 | { | 765 | { |
763 | int ret; | 766 | int ret; |
764 | int retval = 0; | 767 | int retval = 0; |
@@ -767,12 +770,22 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva, | |||
767 | 770 | ||
768 | slots = kvm_memslots(kvm); | 771 | slots = kvm_memslots(kvm); |
769 | kvm_for_each_memslot(memslot, slots) { | 772 | kvm_for_each_memslot(memslot, slots) { |
770 | unsigned long start = memslot->userspace_addr; | 773 | unsigned long hva_start, hva_end; |
771 | unsigned long end; | 774 | gfn_t gfn, gfn_end; |
775 | |||
776 | hva_start = max(start, memslot->userspace_addr); | ||
777 | hva_end = min(end, memslot->userspace_addr + | ||
778 | (memslot->npages << PAGE_SHIFT)); | ||
779 | if (hva_start >= hva_end) | ||
780 | continue; | ||
781 | /* | ||
782 | * {gfn(page) | page intersects with [hva_start, hva_end)} = | ||
783 | * {gfn, gfn+1, ..., gfn_end-1}. | ||
784 | */ | ||
785 | gfn = hva_to_gfn_memslot(hva_start, memslot); | ||
786 | gfn_end = hva_to_gfn_memslot(hva_end + PAGE_SIZE - 1, memslot); | ||
772 | 787 | ||
773 | end = start + (memslot->npages << PAGE_SHIFT); | 788 | for (; gfn < gfn_end; ++gfn) { |
774 | if (hva >= start && hva < end) { | ||
775 | gfn_t gfn = hva_to_gfn_memslot(hva, memslot); | ||
776 | gfn_t gfn_offset = gfn - memslot->base_gfn; | 789 | gfn_t gfn_offset = gfn - memslot->base_gfn; |
777 | 790 | ||
778 | ret = handler(kvm, &memslot->rmap[gfn_offset], gfn); | 791 | ret = handler(kvm, &memslot->rmap[gfn_offset], gfn); |
@@ -783,6 +796,13 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva, | |||
783 | return retval; | 796 | return retval; |
784 | } | 797 | } |
785 | 798 | ||
799 | static int kvm_handle_hva(struct kvm *kvm, unsigned long hva, | ||
800 | int (*handler)(struct kvm *kvm, unsigned long *rmapp, | ||
801 | unsigned long gfn)) | ||
802 | { | ||
803 | return kvm_handle_hva_range(kvm, hva, hva + 1, handler); | ||
804 | } | ||
805 | |||
786 | static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp, | 806 | static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp, |
787 | unsigned long gfn) | 807 | unsigned long gfn) |
788 | { | 808 | { |
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 170a632d9d34..7235b0c9587d 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -1259,10 +1259,13 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
1259 | return 0; | 1259 | return 0; |
1260 | } | 1260 | } |
1261 | 1261 | ||
1262 | static int kvm_handle_hva(struct kvm *kvm, unsigned long hva, | 1262 | static int kvm_handle_hva_range(struct kvm *kvm, |
1263 | unsigned long data, | 1263 | unsigned long start, |
1264 | int (*handler)(struct kvm *kvm, unsigned long *rmapp, | 1264 | unsigned long end, |
1265 | unsigned long data)) | 1265 | unsigned long data, |
1266 | int (*handler)(struct kvm *kvm, | ||
1267 | unsigned long *rmapp, | ||
1268 | unsigned long data)) | ||
1266 | { | 1269 | { |
1267 | int j; | 1270 | int j; |
1268 | int ret; | 1271 | int ret; |
@@ -1273,13 +1276,22 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva, | |||
1273 | slots = kvm_memslots(kvm); | 1276 | slots = kvm_memslots(kvm); |
1274 | 1277 | ||
1275 | kvm_for_each_memslot(memslot, slots) { | 1278 | kvm_for_each_memslot(memslot, slots) { |
1276 | unsigned long start = memslot->userspace_addr; | 1279 | unsigned long hva_start, hva_end; |
1277 | unsigned long end; | 1280 | gfn_t gfn, gfn_end; |
1278 | 1281 | ||
1279 | end = start + (memslot->npages << PAGE_SHIFT); | 1282 | hva_start = max(start, memslot->userspace_addr); |
1280 | if (hva >= start && hva < end) { | 1283 | hva_end = min(end, memslot->userspace_addr + |
1281 | gfn_t gfn = hva_to_gfn_memslot(hva, memslot); | 1284 | (memslot->npages << PAGE_SHIFT)); |
1285 | if (hva_start >= hva_end) | ||
1286 | continue; | ||
1287 | /* | ||
1288 | * {gfn(page) | page intersects with [hva_start, hva_end)} = | ||
1289 | * {gfn, gfn+1, ..., gfn_end-1}. | ||
1290 | */ | ||
1291 | gfn = hva_to_gfn_memslot(hva_start, memslot); | ||
1292 | gfn_end = hva_to_gfn_memslot(hva_end + PAGE_SIZE - 1, memslot); | ||
1282 | 1293 | ||
1294 | for (; gfn < gfn_end; ++gfn) { | ||
1283 | ret = 0; | 1295 | ret = 0; |
1284 | 1296 | ||
1285 | for (j = PT_PAGE_TABLE_LEVEL; | 1297 | for (j = PT_PAGE_TABLE_LEVEL; |
@@ -1289,7 +1301,9 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva, | |||
1289 | rmapp = __gfn_to_rmap(gfn, j, memslot); | 1301 | rmapp = __gfn_to_rmap(gfn, j, memslot); |
1290 | ret |= handler(kvm, rmapp, data); | 1302 | ret |= handler(kvm, rmapp, data); |
1291 | } | 1303 | } |
1292 | trace_kvm_age_page(hva, memslot, ret); | 1304 | trace_kvm_age_page(memslot->userspace_addr + |
1305 | (gfn - memslot->base_gfn) * PAGE_SIZE, | ||
1306 | memslot, ret); | ||
1293 | retval |= ret; | 1307 | retval |= ret; |
1294 | } | 1308 | } |
1295 | } | 1309 | } |
@@ -1297,6 +1311,14 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva, | |||
1297 | return retval; | 1311 | return retval; |
1298 | } | 1312 | } |
1299 | 1313 | ||
1314 | static int kvm_handle_hva(struct kvm *kvm, unsigned long hva, | ||
1315 | unsigned long data, | ||
1316 | int (*handler)(struct kvm *kvm, unsigned long *rmapp, | ||
1317 | unsigned long data)) | ||
1318 | { | ||
1319 | return kvm_handle_hva_range(kvm, hva, hva + 1, data, handler); | ||
1320 | } | ||
1321 | |||
1300 | int kvm_unmap_hva(struct kvm *kvm, unsigned long hva) | 1322 | int kvm_unmap_hva(struct kvm *kvm, unsigned long hva) |
1301 | { | 1323 | { |
1302 | return kvm_handle_hva(kvm, hva, 0, kvm_unmap_rmapp); | 1324 | return kvm_handle_hva(kvm, hva, 0, kvm_unmap_rmapp); |