aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/interrupt.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kvm/interrupt.c')
-rw-r--r--arch/s390/kvm/interrupt.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 52cdf20906ab..b3b4748485ee 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -41,6 +41,11 @@ static int psw_ioint_disabled(struct kvm_vcpu *vcpu)
41 return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_IO); 41 return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_IO);
42} 42}
43 43
44static int psw_mchk_disabled(struct kvm_vcpu *vcpu)
45{
46 return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_MCHECK);
47}
48
44static int psw_interrupts_disabled(struct kvm_vcpu *vcpu) 49static int psw_interrupts_disabled(struct kvm_vcpu *vcpu)
45{ 50{
46 if ((vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PER) || 51 if ((vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PER) ||
@@ -82,6 +87,12 @@ static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu,
82 case KVM_S390_SIGP_SET_PREFIX: 87 case KVM_S390_SIGP_SET_PREFIX:
83 case KVM_S390_RESTART: 88 case KVM_S390_RESTART:
84 return 1; 89 return 1;
90 case KVM_S390_MCHK:
91 if (psw_mchk_disabled(vcpu))
92 return 0;
93 if (vcpu->arch.sie_block->gcr[14] & inti->mchk.cr14)
94 return 1;
95 return 0;
85 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: 96 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
86 if (psw_ioint_disabled(vcpu)) 97 if (psw_ioint_disabled(vcpu))
87 return 0; 98 return 0;
@@ -116,6 +127,7 @@ static void __reset_intercept_indicators(struct kvm_vcpu *vcpu)
116 CPUSTAT_IO_INT | CPUSTAT_EXT_INT | CPUSTAT_STOP_INT, 127 CPUSTAT_IO_INT | CPUSTAT_EXT_INT | CPUSTAT_STOP_INT,
117 &vcpu->arch.sie_block->cpuflags); 128 &vcpu->arch.sie_block->cpuflags);
118 vcpu->arch.sie_block->lctl = 0x0000; 129 vcpu->arch.sie_block->lctl = 0x0000;
130 vcpu->arch.sie_block->ictl &= ~ICTL_LPSW;
119} 131}
120 132
121static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag) 133static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag)
@@ -139,6 +151,12 @@ static void __set_intercept_indicator(struct kvm_vcpu *vcpu,
139 case KVM_S390_SIGP_STOP: 151 case KVM_S390_SIGP_STOP:
140 __set_cpuflag(vcpu, CPUSTAT_STOP_INT); 152 __set_cpuflag(vcpu, CPUSTAT_STOP_INT);
141 break; 153 break;
154 case KVM_S390_MCHK:
155 if (psw_mchk_disabled(vcpu))
156 vcpu->arch.sie_block->ictl |= ICTL_LPSW;
157 else
158 vcpu->arch.sie_block->lctl |= LCTL_CR14;
159 break;
142 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: 160 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
143 if (psw_ioint_disabled(vcpu)) 161 if (psw_ioint_disabled(vcpu))
144 __set_cpuflag(vcpu, CPUSTAT_IO_INT); 162 __set_cpuflag(vcpu, CPUSTAT_IO_INT);
@@ -326,6 +344,32 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
326 exception = 1; 344 exception = 1;
327 break; 345 break;
328 346
347 case KVM_S390_MCHK:
348 VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx",
349 inti->mchk.mcic);
350 trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
351 inti->mchk.cr14,
352 inti->mchk.mcic);
353 rc = kvm_s390_vcpu_store_status(vcpu,
354 KVM_S390_STORE_STATUS_PREFIXED);
355 if (rc == -EFAULT)
356 exception = 1;
357
358 rc = put_guest_u64(vcpu, __LC_MCCK_CODE, inti->mchk.mcic);
359 if (rc == -EFAULT)
360 exception = 1;
361
362 rc = copy_to_guest(vcpu, __LC_MCK_OLD_PSW,
363 &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
364 if (rc == -EFAULT)
365 exception = 1;
366
367 rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
368 __LC_MCK_NEW_PSW, sizeof(psw_t));
369 if (rc == -EFAULT)
370 exception = 1;
371 break;
372
329 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: 373 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
330 { 374 {
331 __u32 param0 = ((__u32)inti->io.subchannel_id << 16) | 375 __u32 param0 = ((__u32)inti->io.subchannel_id << 16) |
@@ -588,6 +632,61 @@ void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
588 } 632 }
589} 633}
590 634
635void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu)
636{
637 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
638 struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int;
639 struct kvm_s390_interrupt_info *n, *inti = NULL;
640 int deliver;
641
642 __reset_intercept_indicators(vcpu);
643 if (atomic_read(&li->active)) {
644 do {
645 deliver = 0;
646 spin_lock_bh(&li->lock);
647 list_for_each_entry_safe(inti, n, &li->list, list) {
648 if ((inti->type == KVM_S390_MCHK) &&
649 __interrupt_is_deliverable(vcpu, inti)) {
650 list_del(&inti->list);
651 deliver = 1;
652 break;
653 }
654 __set_intercept_indicator(vcpu, inti);
655 }
656 if (list_empty(&li->list))
657 atomic_set(&li->active, 0);
658 spin_unlock_bh(&li->lock);
659 if (deliver) {
660 __do_deliver_interrupt(vcpu, inti);
661 kfree(inti);
662 }
663 } while (deliver);
664 }
665
666 if (atomic_read(&fi->active)) {
667 do {
668 deliver = 0;
669 spin_lock(&fi->lock);
670 list_for_each_entry_safe(inti, n, &fi->list, list) {
671 if ((inti->type == KVM_S390_MCHK) &&
672 __interrupt_is_deliverable(vcpu, inti)) {
673 list_del(&inti->list);
674 deliver = 1;
675 break;
676 }
677 __set_intercept_indicator(vcpu, inti);
678 }
679 if (list_empty(&fi->list))
680 atomic_set(&fi->active, 0);
681 spin_unlock(&fi->lock);
682 if (deliver) {
683 __do_deliver_interrupt(vcpu, inti);
684 kfree(inti);
685 }
686 } while (deliver);
687 }
688}
689
591int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code) 690int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
592{ 691{
593 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; 692 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
@@ -641,6 +740,13 @@ int kvm_s390_inject_vm(struct kvm *kvm,
641 case KVM_S390_INT_EMERGENCY: 740 case KVM_S390_INT_EMERGENCY:
642 kfree(inti); 741 kfree(inti);
643 return -EINVAL; 742 return -EINVAL;
743 case KVM_S390_MCHK:
744 VM_EVENT(kvm, 5, "inject: machine check parm64:%llx",
745 s390int->parm64);
746 inti->type = s390int->type;
747 inti->mchk.cr14 = s390int->parm; /* upper bits are not used */
748 inti->mchk.mcic = s390int->parm64;
749 break;
644 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: 750 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
645 if (s390int->type & IOINT_AI_MASK) 751 if (s390int->type & IOINT_AI_MASK)
646 VM_EVENT(kvm, 5, "%s", "inject: I/O (AI)"); 752 VM_EVENT(kvm, 5, "%s", "inject: I/O (AI)");
@@ -749,6 +855,12 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
749 inti->type = s390int->type; 855 inti->type = s390int->type;
750 inti->emerg.code = s390int->parm; 856 inti->emerg.code = s390int->parm;
751 break; 857 break;
858 case KVM_S390_MCHK:
859 VCPU_EVENT(vcpu, 5, "inject: machine check parm64:%llx",
860 s390int->parm64);
861 inti->type = s390int->type;
862 inti->mchk.mcic = s390int->parm64;
863 break;
752 case KVM_S390_INT_VIRTIO: 864 case KVM_S390_INT_VIRTIO:
753 case KVM_S390_INT_SERVICE: 865 case KVM_S390_INT_SERVICE:
754 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: 866 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: