aboutsummaryrefslogtreecommitdiff
path: root/arch/x86/kvm/lapic.c
diff options
context:
space:
mode:
authorKevin Hilman <khilman@linaro.org>2015-06-04 14:43:38 -0700
committerKevin Hilman <khilman@linaro.org>2015-06-04 14:43:38 -0700
commit94865bf8aa24aa359903de3c858a517243e20263 (patch)
tree950de82b3556dbab5a68a4f17aac8fb21af7c090 /arch/x86/kvm/lapic.c
parent1a621b34f2a4bf8495bf801cd0024f063d561472 (diff)
parent474271f666ce974ee183057c022325b3833ecb39 (diff)
Merge tag 'v3.14.43-rt42-lno1' of git://git.linaro.org/people/anders.roxell/linux-rt into linux-linaro-lsk-v3.14-rtlsk-v3.14-15.06-rt
Linux 3.14.43-rt42 Changes since v3.14.39-rt37: - KVM: lapic: mark LAPIC timer handler as irqsafe - KVM: use simple waitqueue for vcpu->wq - hotplug: Use set_cpus_allowed_ptr() in sync_unplug_thread() - rt, nohz_full: fix nohz_full for PREEMPT_RT_FULL - kernel/irq_work: fix no_hz deadlock * tag 'v3.14.43-rt42-lno1' of git://git.linaro.org/people/anders.roxell/linux-rt: (360 commits) Linux 3.14.43-rt42 REBASE rt, nohz_full: fix nohz_full for PREEMPT_RT_FULL hotplug: Use set_cpus_allowed_ptr() in sync_unplug_thread() KVM: use simple waitqueue for vcpu->wq KVM: lapic: mark LAPIC timer handler as irqsafe kernel/irq_work: fix no_hz deadlock netpoll: guard the access to dev->npinfo with rcu_read_lock/unlock_bh() for CONFIG_PREEMPT_RT_FULL=y Revert "timers: do not raise softirq unconditionally" fs,btrfs: fix rt deadlock on extent_buffer->lock staging: Mark rtl8821ae as broken timers: Reduce future __run_timers() latency for first add to empty list timers: Reduce future __run_timers() latency for newly emptied list timers: Reduce __run_timers() latency for empty list timers: Track total number of timers in list fs/aio: simple simple work lockdep: selftest: fix warnings due to missing PREEMPT_RT conditionals thermal: Defer thermal wakups to threads locking: ww_mutex: fix ww_mutex vs self-deadlock Revert "rwsem-rt: Do not allow readers to nest" sunrpc: make svc_xprt_do_enqueue() use get_cpu_light() ...
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r--arch/x86/kvm/lapic.c48
1 files changed, 42 insertions, 6 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 453e5fbbb7ae..8b25d010d5e4 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1031,8 +1031,38 @@ static void update_divide_count(struct kvm_lapic *apic)
apic->divide_count);
}
+
+static enum hrtimer_restart apic_timer_fn(struct hrtimer *data);
+
+static void apic_timer_expired(struct hrtimer *data)
+{
+ int ret, i = 0;
+ enum hrtimer_restart r;
+ struct kvm_timer *ktimer = container_of(data, struct kvm_timer, timer);
+
+ r = apic_timer_fn(data);
+
+ if (r == HRTIMER_RESTART) {
+ do {
+ ret = hrtimer_start_expires(data, HRTIMER_MODE_ABS);
+ if (ret == -ETIME)
+ hrtimer_add_expires_ns(&ktimer->timer,
+ ktimer->period);
+ i++;
+ } while (ret == -ETIME && i < 10);
+
+ if (ret == -ETIME) {
+ printk_once(KERN_ERR "%s: failed to reprogram timer\n",
+ __func__);
+ WARN_ON_ONCE(1);
+ }
+ }
+}
+
+
static void start_apic_timer(struct kvm_lapic *apic)
{
+ int ret;
ktime_t now;
atomic_set(&apic->lapic_timer.pending, 0);
@@ -1062,9 +1092,11 @@ static void start_apic_timer(struct kvm_lapic *apic)
}
}
- hrtimer_start(&apic->lapic_timer.timer,
+ ret = hrtimer_start(&apic->lapic_timer.timer,
ktime_add_ns(now, apic->lapic_timer.period),
HRTIMER_MODE_ABS);
+ if (ret == -ETIME)
+ apic_timer_expired(&apic->lapic_timer.timer);
apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
PRIx64 ", "
@@ -1094,8 +1126,10 @@ static void start_apic_timer(struct kvm_lapic *apic)
ns = (tscdeadline - guest_tsc) * 1000000ULL;
do_div(ns, this_tsc_khz);
}
- hrtimer_start(&apic->lapic_timer.timer,
+ ret = hrtimer_start(&apic->lapic_timer.timer,
ktime_add_ns(now, ns), HRTIMER_MODE_ABS);
+ if (ret == -ETIME)
+ apic_timer_expired(&apic->lapic_timer.timer);
local_irq_restore(flags);
}
@@ -1533,7 +1567,7 @@ static enum hrtimer_restart apic_timer_fn(struct hrtimer *data)
struct kvm_timer *ktimer = container_of(data, struct kvm_timer, timer);
struct kvm_lapic *apic = container_of(ktimer, struct kvm_lapic, lapic_timer);
struct kvm_vcpu *vcpu = apic->vcpu;
- wait_queue_head_t *q = &vcpu->wq;
+ struct swait_head *q = &vcpu->wq;
/*
* There is a race window between reading and incrementing, but we do
@@ -1547,8 +1581,8 @@ static enum hrtimer_restart apic_timer_fn(struct hrtimer *data)
kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
}
- if (waitqueue_active(q))
- wake_up_interruptible(q);
+ if (swaitqueue_active(q))
+ swait_wake_interruptible(q);
if (lapic_is_periodic(apic)) {
hrtimer_add_expires_ns(&ktimer->timer, ktimer->period);
@@ -1581,6 +1615,7 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu)
hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
HRTIMER_MODE_ABS);
apic->lapic_timer.timer.function = apic_timer_fn;
+ apic->lapic_timer.timer.irqsafe = 1;
/*
* APIC is created enabled. This will prevent kvm_lapic_set_base from
@@ -1699,7 +1734,8 @@ void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)
timer = &vcpu->arch.apic->lapic_timer.timer;
if (hrtimer_cancel(timer))
- hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
+ if (hrtimer_start_expires(timer, HRTIMER_MODE_ABS) == -ETIME)
+ apic_timer_expired(timer);
}
/*