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)
|
- purge one pending floating I/O interrupt (KVM_DEV_FLIC_CLEAR_IO_IRQ)
|
||||||
- enable/disable for the guest transparent async page faults
|
- enable/disable for the guest transparent async page faults
|
||||||
- register and modify adapter interrupt sources (KVM_DEV_FLIC_ADAPTER_*)
|
- register and modify adapter interrupt sources (KVM_DEV_FLIC_ADAPTER_*)
|
||||||
|
- modify AIS (adapter-interruption-suppression) mode state (KVM_DEV_FLIC_AISM)
|
||||||
|
|
||||||
Groups:
|
Groups:
|
||||||
KVM_DEV_FLIC_ENQUEUE
|
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
|
release a userspace page for the translated address specified in addr
|
||||||
from the list of mappings
|
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
|
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
|
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
|
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_CNTR_PFAULT 3
|
||||||
#define FIRQ_MAX_COUNT 4
|
#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 {
|
struct kvm_s390_float_interrupt {
|
||||||
unsigned long pending_irqs;
|
unsigned long pending_irqs;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
@ -530,6 +536,10 @@ struct kvm_s390_float_interrupt {
|
|||||||
struct kvm_s390_ext_info srv_signal;
|
struct kvm_s390_ext_info srv_signal;
|
||||||
int next_rr_cpu;
|
int next_rr_cpu;
|
||||||
unsigned long idle_mask[BITS_TO_LONGS(KVM_MAX_VCPUS)];
|
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 {
|
struct kvm_hw_wp_info_arch {
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#define KVM_DEV_FLIC_ADAPTER_REGISTER 6
|
#define KVM_DEV_FLIC_ADAPTER_REGISTER 6
|
||||||
#define KVM_DEV_FLIC_ADAPTER_MODIFY 7
|
#define KVM_DEV_FLIC_ADAPTER_MODIFY 7
|
||||||
#define KVM_DEV_FLIC_CLEAR_IO_IRQ 8
|
#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,
|
* 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.
|
* 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
|
#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_MASK 1
|
||||||
#define KVM_S390_IO_ADAPTER_MAP 2
|
#define KVM_S390_IO_ADAPTER_MAP 2
|
||||||
#define KVM_S390_IO_ADAPTER_UNMAP 3
|
#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;
|
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)
|
static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
|
||||||
{
|
{
|
||||||
int r = 0;
|
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:
|
case KVM_DEV_FLIC_CLEAR_IO_IRQ:
|
||||||
r = clear_io_irq(dev->kvm, attr);
|
r = clear_io_irq(dev->kvm, attr);
|
||||||
break;
|
break;
|
||||||
|
case KVM_DEV_FLIC_AISM:
|
||||||
|
r = modify_ais_mode(dev->kvm, attr);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
r = -EINVAL;
|
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_REGISTER:
|
||||||
case KVM_DEV_FLIC_ADAPTER_MODIFY:
|
case KVM_DEV_FLIC_ADAPTER_MODIFY:
|
||||||
case KVM_DEV_FLIC_CLEAR_IO_IRQ:
|
case KVM_DEV_FLIC_CLEAR_IO_IRQ:
|
||||||
|
case KVM_DEV_FLIC_AISM:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
@ -1515,6 +1515,10 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
|||||||
|
|
||||||
kvm_s390_crypto_init(kvm);
|
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);
|
spin_lock_init(&kvm->arch.float_int.lock);
|
||||||
for (i = 0; i < FIRQ_LIST_COUNT; i++)
|
for (i = 0; i < FIRQ_LIST_COUNT; i++)
|
||||||
INIT_LIST_HEAD(&kvm->arch.float_int.lists[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)
|
__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 */
|
#endif /* _TRACE_KVMS390_H */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user