aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/virtual/kvm/devices/s390_flic.txt36
-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
-rw-r--r--include/linux/kvm_host.h1
-rw-r--r--include/uapi/linux/kvm.h1
-rw-r--r--virt/kvm/kvm_main.c5
8 files changed, 312 insertions, 51 deletions
diff --git a/Documentation/virtual/kvm/devices/s390_flic.txt b/Documentation/virtual/kvm/devices/s390_flic.txt
new file mode 100644
index 000000000000..6b557953066a
--- /dev/null
+++ b/Documentation/virtual/kvm/devices/s390_flic.txt
@@ -0,0 +1,36 @@
1FLIC (floating interrupt controller)
2====================================
3
4FLIC handles floating (non per-cpu) interrupts, i.e. I/O, service and some
5machine check interruptions. All interrupts are stored in a per-vm list of
6pending interrupts. FLIC performs operations on this list.
7
8Only one FLIC instance may be instantiated.
9
10FLIC provides support to
11- add interrupts (KVM_DEV_FLIC_ENQUEUE)
12- inspect currently pending interrupts (KVM_FLIC_GET_ALL_IRQS)
13- purge all pending floating interrupts (KVM_DEV_FLIC_CLEAR_IRQS)
14
15Groups:
16 KVM_DEV_FLIC_ENQUEUE
17 Passes a buffer and length into the kernel which are then injected into
18 the list of pending interrupts.
19 attr->addr contains the pointer to the buffer and attr->attr contains
20 the length of the buffer.
21 The format of the data structure kvm_s390_irq as it is copied from userspace
22 is defined in usr/include/linux/kvm.h.
23
24 KVM_DEV_FLIC_GET_ALL_IRQS
25 Copies all floating interrupts into a buffer provided by userspace.
26 When the buffer is too small it returns -ENOMEM, which is the indication
27 for userspace to try again with a bigger buffer.
28 All interrupts remain pending, i.e. are not deleted from the list of
29 currently pending interrupts.
30 attr->addr contains the userspace address of the buffer into which all
31 interrupt data will be copied.
32 attr->attr contains the size of the buffer in bytes.
33
34 KVM_DEV_FLIC_CLEAR_IRQS
35 Simply deletes all elements from the list of currently pending floating
36 interrupts. No interrupts are injected into the guest.
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 }
738 list_add_tail(&inti->list, &iter->list);
739 }
740 atomic_set(&fi->active, 1);
741 sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS);
742 if (sigcpu == KVM_MAX_VCPUS) {
743 do {
744 sigcpu = fi->next_rr_cpu++;
745 if (sigcpu == KVM_MAX_VCPUS)
746 sigcpu = fi->next_rr_cpu = 0;
747 } while (fi->local_int[sigcpu] == NULL);
748 }
749 li = fi->local_int[sigcpu];
750 spin_lock_bh(&li->lock);
751 atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
752 if (waitqueue_active(li->wq))
753 wake_up_interruptible(li->wq);
754 spin_unlock_bh(&li->lock);
755 spin_unlock(&fi->lock);
756 mutex_unlock(&kvm->lock);
757 return 0; 755 return 0;
758} 756}
759 757
@@ -841,3 +839,207 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
841 mutex_unlock(&vcpu->kvm->lock); 839 mutex_unlock(&vcpu->kvm->lock);
842 return 0; 840 return 0;
843} 841}
842
843static void clear_floating_interrupts(struct kvm *kvm)
844{
845 struct kvm_s390_float_interrupt *fi;
846 struct kvm_s390_interrupt_info *n, *inti = NULL;
847
848 mutex_lock(&kvm->lock);
849 fi = &kvm->arch.float_int;
850 spin_lock(&fi->lock);
851 list_for_each_entry_safe(inti, n, &fi->list, list) {
852 list_del(&inti->list);
853 kfree(inti);
854 }
855 atomic_set(&fi->active, 0);
856 spin_unlock(&fi->lock);
857 mutex_unlock(&kvm->lock);
858}
859
860static inline int copy_irq_to_user(struct kvm_s390_interrupt_info *inti,
861 u8 *addr)
862{
863 struct kvm_s390_irq __user *uptr = (struct kvm_s390_irq __user *) addr;
864 struct kvm_s390_irq irq = {0};
865
866 irq.type = inti->type;
867 switch (inti->type) {
868 case KVM_S390_INT_VIRTIO:
869 case KVM_S390_INT_SERVICE:
870 irq.u.ext = inti->ext;
871 break;
872 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
873 irq.u.io = inti->io;
874 break;
875 case KVM_S390_MCHK:
876 irq.u.mchk = inti->mchk;
877 break;
878 default:
879 return -EINVAL;
880 }
881
882 if (copy_to_user(uptr, &irq, sizeof(irq)))
883 return -EFAULT;
884
885 return 0;
886}
887
888static int get_all_floating_irqs(struct kvm *kvm, __u8 *buf, __u64 len)
889{
890 struct kvm_s390_interrupt_info *inti;
891 struct kvm_s390_float_interrupt *fi;
892 int ret = 0;
893 int n = 0;
894
895 mutex_lock(&kvm->lock);
896 fi = &kvm->arch.float_int;
897 spin_lock(&fi->lock);
898
899 list_for_each_entry(inti, &fi->list, list) {
900 if (len < sizeof(struct kvm_s390_irq)) {
901 /* signal userspace to try again */
902 ret = -ENOMEM;
903 break;
904 }
905 ret = copy_irq_to_user(inti, buf);
906 if (ret)
907 break;
908 buf += sizeof(struct kvm_s390_irq);
909 len -= sizeof(struct kvm_s390_irq);
910 n++;
911 }
912
913 spin_unlock(&fi->lock);
914 mutex_unlock(&kvm->lock);
915
916 return ret < 0 ? ret : n;
917}
918
919static int flic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
920{
921 int r;
922
923 switch (attr->group) {
924 case KVM_DEV_FLIC_GET_ALL_IRQS:
925 r = get_all_floating_irqs(dev->kvm, (u8 *) attr->addr,
926 attr->attr);
927 break;
928 default:
929 r = -EINVAL;
930 }
931
932 return r;
933}
934
935static inline int copy_irq_from_user(struct kvm_s390_interrupt_info *inti,
936 u64 addr)
937{
938 struct kvm_s390_irq __user *uptr = (struct kvm_s390_irq __user *) addr;
939 void *target = NULL;
940 void __user *source;
941 u64 size;
942
943 if (get_user(inti->type, (u64 __user *)addr))
944 return -EFAULT;
945
946 switch (inti->type) {
947 case KVM_S390_INT_VIRTIO:
948 case KVM_S390_INT_SERVICE:
949 target = (void *) &inti->ext;
950 source = &uptr->u.ext;
951 size = sizeof(inti->ext);
952 break;
953 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
954 target = (void *) &inti->io;
955 source = &uptr->u.io;
956 size = sizeof(inti->io);
957 break;
958 case KVM_S390_MCHK:
959 target = (void *) &inti->mchk;
960 source = &uptr->u.mchk;
961 size = sizeof(inti->mchk);
962 break;
963 default:
964 return -EINVAL;
965 }
966
967 if (copy_from_user(target, source, size))
968 return -EFAULT;
969
970 return 0;
971}
972
973static int enqueue_floating_irq(struct kvm_device *dev,
974 struct kvm_device_attr *attr)
975{
976 struct kvm_s390_interrupt_info *inti = NULL;
977 int r = 0;
978 int len = attr->attr;
979
980 if (len % sizeof(struct kvm_s390_irq) != 0)
981 return -EINVAL;
982 else if (len > KVM_S390_FLIC_MAX_BUFFER)
983 return -EINVAL;
984
985 while (len >= sizeof(struct kvm_s390_irq)) {
986 inti = kzalloc(sizeof(*inti), GFP_KERNEL);
987 if (!inti)
988 return -ENOMEM;
989
990 r = copy_irq_from_user(inti, attr->addr);
991 if (r) {
992 kfree(inti);
993 return r;
994 }
995 __inject_vm(dev->kvm, inti);
996 len -= sizeof(struct kvm_s390_irq);
997 attr->addr += sizeof(struct kvm_s390_irq);
998 }
999
1000 return r;
1001}
1002
1003static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
1004{
1005 int r = 0;
1006
1007 switch (attr->group) {
1008 case KVM_DEV_FLIC_ENQUEUE:
1009 r = enqueue_floating_irq(dev, attr);
1010 break;
1011 case KVM_DEV_FLIC_CLEAR_IRQS:
1012 r = 0;
1013 clear_floating_interrupts(dev->kvm);
1014 break;
1015 default:
1016 r = -EINVAL;
1017 }
1018
1019 return r;
1020}
1021
1022static int flic_create(struct kvm_device *dev, u32 type)
1023{
1024 if (!dev)
1025 return -EINVAL;
1026 if (dev->kvm->arch.flic)
1027 return -EINVAL;
1028 dev->kvm->arch.flic = dev;
1029 return 0;
1030}
1031
1032static void flic_destroy(struct kvm_device *dev)
1033{
1034 dev->kvm->arch.flic = NULL;
1035 kfree(dev);
1036}
1037
1038/* s390 floating irq controller (flic) */
1039struct kvm_device_ops kvm_flic_ops = {
1040 .name = "kvm-flic",
1041 .get_attr = flic_get_attr,
1042 .set_attr = flic_set_attr,
1043 .create = flic_create,
1044 .destroy = flic_destroy,
1045};
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index e0676f390d57..782420f3c4d5 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -157,6 +157,7 @@ int kvm_dev_ioctl_check_extension(long ext)
157 case KVM_CAP_ENABLE_CAP: 157 case KVM_CAP_ENABLE_CAP:
158 case KVM_CAP_S390_CSS_SUPPORT: 158 case KVM_CAP_S390_CSS_SUPPORT:
159 case KVM_CAP_IOEVENTFD: 159 case KVM_CAP_IOEVENTFD:
160 case KVM_CAP_DEVICE_CTRL:
160 r = 1; 161 r = 1;
161 break; 162 break;
162 case KVM_CAP_NR_VCPUS: 163 case KVM_CAP_NR_VCPUS:
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index b8e9a43e501a..c0102ef2de48 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1064,6 +1064,7 @@ extern struct kvm_device_ops kvm_mpic_ops;
1064extern struct kvm_device_ops kvm_xics_ops; 1064extern struct kvm_device_ops kvm_xics_ops;
1065extern struct kvm_device_ops kvm_vfio_ops; 1065extern struct kvm_device_ops kvm_vfio_ops;
1066extern struct kvm_device_ops kvm_arm_vgic_v2_ops; 1066extern struct kvm_device_ops kvm_arm_vgic_v2_ops;
1067extern struct kvm_device_ops kvm_flic_ops;
1067 1068
1068#ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT 1069#ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT
1069 1070
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 86faf47ae494..19f717b15297 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -918,6 +918,7 @@ struct kvm_device_attr {
918#define KVM_DEV_VFIO_GROUP_ADD 1 918#define KVM_DEV_VFIO_GROUP_ADD 1
919#define KVM_DEV_VFIO_GROUP_DEL 2 919#define KVM_DEV_VFIO_GROUP_DEL 2
920#define KVM_DEV_TYPE_ARM_VGIC_V2 5 920#define KVM_DEV_TYPE_ARM_VGIC_V2 5
921#define KVM_DEV_TYPE_FLIC 6
921 922
922/* 923/*
923 * ioctls for VM fds 924 * ioctls for VM fds
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 03a0381b1cb7..a9e999a48e43 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2284,6 +2284,11 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
2284 ops = &kvm_arm_vgic_v2_ops; 2284 ops = &kvm_arm_vgic_v2_ops;
2285 break; 2285 break;
2286#endif 2286#endif
2287#ifdef CONFIG_S390
2288 case KVM_DEV_TYPE_FLIC:
2289 ops = &kvm_flic_ops;
2290 break;
2291#endif
2287 default: 2292 default:
2288 return -ENODEV; 2293 return -ENODEV;
2289 } 2294 }