diff options
| author | David Hildenbrand <dahi@linux.vnet.ibm.com> | 2014-05-13 10:54:32 -0400 |
|---|---|---|
| committer | Christian Borntraeger <borntraeger@de.ibm.com> | 2014-07-21 07:22:16 -0400 |
| commit | 0759d0681cae279e77ebb4b76175e330360b01d9 (patch) | |
| tree | 42ce3eb00b2041e40441f2faf7382fd0805adbfe | |
| parent | 6352e4d2dd9a349024a41356148eced553e1dce4 (diff) | |
KVM: s390: cleanup handle_wait by reusing kvm_vcpu_block
This patch cleans up the code in handle_wait by reusing the common code
function kvm_vcpu_block.
signal_pending(), kvm_cpu_has_pending_timer() and kvm_arch_vcpu_runnable() are
sufficient for checking if we need to wake-up that VCPU. kvm_vcpu_block
uses these functions, so no checks are lost.
The flag "timer_due" can be removed - kvm_cpu_has_pending_timer() tests whether
the timer is pending, thus the vcpu is correctly woken up.
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
| -rw-r--r-- | arch/s390/include/asm/kvm_host.h | 1 | ||||
| -rw-r--r-- | arch/s390/kvm/interrupt.c | 41 | ||||
| -rw-r--r-- | arch/s390/kvm/kvm-s390.c | 3 |
3 files changed, 8 insertions, 37 deletions
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index c2ba0208a0e1..b3acf28c8c96 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h | |||
| @@ -305,7 +305,6 @@ struct kvm_s390_local_interrupt { | |||
| 305 | struct list_head list; | 305 | struct list_head list; |
| 306 | atomic_t active; | 306 | atomic_t active; |
| 307 | struct kvm_s390_float_interrupt *float_int; | 307 | struct kvm_s390_float_interrupt *float_int; |
| 308 | int timer_due; /* event indicator for waitqueue below */ | ||
| 309 | wait_queue_head_t *wq; | 308 | wait_queue_head_t *wq; |
| 310 | atomic_t *cpuflags; | 309 | atomic_t *cpuflags; |
| 311 | unsigned int action_bits; | 310 | unsigned int action_bits; |
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 90c8de22a2a0..5fd11ce3dc3d 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
| @@ -585,60 +585,32 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) | |||
| 585 | int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) | 585 | int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) |
| 586 | { | 586 | { |
| 587 | u64 now, sltime; | 587 | u64 now, sltime; |
| 588 | DECLARE_WAITQUEUE(wait, current); | ||
| 589 | 588 | ||
| 590 | vcpu->stat.exit_wait_state++; | 589 | vcpu->stat.exit_wait_state++; |
| 591 | if (kvm_cpu_has_interrupt(vcpu)) | ||
| 592 | return 0; | ||
| 593 | 590 | ||
| 594 | __set_cpu_idle(vcpu); | 591 | /* fast path */ |
| 595 | spin_lock_bh(&vcpu->arch.local_int.lock); | 592 | if (kvm_cpu_has_pending_timer(vcpu) || kvm_arch_vcpu_runnable(vcpu)) |
| 596 | vcpu->arch.local_int.timer_due = 0; | 593 | return 0; |
| 597 | spin_unlock_bh(&vcpu->arch.local_int.lock); | ||
| 598 | 594 | ||
| 599 | if (psw_interrupts_disabled(vcpu)) { | 595 | if (psw_interrupts_disabled(vcpu)) { |
| 600 | VCPU_EVENT(vcpu, 3, "%s", "disabled wait"); | 596 | VCPU_EVENT(vcpu, 3, "%s", "disabled wait"); |
| 601 | __unset_cpu_idle(vcpu); | ||
| 602 | return -EOPNOTSUPP; /* disabled wait */ | 597 | return -EOPNOTSUPP; /* disabled wait */ |
| 603 | } | 598 | } |
| 604 | 599 | ||
| 600 | __set_cpu_idle(vcpu); | ||
| 605 | if (!ckc_interrupts_enabled(vcpu)) { | 601 | if (!ckc_interrupts_enabled(vcpu)) { |
| 606 | VCPU_EVENT(vcpu, 3, "%s", "enabled wait w/o timer"); | 602 | VCPU_EVENT(vcpu, 3, "%s", "enabled wait w/o timer"); |
| 607 | goto no_timer; | 603 | goto no_timer; |
| 608 | } | 604 | } |
| 609 | 605 | ||
| 610 | now = get_tod_clock_fast() + vcpu->arch.sie_block->epoch; | 606 | now = get_tod_clock_fast() + vcpu->arch.sie_block->epoch; |
| 611 | if (vcpu->arch.sie_block->ckc < now) { | ||
| 612 | __unset_cpu_idle(vcpu); | ||
| 613 | return 0; | ||
| 614 | } | ||
| 615 | |||
| 616 | sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now); | 607 | sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now); |
| 617 | |||
| 618 | hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL); | 608 | hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL); |
| 619 | VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime); | 609 | VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime); |
| 620 | no_timer: | 610 | no_timer: |
| 621 | srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); | 611 | srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); |
| 622 | spin_lock(&vcpu->arch.local_int.float_int->lock); | 612 | kvm_vcpu_block(vcpu); |
| 623 | spin_lock_bh(&vcpu->arch.local_int.lock); | ||
| 624 | add_wait_queue(&vcpu->wq, &wait); | ||
| 625 | while (list_empty(&vcpu->arch.local_int.list) && | ||
| 626 | list_empty(&vcpu->arch.local_int.float_int->list) && | ||
| 627 | (!vcpu->arch.local_int.timer_due) && | ||
| 628 | !signal_pending(current) && | ||
| 629 | !kvm_s390_si_ext_call_pending(vcpu)) { | ||
| 630 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 631 | spin_unlock_bh(&vcpu->arch.local_int.lock); | ||
| 632 | spin_unlock(&vcpu->arch.local_int.float_int->lock); | ||
| 633 | schedule(); | ||
| 634 | spin_lock(&vcpu->arch.local_int.float_int->lock); | ||
| 635 | spin_lock_bh(&vcpu->arch.local_int.lock); | ||
| 636 | } | ||
| 637 | __unset_cpu_idle(vcpu); | 613 | __unset_cpu_idle(vcpu); |
| 638 | __set_current_state(TASK_RUNNING); | ||
| 639 | remove_wait_queue(&vcpu->wq, &wait); | ||
| 640 | spin_unlock_bh(&vcpu->arch.local_int.lock); | ||
| 641 | spin_unlock(&vcpu->arch.local_int.float_int->lock); | ||
| 642 | vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); | 614 | vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); |
| 643 | 615 | ||
| 644 | hrtimer_try_to_cancel(&vcpu->arch.ckc_timer); | 616 | hrtimer_try_to_cancel(&vcpu->arch.ckc_timer); |
| @@ -649,11 +621,8 @@ void kvm_s390_tasklet(unsigned long parm) | |||
| 649 | { | 621 | { |
| 650 | struct kvm_vcpu *vcpu = (struct kvm_vcpu *) parm; | 622 | struct kvm_vcpu *vcpu = (struct kvm_vcpu *) parm; |
| 651 | 623 | ||
| 652 | spin_lock(&vcpu->arch.local_int.lock); | ||
| 653 | vcpu->arch.local_int.timer_due = 1; | ||
| 654 | if (waitqueue_active(&vcpu->wq)) | 624 | if (waitqueue_active(&vcpu->wq)) |
| 655 | wake_up_interruptible(&vcpu->wq); | 625 | wake_up_interruptible(&vcpu->wq); |
| 656 | spin_unlock(&vcpu->arch.local_int.lock); | ||
| 657 | } | 626 | } |
| 658 | 627 | ||
| 659 | /* | 628 | /* |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index fdf88f7a539c..ecb135702313 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
| @@ -1068,6 +1068,9 @@ retry: | |||
| 1068 | goto retry; | 1068 | goto retry; |
| 1069 | } | 1069 | } |
| 1070 | 1070 | ||
| 1071 | /* nothing to do, just clear the request */ | ||
| 1072 | clear_bit(KVM_REQ_UNHALT, &vcpu->requests); | ||
| 1073 | |||
| 1071 | return 0; | 1074 | return 0; |
| 1072 | } | 1075 | } |
| 1073 | 1076 | ||
