aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm
diff options
context:
space:
mode:
authorJens Freimann <jfrei@linux.vnet.ibm.com>2014-04-17 04:10:30 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2014-08-25 08:35:56 -0400
commit7939503147f89f0799ddc89afec2aeae57dd7e2c (patch)
tree5e314444b3142d0b96cbeb748c815a9c432ca20a /arch/s390/kvm
parentd3d692c82e4ed79ae7c85f8825ccfdb7d11819da (diff)
KVM: s390: return -EFAULT if lowcore is not mapped during irq delivery
Currently we just kill the userspace process and exit the thread immediatly without making sure that we don't hold any locks etc. Improve this by making KVM_RUN return -EFAULT if the lowcore is not mapped during interrupt delivery. To achieve this we need to pass the return code of guest memory access routines used in interrupt delivery all the way back to the KVM_RUN ioctl. Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com> Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390/kvm')
-rw-r--r--arch/s390/kvm/interrupt.c40
-rw-r--r--arch/s390/kvm/kvm-s390.c7
-rw-r--r--arch/s390/kvm/kvm-s390.h2
3 files changed, 24 insertions, 25 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 34d741edb50a..e2f624058457 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -28,7 +28,7 @@
28#define IOINT_AI_MASK 0x04000000 28#define IOINT_AI_MASK 0x04000000
29#define PFAULT_INIT 0x0600 29#define PFAULT_INIT 0x0600
30 30
31static void deliver_ckc_interrupt(struct kvm_vcpu *vcpu); 31static int deliver_ckc_interrupt(struct kvm_vcpu *vcpu);
32 32
33static int is_ioint(u64 type) 33static int is_ioint(u64 type)
34{ 34{
@@ -307,7 +307,7 @@ static int __deliver_prog_irq(struct kvm_vcpu *vcpu,
307 return rc; 307 return rc;
308} 308}
309 309
310static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, 310static int __do_deliver_interrupt(struct kvm_vcpu *vcpu,
311 struct kvm_s390_interrupt_info *inti) 311 struct kvm_s390_interrupt_info *inti)
312{ 312{
313 const unsigned short table[] = { 2, 4, 4, 6 }; 313 const unsigned short table[] = { 2, 4, 4, 6 };
@@ -345,7 +345,7 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
345 case KVM_S390_INT_CLOCK_COMP: 345 case KVM_S390_INT_CLOCK_COMP:
346 trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 346 trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
347 inti->ext.ext_params, 0); 347 inti->ext.ext_params, 0);
348 deliver_ckc_interrupt(vcpu); 348 rc = deliver_ckc_interrupt(vcpu);
349 break; 349 break;
350 case KVM_S390_INT_CPU_TIMER: 350 case KVM_S390_INT_CPU_TIMER:
351 trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 351 trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
@@ -504,14 +504,11 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
504 default: 504 default:
505 BUG(); 505 BUG();
506 } 506 }
507 if (rc) { 507
508 printk("kvm: The guest lowcore is not mapped during interrupt " 508 return rc;
509 "delivery, killing userspace\n");
510 do_exit(SIGKILL);
511 }
512} 509}
513 510
514static void deliver_ckc_interrupt(struct kvm_vcpu *vcpu) 511static int deliver_ckc_interrupt(struct kvm_vcpu *vcpu)
515{ 512{
516 int rc; 513 int rc;
517 514
@@ -521,11 +518,7 @@ static void deliver_ckc_interrupt(struct kvm_vcpu *vcpu)
521 rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, 518 rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
522 &vcpu->arch.sie_block->gpsw, 519 &vcpu->arch.sie_block->gpsw,
523 sizeof(psw_t)); 520 sizeof(psw_t));
524 if (rc) { 521 return rc;
525 printk("kvm: The guest lowcore is not mapped during interrupt "
526 "delivery, killing userspace\n");
527 do_exit(SIGKILL);
528 }
529} 522}
530 523
531/* Check whether SIGP interpretation facility has an external call pending */ 524/* Check whether SIGP interpretation facility has an external call pending */
@@ -664,12 +657,13 @@ void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu)
664 &vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].ctrl); 657 &vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].ctrl);
665} 658}
666 659
667void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu) 660int kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
668{ 661{
669 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; 662 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
670 struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int; 663 struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int;
671 struct kvm_s390_interrupt_info *n, *inti = NULL; 664 struct kvm_s390_interrupt_info *n, *inti = NULL;
672 int deliver; 665 int deliver;
666 int rc = 0;
673 667
674 __reset_intercept_indicators(vcpu); 668 __reset_intercept_indicators(vcpu);
675 if (atomic_read(&li->active)) { 669 if (atomic_read(&li->active)) {
@@ -688,16 +682,16 @@ void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
688 atomic_set(&li->active, 0); 682 atomic_set(&li->active, 0);
689 spin_unlock(&li->lock); 683 spin_unlock(&li->lock);
690 if (deliver) { 684 if (deliver) {
691 __do_deliver_interrupt(vcpu, inti); 685 rc = __do_deliver_interrupt(vcpu, inti);
692 kfree(inti); 686 kfree(inti);
693 } 687 }
694 } while (deliver); 688 } while (!rc && deliver);
695 } 689 }
696 690
697 if (kvm_cpu_has_pending_timer(vcpu)) 691 if (!rc && kvm_cpu_has_pending_timer(vcpu))
698 deliver_ckc_interrupt(vcpu); 692 rc = deliver_ckc_interrupt(vcpu);
699 693
700 if (atomic_read(&fi->active)) { 694 if (!rc && atomic_read(&fi->active)) {
701 do { 695 do {
702 deliver = 0; 696 deliver = 0;
703 spin_lock(&fi->lock); 697 spin_lock(&fi->lock);
@@ -714,11 +708,13 @@ void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
714 atomic_set(&fi->active, 0); 708 atomic_set(&fi->active, 0);
715 spin_unlock(&fi->lock); 709 spin_unlock(&fi->lock);
716 if (deliver) { 710 if (deliver) {
717 __do_deliver_interrupt(vcpu, inti); 711 rc = __do_deliver_interrupt(vcpu, inti);
718 kfree(inti); 712 kfree(inti);
719 } 713 }
720 } while (deliver); 714 } while (!rc && deliver);
721 } 715 }
716
717 return rc;
722} 718}
723 719
724int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code) 720int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 56193becdca5..c2caa175320c 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -1198,8 +1198,11 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu)
1198 if (test_cpu_flag(CIF_MCCK_PENDING)) 1198 if (test_cpu_flag(CIF_MCCK_PENDING))
1199 s390_handle_mcck(); 1199 s390_handle_mcck();
1200 1200
1201 if (!kvm_is_ucontrol(vcpu->kvm)) 1201 if (!kvm_is_ucontrol(vcpu->kvm)) {
1202 kvm_s390_deliver_pending_interrupts(vcpu); 1202 rc = kvm_s390_deliver_pending_interrupts(vcpu);
1203 if (rc)
1204 return rc;
1205 }
1203 1206
1204 rc = kvm_s390_handle_requests(vcpu); 1207 rc = kvm_s390_handle_requests(vcpu);
1205 if (rc) 1208 if (rc)
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 54c25fd5bed6..99abcb56e478 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -138,7 +138,7 @@ static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm)
138int kvm_s390_handle_wait(struct kvm_vcpu *vcpu); 138int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
139void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu); 139void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu);
140enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer); 140enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);
141void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu); 141int kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu);
142void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu); 142void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu);
143void kvm_s390_clear_float_irqs(struct kvm *kvm); 143void kvm_s390_clear_float_irqs(struct kvm *kvm);
144int __must_check kvm_s390_inject_vm(struct kvm *kvm, 144int __must_check kvm_s390_inject_vm(struct kvm *kvm,