diff options
Diffstat (limited to 'arch/s390/kvm/interrupt.c')
-rw-r--r-- | arch/s390/kvm/interrupt.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 7fbbcbcea6ac..73bafc3d0f41 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
@@ -394,13 +394,20 @@ static int __must_check __deliver_restart(struct kvm_vcpu *vcpu) | |||
394 | 394 | ||
395 | static int __must_check __deliver_stop(struct kvm_vcpu *vcpu) | 395 | static int __must_check __deliver_stop(struct kvm_vcpu *vcpu) |
396 | { | 396 | { |
397 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
398 | struct kvm_s390_stop_info *stop = &li->irq.stop; | ||
399 | |||
400 | spin_lock(&li->lock); | ||
401 | stop->flags = 0; | ||
402 | clear_bit(IRQ_PEND_SIGP_STOP, &li->pending_irqs); | ||
403 | spin_unlock(&li->lock); | ||
404 | |||
397 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop"); | 405 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop"); |
398 | vcpu->stat.deliver_stop_signal++; | 406 | vcpu->stat.deliver_stop_signal++; |
399 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_SIGP_STOP, | 407 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_SIGP_STOP, |
400 | 0, 0); | 408 | 0, 0); |
401 | 409 | ||
402 | __set_cpuflag(vcpu, CPUSTAT_STOP_INT); | 410 | __set_cpuflag(vcpu, CPUSTAT_STOP_INT); |
403 | clear_bit(IRQ_PEND_SIGP_STOP, &vcpu->arch.local_int.pending_irqs); | ||
404 | return 0; | 411 | return 0; |
405 | } | 412 | } |
406 | 413 | ||
@@ -1031,13 +1038,19 @@ static int __inject_set_prefix(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq) | |||
1031 | return 0; | 1038 | return 0; |
1032 | } | 1039 | } |
1033 | 1040 | ||
1041 | #define KVM_S390_STOP_SUPP_FLAGS 0 | ||
1034 | static int __inject_sigp_stop(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq) | 1042 | static int __inject_sigp_stop(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq) |
1035 | { | 1043 | { |
1036 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | 1044 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; |
1045 | struct kvm_s390_stop_info *stop = &li->irq.stop; | ||
1037 | 1046 | ||
1038 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_SIGP_STOP, 0, 0, 2); | 1047 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_SIGP_STOP, 0, 0, 2); |
1039 | 1048 | ||
1049 | if (irq->u.stop.flags & ~KVM_S390_STOP_SUPP_FLAGS) | ||
1050 | return -EINVAL; | ||
1051 | |||
1040 | li->action_bits |= ACTION_STOP_ON_STOP; | 1052 | li->action_bits |= ACTION_STOP_ON_STOP; |
1053 | stop->flags = irq->u.stop.flags; | ||
1041 | set_bit(IRQ_PEND_SIGP_STOP, &li->pending_irqs); | 1054 | set_bit(IRQ_PEND_SIGP_STOP, &li->pending_irqs); |
1042 | return 0; | 1055 | return 0; |
1043 | } | 1056 | } |
@@ -1306,6 +1319,9 @@ int s390int_to_s390irq(struct kvm_s390_interrupt *s390int, | |||
1306 | case KVM_S390_SIGP_SET_PREFIX: | 1319 | case KVM_S390_SIGP_SET_PREFIX: |
1307 | irq->u.prefix.address = s390int->parm; | 1320 | irq->u.prefix.address = s390int->parm; |
1308 | break; | 1321 | break; |
1322 | case KVM_S390_SIGP_STOP: | ||
1323 | irq->u.stop.flags = s390int->parm; | ||
1324 | break; | ||
1309 | case KVM_S390_INT_EXTERNAL_CALL: | 1325 | case KVM_S390_INT_EXTERNAL_CALL: |
1310 | if (irq->u.extcall.code & 0xffff0000) | 1326 | if (irq->u.extcall.code & 0xffff0000) |
1311 | return -EINVAL; | 1327 | return -EINVAL; |