0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/slab.h>
0012 #include <linux/vfio.h>
0013 #include "vfio_ccw_private.h"
0014
0015 static ssize_t vfio_ccw_schib_region_read(struct vfio_ccw_private *private,
0016 char __user *buf, size_t count,
0017 loff_t *ppos)
0018 {
0019 unsigned int i = VFIO_CCW_OFFSET_TO_INDEX(*ppos) - VFIO_CCW_NUM_REGIONS;
0020 loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK;
0021 struct ccw_schib_region *region;
0022 int ret;
0023
0024 if (pos + count > sizeof(*region))
0025 return -EINVAL;
0026
0027 mutex_lock(&private->io_mutex);
0028 region = private->region[i].data;
0029
0030 if (cio_update_schib(private->sch)) {
0031 ret = -ENODEV;
0032 goto out;
0033 }
0034
0035 memcpy(region, &private->sch->schib, sizeof(*region));
0036
0037 if (copy_to_user(buf, (void *)region + pos, count)) {
0038 ret = -EFAULT;
0039 goto out;
0040 }
0041
0042 ret = count;
0043
0044 out:
0045 mutex_unlock(&private->io_mutex);
0046 return ret;
0047 }
0048
0049 static ssize_t vfio_ccw_schib_region_write(struct vfio_ccw_private *private,
0050 const char __user *buf, size_t count,
0051 loff_t *ppos)
0052 {
0053 return -EINVAL;
0054 }
0055
0056
0057 static void vfio_ccw_schib_region_release(struct vfio_ccw_private *private,
0058 struct vfio_ccw_region *region)
0059 {
0060
0061 }
0062
0063 static const struct vfio_ccw_regops vfio_ccw_schib_region_ops = {
0064 .read = vfio_ccw_schib_region_read,
0065 .write = vfio_ccw_schib_region_write,
0066 .release = vfio_ccw_schib_region_release,
0067 };
0068
0069 int vfio_ccw_register_schib_dev_regions(struct vfio_ccw_private *private)
0070 {
0071 return vfio_ccw_register_dev_region(private,
0072 VFIO_REGION_SUBTYPE_CCW_SCHIB,
0073 &vfio_ccw_schib_region_ops,
0074 sizeof(struct ccw_schib_region),
0075 VFIO_REGION_INFO_FLAG_READ,
0076 private->schib_region);
0077 }
0078
0079 static ssize_t vfio_ccw_crw_region_read(struct vfio_ccw_private *private,
0080 char __user *buf, size_t count,
0081 loff_t *ppos)
0082 {
0083 unsigned int i = VFIO_CCW_OFFSET_TO_INDEX(*ppos) - VFIO_CCW_NUM_REGIONS;
0084 loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK;
0085 struct ccw_crw_region *region;
0086 struct vfio_ccw_crw *crw;
0087 int ret;
0088
0089 if (pos + count > sizeof(*region))
0090 return -EINVAL;
0091
0092 crw = list_first_entry_or_null(&private->crw,
0093 struct vfio_ccw_crw, next);
0094
0095 if (crw)
0096 list_del(&crw->next);
0097
0098 mutex_lock(&private->io_mutex);
0099 region = private->region[i].data;
0100
0101 if (crw)
0102 memcpy(®ion->crw, &crw->crw, sizeof(region->crw));
0103
0104 if (copy_to_user(buf, (void *)region + pos, count))
0105 ret = -EFAULT;
0106 else
0107 ret = count;
0108
0109 region->crw = 0;
0110
0111 mutex_unlock(&private->io_mutex);
0112
0113 kfree(crw);
0114
0115
0116 if (!list_empty(&private->crw) && private->crw_trigger)
0117 eventfd_signal(private->crw_trigger, 1);
0118
0119 return ret;
0120 }
0121
0122 static ssize_t vfio_ccw_crw_region_write(struct vfio_ccw_private *private,
0123 const char __user *buf, size_t count,
0124 loff_t *ppos)
0125 {
0126 return -EINVAL;
0127 }
0128
0129 static void vfio_ccw_crw_region_release(struct vfio_ccw_private *private,
0130 struct vfio_ccw_region *region)
0131 {
0132
0133 }
0134
0135 static const struct vfio_ccw_regops vfio_ccw_crw_region_ops = {
0136 .read = vfio_ccw_crw_region_read,
0137 .write = vfio_ccw_crw_region_write,
0138 .release = vfio_ccw_crw_region_release,
0139 };
0140
0141 int vfio_ccw_register_crw_dev_regions(struct vfio_ccw_private *private)
0142 {
0143 return vfio_ccw_register_dev_region(private,
0144 VFIO_REGION_SUBTYPE_CCW_CRW,
0145 &vfio_ccw_crw_region_ops,
0146 sizeof(struct ccw_crw_region),
0147 VFIO_REGION_INFO_FLAG_READ,
0148 private->crw_region);
0149 }