mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-16 17:23:55 +08:00
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>
This commit is contained in:
parent
08fab50da6
commit
5197839354
@ -14,6 +14,7 @@ FLIC provides support to
|
||||
- purge one pending floating I/O interrupt (KVM_DEV_FLIC_CLEAR_IO_IRQ)
|
||||
- enable/disable for the guest transparent async page faults
|
||||
- register and modify adapter interrupt sources (KVM_DEV_FLIC_ADAPTER_*)
|
||||
- modify AIS (adapter-interruption-suppression) mode state (KVM_DEV_FLIC_AISM)
|
||||
|
||||
Groups:
|
||||
KVM_DEV_FLIC_ENQUEUE
|
||||
@ -107,6 +108,25 @@ struct kvm_s390_io_adapter_req {
|
||||
release a userspace page for the translated address specified in addr
|
||||
from the list of mappings
|
||||
|
||||
KVM_DEV_FLIC_AISM
|
||||
modify the adapter-interruption-suppression mode for a given isc if the
|
||||
AIS capability is enabled. Takes a kvm_s390_ais_req describing:
|
||||
|
||||
struct kvm_s390_ais_req {
|
||||
__u8 isc;
|
||||
__u16 mode;
|
||||
};
|
||||
|
||||
isc contains the target I/O interruption subclass, mode the target
|
||||
adapter-interruption-suppression mode. The following modes are
|
||||
currently supported:
|
||||
- KVM_S390_AIS_MODE_ALL: ALL-Interruptions Mode, i.e. airq injection
|
||||
is always allowed;
|
||||
- KVM_S390_AIS_MODE_SINGLE: SINGLE-Interruption Mode, i.e. airq
|
||||
injection is only allowed once and the following adapter interrupts
|
||||
will be suppressed until the mode is set again to ALL-Interruptions
|
||||
or SINGLE-Interruption mode.
|
||||
|
||||
Note: The KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR device ioctls executed on
|
||||
FLIC with an unknown group or attribute gives the error code EINVAL (instead of
|
||||
ENXIO, as specified in the API documentation). It is not possible to conclude
|
||||
|
@ -521,6 +521,12 @@ struct kvm_s390_local_interrupt {
|
||||
#define FIRQ_CNTR_PFAULT 3
|
||||
#define FIRQ_MAX_COUNT 4
|
||||
|
||||
/* mask the AIS mode for a given ISC */
|
||||
#define AIS_MODE_MASK(isc) (0x80 >> isc)
|
||||
|
||||
#define KVM_S390_AIS_MODE_ALL 0
|
||||
#define KVM_S390_AIS_MODE_SINGLE 1
|
||||
|
||||
struct kvm_s390_float_interrupt {
|
||||
unsigned long pending_irqs;
|
||||
spinlock_t lock;
|
||||
@ -530,6 +536,10 @@ struct kvm_s390_float_interrupt {
|
||||
struct kvm_s390_ext_info srv_signal;
|
||||
int next_rr_cpu;
|
||||
unsigned long idle_mask[BITS_TO_LONGS(KVM_MAX_VCPUS)];
|
||||
struct mutex ais_lock;
|
||||
u8 simm;
|
||||
u8 nimm;
|
||||
int ais_enabled;
|
||||
};
|
||||
|
||||
struct kvm_hw_wp_info_arch {
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define KVM_DEV_FLIC_ADAPTER_REGISTER 6
|
||||
#define KVM_DEV_FLIC_ADAPTER_MODIFY 7
|
||||
#define KVM_DEV_FLIC_CLEAR_IO_IRQ 8
|
||||
#define KVM_DEV_FLIC_AISM 9
|
||||
/*
|
||||
* We can have up to 4*64k pending subchannels + 8 adapter interrupts,
|
||||
* as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
|
||||
@ -46,6 +47,11 @@ struct kvm_s390_io_adapter {
|
||||
|
||||
#define KVM_S390_ADAPTER_SUPPRESSIBLE 0x01
|
||||
|
||||
struct kvm_s390_ais_req {
|
||||
__u8 isc;
|
||||
__u16 mode;
|
||||
};
|
||||
|
||||
#define KVM_S390_IO_ADAPTER_MASK 1
|
||||
#define KVM_S390_IO_ADAPTER_MAP 2
|
||||
#define KVM_S390_IO_ADAPTER_UNMAP 3
|
||||
|
@ -2152,6 +2152,45 @@ static int clear_io_irq(struct kvm *kvm, struct kvm_device_attr *attr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int modify_ais_mode(struct kvm *kvm, struct kvm_device_attr *attr)
|
||||
{
|
||||
struct kvm_s390_float_interrupt *fi = &kvm->arch.float_int;
|
||||
struct kvm_s390_ais_req req;
|
||||
int ret = 0;
|
||||
|
||||
if (!fi->ais_enabled)
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (copy_from_user(&req, (void __user *)attr->addr, sizeof(req)))
|
||||
return -EFAULT;
|
||||
|
||||
if (req.isc > MAX_ISC)
|
||||
return -EINVAL;
|
||||
|
||||
trace_kvm_s390_modify_ais_mode(req.isc,
|
||||
(fi->simm & AIS_MODE_MASK(req.isc)) ?
|
||||
(fi->nimm & AIS_MODE_MASK(req.isc)) ?
|
||||
2 : KVM_S390_AIS_MODE_SINGLE :
|
||||
KVM_S390_AIS_MODE_ALL, req.mode);
|
||||
|
||||
mutex_lock(&fi->ais_lock);
|
||||
switch (req.mode) {
|
||||
case KVM_S390_AIS_MODE_ALL:
|
||||
fi->simm &= ~AIS_MODE_MASK(req.isc);
|
||||
fi->nimm &= ~AIS_MODE_MASK(req.isc);
|
||||
break;
|
||||
case KVM_S390_AIS_MODE_SINGLE:
|
||||
fi->simm |= AIS_MODE_MASK(req.isc);
|
||||
fi->nimm &= ~AIS_MODE_MASK(req.isc);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
mutex_unlock(&fi->ais_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
|
||||
{
|
||||
int r = 0;
|
||||
@ -2188,6 +2227,9 @@ static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
|
||||
case KVM_DEV_FLIC_CLEAR_IO_IRQ:
|
||||
r = clear_io_irq(dev->kvm, attr);
|
||||
break;
|
||||
case KVM_DEV_FLIC_AISM:
|
||||
r = modify_ais_mode(dev->kvm, attr);
|
||||
break;
|
||||
default:
|
||||
r = -EINVAL;
|
||||
}
|
||||
@ -2207,6 +2249,7 @@ static int flic_has_attr(struct kvm_device *dev,
|
||||
case KVM_DEV_FLIC_ADAPTER_REGISTER:
|
||||
case KVM_DEV_FLIC_ADAPTER_MODIFY:
|
||||
case KVM_DEV_FLIC_CLEAR_IO_IRQ:
|
||||
case KVM_DEV_FLIC_AISM:
|
||||
return 0;
|
||||
}
|
||||
return -ENXIO;
|
||||
|
@ -1515,6 +1515,10 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
||||
|
||||
kvm_s390_crypto_init(kvm);
|
||||
|
||||
mutex_init(&kvm->arch.float_int.ais_lock);
|
||||
kvm->arch.float_int.simm = 0;
|
||||
kvm->arch.float_int.nimm = 0;
|
||||
kvm->arch.float_int.ais_enabled = 0;
|
||||
spin_lock_init(&kvm->arch.float_int.lock);
|
||||
for (i = 0; i < FIRQ_LIST_COUNT; i++)
|
||||
INIT_LIST_HEAD(&kvm->arch.float_int.lists[i]);
|
||||
|
@ -280,6 +280,37 @@ TRACE_EVENT(kvm_s390_enable_disable_ibs,
|
||||
__entry->state ? "enabling" : "disabling", __entry->id)
|
||||
);
|
||||
|
||||
/*
|
||||
* Trace point for modifying ais mode for a given isc.
|
||||
*/
|
||||
TRACE_EVENT(kvm_s390_modify_ais_mode,
|
||||
TP_PROTO(__u8 isc, __u16 from, __u16 to),
|
||||
TP_ARGS(isc, from, to),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(__u8, isc)
|
||||
__field(__u16, from)
|
||||
__field(__u16, to)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->isc = isc;
|
||||
__entry->from = from;
|
||||
__entry->to = to;
|
||||
),
|
||||
|
||||
TP_printk("for isc %x, modifying interruption mode from %s to %s",
|
||||
__entry->isc,
|
||||
(__entry->from == KVM_S390_AIS_MODE_ALL) ?
|
||||
"ALL-Interruptions Mode" :
|
||||
(__entry->from == KVM_S390_AIS_MODE_SINGLE) ?
|
||||
"Single-Interruption Mode" : "No-Interruptions Mode",
|
||||
(__entry->to == KVM_S390_AIS_MODE_ALL) ?
|
||||
"ALL-Interruptions Mode" :
|
||||
(__entry->to == KVM_S390_AIS_MODE_SINGLE) ?
|
||||
"Single-Interruption Mode" : "No-Interruptions Mode")
|
||||
);
|
||||
|
||||
|
||||
#endif /* _TRACE_KVMS390_H */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user