KVM: MIPS/T&E: Activate GVA page tables in guest context
Activate the GVA page tables when in guest context. This will allow the
normal Linux TLB refill handler to fill from it when guest memory is
read, as well as preventing accidental reading from user memory.
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
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index ddd57ad..16eb852 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -29,9 +29,11 @@
} \
} while (0)
+extern void tlbmiss_handler_setup_pgd(unsigned long);
+
+/* Note: This is also implemented with uasm in arch/mips/kvm/entry.c */
#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
do { \
- extern void tlbmiss_handler_setup_pgd(unsigned long); \
tlbmiss_handler_setup_pgd((unsigned long)(pgd)); \
htw_set_pwbase((unsigned long)pgd); \
} while (0)
diff --git a/arch/mips/kvm/entry.c b/arch/mips/kvm/entry.c
index f818887..f683d12 100644
--- a/arch/mips/kvm/entry.c
+++ b/arch/mips/kvm/entry.c
@@ -13,6 +13,7 @@
#include <linux/kvm_host.h>
#include <linux/log2.h>
+#include <asm/mmu_context.h>
#include <asm/msa.h>
#include <asm/setup.h>
#include <asm/uasm.h>
@@ -316,7 +317,20 @@
#else
uasm_i_andi(&p, K0, K0, MIPS_ENTRYHI_ASID);
#endif
- uasm_i_mtc0(&p, K0, C0_ENTRYHI);
+
+ /*
+ * Set up KVM T&E GVA pgd.
+ * This does roughly the same as TLBMISS_HANDLER_SETUP_PGD():
+ * - call tlbmiss_handler_setup_pgd(mm->pgd)
+ * - but skips write into CP0_PWBase for now
+ */
+ UASM_i_LW(&p, A0, (int)offsetof(struct mm_struct, pgd) -
+ (int)offsetof(struct mm_struct, context.asid), T1);
+
+ UASM_i_LA(&p, T9, (unsigned long)tlbmiss_handler_setup_pgd);
+ uasm_i_jalr(&p, RA, T9);
+ uasm_i_mtc0(&p, K0, C0_ENTRYHI);
+
uasm_i_ehb(&p);
/* Disable RDHWR access */
diff --git a/arch/mips/kvm/trap_emul.c b/arch/mips/kvm/trap_emul.c
index 183150a..f39d427 100644
--- a/arch/mips/kvm/trap_emul.c
+++ b/arch/mips/kvm/trap_emul.c
@@ -704,6 +704,7 @@
{
struct mm_struct *kern_mm = &vcpu->arch.guest_kernel_mm;
struct mm_struct *user_mm = &vcpu->arch.guest_user_mm;
+ struct mm_struct *mm;
/* Allocate new kernel and user ASIDs if needed */
@@ -733,10 +734,9 @@
* on the mode of the Guest (Kernel/User)
*/
if (current->flags & PF_VCPU) {
- if (KVM_GUEST_KERNEL_MODE(vcpu))
- write_c0_entryhi(cpu_asid(cpu, kern_mm));
- else
- write_c0_entryhi(cpu_asid(cpu, user_mm));
+ mm = KVM_GUEST_KERNEL_MODE(vcpu) ? kern_mm : user_mm;
+ write_c0_entryhi(cpu_asid(cpu, mm));
+ TLBMISS_HANDLER_SETUP_PGD(mm->pgd);
kvm_mips_suspend_mm(cpu);
ehb();
}
@@ -757,6 +757,7 @@
get_new_mmu_context(current->mm, cpu);
}
write_c0_entryhi(cpu_asid(cpu, current->mm));
+ TLBMISS_HANDLER_SETUP_PGD(current->mm->pgd);
kvm_mips_resume_mm(cpu);
ehb();
}
@@ -821,6 +822,7 @@
asid_version_mask(cpu)))
get_new_mmu_context(current->mm, cpu);
write_c0_entryhi(cpu_asid(cpu, current->mm));
+ TLBMISS_HANDLER_SETUP_PGD(current->mm->pgd);
kvm_mips_resume_mm(cpu);
htw_start();