|
@@ -656,6 +656,23 @@ void kvm_local_flush_tlb_all(void)
|
|
|
local_irq_restore(flags);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * kvm_mips_migrate_count() - Migrate timer.
|
|
|
+ * @vcpu: Virtual CPU.
|
|
|
+ *
|
|
|
+ * Migrate CP0_Count hrtimer to the current CPU by cancelling and restarting it
|
|
|
+ * if it was running prior to being cancelled.
|
|
|
+ *
|
|
|
+ * Must be called when the VCPU is migrated to a different CPU to ensure that
|
|
|
+ * timer expiry during guest execution interrupts the guest and causes the
|
|
|
+ * interrupt to be delivered in a timely manner.
|
|
|
+ */
|
|
|
+static void kvm_mips_migrate_count(struct kvm_vcpu *vcpu)
|
|
|
+{
|
|
|
+ if (hrtimer_cancel(&vcpu->arch.comparecount_timer))
|
|
|
+ hrtimer_restart(&vcpu->arch.comparecount_timer);
|
|
|
+}
|
|
|
+
|
|
|
/* Restore ASID once we are scheduled back after preemption */
|
|
|
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
|
|
{
|
|
@@ -691,6 +708,12 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
|
|
if (vcpu->arch.last_sched_cpu != cpu) {
|
|
|
kvm_info("[%d->%d]KVM VCPU[%d] switch\n",
|
|
|
vcpu->arch.last_sched_cpu, cpu, vcpu->vcpu_id);
|
|
|
+ /*
|
|
|
+ * Migrate the timer interrupt to the current CPU so that it
|
|
|
+ * always interrupts the guest and synchronously triggers a
|
|
|
+ * guest timer interrupt.
|
|
|
+ */
|
|
|
+ kvm_mips_migrate_count(vcpu);
|
|
|
}
|
|
|
|
|
|
if (!newasid) {
|