aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm
diff options
context:
space:
mode:
authorJens Freimann <jfrei@linux.vnet.ibm.com>2014-01-30 02:40:23 -0500
committerChristian Borntraeger <borntraeger@de.ibm.com>2014-01-30 04:25:23 -0500
commita91b8ebe8671980151e0a19ee9fec6b0e1ae1d58 (patch)
treecb49f6acefa5925bc5f525795ca737b9fe4cfe86 /arch/s390/kvm
parentc05c4186bbe4e99d64e8a36f7ca7f480da5d109f (diff)
KVM: s390: limit floating irqs
Userspace can flood the kernel with interrupts as of now, so let's limit the number of pending floating interrupts injected via either the floating interrupt controller or the KVM_S390_INTERRUPT ioctl. We can have up to 4*64k pending subchannels + 8 adapter interrupts, as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts. There are also sclp and machine checks. This gives us (4*65536+8+64*64+1+1) = 266250 interrupts. Suggested-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Jens Freimann <jfrei@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.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index a5f18babed4c..9c9192b5e339 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -528,6 +528,7 @@ void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
528 list_for_each_entry_safe(inti, n, &fi->list, list) { 528 list_for_each_entry_safe(inti, n, &fi->list, list) {
529 if (__interrupt_is_deliverable(vcpu, inti)) { 529 if (__interrupt_is_deliverable(vcpu, inti)) {
530 list_del(&inti->list); 530 list_del(&inti->list);
531 fi->irq_count--;
531 deliver = 1; 532 deliver = 1;
532 break; 533 break;
533 } 534 }
@@ -583,6 +584,7 @@ void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu)
583 if ((inti->type == KVM_S390_MCHK) && 584 if ((inti->type == KVM_S390_MCHK) &&
584 __interrupt_is_deliverable(vcpu, inti)) { 585 __interrupt_is_deliverable(vcpu, inti)) {
585 list_del(&inti->list); 586 list_del(&inti->list);
587 fi->irq_count--;
586 deliver = 1; 588 deliver = 1;
587 break; 589 break;
588 } 590 }
@@ -650,8 +652,10 @@ struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,
650 inti = iter; 652 inti = iter;
651 break; 653 break;
652 } 654 }
653 if (inti) 655 if (inti) {
654 list_del_init(&inti->list); 656 list_del_init(&inti->list);
657 fi->irq_count--;
658 }
655 if (list_empty(&fi->list)) 659 if (list_empty(&fi->list))
656 atomic_set(&fi->active, 0); 660 atomic_set(&fi->active, 0);
657 spin_unlock(&fi->lock); 661 spin_unlock(&fi->lock);
@@ -659,16 +663,22 @@ struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,
659 return inti; 663 return inti;
660} 664}
661 665
662static void __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti) 666static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
663{ 667{
664 struct kvm_s390_local_interrupt *li; 668 struct kvm_s390_local_interrupt *li;
665 struct kvm_s390_float_interrupt *fi; 669 struct kvm_s390_float_interrupt *fi;
666 struct kvm_s390_interrupt_info *iter; 670 struct kvm_s390_interrupt_info *iter;
667 int sigcpu; 671 int sigcpu;
672 int rc = 0;
668 673
669 mutex_lock(&kvm->lock); 674 mutex_lock(&kvm->lock);
670 fi = &kvm->arch.float_int; 675 fi = &kvm->arch.float_int;
671 spin_lock(&fi->lock); 676 spin_lock(&fi->lock);
677 if (fi->irq_count >= KVM_S390_MAX_FLOAT_IRQS) {
678 rc = -EINVAL;
679 goto unlock_fi;
680 }
681 fi->irq_count++;
672 if (!is_ioint(inti->type)) { 682 if (!is_ioint(inti->type)) {
673 list_add_tail(&inti->list, &fi->list); 683 list_add_tail(&inti->list, &fi->list);
674 } else { 684 } else {
@@ -700,8 +710,10 @@ static void __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
700 if (waitqueue_active(li->wq)) 710 if (waitqueue_active(li->wq))
701 wake_up_interruptible(li->wq); 711 wake_up_interruptible(li->wq);
702 spin_unlock_bh(&li->lock); 712 spin_unlock_bh(&li->lock);
713unlock_fi:
703 spin_unlock(&fi->lock); 714 spin_unlock(&fi->lock);
704 mutex_unlock(&kvm->lock); 715 mutex_unlock(&kvm->lock);
716 return rc;
705} 717}
706 718
707int kvm_s390_inject_vm(struct kvm *kvm, 719int kvm_s390_inject_vm(struct kvm *kvm,
@@ -751,8 +763,7 @@ int kvm_s390_inject_vm(struct kvm *kvm,
751 trace_kvm_s390_inject_vm(s390int->type, s390int->parm, s390int->parm64, 763 trace_kvm_s390_inject_vm(s390int->type, s390int->parm, s390int->parm64,
752 2); 764 2);
753 765
754 __inject_vm(kvm, inti); 766 return __inject_vm(kvm, inti);
755 return 0;
756} 767}
757 768
758int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, 769int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
@@ -852,6 +863,7 @@ static void clear_floating_interrupts(struct kvm *kvm)
852 list_del(&inti->list); 863 list_del(&inti->list);
853 kfree(inti); 864 kfree(inti);
854 } 865 }
866 fi->irq_count = 0;
855 atomic_set(&fi->active, 0); 867 atomic_set(&fi->active, 0);
856 spin_unlock(&fi->lock); 868 spin_unlock(&fi->lock);
857 mutex_unlock(&kvm->lock); 869 mutex_unlock(&kvm->lock);
@@ -992,7 +1004,11 @@ static int enqueue_floating_irq(struct kvm_device *dev,
992 kfree(inti); 1004 kfree(inti);
993 return r; 1005 return r;
994 } 1006 }
995 __inject_vm(dev->kvm, inti); 1007 r = __inject_vm(dev->kvm, inti);
1008 if (r) {
1009 kfree(inti);
1010 return r;
1011 }
996 len -= sizeof(struct kvm_s390_irq); 1012 len -= sizeof(struct kvm_s390_irq);
997 attr->addr += sizeof(struct kvm_s390_irq); 1013 attr->addr += sizeof(struct kvm_s390_irq);
998 } 1014 }