Invalidate TLB0 hardware entry when the related guest TLB entry is invalidated. It's a bug we didn't do this before. It didn't make problem is because that we flushed TLB every time when we enterred to guest's userspace. Signed-off-by: Liu Yu <yu.liu@xxxxxxxxxxxxx> --- arch/powerpc/kvm/e500_tlb.c | 32 ++++++++++++++++++++++++++++++-- 1 files changed, 30 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c index 570185c..ce4a379 100644 --- a/arch/powerpc/kvm/e500_tlb.c +++ b/arch/powerpc/kvm/e500_tlb.c @@ -286,6 +286,30 @@ static void kvmppc_e500_shadow_release(struct kvmppc_vcpu_e500 *vcpu_e500, } } +static void kvmppc_e500_tlb0_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500, + int esel) +{ + struct tlbe *gtlbe = &vcpu_e500->guest_tlb[0][esel]; + u32 eaddr, pid, val; + + eaddr = get_tlb_eaddr(gtlbe); + pid = kvmppc_e500_get_sid(vcpu_e500, get_tlb_ts(gtlbe), + get_tlb_tid(gtlbe)); + val = (pid << 16) | MAS6_SAS; + + local_irq_disable(); + + mtspr(SPRN_MAS6, val); + asm volatile ( "tlbsx 0, %[eaddr]\n" : : [eaddr] "a"(eaddr)); + val = mfspr(SPRN_MAS1); + if (val & MAS1_VALID) { + mtspr(SPRN_MAS1, val & ~MAS1_VALID); + asm volatile ("tlbwe\n" : : ); + } + + local_irq_enable(); +} + static void kvmppc_e500_tlb1_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500, int esel) { @@ -575,8 +599,12 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu) gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel]; - if (get_tlb_v(gtlbe) && tlbsel == 1) - kvmppc_e500_tlb1_invalidate(vcpu_e500, esel); + if (get_tlb_v(gtlbe)) { + if (tlbsel == 0) + kvmppc_e500_tlb0_invalidate(vcpu_e500, esel); + else + kvmppc_e500_tlb1_invalidate(vcpu_e500, esel); + } gtlbe->mas1 = vcpu_e500->mas1; gtlbe->mas2 = vcpu_e500->mas2; -- 1.5.4 -- To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html