diff options
-rw-r--r-- | arch/s390/kvm/interrupt.c | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 4604e9accc65..ef84a803433e 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
@@ -909,9 +909,35 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) | |||
909 | return ckc_irq_pending(vcpu) || cpu_timer_irq_pending(vcpu); | 909 | return ckc_irq_pending(vcpu) || cpu_timer_irq_pending(vcpu); |
910 | } | 910 | } |
911 | 911 | ||
912 | static u64 __calculate_sltime(struct kvm_vcpu *vcpu) | ||
913 | { | ||
914 | u64 now, cputm, sltime = 0; | ||
915 | |||
916 | if (ckc_interrupts_enabled(vcpu)) { | ||
917 | now = kvm_s390_get_tod_clock_fast(vcpu->kvm); | ||
918 | sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now); | ||
919 | /* already expired or overflow? */ | ||
920 | if (!sltime || vcpu->arch.sie_block->ckc <= now) | ||
921 | return 0; | ||
922 | if (cpu_timer_interrupts_enabled(vcpu)) { | ||
923 | cputm = kvm_s390_get_cpu_timer(vcpu); | ||
924 | /* already expired? */ | ||
925 | if (cputm >> 63) | ||
926 | return 0; | ||
927 | return min(sltime, tod_to_ns(cputm)); | ||
928 | } | ||
929 | } else if (cpu_timer_interrupts_enabled(vcpu)) { | ||
930 | sltime = kvm_s390_get_cpu_timer(vcpu); | ||
931 | /* already expired? */ | ||
932 | if (sltime >> 63) | ||
933 | return 0; | ||
934 | } | ||
935 | return sltime; | ||
936 | } | ||
937 | |||
912 | int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) | 938 | int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) |
913 | { | 939 | { |
914 | u64 now, sltime; | 940 | u64 sltime; |
915 | 941 | ||
916 | vcpu->stat.exit_wait_state++; | 942 | vcpu->stat.exit_wait_state++; |
917 | 943 | ||
@@ -924,22 +950,20 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) | |||
924 | return -EOPNOTSUPP; /* disabled wait */ | 950 | return -EOPNOTSUPP; /* disabled wait */ |
925 | } | 951 | } |
926 | 952 | ||
927 | if (!ckc_interrupts_enabled(vcpu)) { | 953 | if (!ckc_interrupts_enabled(vcpu) && |
954 | !cpu_timer_interrupts_enabled(vcpu)) { | ||
928 | VCPU_EVENT(vcpu, 3, "%s", "enabled wait w/o timer"); | 955 | VCPU_EVENT(vcpu, 3, "%s", "enabled wait w/o timer"); |
929 | __set_cpu_idle(vcpu); | 956 | __set_cpu_idle(vcpu); |
930 | goto no_timer; | 957 | goto no_timer; |
931 | } | 958 | } |
932 | 959 | ||
933 | now = kvm_s390_get_tod_clock_fast(vcpu->kvm); | 960 | sltime = __calculate_sltime(vcpu); |
934 | sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now); | 961 | if (!sltime) |
935 | |||
936 | /* underflow */ | ||
937 | if (vcpu->arch.sie_block->ckc < now) | ||
938 | return 0; | 962 | return 0; |
939 | 963 | ||
940 | __set_cpu_idle(vcpu); | 964 | __set_cpu_idle(vcpu); |
941 | hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL); | 965 | hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL); |
942 | VCPU_EVENT(vcpu, 4, "enabled wait via clock comparator: %llu ns", sltime); | 966 | VCPU_EVENT(vcpu, 4, "enabled wait: %llu ns", sltime); |
943 | no_timer: | 967 | no_timer: |
944 | srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); | 968 | srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); |
945 | kvm_vcpu_block(vcpu); | 969 | kvm_vcpu_block(vcpu); |
@@ -966,18 +990,16 @@ void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu) | |||
966 | enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer) | 990 | enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer) |
967 | { | 991 | { |
968 | struct kvm_vcpu *vcpu; | 992 | struct kvm_vcpu *vcpu; |
969 | u64 now, sltime; | 993 | u64 sltime; |
970 | 994 | ||
971 | vcpu = container_of(timer, struct kvm_vcpu, arch.ckc_timer); | 995 | vcpu = container_of(timer, struct kvm_vcpu, arch.ckc_timer); |
972 | now = kvm_s390_get_tod_clock_fast(vcpu->kvm); | 996 | sltime = __calculate_sltime(vcpu); |
973 | sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now); | ||
974 | 997 | ||
975 | /* | 998 | /* |
976 | * If the monotonic clock runs faster than the tod clock we might be | 999 | * If the monotonic clock runs faster than the tod clock we might be |
977 | * woken up too early and have to go back to sleep to avoid deadlocks. | 1000 | * woken up too early and have to go back to sleep to avoid deadlocks. |
978 | */ | 1001 | */ |
979 | if (vcpu->arch.sie_block->ckc > now && | 1002 | if (sltime && hrtimer_forward_now(timer, ns_to_ktime(sltime))) |
980 | hrtimer_forward_now(timer, ns_to_ktime(sltime))) | ||
981 | return HRTIMER_RESTART; | 1003 | return HRTIMER_RESTART; |
982 | kvm_s390_vcpu_wakeup(vcpu); | 1004 | kvm_s390_vcpu_wakeup(vcpu); |
983 | return HRTIMER_NORESTART; | 1005 | return HRTIMER_NORESTART; |