KVM: ppc: fix invalidation of large guest pages

When guest invalidates a large tlb map, there may be more than one
corresponding shadow tlb maps that need to be invalidated. Use eaddr and eend
to find these shadow tlb maps.

Signed-off-by: Liu Yu <yu.liu@freescale.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>

authored by

Hollis Blanchard and committed by
Avi Kivity
cc04454f 5a00a5e7

+6 -4
+3 -2
arch/powerpc/kvm/44x_tlb.c
··· 177 vcpu->arch.msr & MSR_PR); 178 } 179 180 - void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid) 181 { 182 unsigned int pid = asid & 0xff; 183 int i; ··· 192 if (!get_tlb_v(stlbe)) 193 continue; 194 195 - if (eaddr < get_tlb_eaddr(stlbe)) 196 continue; 197 198 if (eaddr > get_tlb_end(stlbe))
··· 177 vcpu->arch.msr & MSR_PR); 178 } 179 180 + void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr, 181 + gva_t eend, u32 asid) 182 { 183 unsigned int pid = asid & 0xff; 184 int i; ··· 191 if (!get_tlb_v(stlbe)) 192 continue; 193 194 + if (eend < get_tlb_eaddr(stlbe)) 195 continue; 196 197 if (eaddr > get_tlb_end(stlbe))
+1 -1
arch/powerpc/kvm/emulate.c
··· 137 if (tlbe->word0 & PPC44x_TLB_VALID) { 138 eaddr = get_tlb_eaddr(tlbe); 139 asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid; 140 - kvmppc_mmu_invalidate(vcpu, eaddr, asid); 141 } 142 143 switch (ws) {
··· 137 if (tlbe->word0 & PPC44x_TLB_VALID) { 138 eaddr = get_tlb_eaddr(tlbe); 139 asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid; 140 + kvmppc_mmu_invalidate(vcpu, eaddr, get_tlb_end(tlbe), asid); 141 } 142 143 switch (ws) {
+2 -1
include/asm-powerpc/kvm_ppc.h
··· 61 62 extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, 63 u64 asid, u32 flags); 64 - extern void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid); 65 extern void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode); 66 67 extern void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu);
··· 61 62 extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, 63 u64 asid, u32 flags); 64 + extern void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr, 65 + gva_t eend, u32 asid); 66 extern void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode); 67 68 extern void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu);