public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [patch 0/2] do not run halted vcpu's
@ 2008-08-01 23:09 Marcelo Tosatti
  2008-08-01 23:09 ` [patch 1/2] KVM: x86: set debug registers after "schedulable" section Marcelo Tosatti
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Marcelo Tosatti @ 2008-08-01 23:09 UTC (permalink / raw)
  To: Avi Kivity; +Cc: kvm

Avi Kivity wrote:

> Any reason this is not in __vcpu_run()?
>
> Our main loop could look like
>
> while (no reason to stop)
>       if (runnable)
>            enter guest
>       else
>            block
>       deal with aftermath
>
> kvm_emulate_halt would then simply modify the mp state.

Like this?

- I don't think it is necessary to test for pending signals inside irq
safe section, so move that to exit processing.

- Same for need_resched().




^ permalink raw reply	[flat|nested] 12+ messages in thread

* [patch 1/2] KVM: x86: set debug registers after "schedulable" section
  2008-08-01 23:09 [patch 0/2] do not run halted vcpu's Marcelo Tosatti
@ 2008-08-01 23:09 ` Marcelo Tosatti
  2008-08-13 10:46   ` Avi Kivity
  2008-08-01 23:09 ` [patch 2/2] KVM: x86: do not execute halted vcpus (v2) Marcelo Tosatti
  2008-08-13 10:44 ` [patch 0/2] do not run halted vcpu's Avi Kivity
  2 siblings, 1 reply; 12+ messages in thread
From: Marcelo Tosatti @ 2008-08-01 23:09 UTC (permalink / raw)
  To: Avi Kivity; +Cc: kvm, Marcelo Tosatti

[-- Attachment #1: kvm-x86-debug --]
[-- Type: text/plain, Size: 1082 bytes --]

The vcpu thread can be preempted after the guest_debug_pre() callback,
resulting in invalid debug registers on the new vcpu.

Move it inside the non-preemptable section.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

Index: kvm/arch/x86/kvm/x86.c
===================================================================
--- kvm.orig/arch/x86/kvm/x86.c
+++ kvm/arch/x86/kvm/x86.c
@@ -3088,10 +3088,6 @@ static int __vcpu_run(struct kvm_vcpu *v
 	down_read(&vcpu->kvm->slots_lock);
 	vapic_enter(vcpu);
 
-preempted:
-	if (vcpu->guest_debug.enabled)
-		kvm_x86_ops->guest_debug_pre(vcpu);
-
 again:
 	if (vcpu->requests)
 		if (test_and_clear_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
@@ -3145,6 +3141,9 @@ again:
 		goto out;
 	}
 
+	if (vcpu->guest_debug.enabled)
+		kvm_x86_ops->guest_debug_pre(vcpu);
+
 	vcpu->guest_mode = 1;
 	/*
 	 * Make sure that guest_mode assignment won't happen after
@@ -3219,7 +3218,7 @@ out:
 	if (r > 0) {
 		kvm_resched(vcpu);
 		down_read(&vcpu->kvm->slots_lock);
-		goto preempted;
+		goto again;
 	}
 
 	post_kvm_run_save(vcpu, kvm_run);

-- 


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [patch 2/2] KVM: x86: do not execute halted vcpus (v2)
  2008-08-01 23:09 [patch 0/2] do not run halted vcpu's Marcelo Tosatti
  2008-08-01 23:09 ` [patch 1/2] KVM: x86: set debug registers after "schedulable" section Marcelo Tosatti
@ 2008-08-01 23:09 ` Marcelo Tosatti
  2008-08-13 10:51   ` Avi Kivity
  2008-08-13 10:44 ` [patch 0/2] do not run halted vcpu's Avi Kivity
  2 siblings, 1 reply; 12+ messages in thread
From: Marcelo Tosatti @ 2008-08-01 23:09 UTC (permalink / raw)
  To: Avi Kivity; +Cc: kvm, Marcelo Tosatti

[-- Attachment #1: refactor-loop --]
[-- Type: text/plain, Size: 7279 bytes --]

Offline or uninitialized vcpu's can be executed if requested to perform
userspace work. 

Follow Avi's suggestion to handle halted vcpu's in the main loop,
simplifying kvm_emulate_halt(). Introduce a new vcpu->requests bit to
indicate events that promote state from halted to running.

Also standardize vcpu wake sites.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

Index: kvm/arch/x86/kvm/x86.c
===================================================================
--- kvm.orig/arch/x86/kvm/x86.c
+++ kvm/arch/x86/kvm/x86.c
@@ -2772,11 +2772,6 @@ int kvm_emulate_halt(struct kvm_vcpu *vc
 	KVMTRACE_0D(HLT, vcpu, handler);
 	if (irqchip_in_kernel(vcpu->kvm)) {
 		vcpu->arch.mp_state = KVM_MP_STATE_HALTED;
-		up_read(&vcpu->kvm->slots_lock);
-		kvm_vcpu_block(vcpu);
-		down_read(&vcpu->kvm->slots_lock);
-		if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
-			return -EINTR;
 		return 1;
 	} else {
 		vcpu->run->exit_reason = KVM_EXIT_HLT;
@@ -3071,24 +3066,10 @@ static void vapic_exit(struct kvm_vcpu *
 	up_read(&vcpu->kvm->slots_lock);
 }
 
-static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	int r;
 
-	if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED)) {
-		pr_debug("vcpu %d received sipi with vector # %x\n",
-		       vcpu->vcpu_id, vcpu->arch.sipi_vector);
-		kvm_lapic_reset(vcpu);
-		r = kvm_x86_ops->vcpu_reset(vcpu);
-		if (r)
-			return r;
-		vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
-	}
-
-	down_read(&vcpu->kvm->slots_lock);
-	vapic_enter(vcpu);
-
-again:
 	if (vcpu->requests)
 		if (test_and_clear_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
 			kvm_mmu_unload(vcpu);
@@ -3132,15 +3113,6 @@ again:
 		goto out;
 	}
 
-	if (signal_pending(current)) {
-		local_irq_enable();
-		preempt_enable();
-		r = -EINTR;
-		kvm_run->exit_reason = KVM_EXIT_INTR;
-		++vcpu->stat.signal_exits;
-		goto out;
-	}
-
 	if (vcpu->guest_debug.enabled)
 		kvm_x86_ops->guest_debug_pre(vcpu);
 
@@ -3201,26 +3173,63 @@ again:
 	kvm_lapic_sync_from_vapic(vcpu);
 
 	r = kvm_x86_ops->handle_exit(kvm_run, vcpu);
+out:
+	return r;
+}
 
-	if (r > 0) {
-		if (dm_request_for_irq_injection(vcpu, kvm_run)) {
-			r = -EINTR;
-			kvm_run->exit_reason = KVM_EXIT_INTR;
-			++vcpu->stat.request_irq_exits;
-			goto out;
-		}
-		if (!need_resched())
-			goto again;
+static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	int r;
+
+	if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED)) {
+		printk("vcpu %d received sipi with vector # %x\n",
+		       vcpu->vcpu_id, vcpu->arch.sipi_vector);
+		kvm_lapic_reset(vcpu);
+		r = kvm_x86_ops->vcpu_reset(vcpu);
+		if (r)
+			return r;
+		vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
 	}
 
-out:
-	up_read(&vcpu->kvm->slots_lock);
-	if (r > 0) {
-		kvm_resched(vcpu);
-		down_read(&vcpu->kvm->slots_lock);
-		goto again;
+	down_read(&vcpu->kvm->slots_lock);
+	vapic_enter(vcpu);
+
+	r = 1;
+	while (r > 0) {
+		if (kvm_arch_vcpu_runnable(vcpu))
+			r = vcpu_enter_guest(vcpu, kvm_run);
+		else {
+			up_read(&vcpu->kvm->slots_lock);
+			kvm_vcpu_block(vcpu);
+			down_read(&vcpu->kvm->slots_lock);
+			if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests))
+				if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED)
+					vcpu->arch.mp_state =
+							KVM_MP_STATE_RUNNABLE;
+			if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
+				r = -EINTR;
+		}
+
+		if (r > 0) {
+			if (dm_request_for_irq_injection(vcpu, kvm_run)) {
+				r = -EINTR;
+				kvm_run->exit_reason = KVM_EXIT_INTR;
+				++vcpu->stat.request_irq_exits;
+			}
+			if (signal_pending(current)) {
+				r = -EINTR;
+				kvm_run->exit_reason = KVM_EXIT_INTR;
+				++vcpu->stat.signal_exits;
+			}
+			if (need_resched()) {
+				up_read(&vcpu->kvm->slots_lock);
+				kvm_resched(vcpu);
+				down_read(&vcpu->kvm->slots_lock);
+			}
+		}
 	}
 
+	up_read(&vcpu->kvm->slots_lock);
 	post_kvm_run_save(vcpu, kvm_run);
 
 	vapic_exit(vcpu);
@@ -3240,6 +3249,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
 
 	if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) {
 		kvm_vcpu_block(vcpu);
+		clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
 		r = -EAGAIN;
 		goto out;
 	}
Index: kvm/include/linux/kvm_host.h
===================================================================
--- kvm.orig/include/linux/kvm_host.h
+++ kvm/include/linux/kvm_host.h
@@ -34,6 +34,7 @@
 #define KVM_REQ_MMU_RELOAD         3
 #define KVM_REQ_TRIPLE_FAULT       4
 #define KVM_REQ_PENDING_TIMER      5
+#define KVM_REQ_UNHALT             6
 
 struct kvm_vcpu;
 extern struct kmem_cache *kvm_vcpu_cache;
Index: kvm/arch/x86/kvm/i8254.c
===================================================================
--- kvm.orig/arch/x86/kvm/i8254.c
+++ kvm/arch/x86/kvm/i8254.c
@@ -200,10 +200,9 @@ static int __pit_timer_fn(struct kvm_kpi
 
 	if (!atomic_inc_and_test(&pt->pending))
 		set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests);
-	if (vcpu0 && waitqueue_active(&vcpu0->wq)) {
-		vcpu0->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+
+	if (vcpu0 && waitqueue_active(&vcpu0->wq))
 		wake_up_interruptible(&vcpu0->wq);
-	}
 
 	pt->timer.expires = ktime_add_ns(pt->timer.expires, pt->period);
 	pt->scheduled = ktime_to_ns(pt->timer.expires);
Index: kvm/virt/kvm/kvm_main.c
===================================================================
--- kvm.orig/virt/kvm/kvm_main.c
+++ kvm/virt/kvm/kvm_main.c
@@ -980,12 +980,12 @@ void kvm_vcpu_block(struct kvm_vcpu *vcp
 	for (;;) {
 		prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
 
-		if (kvm_cpu_has_interrupt(vcpu))
-			break;
-		if (kvm_cpu_has_pending_timer(vcpu))
-			break;
-		if (kvm_arch_vcpu_runnable(vcpu))
+		if (kvm_cpu_has_interrupt(vcpu) ||
+		    kvm_cpu_has_pending_timer(vcpu) ||
+		    kvm_arch_vcpu_runnable(vcpu)) {
+			set_bit(KVM_REQ_UNHALT, &vcpu->requests);
 			break;
+		}
 		if (signal_pending(current))
 			break;
 
Index: kvm/arch/x86/kvm/lapic.c
===================================================================
--- kvm.orig/arch/x86/kvm/lapic.c
+++ kvm/arch/x86/kvm/lapic.c
@@ -339,13 +339,7 @@ static int __apic_accept_irq(struct kvm_
 		} else
 			apic_clear_vector(vector, apic->regs + APIC_TMR);
 
-		if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
-			kvm_vcpu_kick(vcpu);
-		else if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED) {
-			vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
-			if (waitqueue_active(&vcpu->wq))
-				wake_up_interruptible(&vcpu->wq);
-		}
+		kvm_vcpu_kick(vcpu);
 
 		result = (orig_irr == 0);
 		break;
@@ -384,8 +378,7 @@ static int __apic_accept_irq(struct kvm_
 		if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
 			vcpu->arch.sipi_vector = vector;
 			vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
-			if (waitqueue_active(&vcpu->wq))
-				wake_up_interruptible(&vcpu->wq);
+			kvm_vcpu_kick(vcpu);
 		}
 		break;
 
@@ -950,10 +943,9 @@ static int __apic_timer_fn(struct kvm_la
 
 	if(!atomic_inc_and_test(&apic->timer.pending))
 		set_bit(KVM_REQ_PENDING_TIMER, &apic->vcpu->requests);
-	if (waitqueue_active(q)) {
-		apic->vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+	if (waitqueue_active(q))
 		wake_up_interruptible(q);
-	}
+
 	if (apic_lvtt_period(apic)) {
 		result = 1;
 		apic->timer.dev.expires = ktime_add_ns(

-- 


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch 0/2] do not run halted vcpu's
  2008-08-01 23:09 [patch 0/2] do not run halted vcpu's Marcelo Tosatti
  2008-08-01 23:09 ` [patch 1/2] KVM: x86: set debug registers after "schedulable" section Marcelo Tosatti
  2008-08-01 23:09 ` [patch 2/2] KVM: x86: do not execute halted vcpus (v2) Marcelo Tosatti
@ 2008-08-13 10:44 ` Avi Kivity
  2008-08-15  0:19   ` Marcelo Tosatti
  2 siblings, 1 reply; 12+ messages in thread
From: Avi Kivity @ 2008-08-13 10:44 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: kvm

Marcelo Tosatti wrote:
> Avi Kivity wrote:
>
>   
>> Any reason this is not in __vcpu_run()?
>>
>> Our main loop could look like
>>
>> while (no reason to stop)
>>       if (runnable)
>>            enter guest
>>       else
>>            block
>>       deal with aftermath
>>
>> kvm_emulate_halt would then simply modify the mp state.
>>     
>
> Like this?
>
> - I don't think it is necessary to test for pending signals inside irq
> safe section, so move that to exit processing.
>
>   


It is.  We may have received a signal after ioctl processing started but 
before entry.  If we don't don't check before entry, nothing ensures 
we'll ever exit (or we may exit due to some other reason, but the exit 
will be delayed).

> - Same for need_resched().
>
>   

Incorrect for the same reason.  There's no guarantee we will ever exit 
if we ignore the rescheduling IPI.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch 1/2] KVM: x86: set debug registers after "schedulable" section
  2008-08-01 23:09 ` [patch 1/2] KVM: x86: set debug registers after "schedulable" section Marcelo Tosatti
@ 2008-08-13 10:46   ` Avi Kivity
  0 siblings, 0 replies; 12+ messages in thread
From: Avi Kivity @ 2008-08-13 10:46 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: kvm

Marcelo Tosatti wrote:
> The vcpu thread can be preempted after the guest_debug_pre() callback,
> resulting in invalid debug registers on the new vcpu.
>
> Move it inside the non-preemptable section.
>   

Applied, thanks.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch 2/2] KVM: x86: do not execute halted vcpus (v2)
  2008-08-01 23:09 ` [patch 2/2] KVM: x86: do not execute halted vcpus (v2) Marcelo Tosatti
@ 2008-08-13 10:51   ` Avi Kivity
  2008-08-13 10:53     ` Avi Kivity
  0 siblings, 1 reply; 12+ messages in thread
From: Avi Kivity @ 2008-08-13 10:51 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: kvm

Marcelo Tosatti wrote:
> Offline or uninitialized vcpu's can be executed if requested to perform
> userspace work. 
>
> Follow Avi's suggestion to handle halted vcpu's in the main loop,
> simplifying kvm_emulate_halt(). Introduce a new vcpu->requests bit to
> indicate events that promote state from halted to running.
>
> Also standardize vcpu wake sites.
>   

Apart from moving the entry checks to the exit, this looks fine (if 
scary... this code is sensitive).

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch 2/2] KVM: x86: do not execute halted vcpus (v2)
  2008-08-13 10:51   ` Avi Kivity
@ 2008-08-13 10:53     ` Avi Kivity
  0 siblings, 0 replies; 12+ messages in thread
From: Avi Kivity @ 2008-08-13 10:53 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: kvm

Avi Kivity wrote:
> Marcelo Tosatti wrote:
>> Offline or uninitialized vcpu's can be executed if requested to perform
>> userspace work.
>> Follow Avi's suggestion to handle halted vcpu's in the main loop,
>> simplifying kvm_emulate_halt(). Introduce a new vcpu->requests bit to
>> indicate events that promote state from halted to running.
>>
>> Also standardize vcpu wake sites.
>>   
>
> Apart from moving the entry checks to the exit, this looks fine (if 
> scary... this code is sensitive).
>

btw, this is a step forward for big real mode.  We can later split the 
guest entry to have an emulation path if the guest state is not hardware 
friendly.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch 0/2] do not run halted vcpu's
  2008-08-13 10:44 ` [patch 0/2] do not run halted vcpu's Avi Kivity
@ 2008-08-15  0:19   ` Marcelo Tosatti
  2008-08-17  6:31     ` Avi Kivity
  0 siblings, 1 reply; 12+ messages in thread
From: Marcelo Tosatti @ 2008-08-15  0:19 UTC (permalink / raw)
  To: Avi Kivity; +Cc: kvm

On Wed, Aug 13, 2008 at 01:44:33PM +0300, Avi Kivity wrote:
> Marcelo Tosatti wrote:
>> Avi Kivity wrote:
>>
>>   
>>> Any reason this is not in __vcpu_run()?
>>>
>>> Our main loop could look like
>>>
>>> while (no reason to stop)
>>>       if (runnable)
>>>            enter guest
>>>       else
>>>            block
>>>       deal with aftermath
>>>
>>> kvm_emulate_halt would then simply modify the mp state.
>>>     
>>
>> Like this?
>>
>> - I don't think it is necessary to test for pending signals inside irq
>> safe section, so move that to exit processing.
>>
>>   
>
>
> It is.  We may have received a signal after ioctl processing started but  
> before entry.  If we don't don't check before entry, nothing ensures  
> we'll ever exit (or we may exit due to some other reason, but the exit  
> will be delayed).
>
>> - Same for need_resched().
>>
>>   
>
> Incorrect for the same reason.  There's no guarantee we will ever exit  
> if we ignore the rescheduling IPI.

KVM: x86: do not execute halted vcpus

Alright, need_resched was actually checked in vcpu_enter_guest, so this
checks signal_pending too:

Offline or uninitialized vcpu's can be executed if requested to perform
userspace work. 

Follow Avi's suggestion to handle halted vcpu's in the main loop,
simplifying kvm_emulate_halt(). Introduce a new vcpu->requests bit to
indicate events that promote state from halted to running.

Also standardize vcpu wake sites.

Signed-off-by: Marcelo Tosatti <mtosatti <at> redhat.com>


diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index 7d04dd3..6e13d15 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -200,10 +200,9 @@ static int __pit_timer_fn(struct kvm_kpit_state *ps)
 
 	if (!atomic_inc_and_test(&pt->pending))
 		set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests);
-	if (vcpu0 && waitqueue_active(&vcpu0->wq)) {
-		vcpu0->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+
+	if (vcpu0 && waitqueue_active(&vcpu0->wq))
 		wake_up_interruptible(&vcpu0->wq);
-	}
 
 	pt->timer.expires = ktime_add_ns(pt->timer.expires, pt->period);
 	pt->scheduled = ktime_to_ns(pt->timer.expires);
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index be94f93..fd00f69 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -339,13 +339,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
 		} else
 			apic_clear_vector(vector, apic->regs + APIC_TMR);
 
-		if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
-			kvm_vcpu_kick(vcpu);
-		else if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED) {
-			vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
-			if (waitqueue_active(&vcpu->wq))
-				wake_up_interruptible(&vcpu->wq);
-		}
+		kvm_vcpu_kick(vcpu);
 
 		result = (orig_irr == 0);
 		break;
@@ -384,8 +378,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
 		if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
 			vcpu->arch.sipi_vector = vector;
 			vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
-			if (waitqueue_active(&vcpu->wq))
-				wake_up_interruptible(&vcpu->wq);
+			kvm_vcpu_kick(vcpu);
 		}
 		break;
 
@@ -950,10 +943,9 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
 
 	if(!atomic_inc_and_test(&apic->timer.pending))
 		set_bit(KVM_REQ_PENDING_TIMER, &apic->vcpu->requests);
-	if (waitqueue_active(q)) {
-		apic->vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+	if (waitqueue_active(q))
 		wake_up_interruptible(q);
-	}
+
 	if (apic_lvtt_period(apic)) {
 		result = 1;
 		apic->timer.dev.expires = ktime_add_ns(
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index ee005a6..1749d10 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2797,11 +2797,6 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
 	KVMTRACE_0D(HLT, vcpu, handler);
 	if (irqchip_in_kernel(vcpu->kvm)) {
 		vcpu->arch.mp_state = KVM_MP_STATE_HALTED;
-		up_read(&vcpu->kvm->slots_lock);
-		kvm_vcpu_block(vcpu);
-		down_read(&vcpu->kvm->slots_lock);
-		if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
-			return -EINTR;
 		return 1;
 	} else {
 		vcpu->run->exit_reason = KVM_EXIT_HLT;
@@ -3096,24 +3091,10 @@ static void vapic_exit(struct kvm_vcpu *vcpu)
 	up_read(&vcpu->kvm->slots_lock);
 }
 
-static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	int r;
 
-	if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED)) {
-		pr_debug("vcpu %d received sipi with vector # %x\n",
-		       vcpu->vcpu_id, vcpu->arch.sipi_vector);
-		kvm_lapic_reset(vcpu);
-		r = kvm_x86_ops->vcpu_reset(vcpu);
-		if (r)
-			return r;
-		vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
-	}
-
-	down_read(&vcpu->kvm->slots_lock);
-	vapic_enter(vcpu);
-
-again:
 	if (vcpu->requests)
 		if (test_and_clear_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
 			kvm_mmu_unload(vcpu);
@@ -3150,22 +3131,13 @@ again:
 
 	local_irq_disable();
 
-	if (vcpu->requests || need_resched()) {
+	if (vcpu->requests || need_resched() || signal_pending(current)) {
 		local_irq_enable();
 		preempt_enable();
 		r = 1;
 		goto out;
 	}
 
-	if (signal_pending(current)) {
-		local_irq_enable();
-		preempt_enable();
-		r = -EINTR;
-		kvm_run->exit_reason = KVM_EXIT_INTR;
-		++vcpu->stat.signal_exits;
-		goto out;
-	}
-
 	if (vcpu->guest_debug.enabled)
 		kvm_x86_ops->guest_debug_pre(vcpu);
 
@@ -3226,26 +3198,63 @@ again:
 	kvm_lapic_sync_from_vapic(vcpu);
 
 	r = kvm_x86_ops->handle_exit(kvm_run, vcpu);
+out:
+	return r;
+}
 
-	if (r > 0) {
-		if (dm_request_for_irq_injection(vcpu, kvm_run)) {
-			r = -EINTR;
-			kvm_run->exit_reason = KVM_EXIT_INTR;
-			++vcpu->stat.request_irq_exits;
-			goto out;
-		}
-		if (!need_resched())
-			goto again;
+static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	int r;
+
+	if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED)) {
+		printk("vcpu %d received sipi with vector # %x\n",
+		       vcpu->vcpu_id, vcpu->arch.sipi_vector);
+		kvm_lapic_reset(vcpu);
+		r = kvm_x86_ops->vcpu_reset(vcpu);
+		if (r)
+			return r;
+		vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
 	}
 
-out:
-	up_read(&vcpu->kvm->slots_lock);
-	if (r > 0) {
-		kvm_resched(vcpu);
-		down_read(&vcpu->kvm->slots_lock);
-		goto again;
+	down_read(&vcpu->kvm->slots_lock);
+	vapic_enter(vcpu);
+
+	r = 1;
+	while (r > 0) {
+		if (kvm_arch_vcpu_runnable(vcpu))
+			r = vcpu_enter_guest(vcpu, kvm_run);
+		else {
+			up_read(&vcpu->kvm->slots_lock);
+			kvm_vcpu_block(vcpu);
+			down_read(&vcpu->kvm->slots_lock);
+			if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests))
+				if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED)
+					vcpu->arch.mp_state =
+							KVM_MP_STATE_RUNNABLE;
+			if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
+				r = -EINTR;
+		}
+
+		if (r > 0) {
+			if (dm_request_for_irq_injection(vcpu, kvm_run)) {
+				r = -EINTR;
+				kvm_run->exit_reason = KVM_EXIT_INTR;
+				++vcpu->stat.request_irq_exits;
+			}
+			if (signal_pending(current)) {
+				r = -EINTR;
+				kvm_run->exit_reason = KVM_EXIT_INTR;
+				++vcpu->stat.signal_exits;
+			}
+			if (need_resched()) {
+				up_read(&vcpu->kvm->slots_lock);
+				kvm_resched(vcpu);
+				down_read(&vcpu->kvm->slots_lock);
+			}
+		}
 	}
 
+	up_read(&vcpu->kvm->slots_lock);
 	post_kvm_run_save(vcpu, kvm_run);
 
 	vapic_exit(vcpu);
@@ -3265,6 +3274,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
 	if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) {
 		kvm_vcpu_block(vcpu);
+		clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
 		r = -EAGAIN;
 		goto out;
 	}
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index a18aaad..4b03643 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -34,6 +34,7 @@
 #define KVM_REQ_MMU_RELOAD         3
 #define KVM_REQ_TRIPLE_FAULT       4
 #define KVM_REQ_PENDING_TIMER      5
+#define KVM_REQ_UNHALT             6
 
 struct kvm_vcpu;
 extern struct kmem_cache *kvm_vcpu_cache;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 0309571..9212ace 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -980,12 +980,12 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
 	for (;;) {
 		prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
 
-		if (kvm_cpu_has_interrupt(vcpu))
-			break;
-		if (kvm_cpu_has_pending_timer(vcpu))
-			break;
-		if (kvm_arch_vcpu_runnable(vcpu))
+		if (kvm_cpu_has_interrupt(vcpu) ||
+		    kvm_cpu_has_pending_timer(vcpu) ||
+		    kvm_arch_vcpu_runnable(vcpu)) {
+			set_bit(KVM_REQ_UNHALT, &vcpu->requests);
 			break;
+		}
 		if (signal_pending(current))
 			break;
 

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [patch 0/2] do not run halted vcpu's
  2008-08-15  0:19   ` Marcelo Tosatti
