aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2009-03-23 09:11:44 -0400
committerAvi Kivity <avi@redhat.com>2009-06-10 04:48:33 -0400
commit09cec754885f900f6aab23801878c0cd217ee1d6 (patch)
tree3f634b6993af33914b031421e23db67744b84a9f
parent089d034e0c4538d2436512fa64782b91008d4a7c (diff)
KVM: Timer event should not unconditionally unhalt vcpu.
Currently timer events are processed before entering guest mode. Move it to main vcpu event loop since timer events should be processed even while vcpu is halted. Timer may cause interrupt/nmi to be injected and only then vcpu will be unhalted. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--arch/ia64/kvm/kvm-ia64.c6
-rw-r--r--arch/x86/kvm/x86.c57
-rw-r--r--virt/kvm/kvm_main.c5
3 files changed, 40 insertions, 28 deletions
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 4623a90e515a..d2a90fd505b0 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -488,10 +488,10 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
488 hrtimer_cancel(p_ht); 488 hrtimer_cancel(p_ht);
489 vcpu->arch.ht_active = 0; 489 vcpu->arch.ht_active = 0;
490 490
491 if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests)) 491 if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests) ||
492 kvm_cpu_has_pending_timer(vcpu))
492 if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED) 493 if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED)
493 vcpu->arch.mp_state = 494 vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
494 KVM_MP_STATE_RUNNABLE;
495 495
496 if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE) 496 if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
497 return -EINTR; 497 return -EINTR;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c0ae5e6cba9b..8fca7a4e95a3 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3133,9 +3133,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
3133 } 3133 }
3134 } 3134 }
3135 3135
3136 clear_bit(KVM_REQ_PENDING_TIMER, &vcpu->requests);
3137 kvm_inject_pending_timer_irqs(vcpu);
3138
3139 preempt_disable(); 3136 preempt_disable();
3140 3137
3141 kvm_x86_ops->prepare_guest_switch(vcpu); 3138 kvm_x86_ops->prepare_guest_switch(vcpu);
@@ -3235,6 +3232,7 @@ out:
3235 return r; 3232 return r;
3236} 3233}
3237 3234
3235
3238static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 3236static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
3239{ 3237{
3240 int r; 3238 int r;
@@ -3261,29 +3259,42 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
3261 kvm_vcpu_block(vcpu); 3259 kvm_vcpu_block(vcpu);
3262 down_read(&vcpu->kvm->slots_lock); 3260 down_read(&vcpu->kvm->slots_lock);
3263 if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests)) 3261 if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests))
3264 if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED) 3262 {
3263 switch(vcpu->arch.mp_state) {
3264 case KVM_MP_STATE_HALTED:
3265 vcpu->arch.mp_state = 3265 vcpu->arch.mp_state =
3266 KVM_MP_STATE_RUNNABLE; 3266 KVM_MP_STATE_RUNNABLE;
3267 if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE) 3267 case KVM_MP_STATE_RUNNABLE:
3268 r = -EINTR; 3268 break;
3269 case KVM_MP_STATE_SIPI_RECEIVED:
3270 default:
3271 r = -EINTR;
3272 break;
3273 }
3274 }
3269 } 3275 }
3270 3276
3271 if (r > 0) { 3277 if (r <= 0)
3272 if (dm_request_for_irq_injection(vcpu, kvm_run)) { 3278 break;
3273 r = -EINTR; 3279
3274 kvm_run->exit_reason = KVM_EXIT_INTR; 3280 clear_bit(KVM_REQ_PENDING_TIMER, &vcpu->requests);
3275 ++vcpu->stat.request_irq_exits; 3281 if (kvm_cpu_has_pending_timer(vcpu))
3276 } 3282 kvm_inject_pending_timer_irqs(vcpu);
3277 if (signal_pending(current)) { 3283
3278 r = -EINTR; 3284 if (dm_request_for_irq_injection(vcpu, kvm_run)) {
3279 kvm_run->exit_reason = KVM_EXIT_INTR; 3285 r = -EINTR;
3280 ++vcpu->stat.signal_exits; 3286 kvm_run->exit_reason = KVM_EXIT_INTR;
3281 } 3287 ++vcpu->stat.request_irq_exits;
3282 if (need_resched()) { 3288 }
3283 up_read(&vcpu->kvm->slots_lock); 3289 if (signal_pending(current)) {
3284 kvm_resched(vcpu); 3290 r = -EINTR;
3285 down_read(&vcpu->kvm->slots_lock); 3291 kvm_run->exit_reason = KVM_EXIT_INTR;
3286 } 3292 ++vcpu->stat.signal_exits;
3293 }
3294 if (need_resched()) {
3295 up_read(&vcpu->kvm->slots_lock);
3296 kvm_resched(vcpu);
3297 down_read(&vcpu->kvm->slots_lock);
3287 } 3298 }
3288 } 3299 }
3289 3300
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 934dd1c9487e..a1a4272fa57c 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1611,11 +1611,12 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
1611 prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE); 1611 prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
1612 1612
1613 if (kvm_cpu_has_interrupt(vcpu) || 1613 if (kvm_cpu_has_interrupt(vcpu) ||
1614 kvm_cpu_has_pending_timer(vcpu) || 1614 kvm_arch_vcpu_runnable(vcpu)) {
1615 kvm_arch_vcpu_runnable(vcpu)) {
1616 set_bit(KVM_REQ_UNHALT, &vcpu->requests); 1615 set_bit(KVM_REQ_UNHALT, &vcpu->requests);
1617 break; 1616 break;
1618 } 1617 }
1618 if (kvm_cpu_has_pending_timer(vcpu))
1619 break;
1619 if (signal_pending(current)) 1620 if (signal_pending(current))
1620 break; 1621 break;
1621 1622