Skip to content

Commit 5197839

Browse files
Fei LiYi Min Zhao
authored andcommitted
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 <[email protected]> Signed-off-by: Yi Min Zhao <[email protected]> Signed-off-by: Fei Li <[email protected]> Reviewed-by: Cornelia Huck <[email protected]> Signed-off-by: Christian Borntraeger <[email protected]>
1 parent 08fab50 commit 5197839

6 files changed

Lines changed: 114 additions & 0 deletions

File tree

Documentation/virtual/kvm/devices/s390_flic.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ FLIC provides support to
1414
- purge one pending floating I/O interrupt (KVM_DEV_FLIC_CLEAR_IO_IRQ)
1515
- enable/disable for the guest transparent async page faults
1616
- register and modify adapter interrupt sources (KVM_DEV_FLIC_ADAPTER_*)
17+
- modify AIS (adapter-interruption-suppression) mode state (KVM_DEV_FLIC_AISM)
1718

1819
Groups:
1920
KVM_DEV_FLIC_ENQUEUE
@@ -107,6 +108,25 @@ struct kvm_s390_io_adapter_req {
107108
release a userspace page for the translated address specified in addr
108109
from the list of mappings
109110

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+
110130
Note: The KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR device ioctls executed on
111131
FLIC with an unknown group or attribute gives the error code EINVAL (instead of
112132
ENXIO, as specified in the API documentation). It is not possible to conclude

arch/s390/include/asm/kvm_host.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,12 @@ struct kvm_s390_local_interrupt {
521521
#define FIRQ_CNTR_PFAULT 3
522522
#define FIRQ_MAX_COUNT 4
523523

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+
524530
struct kvm_s390_float_interrupt {
525531
unsigned long pending_irqs;
526532
spinlock_t lock;
@@ -530,6 +536,10 @@ struct kvm_s390_float_interrupt {
530536
struct kvm_s390_ext_info srv_signal;
531537
int next_rr_cpu;
532538
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;
533543
};
534544

535545
struct kvm_hw_wp_info_arch {

arch/s390/include/uapi/asm/kvm.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#define KVM_DEV_FLIC_ADAPTER_REGISTER 6
2727
#define KVM_DEV_FLIC_ADAPTER_MODIFY 7
2828
#define KVM_DEV_FLIC_CLEAR_IO_IRQ 8
29+
#define KVM_DEV_FLIC_AISM 9
2930
/*
3031
* We can have up to 4*64k pending subchannels + 8 adapter interrupts,
3132
* as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
@@ -46,6 +47,11 @@ struct kvm_s390_io_adapter {
4647

4748
#define KVM_S390_ADAPTER_SUPPRESSIBLE 0x01
4849

50+
struct kvm_s390_ais_req {
51+
__u8 isc;
52+
__u16 mode;
53+
};
54+
4955
#define KVM_S390_IO_ADAPTER_MASK 1
5056
#define KVM_S390_IO_ADAPTER_MAP 2
5157
#define KVM_S390_IO_ADAPTER_UNMAP 3

arch/s390/kvm/interrupt.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2152,6 +2152,45 @@ static int clear_io_irq(struct kvm *kvm, struct kvm_device_attr *attr)
21522152
return 0;
21532153
}
21542154

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+
21552194
static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
21562195
{
21572196
int r = 0;
@@ -2188,6 +2227,9 @@ static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
21882227
case KVM_DEV_FLIC_CLEAR_IO_IRQ:
21892228
r = clear_io_irq(dev->kvm, attr);
21902229
break;
2230+
case KVM_DEV_FLIC_AISM:
2231+
r = modify_ais_mode(dev->kvm, attr);
2232+
break;
21912233
default:
21922234
r = -EINVAL;
21932235
}
@@ -2207,6 +2249,7 @@ static int flic_has_attr(struct kvm_device *dev,
22072249
case KVM_DEV_FLIC_ADAPTER_REGISTER:
22082250
case KVM_DEV_FLIC_ADAPTER_MODIFY:
22092251
case KVM_DEV_FLIC_CLEAR_IO_IRQ:
2252+
case KVM_DEV_FLIC_AISM:
22102253
return 0;
22112254
}
22122255
return -ENXIO;

arch/s390/kvm/kvm-s390.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,6 +1515,10 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
15151515

15161516
kvm_s390_crypto_init(kvm);
15171517

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;
15181522
spin_lock_init(&kvm->arch.float_int.lock);
15191523
for (i = 0; i < FIRQ_LIST_COUNT; i++)
15201524
INIT_LIST_HEAD(&kvm->arch.float_int.lists[i]);

arch/s390/kvm/trace-s390.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,37 @@ TRACE_EVENT(kvm_s390_enable_disable_ibs,
280280
__entry->state ? "enabling" : "disabling", __entry->id)
281281
);
282282

283+
/*
284+
* Trace point for modifying ais mode for a given isc.
285+
*/
286+
TRACE_EVENT(kvm_s390_modify_ais_mode,
287+
TP_PROTO(__u8 isc, __u16 from, __u16 to),
288+
TP_ARGS(isc, from, to),
289+
290+
TP_STRUCT__entry(
291+
__field(__u8, isc)
292+
__field(__u16, from)
293+
__field(__u16, to)
294+
),
295+
296+
TP_fast_assign(
297+
__entry->isc = isc;
298+
__entry->from = from;
299+
__entry->to = to;
300+
),
301+
302+
TP_printk("for isc %x, modifying interruption mode from %s to %s",
303+
__entry->isc,
304+
(__entry->from == KVM_S390_AIS_MODE_ALL) ?
305+
"ALL-Interruptions Mode" :
306+
(__entry->from == KVM_S390_AIS_MODE_SINGLE) ?
307+
"Single-Interruption Mode" : "No-Interruptions Mode",
308+
(__entry->to == KVM_S390_AIS_MODE_ALL) ?
309+
"ALL-Interruptions Mode" :
310+
(__entry->to == KVM_S390_AIS_MODE_SINGLE) ?
311+
"Single-Interruption Mode" : "No-Interruptions Mode")
312+
);
313+
283314

284315
#endif /* _TRACE_KVMS390_H */
285316

0 commit comments

Comments
 (0)