diff options
author | Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com> | 2011-10-18 06:27:15 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-10-30 06:24:05 -0400 |
commit | 7697e71f72b45a1bd0abe70918c383100fcc8514 (patch) | |
tree | afad6ff9dcd00a031de31b9cd34d2ae09484586a /arch/s390/kvm/interrupt.c | |
parent | 7eef87dc99e419b1cc051e4417c37e4744d7b661 (diff) |
KVM: s390: implement sigp external call
Implement sigp external call, which might be required for guests that
issue an external call instead of an emergency signal for IPI.
This fixes an issue with "KVM: unknown SIGP: 0x02" when booting
such an SMP guest.
Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/s390/kvm/interrupt.c')
-rw-r--r-- | arch/s390/kvm/interrupt.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index c9aeb4b4d0b8..87c16705b381 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
@@ -38,6 +38,11 @@ static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu, | |||
38 | struct kvm_s390_interrupt_info *inti) | 38 | struct kvm_s390_interrupt_info *inti) |
39 | { | 39 | { |
40 | switch (inti->type) { | 40 | switch (inti->type) { |
41 | case KVM_S390_INT_EXTERNAL_CALL: | ||
42 | if (psw_extint_disabled(vcpu)) | ||
43 | return 0; | ||
44 | if (vcpu->arch.sie_block->gcr[0] & 0x2000ul) | ||
45 | return 1; | ||
41 | case KVM_S390_INT_EMERGENCY: | 46 | case KVM_S390_INT_EMERGENCY: |
42 | if (psw_extint_disabled(vcpu)) | 47 | if (psw_extint_disabled(vcpu)) |
43 | return 0; | 48 | return 0; |
@@ -98,6 +103,7 @@ static void __set_intercept_indicator(struct kvm_vcpu *vcpu, | |||
98 | struct kvm_s390_interrupt_info *inti) | 103 | struct kvm_s390_interrupt_info *inti) |
99 | { | 104 | { |
100 | switch (inti->type) { | 105 | switch (inti->type) { |
106 | case KVM_S390_INT_EXTERNAL_CALL: | ||
101 | case KVM_S390_INT_EMERGENCY: | 107 | case KVM_S390_INT_EMERGENCY: |
102 | case KVM_S390_INT_SERVICE: | 108 | case KVM_S390_INT_SERVICE: |
103 | case KVM_S390_INT_VIRTIO: | 109 | case KVM_S390_INT_VIRTIO: |
@@ -143,6 +149,28 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, | |||
143 | exception = 1; | 149 | exception = 1; |
144 | break; | 150 | break; |
145 | 151 | ||
152 | case KVM_S390_INT_EXTERNAL_CALL: | ||
153 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call"); | ||
154 | vcpu->stat.deliver_external_call++; | ||
155 | rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1202); | ||
156 | if (rc == -EFAULT) | ||
157 | exception = 1; | ||
158 | |||
159 | rc = put_guest_u16(vcpu, __LC_CPU_ADDRESS, inti->extcall.code); | ||
160 | if (rc == -EFAULT) | ||
161 | exception = 1; | ||
162 | |||
163 | rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW, | ||
164 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
165 | if (rc == -EFAULT) | ||
166 | exception = 1; | ||
167 | |||
168 | rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw, | ||
169 | __LC_EXT_NEW_PSW, sizeof(psw_t)); | ||
170 | if (rc == -EFAULT) | ||
171 | exception = 1; | ||
172 | break; | ||
173 | |||
146 | case KVM_S390_INT_SERVICE: | 174 | case KVM_S390_INT_SERVICE: |
147 | VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x", | 175 | VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x", |
148 | inti->ext.ext_params); | 176 | inti->ext.ext_params); |
@@ -522,6 +550,7 @@ int kvm_s390_inject_vm(struct kvm *kvm, | |||
522 | break; | 550 | break; |
523 | case KVM_S390_PROGRAM_INT: | 551 | case KVM_S390_PROGRAM_INT: |
524 | case KVM_S390_SIGP_STOP: | 552 | case KVM_S390_SIGP_STOP: |
553 | case KVM_S390_INT_EXTERNAL_CALL: | ||
525 | case KVM_S390_INT_EMERGENCY: | 554 | case KVM_S390_INT_EMERGENCY: |
526 | default: | 555 | default: |
527 | kfree(inti); | 556 | kfree(inti); |
@@ -581,6 +610,7 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, | |||
581 | break; | 610 | break; |
582 | case KVM_S390_SIGP_STOP: | 611 | case KVM_S390_SIGP_STOP: |
583 | case KVM_S390_RESTART: | 612 | case KVM_S390_RESTART: |
613 | case KVM_S390_INT_EXTERNAL_CALL: | ||
584 | case KVM_S390_INT_EMERGENCY: | 614 | case KVM_S390_INT_EMERGENCY: |
585 | VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type); | 615 | VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type); |
586 | inti->type = s390int->type; | 616 | inti->type = s390int->type; |