summaryrefslogtreecommitdiffstats
path: root/arch/mips/kvm/trap_emul.c
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2016-11-18 13:14:37 +0000
committerJames Hogan <james.hogan@imgtec.com>2017-02-03 15:20:46 +0000
commita2c046e40ff16ef6c20d534b0d77d526bc02a684 (patch)
treea016109fa9b7cbcdf636924f30d4972371f5621f /arch/mips/kvm/trap_emul.c
parentc550d53934d821dbdd867ca314d417f2e918c72c (diff)
downloadlinux-stable-a2c046e40ff16ef6c20d534b0d77d526bc02a684.tar.gz
linux-stable-a2c046e40ff16ef6c20d534b0d77d526bc02a684.tar.bz2
linux-stable-a2c046e40ff16ef6c20d534b0d77d526bc02a684.zip
KVM: MIPS: Add vcpu_run() & vcpu_reenter() callbacks
Add implementation callbacks for entering the guest (vcpu_run()) and reentering the guest (vcpu_reenter()), allowing implementation specific operations to be performed before entering the guest or after returning to the host without cluttering kvm_arch_vcpu_ioctl_run(). This allows the T&E specific lazy user GVA flush to be moved into trap_emul.c, along with disabling of the HTW. We also move kvm_mips_deliver_interrupts() as VZ will need to restore the guest timer state prior to delivering interrupts. 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
Diffstat (limited to 'arch/mips/kvm/trap_emul.c')
-rw-r--r--arch/mips/kvm/trap_emul.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/arch/mips/kvm/trap_emul.c b/arch/mips/kvm/trap_emul.c
index c7854d32fd64..92734d095c94 100644
--- a/arch/mips/kvm/trap_emul.c
+++ b/arch/mips/kvm/trap_emul.c
@@ -692,6 +692,52 @@ static int kvm_trap_emul_vcpu_put(struct kvm_vcpu *vcpu, int cpu)
return 0;
}
+static void kvm_trap_emul_vcpu_reenter(struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
+{
+ struct mm_struct *user_mm = &vcpu->arch.guest_user_mm;
+ struct mips_coproc *cop0 = vcpu->arch.cop0;
+ int i, cpu = smp_processor_id();
+ unsigned int gasid;
+
+ /*
+ * Lazy host ASID regeneration for guest user mode.
+ * If the guest ASID has changed since the last guest usermode
+ * execution, regenerate the host ASID so as to invalidate stale TLB
+ * entries.
+ */
+ if (!KVM_GUEST_KERNEL_MODE(vcpu)) {
+ gasid = kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID;
+ if (gasid != vcpu->arch.last_user_gasid) {
+ kvm_get_new_mmu_context(user_mm, cpu, vcpu);
+ for_each_possible_cpu(i)
+ if (i != cpu)
+ cpu_context(i, user_mm) = 0;
+ vcpu->arch.last_user_gasid = gasid;
+ }
+ }
+}
+
+static int kvm_trap_emul_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+ int r;
+
+ /* Check if we have any exceptions/interrupts pending */
+ kvm_mips_deliver_interrupts(vcpu,
+ kvm_read_c0_guest_cause(vcpu->arch.cop0));
+
+ kvm_trap_emul_vcpu_reenter(run, vcpu);
+
+ /* Disable hardware page table walking while in guest */
+ htw_stop();
+
+ r = vcpu->arch.vcpu_run(run, vcpu);
+
+ htw_start();
+
+ return r;
+}
+
static struct kvm_mips_callbacks kvm_trap_emul_callbacks = {
/* exit handlers */
.handle_cop_unusable = kvm_trap_emul_handle_cop_unusable,
@@ -724,6 +770,8 @@ static struct kvm_mips_callbacks kvm_trap_emul_callbacks = {
.set_one_reg = kvm_trap_emul_set_one_reg,
.vcpu_load = kvm_trap_emul_vcpu_load,
.vcpu_put = kvm_trap_emul_vcpu_put,
+ .vcpu_run = kvm_trap_emul_vcpu_run,
+ .vcpu_reenter = kvm_trap_emul_vcpu_reenter,
};
int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks)