diff options
| author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2015-03-20 05:39:43 -0400 |
|---|---|---|
| committer | Alexander Graf <agraf@suse.de> | 2015-04-21 09:21:29 -0400 |
| commit | a4bd6eb07ca72d21a7a34499ad34cfef6f527d4e (patch) | |
| tree | bba74c5424652cc64edb0911da97a670212c418d | |
| parent | 31037ecad275e9ad9bc671c34f72b495cf708ca3 (diff) | |
KVM: PPC: Book3S HV: Add helpers for lock/unlock hpte
This adds helper routines for locking and unlocking HPTEs, and uses
them in the rest of the code. We don't change any locking rules in
this patch.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
| -rw-r--r-- | arch/powerpc/include/asm/kvm_book3s_64.h | 14 | ||||
| -rw-r--r-- | arch/powerpc/kvm/book3s_64_mmu_hv.c | 25 | ||||
| -rw-r--r-- | arch/powerpc/kvm/book3s_hv_rm_mmu.c | 25 |
3 files changed, 33 insertions, 31 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h index 2d81e202bdcc..0789a0f50969 100644 --- a/arch/powerpc/include/asm/kvm_book3s_64.h +++ b/arch/powerpc/include/asm/kvm_book3s_64.h | |||
| @@ -85,6 +85,20 @@ static inline long try_lock_hpte(__be64 *hpte, unsigned long bits) | |||
| 85 | return old == 0; | 85 | return old == 0; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | static inline void unlock_hpte(__be64 *hpte, unsigned long hpte_v) | ||
| 89 | { | ||
| 90 | hpte_v &= ~HPTE_V_HVLOCK; | ||
| 91 | asm volatile(PPC_RELEASE_BARRIER "" : : : "memory"); | ||
| 92 | hpte[0] = cpu_to_be64(hpte_v); | ||
| 93 | } | ||
| 94 | |||
| 95 | /* Without barrier */ | ||
| 96 | static inline void __unlock_hpte(__be64 *hpte, unsigned long hpte_v) | ||
| 97 | { | ||
| 98 | hpte_v &= ~HPTE_V_HVLOCK; | ||
| 99 | hpte[0] = cpu_to_be64(hpte_v); | ||
| 100 | } | ||
| 101 | |||
| 88 | static inline int __hpte_actual_psize(unsigned int lp, int psize) | 102 | static inline int __hpte_actual_psize(unsigned int lp, int psize) |
| 89 | { | 103 | { |
| 90 | int i, shift; | 104 | int i, shift; |
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index dbf127168ca4..6c6825a7ae49 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c | |||
| @@ -338,9 +338,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
| 338 | v = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK; | 338 | v = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK; |
| 339 | gr = kvm->arch.revmap[index].guest_rpte; | 339 | gr = kvm->arch.revmap[index].guest_rpte; |
| 340 | 340 | ||
| 341 | /* Unlock the HPTE */ | 341 | unlock_hpte(hptep, v); |
| 342 | asm volatile("lwsync" : : : "memory"); | ||
| 343 | hptep[0] = cpu_to_be64(v); | ||
| 344 | preempt_enable(); | 342 | preempt_enable(); |
| 345 | 343 | ||
| 346 | gpte->eaddr = eaddr; | 344 | gpte->eaddr = eaddr; |
| @@ -469,8 +467,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
| 469 | hpte[0] = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK; | 467 | hpte[0] = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK; |
| 470 | hpte[1] = be64_to_cpu(hptep[1]); | 468 | hpte[1] = be64_to_cpu(hptep[1]); |
| 471 | hpte[2] = r = rev->guest_rpte; | 469 | hpte[2] = r = rev->guest_rpte; |
| 472 | asm volatile("lwsync" : : : "memory"); | 470 | unlock_hpte(hptep, hpte[0]); |
| 473 | hptep[0] = cpu_to_be64(hpte[0]); | ||
| 474 | preempt_enable(); | 471 | preempt_enable(); |
| 475 | 472 | ||
| 476 | if (hpte[0] != vcpu->arch.pgfault_hpte[0] || | 473 | if (hpte[0] != vcpu->arch.pgfault_hpte[0] || |
| @@ -621,7 +618,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
| 621 | 618 | ||
| 622 | hptep[1] = cpu_to_be64(r); | 619 | hptep[1] = cpu_to_be64(r); |
| 623 | eieio(); | 620 | eieio(); |
| 624 | hptep[0] = cpu_to_be64(hpte[0]); | 621 | __unlock_hpte(hptep, hpte[0]); |
| 625 | asm volatile("ptesync" : : : "memory"); | 622 | asm volatile("ptesync" : : : "memory"); |
| 626 | preempt_enable(); | 623 | preempt_enable(); |
| 627 | if (page && hpte_is_writable(r)) | 624 | if (page && hpte_is_writable(r)) |
| @@ -642,7 +639,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
| 642 | return ret; | 639 | return ret; |
| 643 | 640 | ||
| 644 | out_unlock: | 641 | out_unlock: |
| 645 | hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); | 642 | __unlock_hpte(hptep, be64_to_cpu(hptep[0])); |
| 646 | preempt_enable(); | 643 | preempt_enable(); |
| 647 | goto out_put; | 644 | goto out_put; |
| 648 | } | 645 | } |
| @@ -771,7 +768,7 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
| 771 | } | 768 | } |
| 772 | } | 769 | } |
| 773 | unlock_rmap(rmapp); | 770 | unlock_rmap(rmapp); |
| 774 | hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); | 771 | __unlock_hpte(hptep, be64_to_cpu(hptep[0])); |
| 775 | } | 772 | } |
| 776 | return 0; | 773 | return 0; |
| 777 | } | 774 | } |
| @@ -857,7 +854,7 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
| 857 | } | 854 | } |
| 858 | ret = 1; | 855 | ret = 1; |
| 859 | } | 856 | } |
| 860 | hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); | 857 | __unlock_hpte(hptep, be64_to_cpu(hptep[0])); |
| 861 | } while ((i = j) != head); | 858 | } while ((i = j) != head); |
| 862 | 859 | ||
| 863 | unlock_rmap(rmapp); | 860 | unlock_rmap(rmapp); |
| @@ -974,8 +971,7 @@ static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp) | |||
| 974 | 971 | ||
| 975 | /* Now check and modify the HPTE */ | 972 | /* Now check and modify the HPTE */ |
| 976 | if (!(hptep[0] & cpu_to_be64(HPTE_V_VALID))) { | 973 | if (!(hptep[0] & cpu_to_be64(HPTE_V_VALID))) { |
| 977 | /* unlock and continue */ | 974 | __unlock_hpte(hptep, be64_to_cpu(hptep[0])); |
| 978 | hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); | ||
| 979 | continue; | 975 | continue; |
| 980 | } | 976 | } |
| 981 | 977 | ||
| @@ -996,9 +992,9 @@ static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp) | |||
| 996 | npages_dirty = n; | 992 | npages_dirty = n; |
| 997 | eieio(); | 993 | eieio(); |
| 998 | } | 994 | } |
| 999 | v &= ~(HPTE_V_ABSENT | HPTE_V_HVLOCK); | 995 | v &= ~HPTE_V_ABSENT; |
| 1000 | v |= HPTE_V_VALID; | 996 | v |= HPTE_V_VALID; |
| 1001 | hptep[0] = cpu_to_be64(v); | 997 | __unlock_hpte(hptep, v); |
| 1002 | } while ((i = j) != head); | 998 | } while ((i = j) != head); |
| 1003 | 999 | ||
| 1004 | unlock_rmap(rmapp); | 1000 | unlock_rmap(rmapp); |
| @@ -1218,8 +1214,7 @@ static long record_hpte(unsigned long flags, __be64 *hptp, | |||
| 1218 | r &= ~HPTE_GR_MODIFIED; | 1214 | r &= ~HPTE_GR_MODIFIED; |
| 1219 | revp->guest_rpte = r; | 1215 | revp->guest_rpte = r; |
| 1220 | } | 1216 | } |
| 1221 | asm volatile(PPC_RELEASE_BARRIER "" : : : "memory"); | 1217 | unlock_hpte(hptp, be64_to_cpu(hptp[0])); |
| 1222 | hptp[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); | ||
| 1223 | preempt_enable(); | 1218 | preempt_enable(); |
| 1224 | if (!(valid == want_valid && (first_pass || dirty))) | 1219 | if (!(valid == want_valid && (first_pass || dirty))) |
| 1225 | ok = 0; | 1220 | ok = 0; |
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index 625407e4d3b0..f6bf0b1de6d7 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c | |||
| @@ -150,12 +150,6 @@ static pte_t lookup_linux_pte_and_update(pgd_t *pgdir, unsigned long hva, | |||
| 150 | return kvmppc_read_update_linux_pte(ptep, writing, hugepage_shift); | 150 | return kvmppc_read_update_linux_pte(ptep, writing, hugepage_shift); |
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | static inline void unlock_hpte(__be64 *hpte, unsigned long hpte_v) | ||
| 154 | { | ||
| 155 | asm volatile(PPC_RELEASE_BARRIER "" : : : "memory"); | ||
| 156 | hpte[0] = cpu_to_be64(hpte_v); | ||
| 157 | } | ||
| 158 | |||
| 159 | long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, | 153 | long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, |
| 160 | long pte_index, unsigned long pteh, unsigned long ptel, | 154 | long pte_index, unsigned long pteh, unsigned long ptel, |
| 161 | pgd_t *pgdir, bool realmode, unsigned long *pte_idx_ret) | 155 | pgd_t *pgdir, bool realmode, unsigned long *pte_idx_ret) |
| @@ -271,10 +265,10 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, | |||
| 271 | u64 pte; | 265 | u64 pte; |
| 272 | while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) | 266 | while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) |
| 273 | cpu_relax(); | 267 | cpu_relax(); |
| 274 | pte = be64_to_cpu(*hpte); | 268 | pte = be64_to_cpu(hpte[0]); |
| 275 | if (!(pte & (HPTE_V_VALID | HPTE_V_ABSENT))) | 269 | if (!(pte & (HPTE_V_VALID | HPTE_V_ABSENT))) |
| 276 | break; | 270 | break; |
| 277 | *hpte &= ~cpu_to_be64(HPTE_V_HVLOCK); | 271 | __unlock_hpte(hpte, pte); |
| 278 | hpte += 2; | 272 | hpte += 2; |
| 279 | } | 273 | } |
| 280 | if (i == 8) | 274 | if (i == 8) |
| @@ -290,9 +284,9 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, | |||
| 290 | 284 | ||
| 291 | while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) | 285 | while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) |
| 292 | cpu_relax(); | 286 | cpu_relax(); |
| 293 | pte = be64_to_cpu(*hpte); | 287 | pte = be64_to_cpu(hpte[0]); |
| 294 | if (pte & (HPTE_V_VALID | HPTE_V_ABSENT)) { | 288 | if (pte & (HPTE_V_VALID | HPTE_V_ABSENT)) { |
| 295 | *hpte &= ~cpu_to_be64(HPTE_V_HVLOCK); | 289 | __unlock_hpte(hpte, pte); |
| 296 | return H_PTEG_FULL; | 290 | return H_PTEG_FULL; |
| 297 | } | 291 | } |
| 298 | } | 292 | } |
| @@ -331,7 +325,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, | |||
| 331 | 325 | ||
| 332 | /* Write the first HPTE dword, unlocking the HPTE and making it valid */ | 326 | /* Write the first HPTE dword, unlocking the HPTE and making it valid */ |
| 333 | eieio(); | 327 | eieio(); |
| 334 | hpte[0] = cpu_to_be64(pteh); | 328 | __unlock_hpte(hpte, pteh); |
| 335 | asm volatile("ptesync" : : : "memory"); | 329 | asm volatile("ptesync" : : : "memory"); |
| 336 | 330 | ||
| 337 | *pte_idx_ret = pte_index; | 331 | *pte_idx_ret = pte_index; |
| @@ -412,7 +406,7 @@ long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags, | |||
| 412 | if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 || | 406 | if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 || |
| 413 | ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn) || | 407 | ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn) || |
| 414 | ((flags & H_ANDCOND) && (pte & avpn) != 0)) { | 408 | ((flags & H_ANDCOND) && (pte & avpn) != 0)) { |
| 415 | hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); | 409 | __unlock_hpte(hpte, pte); |
| 416 | return H_NOT_FOUND; | 410 | return H_NOT_FOUND; |
| 417 | } | 411 | } |
| 418 | 412 | ||
| @@ -548,7 +542,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu) | |||
| 548 | be64_to_cpu(hp[0]), be64_to_cpu(hp[1])); | 542 | be64_to_cpu(hp[0]), be64_to_cpu(hp[1])); |
| 549 | rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C); | 543 | rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C); |
| 550 | args[j] |= rcbits << (56 - 5); | 544 | args[j] |= rcbits << (56 - 5); |
| 551 | hp[0] = 0; | 545 | __unlock_hpte(hp, 0); |
| 552 | } | 546 | } |
| 553 | } | 547 | } |
| 554 | 548 | ||
| @@ -574,7 +568,7 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags, | |||
| 574 | pte = be64_to_cpu(hpte[0]); | 568 | pte = be64_to_cpu(hpte[0]); |
| 575 | if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 || | 569 | if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 || |
| 576 | ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn)) { | 570 | ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn)) { |
| 577 | hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); | 571 | __unlock_hpte(hpte, pte); |
| 578 | return H_NOT_FOUND; | 572 | return H_NOT_FOUND; |
| 579 | } | 573 | } |
| 580 | 574 | ||
| @@ -755,8 +749,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v, | |||
| 755 | /* Return with the HPTE still locked */ | 749 | /* Return with the HPTE still locked */ |
| 756 | return (hash << 3) + (i >> 1); | 750 | return (hash << 3) + (i >> 1); |
| 757 | 751 | ||
| 758 | /* Unlock and move on */ | 752 | __unlock_hpte(&hpte[i], v); |
| 759 | hpte[i] = cpu_to_be64(v); | ||
| 760 | } | 753 | } |
| 761 | 754 | ||
| 762 | if (val & HPTE_V_SECONDARY) | 755 | if (val & HPTE_V_SECONDARY) |