@ 2008-08-17  6:31     ` Avi Kivity
  2008-08-17  7:41       ` Avi Kivity
  0 siblings, 1 reply; 12+ messages in thread
From: Avi Kivity @ 2008-08-17  6:31 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: kvm

Marcelo Tosatti wrote:
> KVM: x86: do not execute halted vcpus
>
> Alright, need_resched was actually checked in vcpu_enter_guest, so this
> checks signal_pending too:
>
> Offline or uninitialized vcpu's can be executed if requested to perform
> userspace work. 
>
> Follow Avi's suggestion to handle halted vcpu's in the main loop,
> simplifying kvm_emulate_halt(). Introduce a new vcpu->requests bit to
> indicate events that promote state from halted to running.
>
> Also standardize vcpu wake sites.
>   

Applied, thanks.

-- 
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch 0/2] do not run halted vcpu's
  2008-08-17  6:31     ` Avi Kivity
@ 2008-08-17  7:41       ` Avi Kivity
  2008-08-19 23:07         ` Marcelo Tosatti
  0 siblings, 1 reply; 12+ messages in thread
From: Avi Kivity @ 2008-08-17  7:41 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: kvm

Avi Kivity wrote:
> Marcelo Tosatti wrote:
>> KVM: x86: do not execute halted vcpus
>>
>> Alright, need_resched was actually checked in vcpu_enter_guest, so this
>> checks signal_pending too:
>>
>> Offline or uninitialized vcpu's can be executed if requested to perform
>> userspace work.
>> Follow Avi's suggestion to handle halted vcpu's in the main loop,
>> simplifying kvm_emulate_halt(). Introduce a new vcpu->requests bit to
>> indicate events that promote state from halted to running.
>>
>> Also standardize vcpu wake sites.
>>   
>
> Applied, thanks.
>

This killed reboot, so I reverted it.

-- 
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch 0/2] do not run halted vcpu's
  2008-08-17  7:41       ` Avi Kivity
