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)