linux/drivers/s390/cio/vfio_ccw_ops.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Physical device callbacks for vfio_ccw
   4 *
   5 * Copyright IBM Corp. 2017
   6 * Copyright Red Hat, Inc. 2019
   7 *
   8 * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
   9 *            Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
  10 *            Cornelia Huck <cohuck@redhat.com>
  11 */
  12
  13#include <linux/vfio.h>
  14#include <linux/mdev.h>
  15#include <linux/nospec.h>
  16#include <linux/slab.h>
  17
  18#include "vfio_ccw_private.h"
  19
  20static int vfio_ccw_mdev_reset(struct mdev_device *mdev)
  21{
  22        struct vfio_ccw_private *private;
  23        struct subchannel *sch;
  24        int ret;
  25
  26        private = dev_get_drvdata(mdev_parent_dev(mdev));
  27        sch = private->sch;
  28        /*
  29         * TODO:
  30         * In the cureent stage, some things like "no I/O running" and "no
  31         * interrupt pending" are clear, but we are not sure what other state
  32         * we need to care about.
  33         * There are still a lot more instructions need to be handled. We
  34         * should come back here later.
  35         */
  36        ret = vfio_ccw_sch_quiesce(sch);
  37        if (ret)
  38                return ret;
  39
  40        ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
  41        if (!ret)
  42                private->state = VFIO_CCW_STATE_IDLE;
  43
  44        return ret;
  45}
  46
  47static int vfio_ccw_mdev_notifier(struct notifier_block *nb,
  48                                  unsigned long action,
  49                                  void *data)
  50{
  51        struct vfio_ccw_private *private =
  52                container_of(nb, struct vfio_ccw_private, nb);
  53
  54        /*
  55         * Vendor drivers MUST unpin pages in response to an
  56         * invalidation.
  57         */
  58        if (action == VFIO_IOMMU_NOTIFY_DMA_UNMAP) {
  59                struct vfio_iommu_type1_dma_unmap *unmap = data;
  60
  61                if (!cp_iova_pinned(&private->cp, unmap->iova))
  62                        return NOTIFY_OK;
  63
  64                if (vfio_ccw_mdev_reset(private->mdev))
  65                        return NOTIFY_BAD;
  66
  67                cp_free(&private->cp);
  68                return NOTIFY_OK;
  69        }
  70
  71        return NOTIFY_DONE;
  72}
  73
  74static ssize_t name_show(struct kobject *kobj, struct device *dev, char *buf)
  75{
  76        return sprintf(buf, "I/O subchannel (Non-QDIO)\n");
  77}
  78static MDEV_TYPE_ATTR_RO(name);
  79
  80static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
  81                               char *buf)
  82{
  83        return sprintf(buf, "%s\n", VFIO_DEVICE_API_CCW_STRING);
  84}
  85static MDEV_TYPE_ATTR_RO(device_api);
  86
  87static ssize_t available_instances_show(struct kobject *kobj,
  88                                        struct device *dev, char *buf)
  89{
  90        struct vfio_ccw_private *private = dev_get_drvdata(dev);
  91
  92        return sprintf(buf, "%d\n", atomic_read(&private->avail));
  93}
  94static MDEV_TYPE_ATTR_RO(available_instances);
  95
  96static struct attribute *mdev_types_attrs[] = {
  97        &mdev_type_attr_name.attr,
  98        &mdev_type_attr_device_api.attr,
  99        &mdev_type_attr_available_instances.attr,
 100        NULL,
 101};
 102
 103static struct attribute_group mdev_type_group = {
 104        .name  = "io",
 105        .attrs = mdev_types_attrs,
 106};
 107
 108static struct attribute_group *mdev_type_groups[] = {
 109        &mdev_type_group,
 110        NULL,
 111};
 112
 113static int vfio_ccw_mdev_create(struct kobject *kobj, struct mdev_device *mdev)
 114{
 115        struct vfio_ccw_private *private =
 116                dev_get_drvdata(mdev_parent_dev(mdev));
 117
 118        if (private->state == VFIO_CCW_STATE_NOT_OPER)
 119                return -ENODEV;
 120
 121        if (atomic_dec_if_positive(&private->avail) < 0)
 122                return -EPERM;
 123
 124        private->mdev = mdev;
 125        private->state = VFIO_CCW_STATE_IDLE;
 126
 127        VFIO_CCW_MSG_EVENT(2, "mdev %pUl, sch %x.%x.%04x: create\n",
 128                           mdev_uuid(mdev), private->sch->schid.cssid,
 129                           private->sch->schid.ssid,
 130                           private->sch->schid.sch_no);
 131
 132        return 0;
 133}
 134
 135static int vfio_ccw_mdev_remove(struct mdev_device *mdev)
 136{
 137        struct vfio_ccw_private *private =
 138                dev_get_drvdata(mdev_parent_dev(mdev));
 139
 140        VFIO_CCW_MSG_EVENT(2, "mdev %pUl, sch %x.%x.%04x: remove\n",
 141                           mdev_uuid(mdev), private->sch->schid.cssid,
 142                           private->sch->schid.ssid,
 143                           private->sch->schid.sch_no);
 144
 145        if ((private->state != VFIO_CCW_STATE_NOT_OPER) &&
 146            (private->state != VFIO_CCW_STATE_STANDBY)) {
 147                if (!vfio_ccw_sch_quiesce(private->sch))
 148                        private->state = VFIO_CCW_STATE_STANDBY;
 149                /* The state will be NOT_OPER on error. */
 150        }
 151
 152        cp_free(&private->cp);
 153        private->mdev = NULL;
 154        atomic_inc(&private->avail);
 155
 156        return 0;
 157}
 158
 159static int vfio_ccw_mdev_open(struct mdev_device *mdev)
 160{
 161        struct vfio_ccw_private *private =
 162                dev_get_drvdata(mdev_parent_dev(mdev));
 163        unsigned long events = VFIO_IOMMU_NOTIFY_DMA_UNMAP;
 164        int ret;
 165
 166        private->nb.notifier_call = vfio_ccw_mdev_notifier;
 167
 168        ret = vfio_register_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY,
 169                                     &events, &private->nb);
 170        if (ret)
 171                return ret;
 172
 173        ret = vfio_ccw_register_async_dev_regions(private);
 174        if (ret)
 175                vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY,
 176                                         &private->nb);
 177        return ret;
 178}
 179
 180static void vfio_ccw_mdev_release(struct mdev_device *mdev)
 181{
 182        struct vfio_ccw_private *private =
 183                dev_get_drvdata(mdev_parent_dev(mdev));
 184        int i;
 185
 186        if ((private->state != VFIO_CCW_STATE_NOT_OPER) &&
 187            (private->state != VFIO_CCW_STATE_STANDBY)) {
 188                if (!vfio_ccw_mdev_reset(mdev))
 189                        private->state = VFIO_CCW_STATE_STANDBY;
 190                /* The state will be NOT_OPER on error. */
 191        }
 192
 193        cp_free(&private->cp);
 194        vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY,
 195                                 &private->nb);
 196
 197        for (i = 0; i < private->num_regions; i++)
 198                private->region[i].ops->release(private, &private->region[i]);
 199
 200        private->num_regions = 0;
 201        kfree(private->region);
 202        private->region = NULL;
 203}
 204
 205static ssize_t vfio_ccw_mdev_read_io_region(struct vfio_ccw_private *private,
 206                                            char __user *buf, size_t count,
 207                                            loff_t *ppos)
 208{
 209        loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK;
 210        struct ccw_io_region *region;
 211        int ret;
 212
 213        if (pos + count > sizeof(*region))
 214                return -EINVAL;
 215
 216        mutex_lock(&private->io_mutex);
 217        region = private->io_region;
 218        if (copy_to_user(buf, (void *)region + pos, count))
 219                ret = -EFAULT;
 220        else
 221                ret = count;
 222        mutex_unlock(&private->io_mutex);
 223        return ret;
 224}
 225
 226static ssize_t vfio_ccw_mdev_read(struct mdev_device *mdev,
 227                                  char __user *buf,
 228                                  size_t count,
 229                                  loff_t *ppos)
 230{
 231        unsigned int index = VFIO_CCW_OFFSET_TO_INDEX(*ppos);
 232        struct vfio_ccw_private *private;
 233
 234        private = dev_get_drvdata(mdev_parent_dev(mdev));
 235
 236        if (index >= VFIO_CCW_NUM_REGIONS + private->num_regions)
 237                return -EINVAL;
 238
 239        switch (index) {
 240        case VFIO_CCW_CONFIG_REGION_INDEX:
 241                return vfio_ccw_mdev_read_io_region(private, buf, count, ppos);
 242        default:
 243                index -= VFIO_CCW_NUM_REGIONS;
 244                return private->region[index].ops->read(private, buf, count,
 245                                                        ppos);
 246        }
 247
 248        return -EINVAL;
 249}
 250
 251static ssize_t vfio_ccw_mdev_write_io_region(struct vfio_ccw_private *private,
 252                                             const char __user *buf,
 253                                             size_t count, loff_t *ppos)
 254{
 255        loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK;
 256        struct ccw_io_region *region;
 257        int ret;
 258
 259        if (pos + count > sizeof(*region))
 260                return -EINVAL;
 261
 262        if (!mutex_trylock(&private->io_mutex))
 263                return -EAGAIN;
 264
 265        region = private->io_region;
 266        if (copy_from_user((void *)region + pos, buf, count)) {
 267                ret = -EFAULT;
 268                goto out_unlock;
 269        }
 270
 271        vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_IO_REQ);
 272        if (region->ret_code != 0)
 273                private->state = VFIO_CCW_STATE_IDLE;
 274        ret = (region->ret_code != 0) ? region->ret_code : count;
 275
 276out_unlock:
 277        mutex_unlock(&private->io_mutex);
 278        return ret;
 279}
 280
 281static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev,
 282                                   const char __user *buf,
 283                                   size_t count,
 284                                   loff_t *ppos)
 285{
 286        unsigned int index = VFIO_CCW_OFFSET_TO_INDEX(*ppos);
 287        struct vfio_ccw_private *private;
 288
 289        private = dev_get_drvdata(mdev_parent_dev(mdev));
 290
 291        if (index >= VFIO_CCW_NUM_REGIONS + private->num_regions)
 292                return -EINVAL;
 293
 294        switch (index) {
 295        case VFIO_CCW_CONFIG_REGION_INDEX:
 296                return vfio_ccw_mdev_write_io_region(private, buf, count, ppos);
 297        default:
 298                index -= VFIO_CCW_NUM_REGIONS;
 299                return private->region[index].ops->write(private, buf, count,
 300                                                         ppos);
 301        }
 302
 303        return -EINVAL;
 304}
 305
 306static int vfio_ccw_mdev_get_device_info(struct vfio_device_info *info,
 307                                         struct mdev_device *mdev)
 308{
 309        struct vfio_ccw_private *private;
 310
 311        private = dev_get_drvdata(mdev_parent_dev(mdev));
 312        info->flags = VFIO_DEVICE_FLAGS_CCW | VFIO_DEVICE_FLAGS_RESET;
 313        info->num_regions = VFIO_CCW_NUM_REGIONS + private->num_regions;
 314        info->num_irqs = VFIO_CCW_NUM_IRQS;
 315
 316        return 0;
 317}
 318
 319static int vfio_ccw_mdev_get_region_info(struct vfio_region_info *info,
 320                                         struct mdev_device *mdev,
 321                                         unsigned long arg)
 322{
 323        struct vfio_ccw_private *private;
 324        int i;
 325
 326        private = dev_get_drvdata(mdev_parent_dev(mdev));
 327        switch (info->index) {
 328        case VFIO_CCW_CONFIG_REGION_INDEX:
 329                info->offset = 0;
 330                info->size = sizeof(struct ccw_io_region);
 331                info->flags = VFIO_REGION_INFO_FLAG_READ
 332                              | VFIO_REGION_INFO_FLAG_WRITE;
 333                return 0;
 334        default: /* all other regions are handled via capability chain */
 335        {
 336                struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
 337                struct vfio_region_info_cap_type cap_type = {
 338                        .header.id = VFIO_REGION_INFO_CAP_TYPE,
 339                        .header.version = 1 };
 340                int ret;
 341
 342                if (info->index >=
 343                    VFIO_CCW_NUM_REGIONS + private->num_regions)
 344                        return -EINVAL;
 345
 346                info->index = array_index_nospec(info->index,
 347                                                 VFIO_CCW_NUM_REGIONS +
 348                                                 private->num_regions);
 349
 350                i = info->index - VFIO_CCW_NUM_REGIONS;
 351
 352                info->offset = VFIO_CCW_INDEX_TO_OFFSET(info->index);
 353                info->size = private->region[i].size;
 354                info->flags = private->region[i].flags;
 355
 356                cap_type.type = private->region[i].type;
 357                cap_type.subtype = private->region[i].subtype;
 358
 359                ret = vfio_info_add_capability(&caps, &cap_type.header,
 360                                               sizeof(cap_type));
 361                if (ret)
 362                        return ret;
 363
 364                info->flags |= VFIO_REGION_INFO_FLAG_CAPS;
 365                if (info->argsz < sizeof(*info) + caps.size) {
 366                        info->argsz = sizeof(*info) + caps.size;
 367                        info->cap_offset = 0;
 368                } else {
 369                        vfio_info_cap_shift(&caps, sizeof(*info));
 370                        if (copy_to_user((void __user *)arg + sizeof(*info),
 371                                         caps.buf, caps.size)) {
 372                                kfree(caps.buf);
 373                                return -EFAULT;
 374                        }
 375                        info->cap_offset = sizeof(*info);
 376                }
 377
 378                kfree(caps.buf);
 379
 380        }
 381        }
 382        return 0;
 383}
 384
 385static int vfio_ccw_mdev_get_irq_info(struct vfio_irq_info *info)
 386{
 387        if (info->index != VFIO_CCW_IO_IRQ_INDEX)
 388                return -EINVAL;
 389
 390        info->count = 1;
 391        info->flags = VFIO_IRQ_INFO_EVENTFD;
 392
 393        return 0;
 394}
 395
 396static int vfio_ccw_mdev_set_irqs(struct mdev_device *mdev,
 397                                  uint32_t flags,
 398                                  void __user *data)
 399{
 400        struct vfio_ccw_private *private;
 401        struct eventfd_ctx **ctx;
 402
 403        if (!(flags & VFIO_IRQ_SET_ACTION_TRIGGER))
 404                return -EINVAL;
 405
 406        private = dev_get_drvdata(mdev_parent_dev(mdev));
 407        ctx = &private->io_trigger;
 408
 409        switch (flags & VFIO_IRQ_SET_DATA_TYPE_MASK) {
 410        case VFIO_IRQ_SET_DATA_NONE:
 411        {
 412                if (*ctx)
 413                        eventfd_signal(*ctx, 1);
 414                return 0;
 415        }
 416        case VFIO_IRQ_SET_DATA_BOOL:
 417        {
 418                uint8_t trigger;
 419
 420                if (get_user(trigger, (uint8_t __user *)data))
 421                        return -EFAULT;
 422
 423                if (trigger && *ctx)
 424                        eventfd_signal(*ctx, 1);
 425                return 0;
 426        }
 427        case VFIO_IRQ_SET_DATA_EVENTFD:
 428        {
 429                int32_t fd;
 430
 431                if (get_user(fd, (int32_t __user *)data))
 432                        return -EFAULT;
 433
 434                if (fd == -1) {
 435                        if (*ctx)
 436                                eventfd_ctx_put(*ctx);
 437                        *ctx = NULL;
 438                } else if (fd >= 0) {
 439                        struct eventfd_ctx *efdctx;
 440
 441                        efdctx = eventfd_ctx_fdget(fd);
 442                        if (IS_ERR(efdctx))
 443                                return PTR_ERR(efdctx);
 444
 445                        if (*ctx)
 446                                eventfd_ctx_put(*ctx);
 447
 448                        *ctx = efdctx;
 449                } else
 450                        return -EINVAL;
 451
 452                return 0;
 453        }
 454        default:
 455                return -EINVAL;
 456        }
 457}
 458
 459int vfio_ccw_register_dev_region(struct vfio_ccw_private *private,
 460                                 unsigned int subtype,
 461                                 const struct vfio_ccw_regops *ops,
 462                                 size_t size, u32 flags, void *data)
 463{
 464        struct vfio_ccw_region *region;
 465
 466        region = krealloc(private->region,
 467                          (private->num_regions + 1) * sizeof(*region),
 468                          GFP_KERNEL);
 469        if (!region)
 470                return -ENOMEM;
 471
 472        private->region = region;
 473        private->region[private->num_regions].type = VFIO_REGION_TYPE_CCW;
 474        private->region[private->num_regions].subtype = subtype;
 475        private->region[private->num_regions].ops = ops;
 476        private->region[private->num_regions].size = size;
 477        private->region[private->num_regions].flags = flags;
 478        private->region[private->num_regions].data = data;
 479
 480        private->num_regions++;
 481
 482        return 0;
 483}
 484
 485static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev,
 486                                   unsigned int cmd,
 487                                   unsigned long arg)
 488{
 489        int ret = 0;
 490        unsigned long minsz;
 491
 492        switch (cmd) {
 493        case VFIO_DEVICE_GET_INFO:
 494        {
 495                struct vfio_device_info info;
 496
 497                minsz = offsetofend(struct vfio_device_info, num_irqs);
 498
 499                if (copy_from_user(&info, (void __user *)arg, minsz))
 500                        return -EFAULT;
 501
 502                if (info.argsz < minsz)
 503                        return -EINVAL;
 504
 505                ret = vfio_ccw_mdev_get_device_info(&info, mdev);
 506                if (ret)
 507                        return ret;
 508
 509                return copy_to_user((void __user *)arg, &info, minsz);
 510        }
 511        case VFIO_DEVICE_GET_REGION_INFO:
 512        {
 513                struct vfio_region_info info;
 514
 515                minsz = offsetofend(struct vfio_region_info, offset);
 516
 517                if (copy_from_user(&info, (void __user *)arg, minsz))
 518                        return -EFAULT;
 519
 520                if (info.argsz < minsz)
 521                        return -EINVAL;
 522
 523                ret = vfio_ccw_mdev_get_region_info(&info, mdev, arg);
 524                if (ret)
 525                        return ret;
 526
 527                return copy_to_user((void __user *)arg, &info, minsz);
 528        }
 529        case VFIO_DEVICE_GET_IRQ_INFO:
 530        {
 531                struct vfio_irq_info info;
 532
 533                minsz = offsetofend(struct vfio_irq_info, count);
 534
 535                if (copy_from_user(&info, (void __user *)arg, minsz))
 536                        return -EFAULT;
 537
 538                if (info.argsz < minsz || info.index >= VFIO_CCW_NUM_IRQS)
 539                        return -EINVAL;
 540
 541                ret = vfio_ccw_mdev_get_irq_info(&info);
 542                if (ret)
 543                        return ret;
 544
 545                if (info.count == -1)
 546                        return -EINVAL;
 547
 548                return copy_to_user((void __user *)arg, &info, minsz);
 549        }
 550        case VFIO_DEVICE_SET_IRQS:
 551        {
 552                struct vfio_irq_set hdr;
 553                size_t data_size;
 554                void __user *data;
 555
 556                minsz = offsetofend(struct vfio_irq_set, count);
 557
 558                if (copy_from_user(&hdr, (void __user *)arg, minsz))
 559                        return -EFAULT;
 560
 561                ret = vfio_set_irqs_validate_and_prepare(&hdr, 1,
 562                                                         VFIO_CCW_NUM_IRQS,
 563                                                         &data_size);
 564                if (ret)
 565                        return ret;
 566
 567                data = (void __user *)(arg + minsz);
 568                return vfio_ccw_mdev_set_irqs(mdev, hdr.flags, data);
 569        }
 570        case VFIO_DEVICE_RESET:
 571                return vfio_ccw_mdev_reset(mdev);
 572        default:
 573                return -ENOTTY;
 574        }
 575}
 576
 577static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
 578        .owner                  = THIS_MODULE,
 579        .supported_type_groups  = mdev_type_groups,
 580        .create                 = vfio_ccw_mdev_create,
 581        .remove                 = vfio_ccw_mdev_remove,
 582        .open                   = vfio_ccw_mdev_open,
 583        .release                = vfio_ccw_mdev_release,
 584        .read                   = vfio_ccw_mdev_read,
 585        .write                  = vfio_ccw_mdev_write,
 586        .ioctl                  = vfio_ccw_mdev_ioctl,
 587};
 588
 589int vfio_ccw_mdev_reg(struct subchannel *sch)
 590{
 591        return mdev_register_device(&sch->dev, &vfio_ccw_mdev_ops);
 592}
 593
 594void vfio_ccw_mdev_unreg(struct subchannel *sch)
 595{
 596        mdev_unregister_device(&sch->dev);
 597}
 598