Skip to content

Commit

Permalink
KVM: s390: Fix race condition in kvm_s390_handle_wait
Browse files Browse the repository at this point in the history
The call to add_timer was issued before local_int.lock was taken and before
timer_due was set to 0. If the timer expires before the lock is being taken,
the timer function will set timer_due to 1 and exit before the vcpu falls
asleep. Depending on other external events, the vcpu might sleep forever.
This fix pulls setting timer_due to the beginning of the function before
add_timer, which ensures correct behavior.

Signed-off-by: Carsten Otte <cotte@de.ibm.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
  • Loading branch information
Carsten Otte authored and Avi Kivity committed Jun 6, 2008
1 parent 1f0d0f0 commit e52b2af
Showing 1 changed file with 5 additions and 2 deletions.
7 changes: 5 additions & 2 deletions arch/s390/kvm/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,11 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
if (kvm_cpu_has_interrupt(vcpu))
return 0;

__set_cpu_idle(vcpu);
spin_lock_bh(&vcpu->arch.local_int.lock);
vcpu->arch.local_int.timer_due = 0;
spin_unlock_bh(&vcpu->arch.local_int.lock);

if (psw_interrupts_disabled(vcpu)) {
VCPU_EVENT(vcpu, 3, "%s", "disabled wait");
__unset_cpu_idle(vcpu);
Expand Down Expand Up @@ -366,8 +371,6 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
no_timer:
spin_lock_bh(&vcpu->arch.local_int.float_int->lock);
spin_lock_bh(&vcpu->arch.local_int.lock);
__set_cpu_idle(vcpu);
vcpu->arch.local_int.timer_due = 0;
add_wait_queue(&vcpu->arch.local_int.wq, &wait);
while (list_empty(&vcpu->arch.local_int.list) &&
list_empty(&vcpu->arch.local_int.float_int->list) &&
Expand Down

0 comments on commit e52b2af

Please sign in to comment.