diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2014-06-15 14:47:07 -0400 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2014-06-25 08:07:06 -0400 |
commit | 341acbb3aabbcfbf069d7de4ad35f51b58176faf (patch) | |
tree | f6ea84649db60b6bc5a56bf2e062c8db29046bbd | |
parent | 511c66818d87db2a8931e7f7f92c7904bdd84f72 (diff) |
KVM: PPC: BOOK3S: HV: Use base page size when comparing against slb value
With guests supporting Multiple page size per segment (MPSS),
hpte_page_size returns the actual page size used. Add a new function to
return base page size and use that to compare against the the page size
calculated from SLB. Without this patch a hpte lookup can fail since
we are comparing wrong page size in kvmppc_hv_find_lock_hpte.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
-rw-r--r-- | arch/powerpc/include/asm/kvm_book3s_64.h | 19 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_64_mmu_hv.c | 2 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv_rm_mmu.c | 7 |
3 files changed, 20 insertions, 8 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h index fddb72b48ce9..d645428a65a4 100644 --- a/arch/powerpc/include/asm/kvm_book3s_64.h +++ b/arch/powerpc/include/asm/kvm_book3s_64.h | |||
@@ -198,8 +198,10 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, | |||
198 | return rb; | 198 | return rb; |
199 | } | 199 | } |
200 | 200 | ||
201 | static inline unsigned long hpte_page_size(unsigned long h, unsigned long l) | 201 | static inline unsigned long __hpte_page_size(unsigned long h, unsigned long l, |
202 | bool is_base_size) | ||
202 | { | 203 | { |
204 | |||
203 | int size, a_psize; | 205 | int size, a_psize; |
204 | /* Look at the 8 bit LP value */ | 206 | /* Look at the 8 bit LP value */ |
205 | unsigned int lp = (l >> LP_SHIFT) & ((1 << LP_BITS) - 1); | 207 | unsigned int lp = (l >> LP_SHIFT) & ((1 << LP_BITS) - 1); |
@@ -214,14 +216,27 @@ static inline unsigned long hpte_page_size(unsigned long h, unsigned long l) | |||
214 | continue; | 216 | continue; |
215 | 217 | ||
216 | a_psize = __hpte_actual_psize(lp, size); | 218 | a_psize = __hpte_actual_psize(lp, size); |
217 | if (a_psize != -1) | 219 | if (a_psize != -1) { |
220 | if (is_base_size) | ||
221 | return 1ul << mmu_psize_defs[size].shift; | ||
218 | return 1ul << mmu_psize_defs[a_psize].shift; | 222 | return 1ul << mmu_psize_defs[a_psize].shift; |
223 | } | ||
219 | } | 224 | } |
220 | 225 | ||
221 | } | 226 | } |
222 | return 0; | 227 | return 0; |
223 | } | 228 | } |
224 | 229 | ||
230 | static inline unsigned long hpte_page_size(unsigned long h, unsigned long l) | ||
231 | { | ||
232 | return __hpte_page_size(h, l, 0); | ||
233 | } | ||
234 | |||
235 | static inline unsigned long hpte_base_page_size(unsigned long h, unsigned long l) | ||
236 | { | ||
237 | return __hpte_page_size(h, l, 1); | ||
238 | } | ||
239 | |||
225 | static inline unsigned long hpte_rpn(unsigned long ptel, unsigned long psize) | 240 | static inline unsigned long hpte_rpn(unsigned long ptel, unsigned long psize) |
226 | { | 241 | { |
227 | return ((ptel & HPTE_R_RPN) & ~(psize - 1)) >> PAGE_SHIFT; | 242 | return ((ptel & HPTE_R_RPN) & ~(psize - 1)) >> PAGE_SHIFT; |
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index 80561074078d..68468d695f12 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c | |||
@@ -1562,7 +1562,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf, | |||
1562 | goto out; | 1562 | goto out; |
1563 | } | 1563 | } |
1564 | if (!rma_setup && is_vrma_hpte(v)) { | 1564 | if (!rma_setup && is_vrma_hpte(v)) { |
1565 | unsigned long psize = hpte_page_size(v, r); | 1565 | unsigned long psize = hpte_base_page_size(v, r); |
1566 | unsigned long senc = slb_pgsize_encoding(psize); | 1566 | unsigned long senc = slb_pgsize_encoding(psize); |
1567 | unsigned long lpcr; | 1567 | unsigned long lpcr; |
1568 | 1568 | ||
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index 6e6224318c36..5a24d3c2b6b8 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c | |||
@@ -814,13 +814,10 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v, | |||
814 | r = hpte[i+1]; | 814 | r = hpte[i+1]; |
815 | 815 | ||
816 | /* | 816 | /* |
817 | * Check the HPTE again, including large page size | 817 | * Check the HPTE again, including base page size |
818 | * Since we don't currently allow any MPSS (mixed | ||
819 | * page-size segment) page sizes, it is sufficient | ||
820 | * to check against the actual page size. | ||
821 | */ | 818 | */ |
822 | if ((v & valid) && (v & mask) == val && | 819 | if ((v & valid) && (v & mask) == val && |
823 | hpte_page_size(v, r) == (1ul << pshift)) | 820 | hpte_base_page_size(v, r) == (1ul << pshift)) |
824 | /* Return with the HPTE still locked */ | 821 | /* Return with the HPTE still locked */ |
825 | return (hash << 3) + (i >> 1); | 822 | return (hash << 3) + (i >> 1); |
826 | 823 | ||