@ 2008-08-19 23:07         ` Marcelo Tosatti
  2008-08-20  4:04           ` Avi Kivity
  0 siblings, 1 reply; 12+ messages in thread
From: Marcelo Tosatti @ 2008-08-19 23:07 UTC (permalink / raw)
  To: Avi Kivity; +Cc: kvm

On Sun, Aug 17, 2008 at 10:41:07AM +0300, Avi Kivity wrote:
> Avi Kivity wrote:
>> Marcelo Tosatti wrote:
>>> KVM: x86: do not execute halted vcpus
>>>
>>> Alright, need_resched was actually checked in vcpu_enter_guest, so this
>>> checks signal_pending too:
>>>
>>> Offline or uninitialized vcpu's can be executed if requested to perform
>>> userspace work.
>>> Follow Avi's suggestion to handle halted vcpu's in the main loop,
>>> simplifying kvm_emulate_halt(). Introduce a new vcpu->requests bit to
>>> indicate events that promote state from halted to running.
>>>
>>> Also standardize vcpu wake sites.
>>>   
>>
>> Applied, thanks.
>>
>
> This killed reboot, so I reverted it.

Works for me (both UP/SMP, Windows/Linux, guest initiated/system_reset),
and can't find anything obvious in the diff.

How can it be reproduced?


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch 0/2] do not run halted vcpu's
  2008-08-19 23:07         ` Marcelo Tosatti
@ 2008-08-20  4:04           ` Avi Kivity
  0 siblings, 0 replies; 12+ messages in thread
