0001
0002
0003 #include <linux/fs.h>
0004 #include <linux/poll.h>
0005 #include <linux/sched/signal.h>
0006 #include <linux/eventfd.h>
0007 #include <linux/uaccess.h>
0008 #include <uapi/misc/ocxl.h>
0009 #include <asm/reg.h>
0010 #include <asm/switch_to.h>
0011 #include "ocxl_internal.h"
0012
0013
0014 #define OCXL_NUM_MINORS 256
0015
0016 static dev_t ocxl_dev;
0017 static struct class *ocxl_class;
0018 static DEFINE_MUTEX(minors_idr_lock);
0019 static struct idr minors_idr;
0020
0021 static struct ocxl_file_info *find_and_get_file_info(dev_t devno)
0022 {
0023 struct ocxl_file_info *info;
0024
0025 mutex_lock(&minors_idr_lock);
0026 info = idr_find(&minors_idr, MINOR(devno));
0027 if (info)
0028 get_device(&info->dev);
0029 mutex_unlock(&minors_idr_lock);
0030 return info;
0031 }
0032
0033 static int allocate_minor(struct ocxl_file_info *info)
0034 {
0035 int minor;
0036
0037 mutex_lock(&minors_idr_lock);
0038 minor = idr_alloc(&minors_idr, info, 0, OCXL_NUM_MINORS, GFP_KERNEL);
0039 mutex_unlock(&minors_idr_lock);
0040 return minor;
0041 }
0042
0043 static void free_minor(struct ocxl_file_info *info)
0044 {
0045 mutex_lock(&minors_idr_lock);
0046 idr_remove(&minors_idr, MINOR(info->dev.devt));
0047 mutex_unlock(&minors_idr_lock);
0048 }
0049
0050 static int afu_open(struct inode *inode, struct file *file)
0051 {
0052 struct ocxl_file_info *info;
0053 struct ocxl_context *ctx;
0054 int rc;
0055
0056 pr_debug("%s for device %x\n", __func__, inode->i_rdev);
0057
0058 info = find_and_get_file_info(inode->i_rdev);
0059 if (!info)
0060 return -ENODEV;
0061
0062 rc = ocxl_context_alloc(&ctx, info->afu, inode->i_mapping);
0063 if (rc) {
0064 put_device(&info->dev);
0065 return rc;
0066 }
0067 put_device(&info->dev);
0068 file->private_data = ctx;
0069 return 0;
0070 }
0071
0072 static long afu_ioctl_attach(struct ocxl_context *ctx,
0073 struct ocxl_ioctl_attach __user *uarg)
0074 {
0075 struct ocxl_ioctl_attach arg;
0076 u64 amr = 0;
0077
0078 pr_debug("%s for context %d\n", __func__, ctx->pasid);
0079
0080 if (copy_from_user(&arg, uarg, sizeof(arg)))
0081 return -EFAULT;
0082
0083
0084 if (arg.reserved1 || arg.reserved2 || arg.reserved3)
0085 return -EINVAL;
0086
0087 amr = arg.amr & mfspr(SPRN_UAMOR);
0088 return ocxl_context_attach(ctx, amr, current->mm);
0089 }
0090
0091 static long afu_ioctl_get_metadata(struct ocxl_context *ctx,
0092 struct ocxl_ioctl_metadata __user *uarg)
0093 {
0094 struct ocxl_ioctl_metadata arg;
0095
0096 memset(&arg, 0, sizeof(arg));
0097
0098 arg.version = 0;
0099
0100 arg.afu_version_major = ctx->afu->config.version_major;
0101 arg.afu_version_minor = ctx->afu->config.version_minor;
0102 arg.pasid = ctx->pasid;
0103 arg.pp_mmio_size = ctx->afu->config.pp_mmio_stride;
0104 arg.global_mmio_size = ctx->afu->config.global_mmio_size;
0105
0106 if (copy_to_user(uarg, &arg, sizeof(arg)))
0107 return -EFAULT;
0108
0109 return 0;
0110 }
0111
0112 #ifdef CONFIG_PPC64
0113 static long afu_ioctl_enable_p9_wait(struct ocxl_context *ctx,
0114 struct ocxl_ioctl_p9_wait __user *uarg)
0115 {
0116 struct ocxl_ioctl_p9_wait arg;
0117
0118 memset(&arg, 0, sizeof(arg));
0119
0120 if (cpu_has_feature(CPU_FTR_P9_TIDR)) {
0121 enum ocxl_context_status status;
0122
0123
0124 mutex_lock(&ctx->status_mutex);
0125 if (!ctx->tidr) {
0126 if (set_thread_tidr(current)) {
0127 mutex_unlock(&ctx->status_mutex);
0128 return -ENOENT;
0129 }
0130
0131 ctx->tidr = current->thread.tidr;
0132 }
0133
0134 status = ctx->status;
0135 mutex_unlock(&ctx->status_mutex);
0136
0137 if (status == ATTACHED) {
0138 int rc = ocxl_link_update_pe(ctx->afu->fn->link,
0139 ctx->pasid, ctx->tidr);
0140
0141 if (rc)
0142 return rc;
0143 }
0144
0145 arg.thread_id = ctx->tidr;
0146 } else
0147 return -ENOENT;
0148
0149 if (copy_to_user(uarg, &arg, sizeof(arg)))
0150 return -EFAULT;
0151
0152 return 0;
0153 }
0154 #endif
0155
0156
0157 static long afu_ioctl_get_features(struct ocxl_context *ctx,
0158 struct ocxl_ioctl_features __user *uarg)
0159 {
0160 struct ocxl_ioctl_features arg;
0161
0162 memset(&arg, 0, sizeof(arg));
0163
0164 #ifdef CONFIG_PPC64
0165 if (cpu_has_feature(CPU_FTR_P9_TIDR))
0166 arg.flags[0] |= OCXL_IOCTL_FEATURES_FLAGS0_P9_WAIT;
0167 #endif
0168
0169 if (copy_to_user(uarg, &arg, sizeof(arg)))
0170 return -EFAULT;
0171
0172 return 0;
0173 }
0174
0175 #define CMD_STR(x) (x == OCXL_IOCTL_ATTACH ? "ATTACH" : \
0176 x == OCXL_IOCTL_IRQ_ALLOC ? "IRQ_ALLOC" : \
0177 x == OCXL_IOCTL_IRQ_FREE ? "IRQ_FREE" : \
0178 x == OCXL_IOCTL_IRQ_SET_FD ? "IRQ_SET_FD" : \
0179 x == OCXL_IOCTL_GET_METADATA ? "GET_METADATA" : \
0180 x == OCXL_IOCTL_ENABLE_P9_WAIT ? "ENABLE_P9_WAIT" : \
0181 x == OCXL_IOCTL_GET_FEATURES ? "GET_FEATURES" : \
0182 "UNKNOWN")
0183
0184 static irqreturn_t irq_handler(void *private)
0185 {
0186 struct eventfd_ctx *ev_ctx = private;
0187
0188 eventfd_signal(ev_ctx, 1);
0189 return IRQ_HANDLED;
0190 }
0191
0192 static void irq_free(void *private)
0193 {
0194 struct eventfd_ctx *ev_ctx = private;
0195
0196 eventfd_ctx_put(ev_ctx);
0197 }
0198
0199 static long afu_ioctl(struct file *file, unsigned int cmd,
0200 unsigned long args)
0201 {
0202 struct ocxl_context *ctx = file->private_data;
0203 struct ocxl_ioctl_irq_fd irq_fd;
0204 struct eventfd_ctx *ev_ctx;
0205 int irq_id;
0206 u64 irq_offset;
0207 long rc;
0208 bool closed;
0209
0210 pr_debug("%s for context %d, command %s\n", __func__, ctx->pasid,
0211 CMD_STR(cmd));
0212
0213 mutex_lock(&ctx->status_mutex);
0214 closed = (ctx->status == CLOSED);
0215 mutex_unlock(&ctx->status_mutex);
0216
0217 if (closed)
0218 return -EIO;
0219
0220 switch (cmd) {
0221 case OCXL_IOCTL_ATTACH:
0222 rc = afu_ioctl_attach(ctx,
0223 (struct ocxl_ioctl_attach __user *) args);
0224 break;
0225
0226 case OCXL_IOCTL_IRQ_ALLOC:
0227 rc = ocxl_afu_irq_alloc(ctx, &irq_id);
0228 if (!rc) {
0229 irq_offset = ocxl_irq_id_to_offset(ctx, irq_id);
0230 rc = copy_to_user((u64 __user *) args, &irq_offset,
0231 sizeof(irq_offset));
0232 if (rc) {
0233 ocxl_afu_irq_free(ctx, irq_id);
0234 return -EFAULT;
0235 }
0236 }
0237 break;
0238
0239 case OCXL_IOCTL_IRQ_FREE:
0240 rc = copy_from_user(&irq_offset, (u64 __user *) args,
0241 sizeof(irq_offset));
0242 if (rc)
0243 return -EFAULT;
0244 irq_id = ocxl_irq_offset_to_id(ctx, irq_offset);
0245 rc = ocxl_afu_irq_free(ctx, irq_id);
0246 break;
0247
0248 case OCXL_IOCTL_IRQ_SET_FD:
0249 rc = copy_from_user(&irq_fd, (u64 __user *) args,
0250 sizeof(irq_fd));
0251 if (rc)
0252 return -EFAULT;
0253 if (irq_fd.reserved)
0254 return -EINVAL;
0255 irq_id = ocxl_irq_offset_to_id(ctx, irq_fd.irq_offset);
0256 ev_ctx = eventfd_ctx_fdget(irq_fd.eventfd);
0257 if (IS_ERR(ev_ctx))
0258 return PTR_ERR(ev_ctx);
0259 rc = ocxl_irq_set_handler(ctx, irq_id, irq_handler, irq_free, ev_ctx);
0260 break;
0261
0262 case OCXL_IOCTL_GET_METADATA:
0263 rc = afu_ioctl_get_metadata(ctx,
0264 (struct ocxl_ioctl_metadata __user *) args);
0265 break;
0266
0267 #ifdef CONFIG_PPC64
0268 case OCXL_IOCTL_ENABLE_P9_WAIT:
0269 rc = afu_ioctl_enable_p9_wait(ctx,
0270 (struct ocxl_ioctl_p9_wait __user *) args);
0271 break;
0272 #endif
0273
0274 case OCXL_IOCTL_GET_FEATURES:
0275 rc = afu_ioctl_get_features(ctx,
0276 (struct ocxl_ioctl_features __user *) args);
0277 break;
0278
0279 default:
0280 rc = -EINVAL;
0281 }
0282 return rc;
0283 }
0284
0285 static long afu_compat_ioctl(struct file *file, unsigned int cmd,
0286 unsigned long args)
0287 {
0288 return afu_ioctl(file, cmd, args);
0289 }
0290
0291 static int afu_mmap(struct file *file, struct vm_area_struct *vma)
0292 {
0293 struct ocxl_context *ctx = file->private_data;
0294
0295 pr_debug("%s for context %d\n", __func__, ctx->pasid);
0296 return ocxl_context_mmap(ctx, vma);
0297 }
0298
0299 static bool has_xsl_error(struct ocxl_context *ctx)
0300 {
0301 bool ret;
0302
0303 mutex_lock(&ctx->xsl_error_lock);
0304 ret = !!ctx->xsl_error.addr;
0305 mutex_unlock(&ctx->xsl_error_lock);
0306
0307 return ret;
0308 }
0309
0310
0311
0312
0313
0314
0315 static bool afu_events_pending(struct ocxl_context *ctx)
0316 {
0317 if (has_xsl_error(ctx))
0318 return true;
0319 return false;
0320 }
0321
0322 static unsigned int afu_poll(struct file *file, struct poll_table_struct *wait)
0323 {
0324 struct ocxl_context *ctx = file->private_data;
0325 unsigned int mask = 0;
0326 bool closed;
0327
0328 pr_debug("%s for context %d\n", __func__, ctx->pasid);
0329
0330 poll_wait(file, &ctx->events_wq, wait);
0331
0332 mutex_lock(&ctx->status_mutex);
0333 closed = (ctx->status == CLOSED);
0334 mutex_unlock(&ctx->status_mutex);
0335
0336 if (afu_events_pending(ctx))
0337 mask = EPOLLIN | EPOLLRDNORM;
0338 else if (closed)
0339 mask = EPOLLERR;
0340
0341 return mask;
0342 }
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352 static ssize_t append_xsl_error(struct ocxl_context *ctx,
0353 struct ocxl_kernel_event_header *header,
0354 char __user *buf)
0355 {
0356 struct ocxl_kernel_event_xsl_fault_error body;
0357
0358 memset(&body, 0, sizeof(body));
0359
0360 mutex_lock(&ctx->xsl_error_lock);
0361 if (!ctx->xsl_error.addr) {
0362 mutex_unlock(&ctx->xsl_error_lock);
0363 return 0;
0364 }
0365
0366 body.addr = ctx->xsl_error.addr;
0367 body.dsisr = ctx->xsl_error.dsisr;
0368 body.count = ctx->xsl_error.count;
0369
0370 ctx->xsl_error.addr = 0;
0371 ctx->xsl_error.dsisr = 0;
0372 ctx->xsl_error.count = 0;
0373
0374 mutex_unlock(&ctx->xsl_error_lock);
0375
0376 header->type = OCXL_AFU_EVENT_XSL_FAULT_ERROR;
0377
0378 if (copy_to_user(buf, &body, sizeof(body)))
0379 return -EFAULT;
0380
0381 return sizeof(body);
0382 }
0383
0384 #define AFU_EVENT_BODY_MAX_SIZE sizeof(struct ocxl_kernel_event_xsl_fault_error)
0385
0386
0387
0388
0389
0390
0391
0392
0393 static ssize_t afu_read(struct file *file, char __user *buf, size_t count,
0394 loff_t *off)
0395 {
0396 struct ocxl_context *ctx = file->private_data;
0397 struct ocxl_kernel_event_header header;
0398 ssize_t rc;
0399 ssize_t used = 0;
0400 DEFINE_WAIT(event_wait);
0401
0402 memset(&header, 0, sizeof(header));
0403
0404
0405 if (*off != 0)
0406 return -EINVAL;
0407
0408 if (count < (sizeof(struct ocxl_kernel_event_header) +
0409 AFU_EVENT_BODY_MAX_SIZE))
0410 return -EINVAL;
0411
0412 for (;;) {
0413 prepare_to_wait(&ctx->events_wq, &event_wait,
0414 TASK_INTERRUPTIBLE);
0415
0416 if (afu_events_pending(ctx))
0417 break;
0418
0419 if (ctx->status == CLOSED)
0420 break;
0421
0422 if (file->f_flags & O_NONBLOCK) {
0423 finish_wait(&ctx->events_wq, &event_wait);
0424 return -EAGAIN;
0425 }
0426
0427 if (signal_pending(current)) {
0428 finish_wait(&ctx->events_wq, &event_wait);
0429 return -ERESTARTSYS;
0430 }
0431
0432 schedule();
0433 }
0434
0435 finish_wait(&ctx->events_wq, &event_wait);
0436
0437 if (has_xsl_error(ctx)) {
0438 used = append_xsl_error(ctx, &header, buf + sizeof(header));
0439 if (used < 0)
0440 return used;
0441 }
0442
0443 if (!afu_events_pending(ctx))
0444 header.flags |= OCXL_KERNEL_EVENT_FLAG_LAST;
0445
0446 if (copy_to_user(buf, &header, sizeof(header)))
0447 return -EFAULT;
0448
0449 used += sizeof(header);
0450
0451 rc = used;
0452 return rc;
0453 }
0454
0455 static int afu_release(struct inode *inode, struct file *file)
0456 {
0457 struct ocxl_context *ctx = file->private_data;
0458 int rc;
0459
0460 pr_debug("%s for device %x\n", __func__, inode->i_rdev);
0461 rc = ocxl_context_detach(ctx);
0462 mutex_lock(&ctx->mapping_lock);
0463 ctx->mapping = NULL;
0464 mutex_unlock(&ctx->mapping_lock);
0465 wake_up_all(&ctx->events_wq);
0466 if (rc != -EBUSY)
0467 ocxl_context_free(ctx);
0468 return 0;
0469 }
0470
0471 static const struct file_operations ocxl_afu_fops = {
0472 .owner = THIS_MODULE,
0473 .open = afu_open,
0474 .unlocked_ioctl = afu_ioctl,
0475 .compat_ioctl = afu_compat_ioctl,
0476 .mmap = afu_mmap,
0477 .poll = afu_poll,
0478 .read = afu_read,
0479 .release = afu_release,
0480 };
0481
0482
0483 static void info_release(struct device *dev)
0484 {
0485 struct ocxl_file_info *info = container_of(dev, struct ocxl_file_info, dev);
0486
0487 ocxl_afu_put(info->afu);
0488 kfree(info);
0489 }
0490
0491 static int ocxl_file_make_visible(struct ocxl_file_info *info)
0492 {
0493 int rc;
0494
0495 cdev_init(&info->cdev, &ocxl_afu_fops);
0496 rc = cdev_add(&info->cdev, info->dev.devt, 1);
0497 if (rc) {
0498 dev_err(&info->dev, "Unable to add afu char device: %d\n", rc);
0499 return rc;
0500 }
0501
0502 return 0;
0503 }
0504
0505 static void ocxl_file_make_invisible(struct ocxl_file_info *info)
0506 {
0507 cdev_del(&info->cdev);
0508 }
0509
0510 int ocxl_file_register_afu(struct ocxl_afu *afu)
0511 {
0512 int minor;
0513 int rc;
0514 struct ocxl_file_info *info;
0515 struct ocxl_fn *fn = afu->fn;
0516 struct pci_dev *pci_dev = to_pci_dev(fn->dev.parent);
0517
0518 info = kzalloc(sizeof(*info), GFP_KERNEL);
0519 if (info == NULL)
0520 return -ENOMEM;
0521
0522 minor = allocate_minor(info);
0523 if (minor < 0) {
0524 kfree(info);
0525 return minor;
0526 }
0527
0528 info->dev.parent = &fn->dev;
0529 info->dev.devt = MKDEV(MAJOR(ocxl_dev), minor);
0530 info->dev.class = ocxl_class;
0531 info->dev.release = info_release;
0532
0533 info->afu = afu;
0534 ocxl_afu_get(afu);
0535
0536 rc = dev_set_name(&info->dev, "%s.%s.%hhu",
0537 afu->config.name, dev_name(&pci_dev->dev), afu->config.idx);
0538 if (rc)
0539 goto err_put;
0540
0541 rc = device_register(&info->dev);
0542 if (rc)
0543 goto err_put;
0544
0545 rc = ocxl_sysfs_register_afu(info);
0546 if (rc)
0547 goto err_unregister;
0548
0549 rc = ocxl_file_make_visible(info);
0550 if (rc)
0551 goto err_unregister;
0552
0553 ocxl_afu_set_private(afu, info);
0554
0555 return 0;
0556
0557 err_unregister:
0558 ocxl_sysfs_unregister_afu(info);
0559 free_minor(info);
0560 device_unregister(&info->dev);
0561 return rc;
0562 err_put:
0563 ocxl_afu_put(afu);
0564 free_minor(info);
0565 kfree(info);
0566 return rc;
0567 }
0568
0569 void ocxl_file_unregister_afu(struct ocxl_afu *afu)
0570 {
0571 struct ocxl_file_info *info = ocxl_afu_get_private(afu);
0572
0573 if (!info)
0574 return;
0575
0576 ocxl_file_make_invisible(info);
0577 ocxl_sysfs_unregister_afu(info);
0578 free_minor(info);
0579 device_unregister(&info->dev);
0580 }
0581
0582 static char *ocxl_devnode(struct device *dev, umode_t *mode)
0583 {
0584 return kasprintf(GFP_KERNEL, "ocxl/%s", dev_name(dev));
0585 }
0586
0587 int ocxl_file_init(void)
0588 {
0589 int rc;
0590
0591 idr_init(&minors_idr);
0592
0593 rc = alloc_chrdev_region(&ocxl_dev, 0, OCXL_NUM_MINORS, "ocxl");
0594 if (rc) {
0595 pr_err("Unable to allocate ocxl major number: %d\n", rc);
0596 return rc;
0597 }
0598
0599 ocxl_class = class_create(THIS_MODULE, "ocxl");
0600 if (IS_ERR(ocxl_class)) {
0601 pr_err("Unable to create ocxl class\n");
0602 unregister_chrdev_region(ocxl_dev, OCXL_NUM_MINORS);
0603 return PTR_ERR(ocxl_class);
0604 }
0605
0606 ocxl_class->devnode = ocxl_devnode;
0607 return 0;
0608 }
0609
0610 void ocxl_file_exit(void)
0611 {
0612 class_destroy(ocxl_class);
0613 unregister_chrdev_region(ocxl_dev, OCXL_NUM_MINORS);
0614 idr_destroy(&minors_idr);
0615 }