diff options
-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 | ||