aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/kvm/emulate.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index e788515f766b..43853ec6e160 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -846,6 +846,47 @@ enum emulation_result kvm_mips_emul_tlbr(struct kvm_vcpu *vcpu)
846 return EMULATE_FAIL; 846 return EMULATE_FAIL;
847} 847}
848 848
849/**
850 * kvm_mips_invalidate_guest_tlb() - Indicates a change in guest MMU map.
851 * @vcpu: VCPU with changed mappings.
852 * @tlb: TLB entry being removed.
853 *
854 * This is called to indicate a single change in guest MMU mappings, so that we
855 * can arrange TLB flushes on this and other CPUs.
856 */
857static void kvm_mips_invalidate_guest_tlb(struct kvm_vcpu *vcpu,
858 struct kvm_mips_tlb *tlb)
859{
860 int cpu, i;
861 bool user;
862
863 /* No need to flush for entries which are already invalid */
864 if (!((tlb->tlb_lo[0] | tlb->tlb_lo[1]) & ENTRYLO_V))
865 return;
866 /* User address space doesn't need flushing for KSeg2/3 changes */
867 user = tlb->tlb_hi < KVM_GUEST_KSEG0;
868
869 preempt_disable();
870
871 /*
872 * Probe the shadow host TLB for the entry being overwritten, if one
873 * matches, invalidate it
874 */
875 kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi);
876
877 /* Invalidate the whole ASID on other CPUs */
878 cpu = smp_processor_id();
879 for_each_possible_cpu(i) {
880 if (i == cpu)
881 continue;
882 if (user)
883 vcpu->arch.guest_user_asid[i] = 0;
884 vcpu->arch.guest_kernel_asid[i] = 0;
885 }
886
887 preempt_enable();
888}
889
849/* Write Guest TLB Entry @ Index */ 890/* Write Guest TLB Entry @ Index */
850enum emulation_result kvm_mips_emul_tlbwi(struct kvm_vcpu *vcpu) 891enum emulation_result kvm_mips_emul_tlbwi(struct kvm_vcpu *vcpu)
851{ 892{
@@ -865,11 +906,8 @@ enum emulation_result kvm_mips_emul_tlbwi(struct kvm_vcpu *vcpu)
865 } 906 }
866 907
867 tlb = &vcpu->arch.guest_tlb[index]; 908 tlb = &vcpu->arch.guest_tlb[index];
868 /* 909
869 * Probe the shadow host TLB for the entry being overwritten, if one 910 kvm_mips_invalidate_guest_tlb(vcpu, tlb);
870 * matches, invalidate it
871 */
872 kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi);
873 911
874 tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0); 912 tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0);
875 tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0); 913 tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0);
@@ -898,11 +936,7 @@ enum emulation_result kvm_mips_emul_tlbwr(struct kvm_vcpu *vcpu)
898 936
899 tlb = &vcpu->arch.guest_tlb[index]; 937 tlb = &vcpu->arch.guest_tlb[index];
900 938
901 /* 939 kvm_mips_invalidate_guest_tlb(vcpu, tlb);
902 * Probe the shadow host TLB for the entry being overwritten, if one
903 * matches, invalidate it
904 */
905 kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi);
906 940
907 tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0); 941 tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0);
908 tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0); 942 tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0);
@@ -1026,6 +1060,7 @@ enum emulation_result kvm_mips_emulate_CP0(union mips_instruction inst,
1026 enum emulation_result er = EMULATE_DONE; 1060 enum emulation_result er = EMULATE_DONE;
1027 u32 rt, rd, sel; 1061 u32 rt, rd, sel;
1028 unsigned long curr_pc; 1062 unsigned long curr_pc;
1063 int cpu, i;
1029 1064
1030 /* 1065 /*
1031 * Update PC and hold onto current PC in case there is 1066 * Update PC and hold onto current PC in case there is
@@ -1135,8 +1170,16 @@ enum emulation_result kvm_mips_emulate_CP0(union mips_instruction inst,
1135 & KVM_ENTRYHI_ASID, 1170 & KVM_ENTRYHI_ASID,
1136 nasid); 1171 nasid);
1137 1172
1173 preempt_disable();
1138 /* Blow away the shadow host TLBs */ 1174 /* Blow away the shadow host TLBs */
1139 kvm_mips_flush_host_tlb(1); 1175 kvm_mips_flush_host_tlb(1);
1176 cpu = smp_processor_id();
1177 for_each_possible_cpu(i)
1178 if (i != cpu) {
1179 vcpu->arch.guest_user_asid[i] = 0;
1180 vcpu->arch.guest_kernel_asid[i] = 0;
1181 }
1182 preempt_enable();
1140 } 1183 }
1141 kvm_write_c0_guest_entryhi(cop0, 1184 kvm_write_c0_guest_entryhi(cop0,
1142 vcpu->arch.gprs[rt]); 1185 vcpu->arch.gprs[rt]);