aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/interrupt.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kvm/interrupt.c')
-rw-r--r--arch/s390/kvm/interrupt.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 84efc2ba6a90..5a80af740d3e 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -977,6 +977,11 @@ no_timer:
977 977
978void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu) 978void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu)
979{ 979{
980 /*
981 * We cannot move this into the if, as the CPU might be already
982 * in kvm_vcpu_block without having the waitqueue set (polling)
983 */
984 vcpu->valid_wakeup = true;
980 if (swait_active(&vcpu->wq)) { 985 if (swait_active(&vcpu->wq)) {
981 /* 986 /*
982 * The vcpu gave up the cpu voluntarily, mark it as a good 987 * The vcpu gave up the cpu voluntarily, mark it as a good
@@ -2034,6 +2039,27 @@ static int modify_io_adapter(struct kvm_device *dev,
2034 return ret; 2039 return ret;
2035} 2040}
2036 2041
2042static int clear_io_irq(struct kvm *kvm, struct kvm_device_attr *attr)
2043
2044{
2045 const u64 isc_mask = 0xffUL << 24; /* all iscs set */
2046 u32 schid;
2047
2048 if (attr->flags)
2049 return -EINVAL;
2050 if (attr->attr != sizeof(schid))
2051 return -EINVAL;
2052 if (copy_from_user(&schid, (void __user *) attr->addr, sizeof(schid)))
2053 return -EFAULT;
2054 kfree(kvm_s390_get_io_int(kvm, isc_mask, schid));
2055 /*
2056 * If userspace is conforming to the architecture, we can have at most
2057 * one pending I/O interrupt per subchannel, so this is effectively a
2058 * clear all.
2059 */
2060 return 0;
2061}
2062
2037static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) 2063static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
2038{ 2064{
2039 int r = 0; 2065 int r = 0;
@@ -2067,6 +2093,9 @@ static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
2067 case KVM_DEV_FLIC_ADAPTER_MODIFY: 2093 case KVM_DEV_FLIC_ADAPTER_MODIFY:
2068 r = modify_io_adapter(dev, attr); 2094 r = modify_io_adapter(dev, attr);
2069 break; 2095 break;
2096 case KVM_DEV_FLIC_CLEAR_IO_IRQ:
2097 r = clear_io_irq(dev->kvm, attr);
2098 break;
2070 default: 2099 default:
2071 r = -EINVAL; 2100 r = -EINVAL;
2072 } 2101 }
@@ -2074,6 +2103,23 @@ static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
2074 return r; 2103 return r;
2075} 2104}
2076 2105
2106static int flic_has_attr(struct kvm_device *dev,
2107 struct kvm_device_attr *attr)
2108{
2109 switch (attr->group) {
2110 case KVM_DEV_FLIC_GET_ALL_IRQS:
2111 case KVM_DEV_FLIC_ENQUEUE:
2112 case KVM_DEV_FLIC_CLEAR_IRQS:
2113 case KVM_DEV_FLIC_APF_ENABLE:
2114 case KVM_DEV_FLIC_APF_DISABLE_WAIT:
2115 case KVM_DEV_FLIC_ADAPTER_REGISTER:
2116 case KVM_DEV_FLIC_ADAPTER_MODIFY:
2117 case KVM_DEV_FLIC_CLEAR_IO_IRQ:
2118 return 0;
2119 }
2120 return -ENXIO;
2121}
2122
2077static int flic_create(struct kvm_device *dev, u32 type) 2123static int flic_create(struct kvm_device *dev, u32 type)
2078{ 2124{
2079 if (!dev) 2125 if (!dev)
@@ -2095,6 +2141,7 @@ struct kvm_device_ops kvm_flic_ops = {
2095 .name = "kvm-flic", 2141 .name = "kvm-flic",
2096 .get_attr = flic_get_attr, 2142 .get_attr = flic_get_attr,
2097 .set_attr = flic_set_attr, 2143 .set_attr = flic_set_attr,
2144 .has_attr = flic_has_attr,
2098 .create = flic_create, 2145 .create = flic_create,
2099 .destroy = flic_destroy, 2146 .destroy = flic_destroy,
2100}; 2147};