|
@@ -302,12 +302,31 @@ static inline ktime_t kvm_mips_count_time(struct kvm_vcpu *vcpu)
|
|
*/
|
|
*/
|
|
static uint32_t kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now)
|
|
static uint32_t kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now)
|
|
{
|
|
{
|
|
- ktime_t expires;
|
|
|
|
|
|
+ struct mips_coproc *cop0 = vcpu->arch.cop0;
|
|
|
|
+ ktime_t expires, threshold;
|
|
|
|
+ uint32_t count, compare;
|
|
int running;
|
|
int running;
|
|
|
|
|
|
- /* Is the hrtimer pending? */
|
|
|
|
|
|
+ /* Calculate the biased and scaled guest CP0_Count */
|
|
|
|
+ count = vcpu->arch.count_bias + kvm_mips_ktime_to_count(vcpu, now);
|
|
|
|
+ compare = kvm_read_c0_guest_compare(cop0);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Find whether CP0_Count has reached the closest timer interrupt. If
|
|
|
|
+ * not, we shouldn't inject it.
|
|
|
|
+ */
|
|
|
|
+ if ((int32_t)(count - compare) < 0)
|
|
|
|
+ return count;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * The CP0_Count we're going to return has already reached the closest
|
|
|
|
+ * timer interrupt. Quickly check if it really is a new interrupt by
|
|
|
|
+ * looking at whether the interval until the hrtimer expiry time is
|
|
|
|
+ * less than 1/4 of the timer period.
|
|
|
|
+ */
|
|
expires = hrtimer_get_expires(&vcpu->arch.comparecount_timer);
|
|
expires = hrtimer_get_expires(&vcpu->arch.comparecount_timer);
|
|
- if (ktime_compare(now, expires) >= 0) {
|
|
|
|
|
|
+ threshold = ktime_add_ns(now, vcpu->arch.count_period / 4);
|
|
|
|
+ if (ktime_before(expires, threshold)) {
|
|
/*
|
|
/*
|
|
* Cancel it while we handle it so there's no chance of
|
|
* Cancel it while we handle it so there's no chance of
|
|
* interference with the timeout handler.
|
|
* interference with the timeout handler.
|
|
@@ -329,8 +348,7 @@ static uint32_t kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /* Return the biased and scaled guest CP0_Count */
|
|
|
|
- return vcpu->arch.count_bias + kvm_mips_ktime_to_count(vcpu, now);
|
|
|
|
|
|
+ return count;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|