From: Avi Kivity @ 2008-08-20  4:04 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: kvm

Marcelo Tosatti wrote:
> On Sun, Aug 17, 2008 at 10:41:07AM +0300, Avi Kivity wrote:
>   
>> Avi Kivity wrote:
>>     
>>> Marcelo Tosatti wrote:
>>>       
>>>> KVM: x86: do not execute halted vcpus
>>>>
>>>> Alright, need_resched was actually checked in vcpu_enter_guest, so this
>>>> checks signal_pending too:
>>>>
>>>> Offline or uninitialized vcpu's can be executed if requested to perform
>>>> userspace work.
>>>> Follow Avi's suggestion to handle halted vcpu's in the main loop,
>>>> simplifying kvm_emulate_halt(). Introduce a new vcpu->requests bit to
>>>> indicate events that promote state from halted to running.
>>>>
>>>> Also standardize vcpu wake sites.
>>>>   
>>>>         
>>> Applied, thanks.
>>>
>>>       
>> This killed reboot, so I reverted it.
>>     
>
> Works for me (both UP/SMP, Windows/Linux, guest initiated/system_reset),
> and can't find anything obvious in the diff.
>
> How can it be reproduced?
>
>   

Windows UP guest initiated.

Since you say it worked, I probably botched something while testing. 
I'll try again.

-- 
Do not meddle in the internals of kernels, for they are subtle and quick to panic.


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2008-08-20  4:04 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-01 23:09 [patch 0/2] do not run halted vcpu's Marcelo Tosatti
2008-08-01 23:09 ` [patch 1/2] KVM: x86: set debug registers after "schedulable" section Marcelo Tosatti
2008-08-13 10:46   ` Avi Kivity
2008-08-01 23:09 ` [patch 2/2] KVM: x86: do not execute halted vcpus (v2) Marcelo Tosatti
2008-08-13 10:51   ` Avi Kivity
2008-08-13 10:53     ` Avi Kivity
2008-08-13 10:44 ` [patch 0/2] do not run halted vcpu's Avi Kivity
2008-08-15  0:19   ` Marcelo Tosatti
2008-08-17  6:31     ` Avi Kivity
2008-08-17  7:41       ` Avi Kivity
2008-08-19 23:07         ` Marcelo Tosatti
2008-08-20  4:04           ` Avi Kivity

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox