summaryrefslogtreecommitdiffstats
path: root/arch/mips/kvm/tlb.c
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2017-03-14 10:25:48 +0000
committerJames Hogan <james.hogan@imgtec.com>2017-03-28 15:36:18 +0100
commit824533ad169f8bafcafba385a428e5b680928411 (patch)
tree43d41970ef33182b085a81bae52138aaf917e9bb /arch/mips/kvm/tlb.c
parent867f4da75277aaef10daa4e0e9ad6f905fa33fb1 (diff)
KVM: MIPS/VZ: VZ hardware setup for Octeon III
Set up hardware virtualisation on Octeon III cores, configuring guest interrupt routing and carving out half of the root TLB for guest use, restoring it back again afterwards. We need to be careful to inhibit TLB shutdown machine check exceptions while invalidating guest TLB entries, since TLB invalidation is not available so guest entries must be invalidated by setting them to unique unmapped addresses, which could conflict with mappings set by the guest or root if recently repartitioned. 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: David Daney <david.daney@cavium.com> Cc: Andreas Herrmann <andreas.herrmann@caviumnetworks.com> Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org
Diffstat (limited to 'arch/mips/kvm/tlb.c')
-rw-r--r--arch/mips/kvm/tlb.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/arch/mips/kvm/tlb.c b/arch/mips/kvm/tlb.c
index fbab2f747721..7c6336dd2638 100644
--- a/arch/mips/kvm/tlb.c
+++ b/arch/mips/kvm/tlb.c
@@ -447,6 +447,7 @@ void kvm_vz_local_flush_guesttlb_all(void)
unsigned long old_entrylo[2];
unsigned long old_pagemask;
int entry;
+ u64 cvmmemctl2 = 0;
local_irq_save(flags);
@@ -457,6 +458,15 @@ void kvm_vz_local_flush_guesttlb_all(void)
old_entrylo[1] = read_gc0_entrylo1();
old_pagemask = read_gc0_pagemask();
+ switch (current_cpu_type()) {
+ case CPU_CAVIUM_OCTEON3:
+ /* Inhibit machine check due to multiple matching TLB entries */
+ cvmmemctl2 = read_c0_cvmmemctl2();
+ cvmmemctl2 |= CVMMEMCTL2_INHIBITTS;
+ write_c0_cvmmemctl2(cvmmemctl2);
+ break;
+ };
+
/* Invalidate guest entries in guest TLB */
write_gc0_entrylo0(0);
write_gc0_entrylo1(0);
@@ -468,6 +478,12 @@ void kvm_vz_local_flush_guesttlb_all(void)
mtc0_tlbw_hazard();
guest_tlb_write_indexed();
}
+
+ if (cvmmemctl2) {
+ cvmmemctl2 &= ~CVMMEMCTL2_INHIBITTS;
+ write_c0_cvmmemctl2(cvmmemctl2);
+ };
+
write_gc0_index(old_index);
write_gc0_entryhi(old_entryhi);
write_gc0_entrylo0(old_entrylo[0]);