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 /arch/s390 | |
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>
Diffstat (limited to 'arch/s390')
-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 | ||