Commit a8920950 authored by Yi Min Zhao's avatar Yi Min Zhao Committed by Christian Borntraeger

KVM: s390: introduce adapter interrupt inject function

Inject adapter interrupts on a specified adapter which allows to
retrieve the adapter flags, e.g. if the adapter is subject to AIS
facility or not. And add documentation for this interface.

For adapters subject to AIS, handle the airq injection suppression
for a given ISC according to the interruption mode:
- before injection, if NO-Interruptions Mode, just return 0 and
  suppress, otherwise, allow the injection.
- after injection, if SINGLE-Interruption Mode, change it to
  NO-Interruptions Mode to suppress the following interrupts.

Besides, add tracepoint for suppressed airq and AIS mode transitions.
Signed-off-by: default avatarYi Min Zhao <zyimin@linux.vnet.ibm.com>
Signed-off-by: default avatarFei Li <sherrylf@linux.vnet.ibm.com>
Reviewed-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
parent 51978393
...@@ -15,6 +15,7 @@ FLIC provides support to ...@@ -15,6 +15,7 @@ FLIC provides support to
- 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) - modify AIS (adapter-interruption-suppression) mode state (KVM_DEV_FLIC_AISM)
- inject adapter interrupts on a specified adapter (KVM_DEV_FLIC_AIRQ_INJECT)
Groups: Groups:
KVM_DEV_FLIC_ENQUEUE KVM_DEV_FLIC_ENQUEUE
...@@ -127,6 +128,14 @@ struct kvm_s390_ais_req { ...@@ -127,6 +128,14 @@ struct kvm_s390_ais_req {
will be suppressed until the mode is set again to ALL-Interruptions will be suppressed until the mode is set again to ALL-Interruptions
or SINGLE-Interruption mode. or SINGLE-Interruption mode.
KVM_DEV_FLIC_AIRQ_INJECT
Inject adapter interrupts on a specified adapter.
attr->attr contains the unique id for the adapter, which allows for
adapter-specific checks and actions.
For adapters subject to AIS, handle the airq injection suppression for
an isc according to the adapter-interruption-suppression mode on condition
that the AIS capability is enabled.
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
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#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 #define KVM_DEV_FLIC_AISM 9
#define KVM_DEV_FLIC_AIRQ_INJECT 10
/* /*
* 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.
......
...@@ -2191,6 +2191,48 @@ static int modify_ais_mode(struct kvm *kvm, struct kvm_device_attr *attr) ...@@ -2191,6 +2191,48 @@ static int modify_ais_mode(struct kvm *kvm, struct kvm_device_attr *attr)
return ret; return ret;
} }
static int kvm_s390_inject_airq(struct kvm *kvm,
struct s390_io_adapter *adapter)
{
struct kvm_s390_float_interrupt *fi = &kvm->arch.float_int;
struct kvm_s390_interrupt s390int = {
.type = KVM_S390_INT_IO(1, 0, 0, 0),
.parm = 0,
.parm64 = (adapter->isc << 27) | 0x80000000,
};
int ret = 0;
if (!fi->ais_enabled || !adapter->suppressible)
return kvm_s390_inject_vm(kvm, &s390int);
mutex_lock(&fi->ais_lock);
if (fi->nimm & AIS_MODE_MASK(adapter->isc)) {
trace_kvm_s390_airq_suppressed(adapter->id, adapter->isc);
goto out;
}
ret = kvm_s390_inject_vm(kvm, &s390int);
if (!ret && (fi->simm & AIS_MODE_MASK(adapter->isc))) {
fi->nimm |= AIS_MODE_MASK(adapter->isc);
trace_kvm_s390_modify_ais_mode(adapter->isc,
KVM_S390_AIS_MODE_SINGLE, 2);
}
out:
mutex_unlock(&fi->ais_lock);
return ret;
}
static int flic_inject_airq(struct kvm *kvm, struct kvm_device_attr *attr)
{
unsigned int id = attr->attr;
struct s390_io_adapter *adapter = get_io_adapter(kvm, id);
if (!adapter)
return -EINVAL;
return kvm_s390_inject_airq(kvm, adapter);
}
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;
...@@ -2230,6 +2272,9 @@ static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) ...@@ -2230,6 +2272,9 @@ static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
case KVM_DEV_FLIC_AISM: case KVM_DEV_FLIC_AISM:
r = modify_ais_mode(dev->kvm, attr); r = modify_ais_mode(dev->kvm, attr);
break; break;
case KVM_DEV_FLIC_AIRQ_INJECT:
r = flic_inject_airq(dev->kvm, attr);
break;
default: default:
r = -EINVAL; r = -EINVAL;
} }
...@@ -2250,6 +2295,7 @@ static int flic_has_attr(struct kvm_device *dev, ...@@ -2250,6 +2295,7 @@ static int flic_has_attr(struct kvm_device *dev,
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: case KVM_DEV_FLIC_AISM:
case KVM_DEV_FLIC_AIRQ_INJECT:
return 0; return 0;
} }
return -ENXIO; return -ENXIO;
...@@ -2360,12 +2406,7 @@ static int set_adapter_int(struct kvm_kernel_irq_routing_entry *e, ...@@ -2360,12 +2406,7 @@ static int set_adapter_int(struct kvm_kernel_irq_routing_entry *e,
ret = adapter_indicators_set(kvm, adapter, &e->adapter); ret = adapter_indicators_set(kvm, adapter, &e->adapter);
up_read(&adapter->maps_lock); up_read(&adapter->maps_lock);
if ((ret > 0) && !adapter->masked) { if ((ret > 0) && !adapter->masked) {
struct kvm_s390_interrupt s390int = { ret = kvm_s390_inject_airq(kvm, adapter);
.type = KVM_S390_INT_IO(1, 0, 0, 0),
.parm = 0,
.parm64 = (adapter->isc << 27) | 0x80000000,
};
ret = kvm_s390_inject_vm(kvm, &s390int);
if (ret == 0) if (ret == 0)
ret = 1; ret = 1;
} }
......
...@@ -311,6 +311,27 @@ TRACE_EVENT(kvm_s390_modify_ais_mode, ...@@ -311,6 +311,27 @@ TRACE_EVENT(kvm_s390_modify_ais_mode,
"Single-Interruption Mode" : "No-Interruptions Mode") "Single-Interruption Mode" : "No-Interruptions Mode")
); );
/*
* Trace point for suppressed adapter I/O interrupt.
*/
TRACE_EVENT(kvm_s390_airq_suppressed,
TP_PROTO(__u32 id, __u8 isc),
TP_ARGS(id, isc),
TP_STRUCT__entry(
__field(__u32, id)
__field(__u8, isc)
),
TP_fast_assign(
__entry->id = id;
__entry->isc = isc;
),
TP_printk("adapter I/O interrupt suppressed (id:%x isc:%x)",
__entry->id, __entry->isc)
);
#endif /* _TRACE_KVMS390_H */ #endif /* _TRACE_KVMS390_H */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment