aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFei Li <sherrylf@linux.vnet.ibm.com>2017-02-17 04:06:26 -0500
committerChristian Borntraeger <borntraeger@de.ibm.com>2017-04-06 07:15:36 -0400
commit519783935451764b397f2a712de5ea778ff77fdf (patch)
tree599467b03f2ff2680b4de7b494b1bfaccd37f859
parent08fab50da669e5ee5a542592895fcb63be3cd7b1 (diff)
KVM: s390: introduce ais mode modify function
Provide an interface for userspace to modify AIS (adapter-interruption-suppression) mode state, and add documentation for the interface. Allowed target modes are ALL-Interruptions mode and SINGLE-Interruption mode. We introduce the 'simm' and 'nimm' fields in kvm_s390_float_interrupt to store interruption modes for each ISC. Each bit in 'simm' and 'nimm' targets to one ISC, and collaboratively indicate three modes: ALL-Interruptions, SINGLE-Interruption and NO-Interruptions. This interface can initiate most transitions between the states; transition from SINGLE-Interruption to NO-Interruptions via adapter interrupt injection will be introduced in a following patch. The meaningful combinations are as follows: interruption mode | simm bit | nimm bit ------------------|----------|---------- ALL | 0 | 0 SINGLE | 1 | 0 NO | 1 | 1 Besides, add tracepoint to track AIS mode transitions. Co-Authored-By: Yi Min Zhao <zyimin@linux.vnet.ibm.com> Signed-off-by: Yi Min Zhao <zyimin@linux.vnet.ibm.com> Signed-off-by: Fei Li <sherrylf@linux.vnet.ibm.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
-rw-r--r--Documentation/virtual/kvm/devices/s390_flic.txt20
-rw-r--r--arch/s390/include/asm/kvm_host.h10
-rw-r--r--arch/s390/include/uapi/asm/kvm.h6
-rw-r--r--arch/s390/kvm/interrupt.c43
-rw-r--r--arch/s390/kvm/kvm-s390.c4
-rw-r--r--arch/s390/kvm/trace-s390.h31
6 files changed, 114 insertions, 0 deletions
diff --git a/Documentation/virtual/kvm/devices/s390_flic.txt b/Documentation/virtual/kvm/devices/s390_flic.txt
index e8ee3b6edb05..dfd42fd4abd5 100644
--- a/Documentation/virtual/kvm/devices/s390_flic.txt
+++ b/Documentation/virtual/kvm/devices/s390_flic.txt
@@ -14,6 +14,7 @@ FLIC provides support to
14- purge one pending floating I/O interrupt (KVM_DEV_FLIC_CLEAR_IO_IRQ) 14- purge one pending floating I/O interrupt (KVM_DEV_FLIC_CLEAR_IO_IRQ)
15- enable/disable for the guest transparent async page faults 15- enable/disable for the guest transparent async page faults
16- register and modify adapter interrupt sources (KVM_DEV_FLIC_ADAPTER_*) 16- register and modify adapter interrupt sources (KVM_DEV_FLIC_ADAPTER_*)
17- modify AIS (adapter-interruption-suppression) mode state (KVM_DEV_FLIC_AISM)
17 18
18Groups: 19Groups:
19 KVM_DEV_FLIC_ENQUEUE 20 KVM_DEV_FLIC_ENQUEUE
@@ -107,6 +108,25 @@ struct kvm_s390_io_adapter_req {
107 release a userspace page for the translated address specified in addr 108 release a userspace page for the translated address specified in addr
108 from the list of mappings 109 from the list of mappings
109 110
111 KVM_DEV_FLIC_AISM
112 modify the adapter-interruption-suppression mode for a given isc if the
113 AIS capability is enabled. Takes a kvm_s390_ais_req describing:
114
115struct kvm_s390_ais_req {
116 __u8 isc;
117 __u16 mode;
118};
119
120 isc contains the target I/O interruption subclass, mode the target
121 adapter-interruption-suppression mode. The following modes are
122 currently supported:
123 - KVM_S390_AIS_MODE_ALL: ALL-Interruptions Mode, i.e. airq injection
124 is always allowed;
125 - KVM_S390_AIS_MODE_SINGLE: SINGLE-Interruption Mode, i.e. airq
126 injection is only allowed once and the following adapter interrupts
127 will be suppressed until the mode is set again to ALL-Interruptions
128 or SINGLE-Interruption mode.
129
110Note: The KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR device ioctls executed on 130Note: The KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR device ioctls executed on
111FLIC with an unknown group or attribute gives the error code EINVAL (instead of 131FLIC with an unknown group or attribute gives the error code EINVAL (instead of
112ENXIO, as specified in the API documentation). It is not possible to conclude 132ENXIO, as specified in the API documentation). It is not possible to conclude
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 499c72c2280d..552c319483c6 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -521,6 +521,12 @@ struct kvm_s390_local_interrupt {
521#define FIRQ_CNTR_PFAULT 3 521#define FIRQ_CNTR_PFAULT 3
522#define FIRQ_MAX_COUNT 4 522#define FIRQ_MAX_COUNT 4
523 523
524/* mask the AIS mode for a given ISC */
525#define AIS_MODE_MASK(isc) (0x80 >> isc)
526
527#define KVM_S390_AIS_MODE_ALL 0
528#define KVM_S390_AIS_MODE_SINGLE 1
529
524struct kvm_s390_float_interrupt { 530struct kvm_s390_float_interrupt {
525 unsigned long pending_irqs; 531 unsigned long pending_irqs;
526 spinlock_t lock; 532 spinlock_t lock;
@@ -530,6 +536,10 @@ struct kvm_s390_float_interrupt {
530 struct kvm_s390_ext_info srv_signal; 536 struct kvm_s390_ext_info srv_signal;
531 int next_rr_cpu; 537 int next_rr_cpu;
532 unsigned long idle_mask[BITS_TO_LONGS(KVM_MAX_VCPUS)]; 538 unsigned long idle_mask[BITS_TO_LONGS(KVM_MAX_VCPUS)];
539 struct mutex ais_lock;
540 u8 simm;
541 u8 nimm;
542 int ais_enabled;
533}; 543};
534 544
535struct kvm_hw_wp_info_arch { 545struct kvm_hw_wp_info_arch {
diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h
index 5fa144d1df0a..50d2a927c990 100644
--- a/arch/s390/include/uapi/asm/kvm.h
+++ b/arch/s390/include/uapi/asm/kvm.h
@@ -26,6 +26,7 @@
26#define KVM_DEV_FLIC_ADAPTER_REGISTER 6 26#define KVM_DEV_FLIC_ADAPTER_REGISTER 6
27#define KVM_DEV_FLIC_ADAPTER_MODIFY 7 27#define KVM_DEV_FLIC_ADAPTER_MODIFY 7
28#define KVM_DEV_FLIC_CLEAR_IO_IRQ 8 28#define KVM_DEV_FLIC_CLEAR_IO_IRQ 8
29#define KVM_DEV_FLIC_AISM 9
29/* 30/*
30 * We can have up to 4*64k pending subchannels + 8 adapter interrupts, 31 * We can have up to 4*64k pending subchannels + 8 adapter interrupts,
31 * as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts. 32 * as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
@@ -46,6 +47,11 @@ struct kvm_s390_io_adapter {
46 47
47#define KVM_S390_ADAPTER_SUPPRESSIBLE 0x01 48#define KVM_S390_ADAPTER_SUPPRESSIBLE 0x01
48 49
50struct kvm_s390_ais_req {
51 __u8 isc;
52 __u16 mode;
53};
54
49#define KVM_S390_IO_ADAPTER_MASK 1 55#define KVM_S390_IO_ADAPTER_MASK 1
50#define KVM_S390_IO_ADAPTER_MAP 2 56#define KVM_S390_IO_ADAPTER_MAP 2
51#define KVM_S390_IO_ADAPTER_UNMAP 3 57#define KVM_S390_IO_ADAPTER_UNMAP 3
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index dba51ad62570..96b689e48c08 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -2152,6 +2152,45 @@ static int clear_io_irq(struct kvm *kvm, struct kvm_device_attr *attr)
2152 return 0; 2152 return 0;
2153} 2153}
2154 2154
2155static int modify_ais_mode(struct kvm *kvm, struct kvm_device_attr *attr)
2156{
2157 struct kvm_s390_float_interrupt *fi = &kvm->arch.float_int;
2158 struct kvm_s390_ais_req req;
2159 int ret = 0;
2160
2161 if (!fi->ais_enabled)
2162 return -ENOTSUPP;
2163
2164 if (copy_from_user(&req, (void __user *)attr->addr, sizeof(req)))
2165 return -EFAULT;
2166
2167 if (req.isc > MAX_ISC)
2168 return -EINVAL;
2169
2170 trace_kvm_s390_modify_ais_mode(req.isc,
2171 (fi->simm & AIS_MODE_MASK(req.isc)) ?
2172 (fi->nimm & AIS_MODE_MASK(req.isc)) ?
2173 2 : KVM_S390_AIS_MODE_SINGLE :
2174 KVM_S390_AIS_MODE_ALL, req.mode);
2175
2176 mutex_lock(&fi->ais_lock);
2177 switch (req.mode) {
2178 case KVM_S390_AIS_MODE_ALL:
2179 fi->simm &= ~AIS_MODE_MASK(req.isc);
2180 fi->nimm &= ~AIS_MODE_MASK(req.isc);
2181 break;
2182 case KVM_S390_AIS_MODE_SINGLE:
2183 fi->simm |= AIS_MODE_MASK(req.isc);
2184 fi->nimm &= ~AIS_MODE_MASK(req.isc);
2185 break;
2186 default:
2187 ret = -EINVAL;
2188 }
2189 mutex_unlock(&fi->ais_lock);
2190
2191 return ret;
2192}
2193
2155static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) 2194static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
2156{ 2195{
2157 int r = 0; 2196 int r = 0;
@@ -2188,6 +2227,9 @@ static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
2188 case KVM_DEV_FLIC_CLEAR_IO_IRQ: 2227 case KVM_DEV_FLIC_CLEAR_IO_IRQ:
2189 r = clear_io_irq(dev->kvm, attr); 2228 r = clear_io_irq(dev->kvm, attr);
2190 break; 2229 break;
2230 case KVM_DEV_FLIC_AISM:
2231 r = modify_ais_mode(dev->kvm, attr);
2232 break;
2191 default: 2233 default:
2192 r = -EINVAL; 2234 r = -EINVAL;
2193 } 2235 }
@@ -2207,6 +2249,7 @@ static int flic_has_attr(struct kvm_device *dev,
2207 case KVM_DEV_FLIC_ADAPTER_REGISTER: 2249 case KVM_DEV_FLIC_ADAPTER_REGISTER:
2208 case KVM_DEV_FLIC_ADAPTER_MODIFY: 2250 case KVM_DEV_FLIC_ADAPTER_MODIFY:
2209 case KVM_DEV_FLIC_CLEAR_IO_IRQ: 2251 case KVM_DEV_FLIC_CLEAR_IO_IRQ:
2252 case KVM_DEV_FLIC_AISM:
2210 return 0; 2253 return 0;
2211 } 2254 }
2212 return -ENXIO; 2255 return -ENXIO;
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index f83f18b77f3d..977cc1660a83 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -1515,6 +1515,10 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
1515 1515
1516 kvm_s390_crypto_init(kvm); 1516 kvm_s390_crypto_init(kvm);
1517 1517
1518 mutex_init(&kvm->arch.float_int.ais_lock);
1519 kvm->arch.float_int.simm = 0;
1520 kvm->arch.float_int.nimm = 0;
1521 kvm->arch.float_int.ais_enabled = 0;
1518 spin_lock_init(&kvm->arch.float_int.lock); 1522 spin_lock_init(&kvm->arch.float_int.lock);
1519 for (i = 0; i < FIRQ_LIST_COUNT; i++) 1523 for (i = 0; i < FIRQ_LIST_COUNT; i++)
1520 INIT_LIST_HEAD(&kvm->arch.float_int.lists[i]); 1524 INIT_LIST_HEAD(&kvm->arch.float_int.lists[i]);
diff --git a/arch/s390/kvm/trace-s390.h b/arch/s390/kvm/trace-s390.h
index 396485bca191..b32994d1546a 100644
--- a/arch/s390/kvm/trace-s390.h
+++ b/arch/s390/kvm/trace-s390.h
@@ -280,6 +280,37 @@ TRACE_EVENT(kvm_s390_enable_disable_ibs,