diff options
| author | Fei Li <sherrylf@linux.vnet.ibm.com> | 2017-02-17 04:06:26 -0500 |
|---|---|---|
| committer | Christian Borntraeger <borntraeger@de.ibm.com> | 2017-04-06 07:15:36 -0400 |
| commit | 519783935451764b397f2a712de5ea778ff77fdf (patch) | |
| tree | 599467b03f2ff2680b4de7b494b1bfaccd37f859 | |
| parent | 08fab50da669e5ee5a542592895fcb63be3cd7b1 (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.txt | 20 | ||||
| -rw-r--r-- | arch/s390/include/asm/kvm_host.h | 10 | ||||
| -rw-r--r-- | arch/s390/include/uapi/asm/kvm.h | 6 | ||||
| -rw-r--r-- | arch/s390/kvm/interrupt.c | 43 | ||||
| -rw-r--r-- | arch/s390/kvm/kvm-s390.c | 4 | ||||
| -rw-r--r-- | arch/s390/kvm/trace-s390.h | 31 |
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 | ||
| 18 | Groups: | 19 | Groups: |
| 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 | |||
| 115 | struct 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 | |||
| 110 | Note: The KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR device ioctls executed on | 130 | Note: The KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR device ioctls executed on |
| 111 | FLIC with an unknown group or attribute gives the error code EINVAL (instead of | 131 | FLIC with an unknown group or attribute gives the error code EINVAL (instead of |
| 112 | ENXIO, as specified in the API documentation). It is not possible to conclude | 132 | ENXIO, 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 | |||
| 524 | struct kvm_s390_float_interrupt { | 530 | struct 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 | ||
| 535 | struct kvm_hw_wp_info_arch { | 545 | struct 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 | ||
| 50 | struct 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 | ||
| 2155 | static 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 | |||
| 2155 | static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) | 2194 | static 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, | |||
