aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h3
-rw-r--r--arch/powerpc/include/asm/kvm_host.h2
-rw-r--r--arch/powerpc/kernel/asm-offsets.c1
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_hv.c61
-rw-r--r--arch/powerpc/kvm/book3s_hv.c30
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S4
6 files changed, 80 insertions, 21 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index bc81842ea25a..c55f7e6affaa 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -156,7 +156,8 @@ void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep,
156 unsigned long pte_index); 156 unsigned long pte_index);
157extern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr, 157extern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr,
158 unsigned long *nb_ret); 158 unsigned long *nb_ret);
159extern void kvmppc_unpin_guest_page(struct kvm *kvm, void *addr); 159extern void kvmppc_unpin_guest_page(struct kvm *kvm, void *addr,
160 unsigned long gpa, bool dirty);
160extern long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags, 161extern long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
161 long pte_index, unsigned long pteh, unsigned long ptel); 162 long pte_index, unsigned long pteh, unsigned long ptel);
162extern long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, 163extern long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 8a48e686a755..1443768a6588 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -301,11 +301,13 @@ struct kvmppc_vcore {
301 * that a guest can register. 301 * that a guest can register.
302 */ 302 */
303struct kvmppc_vpa { 303struct kvmppc_vpa {
304 unsigned long gpa; /* Current guest phys addr */
304 void *pinned_addr; /* Address in kernel linear mapping */ 305 void *pinned_addr; /* Address in kernel linear mapping */
305 void *pinned_end; /* End of region */ 306 void *pinned_end; /* End of region */
306 unsigned long next_gpa; /* Guest phys addr for update */ 307 unsigned long next_gpa; /* Guest phys addr for update */
307 unsigned long len; /* Number of bytes required */ 308 unsigned long len; /* Number of bytes required */
308 u8 update_pending; /* 1 => update pinned_addr from next_gpa */ 309 u8 update_pending; /* 1 => update pinned_addr from next_gpa */
310 bool dirty; /* true => area has been modified by kernel */
309}; 311};
310 312
311struct kvmppc_pte { 313struct kvmppc_pte {
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index d87c90886c75..dbfd5498f440 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -477,6 +477,7 @@ int main(void)
477 DEFINE(VCPU_DSISR, offsetof(struct kvm_vcpu, arch.shregs.dsisr)); 477 DEFINE(VCPU_DSISR, offsetof(struct kvm_vcpu, arch.shregs.dsisr));
478 DEFINE(VCPU_DAR, offsetof(struct kvm_vcpu, arch.shregs.dar)); 478 DEFINE(VCPU_DAR, offsetof(struct kvm_vcpu, arch.shregs.dar));
479 DEFINE(VCPU_VPA, offsetof(struct kvm_vcpu, arch.vpa.pinned_addr)); 479 DEFINE(VCPU_VPA, offsetof(struct kvm_vcpu, arch.vpa.pinned_addr));
480 DEFINE(VCPU_VPA_DIRTY, offsetof(struct kvm_vcpu, arch.vpa.dirty));
480#endif 481#endif
481#ifdef CONFIG_PPC_BOOK3S 482#ifdef CONFIG_PPC_BOOK3S
482 DEFINE(VCPU_VCPUID, offsetof(struct kvm_vcpu, vcpu_id)); 483 DEFINE(VCPU_VCPUID, offsetof(struct kvm_vcpu, vcpu_id));
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index d641a6634b02..69efe0d6cedc 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -1099,11 +1099,30 @@ static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp)
1099 return ret; 1099 return ret;
1100} 1100}
1101 1101
1102static void harvest_vpa_dirty(struct kvmppc_vpa *vpa,
1103 struct kvm_memory_slot *memslot,
1104 unsigned long *map)
1105{
1106 unsigned long gfn;
1107
1108 if (!vpa->dirty || !vpa->pinned_addr)
1109 return;
1110 gfn = vpa->gpa >> PAGE_SHIFT;
1111 if (gfn < memslot->base_gfn ||
1112 gfn >= memslot->base_gfn + memslot->npages)
1113 return;
1114
1115 vpa->dirty = false;
1116 if (map)
1117 __set_bit_le(gfn - memslot->base_gfn, map);
1118}
1119
1102long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot, 1120long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot,
1103 unsigned long *map) 1121 unsigned long *map)
1104{ 1122{
1105 unsigned long i; 1123 unsigned long i;
1106 unsigned long *rmapp; 1124 unsigned long *rmapp;
1125 struct kvm_vcpu *vcpu;
1107 1126
1108 preempt_disable(); 1127 preempt_disable();
1109 rmapp = memslot->arch.rmap; 1128 rmapp = memslot->arch.rmap;
@@ -1112,6 +1131,15 @@ long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot,
1112 __set_bit_le(i, map); 1131 __set_bit_le(i, map);
1113 ++rmapp; 1132 ++rmapp;
1114 } 1133 }
1134
1135 /* Harvest dirty bits from VPA and DTL updates */
1136 /* Note: we never modify the SLB shadow buffer areas */
1137 kvm_for_each_vcpu(i, vcpu, kvm) {
1138 spin_lock(&vcpu->arch.vpa_update_lock);
1139 harvest_vpa_dirty(&vcpu->arch.vpa, memslot, map);
1140 harvest_vpa_dirty(&vcpu->arch.dtl, memslot, map);
1141 spin_unlock(&vcpu->arch.vpa_update_lock);
1142 }
1115 preempt_enable(); 1143 preempt_enable();
1116 return 0; 1144 return 0;
1117} 1145}
@@ -1123,7 +1151,7 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
1123 unsigned long gfn = gpa >> PAGE_SHIFT; 1151 unsigned long gfn = gpa >> PAGE_SHIFT;
1124 struct page *page, *pages[1]; 1152 struct page *page, *pages[1];
1125 int npages; 1153 int npages;
1126 unsigned long hva, psize, offset; 1154 unsigned long hva, offset;
1127 unsigned long pa; 1155 unsigned long pa;
1128 unsigned long *physp; 1156 unsigned long *physp;
1129 int srcu_idx; 1157 int srcu_idx;
@@ -1155,14 +1183,9 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
1155 } 1183 }
1156 srcu_read_unlock(&kvm->srcu, srcu_idx); 1184 srcu_read_unlock(&kvm->srcu, srcu_idx);
1157 1185
1158 psize = PAGE_SIZE; 1186 offset = gpa & (PAGE_SIZE - 1);
1159 if (PageHuge(page)) {
1160 page = compound_head(page);
1161 psize <<= compound_order(page);
1162 }
1163 offset = gpa & (psize - 1);
1164 if (nb_ret) 1187 if (nb_ret)
1165 *nb_ret = psize - offset; 1188 *nb_ret = PAGE_SIZE - offset;
1166 return page_address(page) + offset; 1189 return page_address(page) + offset;
1167 1190
1168 err: 1191 err:
@@ -1170,11 +1193,31 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
1170 return NULL; 1193 return NULL;
1171} 1194}
1172 1195
1173void kvmppc_unpin_guest_page(struct kvm *kvm, void *va) 1196void kvmppc_unpin_guest_page(struct kvm *kvm, void *va, unsigned long gpa,
1197 bool dirty)
1174{ 1198{
1175 struct page *page = virt_to_page(va); 1199 struct page *page = virt_to_page(va);
1200 struct kvm_memory_slot *memslot;
1201 unsigned long gfn;
1202 unsigned long *rmap;
1203 int srcu_idx;
1176 1204
1177 put_page(page); 1205 put_page(page);
1206
1207 if (!dirty || !kvm->arch.using_mmu_notifiers)
1208 return;
1209
1210 /* We need to mark this page dirty in the rmap chain */
1211 gfn = gpa >> PAGE_SHIFT;
1212 srcu_idx = srcu_read_lock(&kvm->srcu);
1213 memslot = gfn_to_memslot(kvm, gfn);
1214 if (memslot) {
1215 rmap = &memslot->arch.rmap[gfn - memslot->base_gfn];
1216 lock_rmap(rmap);
1217 *rmap |= KVMPPC_RMAP_CHANGED;
1218 unlock_rmap(rmap);
1219 }
1220 srcu_read_unlock(&kvm->srcu, srcu_idx);
1178} 1221}
1179 1222
1180/* 1223/*
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 1e521baf9a7d..5af0f2979833 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -259,7 +259,7 @@ static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu,
259 len = ((struct reg_vpa *)va)->length.hword; 259 len = ((struct reg_vpa *)va)->length.hword;
260 else 260 else
261 len = ((struct reg_vpa *)va)->length.word; 261 len = ((struct reg_vpa *)va)->length.word;
262 kvmppc_unpin_guest_page(kvm, va); 262 kvmppc_unpin_guest_page(kvm, va, vpa, false);
263 263
264 /* Check length */ 264 /* Check length */
265 if (len > nb || len < sizeof(struct reg_vpa)) 265 if (len > nb || len < sizeof(struct reg_vpa))
@@ -359,13 +359,13 @@ static void kvmppc_update_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *vpap)
359 va = NULL; 359 va = NULL;
360 nb = 0; 360 nb = 0;
361 if (gpa) 361 if (gpa)
362 va = kvmppc_pin_guest_page(kvm, vpap->next_gpa, &nb); 362 va = kvmppc_pin_guest_page(kvm, gpa, &nb);
363 spin_lock(&vcpu->arch.vpa_update_lock); 363 spin_lock(&vcpu->arch.vpa_update_lock);
364 if (gpa == vpap->next_gpa) 364 if (gpa == vpap->next_gpa)
365 break; 365 break;
366 /* sigh... unpin that one and try again */ 366 /* sigh... unpin that one and try again */
367 if (va) 367 if (va)
368 kvmppc_unpin_guest_page(kvm, va); 368 kvmppc_unpin_guest_page(kvm, va, gpa, false);
369 } 369 }
370 370
371 vpap->update_pending = 0; 371 vpap->update_pending = 0;
@@ -375,12 +375,15 @@ static void kvmppc_update_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *vpap)
375 * has changed the mappings underlying guest memory, 375 * has changed the mappings underlying guest memory,
376 * so unregister the region. 376 * so unregister the region.
377 */ 377 */
378 kvmppc_unpin_guest_page(kvm, va); 378 kvmppc_unpin_guest_page(kvm, va, gpa, false);
379 va = NULL; 379 va = NULL;
380 } 380 }
381 if (vpap->pinned_addr) 381 if (vpap->pinned_addr)
382 kvmppc_unpin_guest_page(kvm, vpap->pinned_addr); 382 kvmppc_unpin_guest_page(kvm, vpap->pinned_addr, vpap->gpa,
383 vpap->dirty);
384 vpap->gpa = gpa;
383 vpap->pinned_addr = va; 385 vpap->pinned_addr = va;
386 vpap->dirty = false;
384 if (va) 387 if (va)
385 vpap->pinned_end = va + vpap->len; 388 vpap->pinned_end = va + vpap->len;
386} 389}
@@ -472,6 +475,7 @@ static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu,
472 /* order writing *dt vs. writing vpa->dtl_idx */ 475 /* order writing *dt vs. writing vpa->dtl_idx */
473 smp_wmb(); 476 smp_wmb();
474 vpa->dtl_idx = ++vcpu->arch.dtl_index; 477 vpa->dtl_idx = ++vcpu->arch.dtl_index;
478 vcpu->arch.dtl.dirty = true;
475} 479}
476 480
477int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) 481int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
@@ -913,15 +917,19 @@ out:
913 return ERR_PTR(err); 917 return ERR_PTR(err);
914} 918}
915 919
920static void unpin_vpa(struct kvm *kvm, struct kvmppc_vpa *vpa)
921{
922 if (vpa->pinned_addr)
923 kvmppc_unpin_guest_page(kvm, vpa->pinned_addr, vpa->gpa,
924 vpa->dirty);
925}
926
916void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) 927void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
917{ 928{
918 spin_lock(&vcpu->arch.vpa_update_lock); 929 spin_lock(&vcpu->arch.vpa_update_lock);
919 if (vcpu->arch.dtl.pinned_addr) 930 unpin_vpa(vcpu->kvm, &vcpu->arch.dtl);
920 kvmppc_unpin_guest_page(vcpu->kvm, vcpu->arch.dtl.pinned_addr); 931 unpin_vpa(vcpu->kvm, &vcpu->arch.slb_shadow);
921 if (vcpu->arch.slb_shadow.pinned_addr) 932 unpin_vpa(vcpu->kvm, &vcpu->arch.vpa);
922 kvmppc_unpin_guest_page(vcpu->kvm, vcpu->arch.slb_shadow.pinned_addr);
923 if (vcpu->arch.vpa.pinned_addr)
924 kvmppc_unpin_guest_page(vcpu->kvm, vcpu->arch.vpa.pinned_addr);
925 spin_unlock(&vcpu->arch.vpa_update_lock); 933 spin_unlock(&vcpu->arch.vpa_update_lock);
926 kvm_vcpu_uninit(vcpu); 934 kvm_vcpu_uninit(vcpu);
927 kmem_cache_free(kvm_vcpu_cache, vcpu); 935 kmem_cache_free(kvm_vcpu_cache, vcpu);
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index e33d11f1b977..0f23bb851711 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -260,6 +260,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
260 lwz r5, LPPACA_YIELDCOUNT(r3) 260 lwz r5, LPPACA_YIELDCOUNT(r3)
261 addi r5, r5, 1 261 addi r5, r5, 1
262 stw r5, LPPACA_YIELDCOUNT(r3) 262 stw r5, LPPACA_YIELDCOUNT(r3)
263 li r6, 1
264 stb r6, VCPU_VPA_DIRTY(r4)
26325: 26525:
264 /* Load up DAR and DSISR */ 266 /* Load up DAR and DSISR */
265 ld r5, VCPU_DAR(r4) 267 ld r5, VCPU_DAR(r4)
@@ -1018,6 +1020,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
1018 lwz r3, LPPACA_YIELDCOUNT(r8) 1020 lwz r3, LPPACA_YIELDCOUNT(r8)
1019 addi r3, r3, 1 1021 addi r3, r3, 1
1020 stw r3, LPPACA_YIELDCOUNT(r8) 1022 stw r3, LPPACA_YIELDCOUNT(r8)
1023 li r3, 1
1024 stb r3, VCPU_VPA_DIRTY(r9)
102125: 102525:
1022 /* Save PMU registers if requested */ 1026 /* Save PMU registers if requested */
1023 /* r8 and cr0.eq are live here */ 1027 /* r8 and cr0.eq are live here */