diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2014-01-08 12:07:54 -0500 |
---|---|---|
committer | Christian Borntraeger <borntraeger@de.ibm.com> | 2014-04-22 07:24:45 -0400 |
commit | 2f32d4ea280c35d5f3a43fe7724020cb4824fffa (patch) | |
tree | 88e63d59d2c59aa2ebcd1d86d816e3c3f08fe5bc | |
parent | 4799b557c9aa3a7b540121f2bece719f22229a21 (diff) |
KVM: s390: reinject io interrupt on tpi failure
The tpi instruction should be suppressed on addressing and protection
exceptions, so we need to re-inject the dequeued io interrupt in that
case.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
-rw-r--r-- | arch/s390/kvm/interrupt.c | 6 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.h | 2 | ||||
-rw-r--r-- | arch/s390/kvm/priv.c | 10 |
3 files changed, 17 insertions, 1 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index a1403ba75bfc..1c74bb92329b 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
@@ -846,6 +846,12 @@ int kvm_s390_inject_vm(struct kvm *kvm, | |||
846 | return __inject_vm(kvm, inti); | 846 | return __inject_vm(kvm, inti); |
847 | } | 847 | } |
848 | 848 | ||
849 | void kvm_s390_reinject_io_int(struct kvm *kvm, | ||
850 | struct kvm_s390_interrupt_info *inti) | ||
851 | { | ||
852 | __inject_vm(kvm, inti); | ||
853 | } | ||
854 | |||
849 | int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, | 855 | int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, |
850 | struct kvm_s390_interrupt *s390int) | 856 | struct kvm_s390_interrupt *s390int) |
851 | { | 857 | { |
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index 11ed0a596b5a..dc506f3782ea 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h | |||
@@ -137,6 +137,8 @@ int __must_check kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, | |||
137 | int __must_check kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code); | 137 | int __must_check kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code); |
138 | struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, | 138 | struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, |
139 | u64 cr6, u64 schid); | 139 | u64 cr6, u64 schid); |
140 | void kvm_s390_reinject_io_int(struct kvm *kvm, | ||
141 | struct kvm_s390_interrupt_info *inti); | ||
140 | int kvm_s390_mask_adapter(struct kvm *kvm, unsigned int id, bool masked); | 142 | int kvm_s390_mask_adapter(struct kvm *kvm, unsigned int id, bool masked); |
141 | 143 | ||
142 | /* implemented in priv.c */ | 144 | /* implemented in priv.c */ |
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 4f6bc165d79b..f4451f09b9ed 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -259,7 +259,15 @@ static int handle_tpi(struct kvm_vcpu *vcpu) | |||
259 | if (write_guest_lc(vcpu, __LC_SUBCHANNEL_ID, &tpi_data, len)) | 259 | if (write_guest_lc(vcpu, __LC_SUBCHANNEL_ID, &tpi_data, len)) |
260 | rc = -EFAULT; | 260 | rc = -EFAULT; |
261 | } | 261 | } |
262 | kfree(inti); | 262 | /* |
263 | * If we encounter a problem storing the interruption code, the | ||
264 | * instruction is suppressed from the guest's view: reinject the | ||
265 | * interrupt. | ||
266 | */ | ||
267 | if (!rc) | ||
268 | kfree(inti); | ||
269 | else | ||
270 | kvm_s390_reinject_io_int(vcpu->kvm, inti); | ||
263 | no_interrupt: | 271 | no_interrupt: |
264 | /* Set condition code and we're done. */ | 272 | /* Set condition code and we're done. */ |
265 | if (!rc) | 273 | if (!rc) |