diff options
author | Kevin Hilman <khilman@linaro.org> | 2015-06-04 14:43:38 -0700 |
---|---|---|
committer | Kevin Hilman <khilman@linaro.org> | 2015-06-04 14:43:38 -0700 |
commit | 94865bf8aa24aa359903de3c858a517243e20263 (patch) | |
tree | 950de82b3556dbab5a68a4f17aac8fb21af7c090 /arch/x86/kvm/lapic.c | |
parent | 1a621b34f2a4bf8495bf801cd0024f063d561472 (diff) | |
parent | 474271f666ce974ee183057c022325b3833ecb39 (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.c | 48 |
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); } /* |