vfio: ccw: introduce ccw_io_region

To provide user-space a set of interfaces to:
1. pass in a ccw program to perform an I/O operation.
2. read back I/O results of the completed I/O operations.
We introduce an MMIO region for the vfio-ccw device here.

This region is defined to content:
1. areas to store arguments that an ssch required.
2. areas to store the I/O results.

Using pwrite/pread to the device on this region, a user-space program
could write/read data to/from the vfio-ccw device.

Reviewed-by: Pierre Morel <pmorel@linux.vnet.ibm.com>
Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
Message-Id: <20170317031743.40128-8-bjsdjshi@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
This commit is contained in:
Dong Jia Shi 2017-03-17 04:17:34 +01:00 committed by Cornelia Huck
parent 84cd8fc484
commit 060d2b5afc
3 changed files with 75 additions and 0 deletions

View File

@ -127,6 +127,51 @@ void vfio_ccw_mdev_release(struct mdev_device *mdev)
&private->nb); &private->nb);
} }
static ssize_t vfio_ccw_mdev_read(struct mdev_device *mdev,
char __user *buf,
size_t count,
loff_t *ppos)
{
struct vfio_ccw_private *private;
struct ccw_io_region *region;
if (*ppos + count > sizeof(*region))
return -EINVAL;
private = dev_get_drvdata(mdev_parent_dev(mdev));
if (!private)
return -ENODEV;
region = &private->io_region;
if (copy_to_user(buf, (void *)region + *ppos, count))
return -EFAULT;
return count;
}
static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev,
const char __user *buf,
size_t count,
loff_t *ppos)
{
struct vfio_ccw_private *private;
struct ccw_io_region *region;
if (*ppos + count > sizeof(*region))
return -EINVAL;
private = dev_get_drvdata(mdev_parent_dev(mdev));
if (!private)
return -ENODEV;
region = &private->io_region;
if (copy_from_user((void *)region + *ppos, buf, count))
return -EFAULT;
region->ret_code = 0;
return count;
}
static const struct mdev_parent_ops vfio_ccw_mdev_ops = { static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.supported_type_groups = mdev_type_groups, .supported_type_groups = mdev_type_groups,
@ -134,6 +179,8 @@ static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
.remove = vfio_ccw_mdev_remove, .remove = vfio_ccw_mdev_remove,
.open = vfio_ccw_mdev_open, .open = vfio_ccw_mdev_open,
.release = vfio_ccw_mdev_release, .release = vfio_ccw_mdev_release,
.read = vfio_ccw_mdev_read,
.write = vfio_ccw_mdev_write,
}; };
int vfio_ccw_mdev_reg(struct subchannel *sch) int vfio_ccw_mdev_reg(struct subchannel *sch)

View File

@ -10,6 +10,8 @@
#ifndef _VFIO_CCW_PRIVATE_H_ #ifndef _VFIO_CCW_PRIVATE_H_
#define _VFIO_CCW_PRIVATE_H_ #define _VFIO_CCW_PRIVATE_H_
#include <linux/vfio_ccw.h>
#include "css.h" #include "css.h"
/** /**
@ -19,6 +21,7 @@
* @avail: available for creating a mediated device * @avail: available for creating a mediated device
* @mdev: pointer to the mediated device * @mdev: pointer to the mediated device
* @nb: notifier for vfio events * @nb: notifier for vfio events
* @io_region: MMIO region to input/output I/O arguments/results
*/ */
struct vfio_ccw_private { struct vfio_ccw_private {
struct subchannel *sch; struct subchannel *sch;
@ -26,6 +29,7 @@ struct vfio_ccw_private {
atomic_t avail; atomic_t avail;
struct mdev_device *mdev; struct mdev_device *mdev;
struct notifier_block nb; struct notifier_block nb;
struct ccw_io_region io_region;
} __aligned(8); } __aligned(8);
extern int vfio_ccw_mdev_reg(struct subchannel *sch); extern int vfio_ccw_mdev_reg(struct subchannel *sch);

View File

@ -0,0 +1,24 @@
/*
* Interfaces for vfio-ccw
*
* Copyright IBM Corp. 2017
*
* Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
*/
#ifndef _VFIO_CCW_H_
#define _VFIO_CCW_H_
#include <linux/types.h>
struct ccw_io_region {
#define ORB_AREA_SIZE 12
__u8 orb_area[ORB_AREA_SIZE];
#define SCSW_AREA_SIZE 12
__u8 scsw_area[SCSW_AREA_SIZE];
#define IRB_AREA_SIZE 96
__u8 irb_area[IRB_AREA_SIZE];
__u32 ret_code;
} __packed;
#endif