diff options
-rw-r--r-- | arch/powerpc/include/asm/kvm_book3s.h | 2 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 5 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_64_mmu_hv.c | 33 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv.c | 18 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_pr.c | 7 | ||||
-rw-r--r-- | arch/powerpc/kvm/booke.c | 7 | ||||
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 3 |
8 files changed, 64 insertions, 13 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h index f0e0c6a66d97..ab738005d2ea 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h | |||
@@ -160,7 +160,7 @@ extern long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags, | |||
160 | extern long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags, | 160 | extern long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags, |
161 | long pte_index, unsigned long pteh, unsigned long ptel); | 161 | long pte_index, unsigned long pteh, unsigned long ptel); |
162 | extern long kvmppc_hv_get_dirty_log(struct kvm *kvm, | 162 | extern long kvmppc_hv_get_dirty_log(struct kvm *kvm, |
163 | struct kvm_memory_slot *memslot); | 163 | struct kvm_memory_slot *memslot, unsigned long *map); |
164 | 164 | ||
165 | extern void kvmppc_entry_trampoline(void); | 165 | extern void kvmppc_entry_trampoline(void); |
166 | extern void kvmppc_hv_entry_trampoline(void); | 166 | extern void kvmppc_hv_entry_trampoline(void); |
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 41a00eae68c7..3fb980d293e5 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h | |||
@@ -151,9 +151,12 @@ extern int kvmppc_core_prepare_memory_region(struct kvm *kvm, | |||
151 | struct kvm_memory_slot *memslot, | 151 | struct kvm_memory_slot *memslot, |
152 | struct kvm_userspace_memory_region *mem); | 152 | struct kvm_userspace_memory_region *mem); |
153 | extern void kvmppc_core_commit_memory_region(struct kvm *kvm, | 153 | extern void kvmppc_core_commit_memory_region(struct kvm *kvm, |
154 | struct kvm_userspace_memory_region *mem); | 154 | struct kvm_userspace_memory_region *mem, |
155 | struct kvm_memory_slot old); | ||
155 | extern int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm, | 156 | extern int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm, |
156 | struct kvm_ppc_smmu_info *info); | 157 | struct kvm_ppc_smmu_info *info); |
158 | extern void kvmppc_core_flush_memslot(struct kvm *kvm, | ||
159 | struct kvm_memory_slot *memslot); | ||
157 | 160 | ||
158 | extern int kvmppc_bookehv_init(void); | 161 | extern int kvmppc_bookehv_init(void); |
159 | extern void kvmppc_bookehv_exit(void); | 162 | extern void kvmppc_bookehv_exit(void); |
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index a389cc62b16c..f598366e51c6 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c | |||
@@ -851,7 +851,8 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
851 | psize = hpte_page_size(hptep[0], ptel); | 851 | psize = hpte_page_size(hptep[0], ptel); |
852 | if ((hptep[0] & HPTE_V_VALID) && | 852 | if ((hptep[0] & HPTE_V_VALID) && |
853 | hpte_rpn(ptel, psize) == gfn) { | 853 | hpte_rpn(ptel, psize) == gfn) { |
854 | hptep[0] |= HPTE_V_ABSENT; | 854 | if (kvm->arch.using_mmu_notifiers) |
855 | hptep[0] |= HPTE_V_ABSENT; | ||
855 | kvmppc_invalidate_hpte(kvm, hptep, i); | 856 | kvmppc_invalidate_hpte(kvm, hptep, i); |
856 | /* Harvest R and C */ | 857 | /* Harvest R and C */ |
857 | rcbits = hptep[1] & (HPTE_R_R | HPTE_R_C); | 858 | rcbits = hptep[1] & (HPTE_R_R | HPTE_R_C); |
@@ -878,6 +879,28 @@ int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end) | |||
878 | return 0; | 879 | return 0; |
879 | } | 880 | } |
880 | 881 | ||
882 | void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot) | ||
883 | { | ||
884 | unsigned long *rmapp; | ||
885 | unsigned long gfn; | ||
886 | unsigned long n; | ||
887 | |||
888 | rmapp = memslot->arch.rmap; | ||
889 | gfn = memslot->base_gfn; | ||
890 | for (n = memslot->npages; n; --n) { | ||
891 | /* | ||
892 | * Testing the present bit without locking is OK because | ||
893 | * the memslot has been marked invalid already, and hence | ||
894 | * no new HPTEs referencing this page can be created, | ||
895 | * thus the present bit can't go from 0 to 1. | ||
896 | */ | ||
897 | if (*rmapp & KVMPPC_RMAP_PRESENT) | ||
898 | kvm_unmap_rmapp(kvm, rmapp, gfn); | ||
899 | ++rmapp; | ||
900 | ++gfn; | ||
901 | } | ||
902 | } | ||
903 | |||
881 | static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp, | 904 | static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp, |
882 | unsigned long gfn) | 905 | unsigned long gfn) |
883 | { | 906 | { |
@@ -1031,16 +1054,16 @@ static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp) | |||
1031 | return ret; | 1054 | return ret; |
1032 | } | 1055 | } |
1033 | 1056 | ||
1034 | long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot) | 1057 | long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot, |
1058 | unsigned long *map) | ||
1035 | { | 1059 | { |
1036 | unsigned long i; | 1060 | unsigned long i; |
1037 | unsigned long *rmapp, *map; | 1061 | unsigned long *rmapp; |
1038 | 1062 | ||
1039 | preempt_disable(); | 1063 | preempt_disable(); |
1040 | rmapp = memslot->arch.rmap; | 1064 | rmapp = memslot->arch.rmap; |
1041 | map = memslot->dirty_bitmap; | ||
1042 | for (i = 0; i < memslot->npages; ++i) { | 1065 | for (i = 0; i < memslot->npages; ++i) { |
1043 | if (kvm_test_clear_dirty(kvm, rmapp)) | 1066 | if (kvm_test_clear_dirty(kvm, rmapp) && map) |
1044 | __set_bit_le(i, map); | 1067 | __set_bit_le(i, map); |
1045 | ++rmapp; | 1068 | ++rmapp; |
1046 | } | 1069 | } |
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 817837de7362..38c7f1bc3495 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
@@ -1288,7 +1288,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) | |||
1288 | n = kvm_dirty_bitmap_bytes(memslot); | 1288 | n = kvm_dirty_bitmap_bytes(memslot); |
1289 | memset(memslot->dirty_bitmap, 0, n); | 1289 | memset(memslot->dirty_bitmap, 0, n); |
1290 | 1290 | ||
1291 | r = kvmppc_hv_get_dirty_log(kvm, memslot); | 1291 | r = kvmppc_hv_get_dirty_log(kvm, memslot, memslot->dirty_bitmap); |
1292 | if (r) | 1292 | if (r) |
1293 | goto out; | 1293 | goto out; |
1294 | 1294 | ||
@@ -1378,8 +1378,22 @@ int kvmppc_core_prepare_memory_region(struct kvm *kvm, | |||
1378 | } | 1378 | } |
1379 | 1379 | ||
1380 | void kvmppc_core_commit_memory_region(struct kvm *kvm, | 1380 | void kvmppc_core_commit_memory_region(struct kvm *kvm, |
1381 | struct kvm_userspace_memory_region *mem) | 1381 | struct kvm_userspace_memory_region *mem, |
1382 | struct kvm_memory_slot old) | ||
1382 | { | 1383 | { |
1384 | unsigned long npages = mem->memory_size >> PAGE_SHIFT; | ||
1385 | struct kvm_memory_slot *memslot; | ||
1386 | |||
1387 | if (npages && old.npages) { | ||
1388 | /* | ||
1389 | * If modifying a memslot, reset all the rmap dirty bits. | ||
1390 | * If this is a new memslot, we don't need to do anything | ||
1391 | * since the rmap array starts out as all zeroes, | ||
1392 | * i.e. no pages are dirty. | ||
1393 | */ | ||
1394 | memslot = id_to_memslot(kvm->memslots, mem->slot); | ||
1395 | kvmppc_hv_get_dirty_log(kvm, memslot, NULL); | ||
1396 | } | ||
1383 | } | 1397 | } |
1384 | 1398 | ||
1385 | static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) | 1399 | static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) |
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index 63eb94e63cc3..9955216477a4 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c | |||
@@ -81,7 +81,7 @@ static void remove_revmap_chain(struct kvm *kvm, long pte_index, | |||
81 | ptel = rev->guest_rpte |= rcbits; | 81 | ptel = rev->guest_rpte |= rcbits; |
82 | gfn = hpte_rpn(ptel, hpte_page_size(hpte_v, ptel)); | 82 | gfn = hpte_rpn(ptel, hpte_page_size(hpte_v, ptel)); |
83 | memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn); | 83 | memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn); |
84 | if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) | 84 | if (!memslot) |
85 | return; | 85 | return; |
86 | 86 | ||
87 | rmap = real_vmalloc_addr(&memslot->arch.rmap[gfn - memslot->base_gfn]); | 87 | rmap = real_vmalloc_addr(&memslot->arch.rmap[gfn - memslot->base_gfn]); |
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index fdadc9e57da2..4d0667a810a4 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c | |||
@@ -1239,7 +1239,12 @@ int kvmppc_core_prepare_memory_region(struct kvm *kvm, | |||
1239 | } | 1239 | } |
1240 | 1240 | ||
1241 | void kvmppc_core_commit_memory_region(struct kvm *kvm, | 1241 | void kvmppc_core_commit_memory_region(struct kvm *kvm, |
1242 | struct kvm_userspace_memory_region *mem) | 1242 | struct kvm_userspace_memory_region *mem, |
1243 | struct kvm_memory_slot old) | ||
1244 | { | ||
1245 | } | ||
1246 | |||
1247 | void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot) | ||
1243 | { | 1248 | { |
1244 | } | 1249 | } |
1245 | 1250 | ||
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 514405752988..3a6490fc6fcd 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
@@ -1457,7 +1457,12 @@ int kvmppc_core_prepare_memory_region(struct kvm *kvm, | |||
1457 | } | 1457 | } |
1458 | 1458 | ||
1459 | void kvmppc_core_commit_memory_region(struct kvm *kvm, | 1459 | void kvmppc_core_commit_memory_region(struct kvm *kvm, |
1460 | struct kvm_userspace_memory_region *mem) | 1460 | struct kvm_userspace_memory_region *mem, |
1461 | struct kvm_memory_slot old) | ||
1462 | { | ||
1463 | } | ||
1464 | |||
1465 | void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot) | ||
1461 | { | 1466 | { |
1462 | } | 1467 | } |
1463 | 1468 | ||
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 33122dd89da9..8443e23f3605 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -411,7 +411,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, | |||
411 | struct kvm_memory_slot old, | 411 | struct kvm_memory_slot old, |
412 | int user_alloc) | 412 | int user_alloc) |
413 | { | 413 | { |
414 | kvmppc_core_commit_memory_region(kvm, mem); | 414 | kvmppc_core_commit_memory_region(kvm, mem, old); |
415 | } | 415 | } |
416 | 416 | ||
417 | void kvm_arch_flush_shadow_all(struct kvm *kvm) | 417 | void kvm_arch_flush_shadow_all(struct kvm *kvm) |
@@ -421,6 +421,7 @@ void kvm_arch_flush_shadow_all(struct kvm *kvm) | |||
421 | void kvm_arch_flush_shadow_memslot(struct kvm *kvm, | 421 | void kvm_arch_flush_shadow_memslot(struct kvm *kvm, |
422 | struct kvm_memory_slot *slot) | 422 | struct kvm_memory_slot *slot) |
423 | { | 423 | { |
424 | kvmppc_core_flush_memslot(kvm, slot); | ||
424 | } | 425 | } |
425 | 426 | ||
426 | struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) | 427 | struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) |