History

KVM: s390: Support for I/O interrupts.

Add support for handling I/O interrupts (standard, subchannel-related ones and rudimentary adapter interrupts). The subchannel-identifying parameters are encoded into the interrupt type. I/O interrupts are floating, so they can't be injected on a specific vcpu.

Cornelia Huck committed 13 years ago

Commit d8346b71 parent b1c571a4 files · +116 −2Browse files

Unified · Split

4 files
  1. Documentation/virtual/kvm/api.txt +4 −0
  2. arch/s390/include/asm/kvm_host.h +2 −0
  3. arch/s390/kvm/interrupt.c +101 −2
  4. include/uapi/linux/kvm.h +9 −0
Documentation/virtual/kvm/api.txt+4−0
@@ -2069,6 +2069,10 @@ KVM_S390_INT_VIRTIO (vm) - virtio external interrupt; external interrupt · 2068 unmodified lines
20692069 KVM_S390_INT_SERVICE (vm) - sclp external interrupt; sclp parameter in parm
20702070 KVM_S390_INT_EMERGENCY (vcpu) - sigp emergency; source cpu in parm
20712071 KVM_S390_INT_EXTERNAL_CALL (vcpu) - sigp external call; source cpu in parm
2072+KVM_S390_INT_IO(ai,cssid,ssid,schid) (vm) - compound value to indicate an
2073+ I/O interrupt (ai - adapter interrupt; cssid,ssid,schid - subchannel);
2074+ I/O interruption parameters in parm (subchannel) and parm64 (intparm,
2075+ interruption subclass)
20722076
20732077 Note that the vcpu ioctl is asynchronous to vcpu execution.
20742078
arch/s390/include/asm/kvm_host.h+2−0
@@ -74,6 +74,7 @@ struct kvm_s390_sie_block { · 73 unmodified lines
7474 __u64 epoch; /* 0x0038 */
7575 __u8 reserved40[4]; /* 0x0040 */
7676 #define LCTL_CR0 0x8000
77+#define LCTL_CR6 0x0200
7778 __u16 lctl; /* 0x0044 */
7879 __s16 icpua; /* 0x0046 */
7980 __u32 ictl; /* 0x0048 */
@@ -125,6 +126,7 @@ struct kvm_vcpu_stat { · 45 unmodified lines
125126 u32 deliver_prefix_signal;
126127 u32 deliver_restart_signal;
127128 u32 deliver_program_int;
129+ u32 deliver_io_int;
128130 u32 exit_wait_state;
129131 u32 instruction_stidp;
130132 u32 instruction_spx;
arch/s390/kvm/interrupt.c+101−2
@@ -21,11 +21,26 @@ · 20 unmodified lines
2121 #include "gaccess.h"
2222 #include "trace-s390.h"
2323
24+#define IOINT_SCHID_MASK 0x0000ffff
25+#define IOINT_SSID_MASK 0x00030000
26+#define IOINT_CSSID_MASK 0x03fc0000
27+#define IOINT_AI_MASK 0x04000000
28+
29+static int is_ioint(u64 type)
30+{
31+ return ((type & 0xfffe0000u) != 0xfffe0000u);
32+}
33+
2434 static int psw_extint_disabled(struct kvm_vcpu *vcpu)
2535 {
2636 return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_EXT);
2737 }
2838
39+static int psw_ioint_disabled(struct kvm_vcpu *vcpu)
40+{
41+ return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_IO);
42+}
43+
2944 static int psw_interrupts_disabled(struct kvm_vcpu *vcpu)
3045 {
3146 if ((vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PER) ||
@@ -67,7 +82,15 @@ static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu, · 35 unmodified lines
6782 case KVM_S390_SIGP_SET_PREFIX:
6883 case KVM_S390_RESTART:
6984 return 1;
85+ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
86+ if (psw_ioint_disabled(vcpu))
87+ return 0;
88+ if (vcpu->arch.sie_block->gcr[6] & inti->io.io_int_word)
89+ return 1;
90+ return 0;
7091 default:
92+ printk(KERN_WARNING "illegal interrupt type %llx\n",
93+ inti->type);
7194 BUG();
7295 }
7396 return 0;
@@ -116,6 +139,12 @@ static void __set_intercept_indicator(struct kvm_vcpu *vcpu, · 42 unmodified lines
116139 case KVM_S390_SIGP_STOP:
117140 __set_cpuflag(vcpu, CPUSTAT_STOP_INT);
118141 break;
142+ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
143+ if (psw_ioint_disabled(vcpu))
144+ __set_cpuflag(vcpu, CPUSTAT_IO_INT);
145+ else
146+ vcpu->arch.sie_block->lctl |= LCTL_CR6;
147+ break;
119148 default:
120149 BUG();
121150 }
@@ -297,6 +326,47 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, · 175 unmodified lines
297326 exception = 1;
298327 break;
299328
329+ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
330+ {
331+ __u32 param0 = ((__u32)inti->io.subchannel_id << 16) |
332+ inti->io.subchannel_nr;
333+ __u64 param1 = ((__u64)inti->io.io_int_parm << 32) |
334+ inti->io.io_int_word;
335+ VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->type);
336+ vcpu->stat.deliver_io_int++;
337+ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
338+ param0, param1);
339+ rc = put_guest_u16(vcpu, __LC_SUBCHANNEL_ID,
340+ inti->io.subchannel_id);
341+ if (rc == -EFAULT)
342+ exception = 1;
343+
344+ rc = put_guest_u16(vcpu, __LC_SUBCHANNEL_NR,
345+ inti->io.subchannel_nr);
346+ if (rc == -EFAULT)
347+ exception = 1;
348+
349+ rc = put_guest_u32(vcpu, __LC_IO_INT_PARM,
350+ inti->io.io_int_parm);
351+ if (rc == -EFAULT)
352+ exception = 1;
353+
354+ rc = put_guest_u32(vcpu, __LC_IO_INT_WORD,
355+ inti->io.io_int_word);
356+ if (rc == -EFAULT)
357+ exception = 1;
358+
359+ rc = copy_to_guest(vcpu, __LC_IO_OLD_PSW,
360+ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
361+ if (rc == -EFAULT)
362+ exception = 1;
363+
364+ rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
365+ __LC_IO_NEW_PSW, sizeof(psw_t));
366+ if (rc == -EFAULT)
367+ exception = 1;
368+ break;
369+ }
300370 default:
301371 BUG();
302372 }
@@ -545,7 +615,7 @@ int kvm_s390_inject_vm(struct kvm *kvm, · 242 unmodified lines
545615 {
546616 struct kvm_s390_local_interrupt *li;
547617 struct kvm_s390_float_interrupt *fi;
548− struct kvm_s390_interrupt_info *inti;
618+ struct kvm_s390_interrupt_info *inti, *iter;
549619 int sigcpu;
550620
551621 inti = kzalloc(sizeof(*inti), GFP_KERNEL);
@@ -569,6 +639,22 @@ int kvm_s390_inject_vm(struct kvm *kvm, · 17 unmodified lines
569639 case KVM_S390_SIGP_STOP:
570640 case KVM_S390_INT_EXTERNAL_CALL:
571641 case KVM_S390_INT_EMERGENCY:
642+ kfree(inti);
643+ return -EINVAL;
644+ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
645+ if (s390int->type & IOINT_AI_MASK)
646+ VM_EVENT(kvm, 5, "%s", "inject: I/O (AI)");
647+ else
648+ VM_EVENT(kvm, 5, "inject: I/O css %x ss %x schid %04x",
649+ s390int->type & IOINT_CSSID_MASK,
650+ s390int->type & IOINT_SSID_MASK,
651+ s390int->type & IOINT_SCHID_MASK);
652+ inti->type = s390int->type;
653+ inti->io.subchannel_id = s390int->parm >> 16;
654+ inti->io.subchannel_nr = s390int->parm & 0x0000ffffu;
655+ inti->io.io_int_parm = s390int->parm64 >> 32;
656+ inti->io.io_int_word = s390int->parm64 & 0x00000000ffffffffull;
657+ break;
572658 default:
573659 kfree(inti);
574660 return -EINVAL;
@@ -579,7 +665,19 @@ int kvm_s390_inject_vm(struct kvm *kvm, · 4 unmodified lines
579665 mutex_lock(&kvm->lock);
580666 fi = &kvm->arch.float_int;
581667 spin_lock(&fi->lock);
582− list_add_tail(&inti->list, &fi->list);
668+ if (!is_ioint(inti->type))
669+ list_add_tail(&inti->list, &fi->list);
670+ else {
671+ /* Keep I/O interrupts sorted in isc order. */
672+ list_for_each_entry(iter, &fi->list, list) {
673+ if (!is_ioint(iter->type))
674+ continue;
675+ if (iter->io.io_int_word <= inti->io.io_int_word)
676+ continue;
677+ break;
678+ }
679+ list_add_tail(&inti->list, &iter->list);
680+ }
583681 atomic_set(&fi->active, 1);
584682 sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS);
585683 if (sigcpu == KVM_MAX_VCPUS) {
@@ -653,6 +751,7 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, · 67 unmodified lines
653751 break;
654752 case KVM_S390_INT_VIRTIO:
655753 case KVM_S390_INT_SERVICE:
754+ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
656755 default:
657756 kfree(inti);
658757 return -EINVAL;
include/uapi/linux/kvm.h+9−0
@@ -401,6 +401,15 @@ struct kvm_s390_psw { · 400 unmodified lines
401401 #define KVM_S390_INT_SERVICE 0xffff2401u
402402 #define KVM_S390_INT_EMERGENCY 0xffff1201u
403403 #define KVM_S390_INT_EXTERNAL_CALL 0xffff1202u
404+/* Anything below 0xfffe0000u is taken by INT_IO */
405+#define KVM_S390_INT_IO(ai,cssid,ssid,schid) \
406+ (((schid)) | \
407+ ((ssid) << 16) | \
408+ ((cssid) << 18) | \
409+ ((ai) << 26))
410+#define KVM_S390_INT_IO_MIN 0x00000000u
411+#define KVM_S390_INT_IO_MAX 0xfffdffffu
412+
404413
405414 struct kvm_s390_interrupt {
406415 __u32 type;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t