cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vfio_ccw_async.c (2197B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Async I/O region for vfio_ccw
      4 *
      5 * Copyright Red Hat, Inc. 2019
      6 *
      7 * Author(s): Cornelia Huck <cohuck@redhat.com>
      8 */
      9
     10#include <linux/vfio.h>
     11#include <linux/mdev.h>
     12
     13#include "vfio_ccw_private.h"
     14
     15static ssize_t vfio_ccw_async_region_read(struct vfio_ccw_private *private,
     16					  char __user *buf, size_t count,
     17					  loff_t *ppos)
     18{
     19	unsigned int i = VFIO_CCW_OFFSET_TO_INDEX(*ppos) - VFIO_CCW_NUM_REGIONS;
     20	loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK;
     21	struct ccw_cmd_region *region;
     22	int ret;
     23
     24	if (pos + count > sizeof(*region))
     25		return -EINVAL;
     26
     27	mutex_lock(&private->io_mutex);
     28	region = private->region[i].data;
     29	if (copy_to_user(buf, (void *)region + pos, count))
     30		ret = -EFAULT;
     31	else
     32		ret = count;
     33	mutex_unlock(&private->io_mutex);
     34	return ret;
     35}
     36
     37static ssize_t vfio_ccw_async_region_write(struct vfio_ccw_private *private,
     38					   const char __user *buf, size_t count,
     39					   loff_t *ppos)
     40{
     41	unsigned int i = VFIO_CCW_OFFSET_TO_INDEX(*ppos) - VFIO_CCW_NUM_REGIONS;
     42	loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK;
     43	struct ccw_cmd_region *region;
     44	int ret;
     45
     46	if (pos + count > sizeof(*region))
     47		return -EINVAL;
     48
     49	if (!mutex_trylock(&private->io_mutex))
     50		return -EAGAIN;
     51
     52	region = private->region[i].data;
     53	if (copy_from_user((void *)region + pos, buf, count)) {
     54		ret = -EFAULT;
     55		goto out_unlock;
     56	}
     57
     58	vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_ASYNC_REQ);
     59
     60	ret = region->ret_code ? region->ret_code : count;
     61
     62out_unlock:
     63	mutex_unlock(&private->io_mutex);
     64	return ret;
     65}
     66
     67static void vfio_ccw_async_region_release(struct vfio_ccw_private *private,
     68					  struct vfio_ccw_region *region)
     69{
     70
     71}
     72
     73static const struct vfio_ccw_regops vfio_ccw_async_region_ops = {
     74	.read = vfio_ccw_async_region_read,
     75	.write = vfio_ccw_async_region_write,
     76	.release = vfio_ccw_async_region_release,
     77};
     78
     79int vfio_ccw_register_async_dev_regions(struct vfio_ccw_private *private)
     80{
     81	return vfio_ccw_register_dev_region(private,
     82					    VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD,
     83					    &vfio_ccw_async_region_ops,
     84					    sizeof(struct ccw_cmd_region),
     85					    VFIO_REGION_INFO_FLAG_READ |
     86					    VFIO_REGION_INFO_FLAG_WRITE,
     87					    private->cmd_region);
     88}