On vcpu schedule, the condition checked for tlb pollution is too tight. The tlb entries of one vcpu are polluted when a different vcpu from the same partition runs in-between. Relax the current tlb invalidation condition taking into account the lpid. Signed-off-by: Mihai Caraman <mihai.caraman <at> freescale.com> Cc: Scott Wood <scottwood <at> freescale.com> --- arch/powerpc/kvm/e500mc.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c index 17e4562..2e0cd69 100644 --- a/arch/powerpc/kvm/e500mc.c +++ b/arch/powerpc/kvm/e500mc.c @@ -111,10 +111,12 @@ void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr) } static DEFINE_PER_CPU(struct kvm_vcpu *, last_vcpu_on_cpu); +static DEFINE_PER_CPU(int, last_lpid_on_cpu); static void kvmppc_core_vcpu_load_e500mc(struct kvm_vcpu *vcpu, int cpu) { struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + bool update_last = false, inval_tlb = false; kvmppc_booke_vcpu_load(vcpu, cpu); @@ -140,12 +142,24 @@ static void kvmppc_core_vcpu_load_e500mc(struct kvm_vcpu *vcpu, int cpu) mtspr(SPRN_GDEAR, vcpu->arch.shared->dar); mtspr(SPRN_GESR, vcpu->arch.shared->esr); - if (vcpu->arch.oldpir != mfspr(SPRN_PIR) || - __get_cpu_var(last_vcpu_on_cpu) != vcpu) { - kvmppc_e500_tlbil_all(vcpu_e500); + if (vcpu->arch.oldpir != mfspr(SPRN_PIR)) { + /* tlb entries deprecated */ + inval_tlb = update_last = true; + } else if (__get_cpu_var(last_vcpu_on_cpu) != vcpu) { + update_last = true; + /* tlb entries polluted */ + inval_tlb = __get_cpu_var(last_lpid_on_cpu) == + vcpu->kvm->arch.lpid; + } + + if (update_last) { __get_cpu_var(last_vcpu_on_cpu) = vcpu; + __get_cpu_var(last_lpid_on_cpu) = vcpu->kvm->arch.lpid; } + if (inval_tlb) + kvmppc_e500_tlbil_all(vcpu_e500); + kvmppc_load_guest_fp(vcpu); } -- 1.7.11.7 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html