From: Eric Farman <farman@linux.ibm.com> To: Cornelia Huck <cohuck@redhat.com>, Halil Pasic <pasic@linux.ibm.com>, Farhan Ali <alifm@linux.ibm.com>, Pierre Morel <pmorel@linux.ibm.com> Cc: linux-s390@vger.kernel.org, kvm@vger.kernel.org, qemu-devel@nongnu.org, qemu-s390x@nongnu.org, Alex Williamson <alex.williamson@redhat.com> Subject: Re: [Qemu-devel] [PATCH v4 4/6] vfio-ccw: add capabilities chain Date: Mon, 15 Apr 2019 10:40:59 -0400 [thread overview] Message-ID: <9d692710-cf9e-99c6-45d1-bb18a2ba7b94@linux.ibm.com> (raw) In-Reply-To: <20190301093902.27799-5-cohuck@redhat.com> On 3/1/19 4:39 AM, Cornelia Huck wrote: > Allow to extend the regions used by vfio-ccw. The first user will be > handling of halt and clear subchannel. > > Signed-off-by: Cornelia Huck <cohuck@redhat.com> Reviewed-by: Eric Farman <farman@linux.ibm.com> > --- > drivers/s390/cio/vfio_ccw_ops.c | 186 ++++++++++++++++++++++++---- > drivers/s390/cio/vfio_ccw_private.h | 38 ++++++ > include/uapi/linux/vfio.h | 2 + > 3 files changed, 200 insertions(+), 26 deletions(-) > > diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c > index 025c8a832bc8..3fd663320bbf 100644 > --- a/drivers/s390/cio/vfio_ccw_ops.c > +++ b/drivers/s390/cio/vfio_ccw_ops.c > @@ -3,13 +3,16 @@ > * Physical device callbacks for vfio_ccw > * > * Copyright IBM Corp. 2017 > + * Copyright Red Hat, Inc. 2019 > * > * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> > * Xiao Feng Ren <renxiaof@linux.vnet.ibm.com> > + * Cornelia Huck <cohuck@redhat.com> > */ > > #include <linux/vfio.h> > #include <linux/mdev.h> > +#include <linux/nospec.h> > > #include "vfio_ccw_private.h" > > @@ -157,27 +160,33 @@ static void vfio_ccw_mdev_release(struct mdev_device *mdev) > { > struct vfio_ccw_private *private = > dev_get_drvdata(mdev_parent_dev(mdev)); > + int i; > > vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY, > &private->nb); > + > + for (i = 0; i < private->num_regions; i++) > + private->region[i].ops->release(private, &private->region[i]); > + > + private->num_regions = 0; > + kfree(private->region); > + private->region = NULL; > } > > -static ssize_t vfio_ccw_mdev_read(struct mdev_device *mdev, > - char __user *buf, > - size_t count, > - loff_t *ppos) > +static ssize_t vfio_ccw_mdev_read_io_region(struct vfio_ccw_private *private, > + char __user *buf, size_t count, > + loff_t *ppos) > { > - struct vfio_ccw_private *private; > + loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK; > struct ccw_io_region *region; > int ret; > > - if (*ppos + count > sizeof(*region)) > + if (pos + count > sizeof(*region)) > return -EINVAL; > > - private = dev_get_drvdata(mdev_parent_dev(mdev)); > mutex_lock(&private->io_mutex); > region = private->io_region; > - if (copy_to_user(buf, (void *)region + *ppos, count)) > + if (copy_to_user(buf, (void *)region + pos, count)) > ret = -EFAULT; > else > ret = count; > @@ -185,24 +194,47 @@ static ssize_t vfio_ccw_mdev_read(struct mdev_device *mdev, > return ret; > } > > -static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev, > - const char __user *buf, > - size_t count, > - loff_t *ppos) > +static ssize_t vfio_ccw_mdev_read(struct mdev_device *mdev, > + char __user *buf, > + size_t count, > + loff_t *ppos) > { > + unsigned int index = VFIO_CCW_OFFSET_TO_INDEX(*ppos); > struct vfio_ccw_private *private; > + > + private = dev_get_drvdata(mdev_parent_dev(mdev)); > + > + if (index >= VFIO_CCW_NUM_REGIONS + private->num_regions) > + return -EINVAL; > + > + switch (index) { > + case VFIO_CCW_CONFIG_REGION_INDEX: > + return vfio_ccw_mdev_read_io_region(private, buf, count, ppos); > + default: > + index -= VFIO_CCW_NUM_REGIONS; > + return private->region[index].ops->read(private, buf, count, > + ppos); > + } > + > + return -EINVAL; > +} > + > +static ssize_t vfio_ccw_mdev_write_io_region(struct vfio_ccw_private *private, > + const char __user *buf, > + size_t count, loff_t *ppos) > +{ > + loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK; > struct ccw_io_region *region; > int ret; > > - if (*ppos + count > sizeof(*region)) > + if (pos + count > sizeof(*region)) > return -EINVAL; > > - private = dev_get_drvdata(mdev_parent_dev(mdev)); > if (!mutex_trylock(&private->io_mutex)) > return -EAGAIN; > > region = private->io_region; > - if (copy_from_user((void *)region + *ppos, buf, count)) { > + if (copy_from_user((void *)region + pos, buf, count)) { > ret = -EFAULT; > goto out_unlock; > } > @@ -217,19 +249,52 @@ static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev, > return ret; > } > > -static int vfio_ccw_mdev_get_device_info(struct vfio_device_info *info) > +static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev, > + const char __user *buf, > + size_t count, > + loff_t *ppos) > { > + unsigned int index = VFIO_CCW_OFFSET_TO_INDEX(*ppos); > + struct vfio_ccw_private *private; > + > + private = dev_get_drvdata(mdev_parent_dev(mdev)); > + > + if (index >= VFIO_CCW_NUM_REGIONS + private->num_regions) > + return -EINVAL; > + > + switch (index) { > + case VFIO_CCW_CONFIG_REGION_INDEX: > + return vfio_ccw_mdev_write_io_region(private, buf, count, ppos); > + default: > + index -= VFIO_CCW_NUM_REGIONS; > + return private->region[index].ops->write(private, buf, count, > + ppos); > + } > + > + return -EINVAL; > +} > + > +static int vfio_ccw_mdev_get_device_info(struct vfio_device_info *info, > + struct mdev_device *mdev) > +{ > + struct vfio_ccw_private *private; > + > + private = dev_get_drvdata(mdev_parent_dev(mdev)); > info->flags = VFIO_DEVICE_FLAGS_CCW | VFIO_DEVICE_FLAGS_RESET; > - info->num_regions = VFIO_CCW_NUM_REGIONS; > + info->num_regions = VFIO_CCW_NUM_REGIONS + private->num_regions; > info->num_irqs = VFIO_CCW_NUM_IRQS; > > return 0; > } > > static int vfio_ccw_mdev_get_region_info(struct vfio_region_info *info, > - u16 *cap_type_id, > - void **cap_type) > + struct mdev_device *mdev, > + unsigned long arg) > { > + struct vfio_ccw_private *private; > + int i; > + > + private = dev_get_drvdata(mdev_parent_dev(mdev)); > switch (info->index) { > case VFIO_CCW_CONFIG_REGION_INDEX: > info->offset = 0; > @@ -237,9 +302,55 @@ static int vfio_ccw_mdev_get_region_info(struct vfio_region_info *info, > info->flags = VFIO_REGION_INFO_FLAG_READ > | VFIO_REGION_INFO_FLAG_WRITE; > return 0; > - default: > - return -EINVAL; > + default: /* all other regions are handled via capability chain */ > + { > + struct vfio_info_cap caps = { .buf = NULL, .size = 0 }; > + struct vfio_region_info_cap_type cap_type = { > + .header.id = VFIO_REGION_INFO_CAP_TYPE, > + .header.version = 1 }; > + int ret; > + > + if (info->index >= > + VFIO_CCW_NUM_REGIONS + private->num_regions) > + return -EINVAL; > + > + info->index = array_index_nospec(info->index, > + VFIO_CCW_NUM_REGIONS + > + private->num_regions); > + > + i = info->index - VFIO_CCW_NUM_REGIONS; > + > + info->offset = VFIO_CCW_INDEX_TO_OFFSET(info->index); > + info->size = private->region[i].size; > + info->flags = private->region[i].flags; > + > + cap_type.type = private->region[i].type; > + cap_type.subtype = private->region[i].subtype; > + > + ret = vfio_info_add_capability(&caps, &cap_type.header, > + sizeof(cap_type)); > + if (ret) > + return ret; > + > + info->flags |= VFIO_REGION_INFO_FLAG_CAPS; > + if (info->argsz < sizeof(*info) + caps.size) { > + info->argsz = sizeof(*info) + caps.size; > + info->cap_offset = 0; > + } else { > + vfio_info_cap_shift(&caps, sizeof(*info)); > + if (copy_to_user((void __user *)arg + sizeof(*info), > + caps.buf, caps.size)) { > + kfree(caps.buf); > + return -EFAULT; > + } > + info->cap_offset = sizeof(*info); > + } > + > + kfree(caps.buf); > + > + } > } > + return 0; > } > > static int vfio_ccw_mdev_get_irq_info(struct vfio_irq_info *info) > @@ -316,6 +427,32 @@ static int vfio_ccw_mdev_set_irqs(struct mdev_device *mdev, > } > } > > +int vfio_ccw_register_dev_region(struct vfio_ccw_private *private, > + unsigned int subtype, > + const struct vfio_ccw_regops *ops, > + size_t size, u32 flags, void *data) > +{ > + struct vfio_ccw_region *region; > + > + region = krealloc(private->region, > + (private->num_regions + 1) * sizeof(*region), > + GFP_KERNEL); > + if (!region) > + return -ENOMEM; > + > + private->region = region; > + private->region[private->num_regions].type = VFIO_REGION_TYPE_CCW; > + private->region[private->num_regions].subtype = subtype; > + private->region[private->num_regions].ops = ops; > + private->region[private->num_regions].size = size; > + private->region[private->num_regions].flags = flags; > + private->region[private->num_regions].data = data; > + > + private->num_regions++; > + > + return 0; > +} > + > static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, > unsigned int cmd, > unsigned long arg) > @@ -336,7 +473,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, > if (info.argsz < minsz) > return -EINVAL; > > - ret = vfio_ccw_mdev_get_device_info(&info); > + ret = vfio_ccw_mdev_get_device_info(&info, mdev); > if (ret) > return ret; > > @@ -345,8 +482,6 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, > case VFIO_DEVICE_GET_REGION_INFO: > { > struct vfio_region_info info; > - u16 cap_type_id = 0; > - void *cap_type = NULL; > > minsz = offsetofend(struct vfio_region_info, offset); > > @@ -356,8 +491,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, > if (info.argsz < minsz) > return -EINVAL; > > - ret = vfio_ccw_mdev_get_region_info(&info, &cap_type_id, > - &cap_type); > + ret = vfio_ccw_mdev_get_region_info(&info, mdev, arg); > if (ret) > return ret; > > diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h > index 32173cbd838d..d888a2573470 100644 > --- a/drivers/s390/cio/vfio_ccw_private.h > +++ b/drivers/s390/cio/vfio_ccw_private.h > @@ -3,9 +3,11 @@ > * Private stuff for vfio_ccw driver > * > * Copyright IBM Corp. 2017 > + * Copyright Red Hat, Inc. 2019 > * > * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> > * Xiao Feng Ren <renxiaof@linux.vnet.ibm.com> > + * Cornelia Huck <cohuck@redhat.com> > */ > > #ifndef _VFIO_CCW_PRIVATE_H_ > @@ -19,6 +21,38 @@ > #include "css.h" > #include "vfio_ccw_cp.h" > > +#define VFIO_CCW_OFFSET_SHIFT 10 > +#define VFIO_CCW_OFFSET_TO_INDEX(off) (off >> VFIO_CCW_OFFSET_SHIFT) > +#define VFIO_CCW_INDEX_TO_OFFSET(index) ((u64)(index) << VFIO_CCW_OFFSET_SHIFT) > +#define VFIO_CCW_OFFSET_MASK (((u64)(1) << VFIO_CCW_OFFSET_SHIFT) - 1) > + > +/* capability chain handling similar to vfio-pci */ > +struct vfio_ccw_private; > +struct vfio_ccw_region; > + > +struct vfio_ccw_regops { > + ssize_t (*read)(struct vfio_ccw_private *private, char __user *buf, > + size_t count, loff_t *ppos); > + ssize_t (*write)(struct vfio_ccw_private *private, > + const char __user *buf, size_t count, loff_t *ppos); > + void (*release)(struct vfio_ccw_private *private, > + struct vfio_ccw_region *region); > +}; > + > +struct vfio_ccw_region { > + u32 type; > + u32 subtype; > + const struct vfio_ccw_regops *ops; > + void *data; > + size_t size; > + u32 flags; > +}; > + > +int vfio_ccw_register_dev_region(struct vfio_ccw_private *private, > + unsigned int subtype, > + const struct vfio_ccw_regops *ops, > + size_t size, u32 flags, void *data); > + > /** > * struct vfio_ccw_private > * @sch: pointer to the subchannel > @@ -29,6 +63,8 @@ > * @nb: notifier for vfio events > * @io_region: MMIO region to input/output I/O arguments/results > * @io_mutex: protect against concurrent update of I/O regions > + * @region: additional regions for other subchannel operations > + * @num_regions: number of additional regions > * @cp: channel program for the current I/O operation > * @irb: irb info received from interrupt > * @scsw: scsw info > @@ -44,6 +80,8 @@ struct vfio_ccw_private { > struct notifier_block nb; > struct ccw_io_region *io_region; > struct mutex io_mutex; > + struct vfio_ccw_region *region; > + int num_regions; > > struct channel_program cp; > struct irb irb; > diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h > index 02bb7ad6e986..56e2413d3e00 100644 > --- a/include/uapi/linux/vfio.h > +++ b/include/uapi/linux/vfio.h > @@ -353,6 +353,8 @@ struct vfio_region_gfx_edid { > #define VFIO_DEVICE_GFX_LINK_STATE_DOWN 2 > }; > > +#define VFIO_REGION_TYPE_CCW (2) > + > /* > * 10de vendor sub-type > * >
WARNING: multiple messages have this Message-ID (diff)
From: Eric Farman <farman@linux.ibm.com> To: Cornelia Huck <cohuck@redhat.com>, Halil Pasic <pasic@linux.ibm.com>, Farhan Ali <alifm@linux.ibm.com>, Pierre Morel <pmorel@linux.ibm.com> Cc: linux-s390@vger.kernel.org, qemu-s390x@nongnu.org, Alex Williamson <alex.williamson@redhat.com>, qemu-devel@nongnu.org, kvm@vger.kernel.org Subject: Re: [Qemu-devel] [PATCH v4 4/6] vfio-ccw: add capabilities chain Date: Mon, 15 Apr 2019 10:40:59 -0400 [thread overview] Message-ID: <9d692710-cf9e-99c6-45d1-bb18a2ba7b94@linux.ibm.com> (raw) Message-ID: <20190415144059.Y2KFFQ-jJ0PX26MLds3RsK_duVxTdMkkTHWviKPCqW8@z> (raw) In-Reply-To: <20190301093902.27799-5-cohuck@redhat.com> On 3/1/19 4:39 AM, Cornelia Huck wrote: > Allow to extend the regions used by vfio-ccw. The first user will be > handling of halt and clear subchannel. > > Signed-off-by: Cornelia Huck <cohuck@redhat.com> Reviewed-by: Eric Farman <farman@linux.ibm.com> > --- > drivers/s390/cio/vfio_ccw_ops.c | 186 ++++++++++++++++++++++++---- > drivers/s390/cio/vfio_ccw_private.h | 38 ++++++ > include/uapi/linux/vfio.h | 2 + > 3 files changed, 200 insertions(+), 26 deletions(-) > > diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c > index 025c8a832bc8..3fd663320bbf 100644 > --- a/drivers/s390/cio/vfio_ccw_ops.c > +++ b/drivers/s390/cio/vfio_ccw_ops.c > @@ -3,13 +3,16 @@ > * Physical device callbacks for vfio_ccw > * > * Copyright IBM Corp. 2017 > + * Copyright Red Hat, Inc. 2019 > * > * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> > * Xiao Feng Ren <renxiaof@linux.vnet.ibm.com> > + * Cornelia Huck <cohuck@redhat.com> > */ > > #include <linux/vfio.h> > #include <linux/mdev.h> > +#include <linux/nospec.h> > > #include "vfio_ccw_private.h" > > @@ -157,27 +160,33 @@ static void vfio_ccw_mdev_release(struct mdev_device *mdev) > { > struct vfio_ccw_private *private = > dev_get_drvdata(mdev_parent_dev(mdev)); > + int i; > > vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY, > &private->nb); > + > + for (i = 0; i < private->num_regions; i++) > + private->region[i].ops->release(private, &private->region[i]); > + > + private->num_regions = 0; > + kfree(private->region); > + private->region = NULL; > } > > -static ssize_t vfio_ccw_mdev_read(struct mdev_device *mdev, > - char __user *buf, > - size_t count, > - loff_t *ppos) > +static ssize_t vfio_ccw_mdev_read_io_region(struct vfio_ccw_private *private, > + char __user *buf, size_t count, > + loff_t *ppos) > { > - struct vfio_ccw_private *private; > + loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK; > struct ccw_io_region *region; > int ret; > > - if (*ppos + count > sizeof(*region)) > + if (pos + count > sizeof(*region)) > return -EINVAL; > > - private = dev_get_drvdata(mdev_parent_dev(mdev)); > mutex_lock(&private->io_mutex); > region = private->io_region; > - if (copy_to_user(buf, (void *)region + *ppos, count)) > + if (copy_to_user(buf, (void *)region + pos, count)) > ret = -EFAULT; > else > ret = count; > @@ -185,24 +194,47 @@ static ssize_t vfio_ccw_mdev_read(struct mdev_device *mdev, > return ret; > } > > -static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev, > - const char __user *buf, > - size_t count, > - loff_t *ppos) > +static ssize_t vfio_ccw_mdev_read(struct mdev_device *mdev, > + char __user *buf, > + size_t count, > + loff_t *ppos) > { > + unsigned int index = VFIO_CCW_OFFSET_TO_INDEX(*ppos); > struct vfio_ccw_private *private; > + > + private = dev_get_drvdata(mdev_parent_dev(mdev)); > + > + if (index >= VFIO_CCW_NUM_REGIONS + private->num_regions) > + return -EINVAL; > + > + switch (index) { > + case VFIO_CCW_CONFIG_REGION_INDEX: > + return vfio_ccw_mdev_read_io_region(private, buf, count, ppos); > + default: > + index -= VFIO_CCW_NUM_REGIONS; > + return private->region[index].ops->read(private, buf, count, > + ppos); > + } > + > + return -EINVAL; > +} > + > +static ssize_t vfio_ccw_mdev_write_io_region(struct vfio_ccw_private *private, > + const char __user *buf, > + size_t count, loff_t *ppos) > +{ > + loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK; > struct ccw_io_region *region; > int ret; > > - if (*ppos + count > sizeof(*region)) > + if (pos + count > sizeof(*region)) > return -EINVAL; > > - private = dev_get_drvdata(mdev_parent_dev(mdev)); > if (!mutex_trylock(&private->io_mutex)) > return -EAGAIN; > > region = private->io_region; > - if (copy_from_user((void *)region + *ppos, buf, count)) { > + if (copy_from_user((void *)region + pos, buf, count)) { > ret = -EFAULT; > goto out_unlock; > } > @@ -217,19 +249,52 @@ static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev, > return ret; > } > > -static int vfio_ccw_mdev_get_device_info(struct vfio_device_info *info) > +static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev, > + const char __user *buf, > + size_t count, > + loff_t *ppos) > { > + unsigned int index = VFIO_CCW_OFFSET_TO_INDEX(*ppos); > + struct vfio_ccw_private *private; > + > + private = dev_get_drvdata(mdev_parent_dev(mdev)); > + > + if (index >= VFIO_CCW_NUM_REGIONS + private->num_regions) > + return -EINVAL; > + > + switch (index) { > + case VFIO_CCW_CONFIG_REGION_INDEX: > + return vfio_ccw_mdev_write_io_region(private, buf, count, ppos); > + default: > + index -= VFIO_CCW_NUM_REGIONS; > + return private->region[index].ops->write(private, buf, count, > + ppos); > + } > + > + return -EINVAL; > +} > + > +static int vfio_ccw_mdev_get_device_info(struct vfio_device_info *info, > + struct mdev_device *mdev) > +{ > + struct vfio_ccw_private *private; > + > + private = dev_get_drvdata(mdev_parent_dev(mdev)); > info->flags = VFIO_DEVICE_FLAGS_CCW | VFIO_DEVICE_FLAGS_RESET; > - info->num_regions = VFIO_CCW_NUM_REGIONS; > + info->num_regions = VFIO_CCW_NUM_REGIONS + private->num_regions; > info->num_irqs = VFIO_CCW_NUM_IRQS; > > return 0; > } > > static int vfio_ccw_mdev_get_region_info(struct vfio_region_info *info, > - u16 *cap_type_id, > - void **cap_type) > + struct mdev_device *mdev, > + unsigned long arg) > { > + struct vfio_ccw_private *private; > + int i; > + > + private = dev_get_drvdata(mdev_parent_dev(mdev)); > switch (info->index) { > case VFIO_CCW_CONFIG_REGION_INDEX: > info->offset = 0; > @@ -237,9 +302,55 @@ static int vfio_ccw_mdev_get_region_info(struct vfio_region_info *info, > info->flags = VFIO_REGION_INFO_FLAG_READ > | VFIO_REGION_INFO_FLAG_WRITE; > return 0; > - default: > - return -EINVAL; > + default: /* all other regions are handled via capability chain */ > + { > + struct vfio_info_cap caps = { .buf = NULL, .size = 0 }; > + struct vfio_region_info_cap_type cap_type = { > + .header.id = VFIO_REGION_INFO_CAP_TYPE, > + .header.version = 1 }; > + int ret; > + > + if (info->index >= > + VFIO_CCW_NUM_REGIONS + private->num_regions) > + return -EINVAL; > + > + info->index = array_index_nospec(info->index, > + VFIO_CCW_NUM_REGIONS + > + private->num_regions); > + > + i = info->index - VFIO_CCW_NUM_REGIONS; > + > + info->offset = VFIO_CCW_INDEX_TO_OFFSET(info->index); > + info->size = private->region[i].size; > + info->flags = private->region[i].flags; > + > + cap_type.type = private->region[i].type; > + cap_type.subtype = private->region[i].subtype; > + > + ret = vfio_info_add_capability(&caps, &cap_type.header, > + sizeof(cap_type)); > + if (ret) > + return ret; > + > + info->flags |= VFIO_REGION_INFO_FLAG_CAPS; > + if (info->argsz < sizeof(*info) + caps.size) { > + info->argsz = sizeof(*info) + caps.size; > + info->cap_offset = 0; > + } else { > + vfio_info_cap_shift(&caps, sizeof(*info)); > + if (copy_to_user((void __user *)arg + sizeof(*info), > + caps.buf, caps.size)) { > + kfree(caps.buf); > + return -EFAULT; > + } > + info->cap_offset = sizeof(*info); > + } > + > + kfree(caps.buf); > + > + } > } > + return 0; > } > > static int vfio_ccw_mdev_get_irq_info(struct vfio_irq_info *info) > @@ -316,6 +427,32 @@ static int vfio_ccw_mdev_set_irqs(struct mdev_device *mdev, > } > } > > +int vfio_ccw_register_dev_region(struct vfio_ccw_private *private, > + unsigned int subtype, > + const struct vfio_ccw_regops *ops, > + size_t size, u32 flags, void *data) > +{ > + struct vfio_ccw_region *region; > + > + region = krealloc(private->region, > + (private->num_regions + 1) * sizeof(*region), > + GFP_KERNEL); > + if (!region) > + return -ENOMEM; > + > + private->region = region; > + private->region[private->num_regions].type = VFIO_REGION_TYPE_CCW; > + private->region[private->num_regions].subtype = subtype; > + private->region[private->num_regions].ops = ops; > + private->region[private->num_regions].size = size; > + private->region[private->num_regions].flags = flags; > + private->region[private->num_regions].data = data; > + > + private->num_regions++; > + > + return 0; > +} > + > static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, > unsigned int cmd, > unsigned long arg) > @@ -336,7 +473,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, > if (info.argsz < minsz) > return -EINVAL; > > - ret = vfio_ccw_mdev_get_device_info(&info); > + ret = vfio_ccw_mdev_get_device_info(&info, mdev); > if (ret) > return ret; > > @@ -345,8 +482,6 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, > case VFIO_DEVICE_GET_REGION_INFO: > { > struct vfio_region_info info; > - u16 cap_type_id = 0; > - void *cap_type = NULL; > > minsz = offsetofend(struct vfio_region_info, offset); > > @@ -356,8 +491,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, > if (info.argsz < minsz) > return -EINVAL; > > - ret = vfio_ccw_mdev_get_region_info(&info, &cap_type_id, > - &cap_type); > + ret = vfio_ccw_mdev_get_region_info(&info, mdev, arg); > if (ret) > return ret; > > diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h > index 32173cbd838d..d888a2573470 100644 > --- a/drivers/s390/cio/vfio_ccw_private.h > +++ b/drivers/s390/cio/vfio_ccw_private.h > @@ -3,9 +3,11 @@ > * Private stuff for vfio_ccw driver > * > * Copyright IBM Corp. 2017 > + * Copyright Red Hat, Inc. 2019 > * > * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> > * Xiao Feng Ren <renxiaof@linux.vnet.ibm.com> > + * Cornelia Huck <cohuck@redhat.com> > */ > > #ifndef _VFIO_CCW_PRIVATE_H_ > @@ -19,6 +21,38 @@ > #include "css.h" > #include "vfio_ccw_cp.h" > > +#define VFIO_CCW_OFFSET_SHIFT 10 > +#define VFIO_CCW_OFFSET_TO_INDEX(off) (off >> VFIO_CCW_OFFSET_SHIFT) > +#define VFIO_CCW_INDEX_TO_OFFSET(index) ((u64)(index) << VFIO_CCW_OFFSET_SHIFT) > +#define VFIO_CCW_OFFSET_MASK (((u64)(1) << VFIO_CCW_OFFSET_SHIFT) - 1) > + > +/* capability chain handling similar to vfio-pci */ > +struct vfio_ccw_private; > +struct vfio_ccw_region; > + > +struct vfio_ccw_regops { > + ssize_t (*read)(struct vfio_ccw_private *private, char __user *buf, > + size_t count, loff_t *ppos); > + ssize_t (*write)(struct vfio_ccw_private *private, > + const char __user *buf, size_t count, loff_t *ppos); > + void (*release)(struct vfio_ccw_private *private, > + struct vfio_ccw_region *region); > +}; > + > +struct vfio_ccw_region { > + u32 type; > + u32 subtype; > + const struct vfio_ccw_regops *ops; > + void *data; > + size_t size; > + u32 flags; > +}; > + > +int vfio_ccw_register_dev_region(struct vfio_ccw_private *private, > + unsigned int subtype, > + const struct vfio_ccw_regops *ops, > + size_t size, u32 flags, void *data); > + > /** > * struct vfio_ccw_private > * @sch: pointer to the subchannel > @@ -29,6 +63,8 @@ > * @nb: notifier for vfio events > * @io_region: MMIO region to input/output I/O arguments/results > * @io_mutex: protect against concurrent update of I/O regions > + * @region: additional regions for other subchannel operations > + * @num_regions: number of additional regions > * @cp: channel program for the current I/O operation > * @irb: irb info received from interrupt > * @scsw: scsw info > @@ -44,6 +80,8 @@ struct vfio_ccw_private { > struct notifier_block nb; > struct ccw_io_region *io_region; > struct mutex io_mutex; > + struct vfio_ccw_region *region; > + int num_regions; > > struct channel_program cp; > struct irb irb; > diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h > index 02bb7ad6e986..56e2413d3e00 100644 > --- a/include/uapi/linux/vfio.h > +++ b/include/uapi/linux/vfio.h > @@ -353,6 +353,8 @@ struct vfio_region_gfx_edid { > #define VFIO_DEVICE_GFX_LINK_STATE_DOWN 2 > }; > > +#define VFIO_REGION_TYPE_CCW (2) > + > /* > * 10de vendor sub-type > * >
next prev parent reply other threads:[~2019-04-15 14:41 UTC|newest] Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-03-01 9:38 [Qemu-devel] [PATCH v4 0/6] vfio-ccw: support hsch/csch (kernel part) Cornelia Huck 2019-03-01 9:38 ` [Qemu-devel] [PATCH v4 1/6] vfio-ccw: make it safe to access channel programs Cornelia Huck 2019-04-08 17:02 ` Farhan Ali 2019-04-08 17:02 ` Farhan Ali 2019-04-08 17:07 ` Cornelia Huck 2019-04-08 17:07 ` Cornelia Huck 2019-04-08 17:19 ` Farhan Ali 2019-04-08 17:19 ` Farhan Ali 2019-04-08 20:25 ` Eric Farman 2019-04-08 20:25 ` Eric Farman 2019-04-09 23:34 ` Halil Pasic 2019-04-09 23:34 ` Halil Pasic 2019-04-11 2:59 ` Eric Farman 2019-04-11 2:59 ` Eric Farman 2019-04-11 15:58 ` [Qemu-devel] [qemu-s390x] " Halil Pasic 2019-04-11 15:58 ` Halil Pasic 2019-04-11 16:25 ` Eric Farman 2019-04-11 16:25 ` Eric Farman 2019-04-11 16:36 ` Cornelia Huck 2019-04-11 16:36 ` Cornelia Huck 2019-04-11 18:07 ` Halil Pasic 2019-04-11 18:07 ` Halil Pasic 2019-04-11 21:27 ` [Qemu-devel] " Eric Farman 2019-04-11 21:27 ` Eric Farman 2019-04-12 8:14 ` Cornelia Huck 2019-04-12 8:14 ` Cornelia Huck 2019-03-01 9:38 ` [Qemu-devel] [PATCH v4 2/6] vfio-ccw: rework ssch state handling Cornelia Huck 2019-03-08 22:18 ` Eric Farman 2019-03-11 9:47 ` Cornelia Huck 2019-03-01 9:38 ` [Qemu-devel] [PATCH v4 3/6] vfio-ccw: protect the I/O region Cornelia Huck 2019-03-01 9:39 ` [Qemu-devel] [PATCH v4 4/6] vfio-ccw: add capabilities chain Cornelia Huck 2019-04-15 14:40 ` Eric Farman [this message] 2019-04-15 14:40 ` Eric Farman 2019-04-15 15:24 ` Farhan Ali 2019-04-15 15:24 ` Farhan Ali 2019-03-01 9:39 ` [Qemu-devel] [PATCH v4 5/6] s390/cio: export hsch to modules Cornelia Huck 2019-03-01 9:39 ` [Qemu-devel] [PATCH v4 6/6] vfio-ccw: add handling for async channel instructions Cornelia Huck 2019-04-15 14:56 ` Eric Farman 2019-04-15 14:56 ` Eric Farman 2019-04-15 15:25 ` Farhan Ali 2019-04-15 15:25 ` Farhan Ali 2019-03-07 21:28 ` [Qemu-devel] [PATCH v4 0/6] vfio-ccw: support hsch/csch (kernel part) Eric Farman 2019-04-15 11:51 ` Cornelia Huck 2019-04-15 11:51 ` Cornelia Huck 2019-04-15 16:43 ` Cornelia Huck 2019-04-15 16:43 ` Cornelia Huck
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=9d692710-cf9e-99c6-45d1-bb18a2ba7b94@linux.ibm.com \ --to=farman@linux.ibm.com \ --cc=alex.williamson@redhat.com \ --cc=alifm@linux.ibm.com \ --cc=cohuck@redhat.com \ --cc=kvm@vger.kernel.org \ --cc=linux-s390@vger.kernel.org \ --cc=pasic@linux.ibm.com \ --cc=pmorel@linux.ibm.com \ --cc=qemu-devel@nongnu.org \ --cc=qemu-s390x@nongnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).