aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2016-09-13 07:58:08 -0400
committerJames Hogan <james.hogan@imgtec.com>2017-02-03 10:21:03 -0500
commit7071a8859bb36d34b8f766275b239e98760f010c (patch)
treeb8c193a8310f0012e770292869c9029772795e28
parent49ec508e3bd0b11aaf534af0d63e4a17e05594e4 (diff)
KVM: MIPS/Emulate: Drop redundant TLB flushes on exceptions
When exceptions are injected into the MIPS KVM guest, the whole host TLB is flushed (except any entries in the guest KSeg0 range). This is certainly not mandated by the architecture when exceptions are taken (userland can't directly change TLB mappings anyway), and is a pretty heavyweight operation: - There may be hundreds of TLB entries especially when a 512 entry FTLB is present. These are walked and read and conditionally invalidated, so the TLBINV feature can't be used either. - It'll indiscriminately wipe out entries belonging to other memory spaces. A simple ASID regeneration would be much faster to perform, although it'd wipe out the guest KSeg0 mappings too. My suspicion is that this was simply to plaster over the fact that kvm_mips_host_tlb_inv() incorrectly only invalidated TLB entries in the ASID for guest usermode, and not the ASID for guest kernelmode. Now that the recent commit "KVM: MIPS/TLB: Flush host TLB entry in kernel ASID" fixes kvm_mips_host_tlb_inv() to flush TLB entries in the kernelmode ASID when the guest TLB changes, lets drop these calls and the otherwise unused kvm_mips_flush_host_tlb(). Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: "Radim Krčmář" <rkrcmar@redhat.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org
-rw-r--r--arch/mips/include/asm/kvm_host.h1
-rw-r--r--arch/mips/kvm/emulate.c10
-rw-r--r--arch/mips/kvm/tlb.c49
3 files changed, 0 insertions, 60 deletions
diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
index 1a83b6f85de2..174857f146b1 100644
--- a/arch/mips/include/asm/kvm_host.h
+++ b/arch/mips/include/asm/kvm_host.h
@@ -608,7 +608,6 @@ extern enum emulation_result kvm_mips_handle_tlbmod(u32 cause,
608 608
609extern void kvm_mips_dump_host_tlbs(void); 609extern void kvm_mips_dump_host_tlbs(void);
610extern void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu); 610extern void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu);
611extern void kvm_mips_flush_host_tlb(int skip_kseg0);
612extern int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long entryhi, 611extern int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long entryhi,
613 bool user, bool kernel); 612 bool user, bool kernel);
614 613
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index 9ac8e45017ce..cd11d787d9dc 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -1968,8 +1968,6 @@ enum emulation_result kvm_mips_emulate_tlbmiss_ld(u32 cause,
1968 kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr); 1968 kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
1969 /* XXXKYMA: is the context register used by linux??? */ 1969 /* XXXKYMA: is the context register used by linux??? */
1970 kvm_write_c0_guest_entryhi(cop0, entryhi); 1970 kvm_write_c0_guest_entryhi(cop0, entryhi);
1971 /* Blow away the shadow host TLBs */
1972 kvm_mips_flush_host_tlb(1);
1973 1971
1974 return EMULATE_DONE; 1972 return EMULATE_DONE;
1975} 1973}
@@ -2014,8 +2012,6 @@ enum emulation_result kvm_mips_emulate_tlbinv_ld(u32 cause,
2014 kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr); 2012 kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
2015 /* XXXKYMA: is the context register used by linux??? */ 2013 /* XXXKYMA: is the context register used by linux??? */
2016 kvm_write_c0_guest_entryhi(cop0, entryhi); 2014 kvm_write_c0_guest_entryhi(cop0, entryhi);
2017 /* Blow away the shadow host TLBs */
2018 kvm_mips_flush_host_tlb(1);
2019 2015
2020 return EMULATE_DONE; 2016 return EMULATE_DONE;
2021} 2017}
@@ -2058,8 +2054,6 @@ enum emulation_result kvm_mips_emulate_tlbmiss_st(u32 cause,
2058 kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr); 2054 kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
2059 /* XXXKYMA: is the context register used by linux??? */ 2055 /* XXXKYMA: is the context register used by linux??? */
2060 kvm_write_c0_guest_entryhi(cop0, entryhi); 2056 kvm_write_c0_guest_entryhi(cop0, entryhi);
2061 /* Blow away the shadow host TLBs */
2062 kvm_mips_flush_host_tlb(1);
2063 2057
2064 return EMULATE_DONE; 2058 return EMULATE_DONE;
2065} 2059}
@@ -2102,8 +2096,6 @@ enum emulation_result kvm_mips_emulate_tlbinv_st(u32 cause,
2102 kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr); 2096 kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
2103 /* XXXKYMA: is the context register used by linux??? */ 2097 /* XXXKYMA: is the context register used by linux??? */
2104 kvm_write_c0_guest_entryhi(cop0, entryhi); 2098 kvm_write_c0_guest_entryhi(cop0, entryhi);
2105 /* Blow away the shadow host TLBs */
2106 kvm_mips_flush_host_tlb(1);
2107 2099
2108 return EMULATE_DONE; 2100 return EMULATE_DONE;
2109} 2101}
@@ -2176,8 +2168,6 @@ enum emulation_result kvm_mips_emulate_tlbmod(u32 cause,
2176 kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr); 2168 kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
2177 /* XXXKYMA: is the context register used by linux??? */ 2169 /* XXXKYMA: is the context register used by linux??? */
2178 kvm_write_c0_guest_entryhi(cop0, entryhi); 2170 kvm_write_c0_guest_entryhi(cop0, entryhi);
2179 /* Blow away the shadow host TLBs */
2180 kvm_mips_flush_host_tlb(1);
2181 2171
2182 return EMULATE_DONE; 2172 return EMULATE_DONE;
2183} 2173}
diff --git a/arch/mips/kvm/tlb.c b/arch/mips/kvm/tlb.c
index 51f4aee717e7..cee2e9feb942 100644
--- a/arch/mips/kvm/tlb.c
+++ b/arch/mips/kvm/tlb.c
@@ -214,55 +214,6 @@ int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va,
214} 214}
215EXPORT_SYMBOL_GPL(kvm_mips_host_tlb_inv); 215EXPORT_SYMBOL_GPL(kvm_mips_host_tlb_inv);
216 216
217void kvm_mips_flush_host_tlb(int skip_kseg0)
218{
219 unsigned long flags;
220 unsigned long old_entryhi, entryhi;
221 unsigned long old_pagemask;
222 int entry = 0;
223 int maxentry = current_cpu_data.tlbsize;
224
225 local_irq_save(flags);
226
227 old_entryhi = read_c0_entryhi();
228 old_pagemask = read_c0_pagemask();
229
230 /* Blast 'em all away. */
231 for (entry = 0; entry < maxentry; entry++) {
232 write_c0_index(entry);
233
234 if (skip_kseg0) {
235 mtc0_tlbr_hazard();
236 tlb_read();
237 tlb_read_hazard();
238
239 entryhi = read_c0_entryhi();
240
241 /* Don't blow away guest kernel entries */
242 if (KVM_GUEST_KSEGX(entryhi) == KVM_GUEST_KSEG0)
243 continue;
244
245 write_c0_pagemask(old_pagemask);
246 }
247
248 /* Make sure all entries differ. */
249 write_c0_entryhi(UNIQUE_ENTRYHI(entry));
250 write_c0_entrylo0(0);
251 write_c0_entrylo1(0);
252 mtc0_tlbw_hazard();
253
254 tlb_write_indexed();
255 tlbw_use_hazard();
256 }
257
258 write_c0_entryhi(old_entryhi);
259 write_c0_pagemask(old_pagemask);
260 mtc0_tlbw_hazard();
261
262 local_irq_restore(flags);
263}
264EXPORT_SYMBOL_GPL(kvm_mips_flush_host_tlb);
265
266/** 217/**
267 * kvm_mips_suspend_mm() - Suspend the active mm. 218 * kvm_mips_suspend_mm() - Suspend the active mm.
268 * @cpu The CPU we're running on. 219 * @cpu The CPU we're running on.