| From f064a0de1579fabded8990bed93971e30deb9ecb Mon Sep 17 00:00:00 2001 |
| From: Paul Mackerras <paulus@ozlabs.org> |
| Date: Wed, 16 Nov 2016 16:43:28 +1100 |
| Subject: KVM: PPC: Book3S HV: Don't lose hardware R/C bit updates in H_PROTECT |
| |
| From: Paul Mackerras <paulus@ozlabs.org> |
| |
| commit f064a0de1579fabded8990bed93971e30deb9ecb upstream. |
| |
| The hashed page table MMU in POWER processors can update the R |
| (reference) and C (change) bits in a HPTE at any time until the |
| HPTE has been invalidated and the TLB invalidation sequence has |
| completed. In kvmppc_h_protect, which implements the H_PROTECT |
| hypercall, we read the HPTE, modify the second doubleword, |
| invalidate the HPTE in memory, do the TLB invalidation sequence, |
| and then write the modified value of the second doubleword back |
| to memory. In doing so we could overwrite an R/C bit update done |
| by hardware between when we read the HPTE and when the TLB |
| invalidation completed. To fix this we re-read the second |
| doubleword after the TLB invalidation and OR in the (possibly) |
| new values of R and C. We can use an OR since hardware only ever |
| sets R and C, never clears them. |
| |
| This race was found by code inspection. In principle this bug could |
| cause occasional guest memory corruption under host memory pressure. |
| |
| Fixes: a8606e20e41a ("KVM: PPC: Handle some PAPR hcalls in the kernel", 2011-06-29) |
| Signed-off-by: Paul Mackerras <paulus@ozlabs.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 ++ |
| 1 file changed, 2 insertions(+) |
| |
| --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c |
| +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c |
| @@ -653,6 +653,8 @@ long kvmppc_h_protect(struct kvm_vcpu *v |
| HPTE_V_ABSENT); |
| do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), |
| true); |
| + /* Don't lose R/C bit updates done by hardware */ |
| + r |= be64_to_cpu(hpte[1]) & (HPTE_R_R | HPTE_R_C); |
| hpte[1] = cpu_to_be64(r); |
| } |
| } |