aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJens Freimann <jfrei@linux.vnet.ibm.com>2013-10-07 10:13:45 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2014-01-30 04:25:20 -0500
commitc05c4186bbe4e99d64e8a36f7ca7f480da5d109f (patch)
tree746d5b7f59b3c74668ab2b0abcfb48b64b4512e9 /arch
parent81aa8efe0190cf5bf7eaafb57341cd7d0aea96cd (diff)
KVM: s390: add floating irq controller
This patch adds a floating irq controller as a kvm_device. It will be necessary for migration of floating interrupts as well as for hardening the reset code by allowing user space to explicitly remove all pending floating interrupts. 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')
-rw-r--r--arch/s390/include/asm/kvm_host.h1
-rw-r--r--arch/s390/include/uapi/asm/kvm.h14
-rw-r--r--arch/s390/kvm/interrupt.c304
-rw-r--r--arch/s390/kvm/kvm-s390.c1
4 files changed, 269 insertions, 51 deletions
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 3ffc9646e742..59635b5c59a6 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -243,6 +243,7 @@ struct kvm_arch{
243 struct sca_block *sca; 243 struct sca_block *sca;
244 debug_info_t *dbf; 244 debug_info_t *dbf;
245 struct kvm_s390_float_interrupt float_int; 245 struct kvm_s390_float_interrupt float_int;
246 struct kvm_device *flic;
246 struct gmap *gmap; 247 struct gmap *gmap;
247 int css_support; 248 int css_support;
248}; 249};
diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h
index d25da598ec62..38d5f98552bb 100644
--- a/arch/s390/include/uapi/asm/kvm.h
+++ b/arch/s390/include/uapi/asm/kvm.h
@@ -16,6 +16,20 @@
16 16
17#define __KVM_S390 17#define __KVM_S390
18 18
19/* Device control API: s390-specific devices */
20#define KVM_DEV_FLIC_GET_ALL_IRQS 1
21#define KVM_DEV_FLIC_ENQUEUE 2
22#define KVM_DEV_FLIC_CLEAR_IRQS 3
23/*
24 * We can have up to 4*64k pending subchannels + 8 adapter interrupts,
25 * as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
26 * There are also sclp and machine checks. This gives us
27 * sizeof(kvm_s390_irq)*(4*65536+8+64*64+1+1) = 72 * 266250 = 19170000
28 * Lets round up to 8192 pages.
29 */
30
31#define KVM_S390_FLIC_MAX_BUFFER 0x2000000
32
19/* for KVM_GET_REGS and KVM_SET_REGS */ 33/* for KVM_GET_REGS and KVM_SET_REGS */
20struct kvm_regs { 34struct kvm_regs {
21 /* general purpose regs for s390 */ 35 /* general purpose regs for s390 */
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 5f79d2d79ca7..a5f18babed4c 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -659,53 +659,86 @@ struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,
659 return inti; 659 return inti;
660} 660}
661 661
662int kvm_s390_inject_vm(struct kvm *kvm, 662static void __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
663 struct kvm_s390_interrupt *s390int)
664{ 663{
665 struct kvm_s390_local_interrupt *li; 664 struct kvm_s390_local_interrupt *li;
666 struct kvm_s390_float_interrupt *fi; 665 struct kvm_s390_float_interrupt *fi;
667 struct kvm_s390_interrupt_info *inti, *iter; 666 struct kvm_s390_interrupt_info *iter;
668 int sigcpu; 667 int sigcpu;
669 668
669 mutex_lock(&kvm->lock);
670 fi = &kvm->arch.float_int;
671 spin_lock(&fi->lock);
672 if (!is_ioint(inti->type)) {
673 list_add_tail(&inti->list, &fi->list);
674 } else {
675 u64 isc_bits = int_word_to_isc_bits(inti->io.io_int_word);
676
677 /* Keep I/O interrupts sorted in isc order. */
678 list_for_each_entry(iter, &fi->list, list) {
679 if (!is_ioint(iter->type))
680 continue;
681 if (int_word_to_isc_bits(iter->io.io_int_word)
682 <= isc_bits)
683 continue;
684 break;
685 }
686 list_add_tail(&inti->list, &iter->list);
687 }
688 atomic_set(&fi->active, 1);
689 sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS);
690 if (sigcpu == KVM_MAX_VCPUS) {
691 do {
692 sigcpu = fi->next_rr_cpu++;
693 if (sigcpu == KVM_MAX_VCPUS)
694 sigcpu = fi->next_rr_cpu = 0;
695 } while (fi->local_int[sigcpu] == NULL);
696 }
697 li = fi->local_int[sigcpu];
698 spin_lock_bh(&li->lock);
699 atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
700 if (waitqueue_active(li->wq))
701 wake_up_interruptible(li->wq);
702 spin_unlock_bh(&li->lock);
703 spin_unlock(&fi->lock);
704 mutex_unlock(&kvm->lock);
705}
706
707int kvm_s390_inject_vm(struct kvm *kvm,
708 struct kvm_s390_interrupt *s390int)
709{
710 struct kvm_s390_interrupt_info *inti;
711
670 inti = kzalloc(sizeof(*inti), GFP_KERNEL); 712 inti = kzalloc(sizeof(*inti), GFP_KERNEL);
671 if (!inti) 713 if (!inti)
672 return -ENOMEM; 714 return -ENOMEM;
673 715
674 switch (s390int->type) { 716 inti->type = s390int->type;
717 switch (inti->type) {
675 case KVM_S390_INT_VIRTIO: 718 case KVM_S390_INT_VIRTIO:
676 VM_EVENT(kvm, 5, "inject: virtio parm:%x,parm64:%llx", 719 VM_EVENT(kvm, 5, "inject: virtio parm:%x,parm64:%llx",
677 s390int->parm, s390int->parm64); 720 s390int->parm, s390int->parm64);
678 inti->type = s390int->type;
679 inti->ext.ext_params = s390int->parm; 721 inti->ext.ext_params = s390int->parm;
680 inti->ext.ext_params2 = s390int->parm64; 722 inti->ext.ext_params2 = s390int->parm64;
681 break; 723 break;
682 case KVM_S390_INT_SERVICE: 724 case KVM_S390_INT_SERVICE:
683 VM_EVENT(kvm, 5, "inject: sclp parm:%x", s390int->parm); 725 VM_EVENT(kvm, 5, "inject: sclp parm:%x", s390int->parm);
684 inti->type = s390int->type;
685 inti->ext.ext_params = s390int->parm; 726 inti->ext.ext_params = s390int->parm;
686 break; 727 break;
687 case KVM_S390_PROGRAM_INT:
688 case KVM_S390_SIGP_STOP:
689 case KVM_S390_INT_EXTERNAL_CALL:
690 case KVM_S390_INT_EMERGENCY:
691 kfree(inti);
692 return -EINVAL;
693 case KVM_S390_MCHK: 728 case KVM_S390_MCHK:
694 VM_EVENT(kvm, 5, "inject: machine check parm64:%llx", 729 VM_EVENT(kvm, 5, "inject: machine check parm64:%llx",
695 s390int->parm64); 730 s390int->parm64);
696 inti->type = s390int->type;
697 inti->mchk.cr14 = s390int->parm; /* upper bits are not used */ 731 inti->mchk.cr14 = s390int->parm; /* upper bits are not used */
698 inti->mchk.mcic = s390int->parm64; 732 inti->mchk.mcic = s390int->parm64;
699 break; 733 break;
700 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: 734 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
701 if (s390int->type & IOINT_AI_MASK) 735 if (inti->type & IOINT_AI_MASK)
702 VM_EVENT(kvm, 5, "%s", "inject: I/O (AI)"); 736 VM_EVENT(kvm, 5, "%s", "inject: I/O (AI)");
703 else 737 else
704 VM_EVENT(kvm, 5, "inject: I/O css %x ss %x schid %04x", 738 VM_EVENT(kvm, 5, "inject: I/O css %x ss %x schid %04x",
705 s390int->type & IOINT_CSSID_MASK, 739 s390int->type & IOINT_CSSID_MASK,
706 s390int->type & IOINT_SSID_MASK, 740 s390int->type & IOINT_SSID_MASK,
707 s390int->type & IOINT_SCHID_MASK); 741 s390int->type & IOINT_SCHID_MASK);
708 inti->type = s390int->type;
709 inti->io.subchannel_id = s390int->parm >> 16; 742 inti->io.subchannel_id = s390int->parm >> 16;
710 inti->io.subchannel_nr = s390int->parm & 0x0000ffffu; 743 inti->io.subchannel_nr = s390int->parm & 0x0000ffffu;
711 inti->io.io_int_parm = s390int->parm64 >> 32; 744 inti->io.io_int_parm = s390int->parm64 >> 32;
@@ -718,42 +751,7 @@ int kvm_s390_inject_vm(struct kvm *kvm,
718 trace_kvm_s390_inject_vm(s390int->type, s390int->parm, s390int->parm64, 751 trace_kvm_s390_inject_vm(s390int->type, s390int->parm, s390int->parm64,
719 2); 752 2);
720 753
721 mutex_lock(&kvm->lock); 754 __inject_vm(kvm, inti);
722 fi = &kvm->arch.float_int;
723 spin_lock(&fi->lock);
724 if (!is_ioint(inti->type))
725 list_add_tail(&inti->list, &fi->list);
726 else {
727 u64 isc_bits = int_word_to_isc_bits(inti->io.io_int_word);
728
729 /* Keep I/O interrupts sorted in isc order. */
730 list_for_each_entry(iter, &fi->list, list) {
731 if (!is_ioint(iter->type))
732 continue;
733 if (int_word_to_isc_bits(iter->io.io_int_word)
734 <= isc_bits)
735 continue;
736 break;
737 } <