e.priority = KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL;
kvm_xen_set_evtchn(&e, vcpu->kvm);
+
+ vcpu->arch.xen.timer_expires = 0;
atomic_set(&vcpu->arch.xen.timer_pending, 0);
}
}
{
struct kvm_vcpu *vcpu = container_of(timer, struct kvm_vcpu,
arch.xen.timer);
- struct kvm_xen_evtchn e;
-
if (atomic_read(&vcpu->arch.xen.timer_pending))
return HRTIMER_NORESTART;
- e.vcpu_id = vcpu->vcpu_id;
- e.vcpu_idx = vcpu->vcpu_idx;
- e.port = vcpu->arch.xen.timer_virq;
- e.priority = KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL;
-
- if (kvm_xen_set_evtchn_fast(&e, vcpu->kvm) != -EWOULDBLOCK)
- return HRTIMER_NORESTART;
-
atomic_inc(&vcpu->arch.xen.timer_pending);
kvm_make_request(KVM_REQ_UNBLOCK, vcpu);
kvm_vcpu_kick(vcpu);
return HRTIMER_NORESTART;
}
-void __kvm_migrate_xen_timer(struct kvm_vcpu *vcpu)
-{
- struct hrtimer *timer;
-
- if (!kvm_xen_timer_enabled(vcpu))
- return;
-
- timer = &vcpu->arch.xen.timer;
- if (hrtimer_cancel(timer))
- hrtimer_start_expires(timer, HRTIMER_MODE_ABS_PINNED);
-}
-
-static void kvm_xen_start_timer(struct kvm_vcpu *vcpu, u64 guest_abs, u64 delta_ns)
+static void kvm_xen_start_timer(struct kvm_vcpu *vcpu, u64 guest_abs, s64 delta_ns)
{
- ktime_t ktime_now;
-
atomic_set(&vcpu->arch.xen.timer_pending, 0);
vcpu->arch.xen.timer_expires = guest_abs;
- ktime_now = ktime_get();
- hrtimer_start(&vcpu->arch.xen.timer,
- ktime_add_ns(ktime_now, delta_ns),
- HRTIMER_MODE_ABS_PINNED);
+ if (delta_ns <= 0) {
+ xen_timer_callback(&vcpu->arch.xen.timer);
+ } else {
+ ktime_t ktime_now = ktime_get();
+ hrtimer_start(&vcpu->arch.xen.timer,
+ ktime_add_ns(ktime_now, delta_ns),
+ HRTIMER_MODE_ABS_HARD);
+ }
}
static void kvm_xen_stop_timer(struct kvm_vcpu *vcpu)
static void kvm_xen_init_timer(struct kvm_vcpu *vcpu)
{
hrtimer_init(&vcpu->arch.xen.timer, CLOCK_MONOTONIC,
- HRTIMER_MODE_ABS_PINNED);
+ HRTIMER_MODE_ABS_HARD);
vcpu->arch.xen.timer.function = xen_timer_callback;
}
if (timeout) {
uint64_t guest_now = get_kvmclock_ns(vcpu->kvm);
- long delta = timeout - guest_now;
+ int64_t delta = timeout - guest_now;
/* Xen has a 'Linux workaround' in do_set_timer_op() which
* checks for negative absolute timeout values (caused by