aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2015-03-30 01:09:12 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2015-04-16 21:23:24 -0400
commit5e1d44aef1673b504dde475aa714b1bdb9b875c4 (patch)
tree714b46d9dc7be08812ada52878088dc2e8165b5c
parent1cbee462a5afc1cc30389915b3d18bdcb3c47ad6 (diff)
KVM: PPC: Use READ_ONCE when dereferencing pte_t pointer
pte can get updated from other CPUs as part of multiple activities like THP split, huge page collapse, unmap. We need to make sure we don't reload the pte value again and again for different checks. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_64.h5
-rw-r--r--arch/powerpc/kvm/e500_mmu_host.c20
2 files changed, 16 insertions, 9 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 14619a59ec09..23b724c746e9 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -290,7 +290,10 @@ static inline pte_t kvmppc_read_update_linux_pte(pte_t *ptep, int writing,
290 pte_t old_pte, new_pte = __pte(0); 290 pte_t old_pte, new_pte = __pte(0);
291 291
292 while (1) { 292 while (1) {
293 old_pte = *ptep; 293 /*
294 * Make sure we don't reload from ptep
295 */
296 old_pte = READ_ONCE(*ptep);
294 /* 297 /*
295 * wait until _PAGE_BUSY is clear then set it atomically 298 * wait until _PAGE_BUSY is clear then set it atomically
296 */ 299 */
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c
index cc536d4a75ef..5840d546aa03 100644
--- a/arch/powerpc/kvm/e500_mmu_host.c
+++ b/arch/powerpc/kvm/e500_mmu_host.c
@@ -469,14 +469,18 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
469 469
470 pgdir = vcpu_e500->vcpu.arch.pgdir; 470 pgdir = vcpu_e500->vcpu.arch.pgdir;
471 ptep = lookup_linux_ptep(pgdir, hva, &tsize_pages); 471 ptep = lookup_linux_ptep(pgdir, hva, &tsize_pages);
472 if (pte_present(*ptep)) 472 if (ptep) {
473 wimg = (*ptep >> PTE_WIMGE_SHIFT) & MAS2_WIMGE_MASK; 473 pte_t pte = READ_ONCE(*ptep);
474 else { 474
475 if (printk_ratelimit()) 475 if (pte_present(pte))
476 pr_err("%s: pte not present: gfn %lx, pfn %lx\n", 476 wimg = (pte_val(pte) >> PTE_WIMGE_SHIFT) &
477 __func__, (long)gfn, pfn); 477 MAS2_WIMGE_MASK;
478 ret = -EINVAL; 478 else {
479 goto out; 479 pr_err_ratelimited("%s: pte not present: gfn %lx,pfn %lx\n",
480 __func__, (long)gfn, pfn);
481 ret = -EINVAL;
482 goto out;
483 }
480 } 484 }
481 kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg); 485 kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg);
482 486