From: Marcelo Tosatti <mtosatti@redhat.com>
To: Avi Kivity <avi@qumranet.com>
Cc: kvm-devel@lists.sourceforge.net, Marcelo Tosatti <mtosatti@redhat.com>
Subject: [patch 1/2] KVM: hlt emulation should take in-kernel APIC/PIT timers into account
Date: Thu, 10 Apr 2008 17:12:55 -0300 [thread overview]
Message-ID: <20080410201402.382704482@localhost.localdomain> (raw)
In-Reply-To: 20080410201254.316224847@localhost.localdomain
[-- Attachment #1: fix-timer-wakeup --]
[-- Type: text/plain, Size: 4695 bytes --]
Timers that fire between guest hlt and vcpu_block's add_wait_queue() are
ignored, possibly resulting in hangs.
Also make sure that atomic_inc and waitqueue_active tests happen in the
specified order, otherwise the following race is open:
CPU0 CPU1
if (waitqueue_active(wq))
add_wait_queue()
if (!atomic_read(pit_timer->pending))
schedule()
atomic_inc(pit_timer->pending)
Which is not an issue for the APIC timer due to migration logic.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: kvm/arch/x86/kvm/i8254.c
===================================================================
--- kvm.orig/arch/x86/kvm/i8254.c
+++ kvm/arch/x86/kvm/i8254.c
@@ -199,6 +199,7 @@ int __pit_timer_fn(struct kvm_kpit_state
struct kvm_kpit_timer *pt = &ps->pit_timer;
atomic_inc(&pt->pending);
+ smp_mb__after_atomic_inc();
if (vcpu0 && waitqueue_active(&vcpu0->wq)) {
vcpu0->arch.mp_state = VCPU_MP_STATE_RUNNABLE;
wake_up_interruptible(&vcpu0->wq);
@@ -210,6 +211,16 @@ int __pit_timer_fn(struct kvm_kpit_state
return (pt->period == 0 ? 0 : 1);
}
+int pit_has_pending_timer(struct kvm_vcpu *vcpu)
+{
+ struct kvm_pit *pit = vcpu->kvm->arch.vpit;
+
+ if (pit && vcpu->vcpu_id == 0)
+ return atomic_read(&pit->pit_state.pit_timer.pending);
+
+ return 0;
+}
+
static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
{
struct kvm_kpit_state *ps;
Index: kvm/arch/x86/kvm/irq.c
===================================================================
--- kvm.orig/arch/x86/kvm/irq.c
+++ kvm/arch/x86/kvm/irq.c
@@ -26,6 +26,21 @@
#include "i8254.h"
/*
+ * check if there are pending timer events
+ * to be processed.
+ */
+int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
+{
+ int ret;
+
+ ret = pit_has_pending_timer(vcpu);
+ ret |= apic_has_pending_timer(vcpu);
+
+ return ret;
+}
+EXPORT_SYMBOL(kvm_cpu_has_pending_timer);
+
+/*
* check if there is pending interrupt without
* intack.
*/
Index: kvm/arch/x86/kvm/irq.h
===================================================================
--- kvm.orig/arch/x86/kvm/irq.h
+++ kvm/arch/x86/kvm/irq.h
@@ -85,4 +85,7 @@ void kvm_inject_pending_timer_irqs(struc
void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu);
void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu);
+int pit_has_pending_timer(struct kvm_vcpu *vcpu);
+int apic_has_pending_timer(struct kvm_vcpu *vcpu);
+
#endif
Index: kvm/arch/x86/kvm/lapic.c
===================================================================
--- kvm.orig/arch/x86/kvm/lapic.c
+++ kvm/arch/x86/kvm/lapic.c
@@ -952,6 +952,16 @@ static int __apic_timer_fn(struct kvm_la
return result;
}
+int apic_has_pending_timer(struct kvm_vcpu *vcpu)
+{
+ struct kvm_lapic *lapic = vcpu->arch.apic;
+
+ if (lapic)
+ return atomic_read(&lapic->timer.pending);
+
+ return 0;
+}
+
static int __inject_apic_timer_irq(struct kvm_lapic *apic)
{
int vector;
Index: kvm/include/linux/kvm_host.h
===================================================================
--- kvm.orig/include/linux/kvm_host.h
+++ kvm/include/linux/kvm_host.h
@@ -272,6 +272,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm
int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
int kvm_cpu_has_interrupt(struct kvm_vcpu *v);
+int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu);
void kvm_vcpu_kick(struct kvm_vcpu *vcpu);
static inline void kvm_guest_enter(void)
Index: kvm/virt/kvm/kvm_main.c
===================================================================
--- kvm.orig/virt/kvm/kvm_main.c
+++ kvm/virt/kvm/kvm_main.c
@@ -752,6 +752,7 @@ void mark_page_dirty(struct kvm *kvm, gf
}
}
+#ifdef CONFIG_X86
/*
* The vCPU has executed a HLT instruction with in-kernel mode enabled.
*/
@@ -765,6 +766,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcp
* We will block until either an interrupt or a signal wakes us up
*/
while (!kvm_cpu_has_interrupt(vcpu)
+ && !kvm_cpu_has_pending_timer(vcpu)
&& !signal_pending(current)
&& !kvm_arch_vcpu_runnable(vcpu)) {
set_current_state(TASK_INTERRUPTIBLE);
@@ -776,6 +778,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcp
__set_current_state(TASK_RUNNING);
remove_wait_queue(&vcpu->wq, &wait);
}
+#endif
void kvm_resched(struct kvm_vcpu *vcpu)
{
--
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
next prev parent reply other threads:[~2008-04-10 20:12 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-04-10 20:12 [patch 0/2] fix in-kernel timer / IRQ injection races Marcelo Tosatti
2008-04-10 20:12 ` Marcelo Tosatti [this message]
2008-04-11 12:12 ` [patch 1/2] KVM: hlt emulation should take in-kernel APIC/PIT timers into account Avi Kivity
2008-04-11 17:53 ` Marcelo Tosatti
2008-04-13 9:28 ` Avi Kivity
2008-05-09 7:49 ` Yang, Sheng
2008-05-09 14:53 ` Marcelo Tosatti
2008-05-10 2:12 ` Yang, Sheng
2008-05-12 16:40 ` Marcelo Tosatti
2008-05-14 3:03 ` Yang, Sheng
2008-04-11 22:30 ` Carsten Otte
2008-04-13 9:47 ` Avi Kivity
2008-04-14 9:18 ` Carsten Otte
2008-04-10 20:12 ` [patch 2/2] KVM: fix kvm_vcpu_kick vs __vcpu_run race Marcelo Tosatti
2008-04-11 12:18 ` Avi Kivity
2008-04-11 18:01 ` Marcelo Tosatti
2008-04-13 10:08 ` Avi Kivity
2008-04-13 16:07 ` Avi Kivity
2008-04-13 16:35 ` Avi Kivity
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080410201402.382704482@localhost.localdomain \
--to=mtosatti@redhat.com \
--cc=avi@qumranet.com \
--cc=kvm-devel@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.