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

file.c (13514B)


      1// SPDX-License-Identifier: GPL-2.0+
      2// Copyright 2017 IBM Corp.
      3#include <linux/fs.h>
      4#include <linux/poll.h>
      5#include <linux/sched/signal.h>
      6#include <linux/eventfd.h>
      7#include <linux/uaccess.h>
      8#include <uapi/misc/ocxl.h>
      9#include <asm/reg.h>
     10#include <asm/switch_to.h>
     11#include "ocxl_internal.h"
     12
     13
     14#define OCXL_NUM_MINORS 256 /* Total to reserve */
     15
     16static dev_t ocxl_dev;
     17static struct class *ocxl_class;
     18static DEFINE_MUTEX(minors_idr_lock);
     19static struct idr minors_idr;
     20
     21static struct ocxl_file_info *find_and_get_file_info(dev_t devno)
     22{
     23	struct ocxl_file_info *info;
     24
     25	mutex_lock(&minors_idr_lock);
     26	info = idr_find(&minors_idr, MINOR(devno));
     27	if (info)
     28		get_device(&info->dev);
     29	mutex_unlock(&minors_idr_lock);
     30	return info;
     31}
     32
     33static int allocate_minor(struct ocxl_file_info *info)
     34{
     35	int minor;
     36
     37	mutex_lock(&minors_idr_lock);
     38	minor = idr_alloc(&minors_idr, info, 0, OCXL_NUM_MINORS, GFP_KERNEL);
     39	mutex_unlock(&minors_idr_lock);
     40	return minor;
     41}
     42
     43static void free_minor(struct ocxl_file_info *info)
     44{
     45	mutex_lock(&minors_idr_lock);
     46	idr_remove(&minors_idr, MINOR(info->dev.devt));
     47	mutex_unlock(&minors_idr_lock);
     48}
     49
     50static int afu_open(struct inode *inode, struct file *file)
     51{
     52	struct ocxl_file_info *info;
     53	struct ocxl_context *ctx;
     54	int rc;
     55
     56	pr_debug("%s for device %x\n", __func__, inode->i_rdev);
     57
     58	info = find_and_get_file_info(inode->i_rdev);
     59	if (!info)
     60		return -ENODEV;
     61
     62	rc = ocxl_context_alloc(&ctx, info->afu, inode->i_mapping);
     63	if (rc) {
     64		put_device(&info->dev);
     65		return rc;
     66	}
     67	put_device(&info->dev);
     68	file->private_data = ctx;
     69	return 0;
     70}
     71
     72static long afu_ioctl_attach(struct ocxl_context *ctx,
     73			struct ocxl_ioctl_attach __user *uarg)
     74{
     75	struct ocxl_ioctl_attach arg;
     76	u64 amr = 0;
     77
     78	pr_debug("%s for context %d\n", __func__, ctx->pasid);
     79
     80	if (copy_from_user(&arg, uarg, sizeof(arg)))
     81		return -EFAULT;
     82
     83	/* Make sure reserved fields are not set for forward compatibility */
     84	if (arg.reserved1 || arg.reserved2 || arg.reserved3)
     85		return -EINVAL;
     86
     87	amr = arg.amr & mfspr(SPRN_UAMOR);
     88	return ocxl_context_attach(ctx, amr, current->mm);
     89}
     90
     91static long afu_ioctl_get_metadata(struct ocxl_context *ctx,
     92		struct ocxl_ioctl_metadata __user *uarg)
     93{
     94	struct ocxl_ioctl_metadata arg;
     95
     96	memset(&arg, 0, sizeof(arg));
     97
     98	arg.version = 0;
     99
    100	arg.afu_version_major = ctx->afu->config.version_major;
    101	arg.afu_version_minor = ctx->afu->config.version_minor;
    102	arg.pasid = ctx->pasid;
    103	arg.pp_mmio_size = ctx->afu->config.pp_mmio_stride;
    104	arg.global_mmio_size = ctx->afu->config.global_mmio_size;
    105
    106	if (copy_to_user(uarg, &arg, sizeof(arg)))
    107		return -EFAULT;
    108
    109	return 0;
    110}
    111
    112#ifdef CONFIG_PPC64
    113static long afu_ioctl_enable_p9_wait(struct ocxl_context *ctx,
    114		struct ocxl_ioctl_p9_wait __user *uarg)
    115{
    116	struct ocxl_ioctl_p9_wait arg;
    117
    118	memset(&arg, 0, sizeof(arg));
    119
    120	if (cpu_has_feature(CPU_FTR_P9_TIDR)) {
    121		enum ocxl_context_status status;
    122
    123		// Locks both status & tidr
    124		mutex_lock(&ctx->status_mutex);
    125		if (!ctx->tidr) {
    126			if (set_thread_tidr(current)) {
    127				mutex_unlock(&ctx->status_mutex);
    128				return -ENOENT;
    129			}
    130
    131			ctx->tidr = current->thread.tidr;
    132		}
    133
    134		status = ctx->status;
    135		mutex_unlock(&ctx->status_mutex);
    136
    137		if (status == ATTACHED) {
    138			int rc = ocxl_link_update_pe(ctx->afu->fn->link,
    139				ctx->pasid, ctx->tidr);
    140
    141			if (rc)
    142				return rc;
    143		}
    144
    145		arg.thread_id = ctx->tidr;
    146	} else
    147		return -ENOENT;
    148
    149	if (copy_to_user(uarg, &arg, sizeof(arg)))
    150		return -EFAULT;
    151
    152	return 0;
    153}
    154#endif
    155
    156
    157static long afu_ioctl_get_features(struct ocxl_context *ctx,
    158		struct ocxl_ioctl_features __user *uarg)
    159{
    160	struct ocxl_ioctl_features arg;
    161
    162	memset(&arg, 0, sizeof(arg));
    163
    164#ifdef CONFIG_PPC64
    165	if (cpu_has_feature(CPU_FTR_P9_TIDR))
    166		arg.flags[0] |= OCXL_IOCTL_FEATURES_FLAGS0_P9_WAIT;
    167#endif
    168
    169	if (copy_to_user(uarg, &arg, sizeof(arg)))
    170		return -EFAULT;
    171
    172	return 0;
    173}
    174
    175#define CMD_STR(x) (x == OCXL_IOCTL_ATTACH ? "ATTACH" :			\
    176			x == OCXL_IOCTL_IRQ_ALLOC ? "IRQ_ALLOC" :	\
    177			x == OCXL_IOCTL_IRQ_FREE ? "IRQ_FREE" :		\
    178			x == OCXL_IOCTL_IRQ_SET_FD ? "IRQ_SET_FD" :	\
    179			x == OCXL_IOCTL_GET_METADATA ? "GET_METADATA" :	\
    180			x == OCXL_IOCTL_ENABLE_P9_WAIT ? "ENABLE_P9_WAIT" :	\
    181			x == OCXL_IOCTL_GET_FEATURES ? "GET_FEATURES" :	\
    182			"UNKNOWN")
    183
    184static irqreturn_t irq_handler(void *private)
    185{
    186	struct eventfd_ctx *ev_ctx = private;
    187
    188	eventfd_signal(ev_ctx, 1);
    189	return IRQ_HANDLED;
    190}
    191
    192static void irq_free(void *private)
    193{
    194	struct eventfd_ctx *ev_ctx = private;
    195
    196	eventfd_ctx_put(ev_ctx);
    197}
    198
    199static long afu_ioctl(struct file *file, unsigned int cmd,
    200		unsigned long args)
    201{
    202	struct ocxl_context *ctx = file->private_data;
    203	struct ocxl_ioctl_irq_fd irq_fd;
    204	struct eventfd_ctx *ev_ctx;
    205	int irq_id;
    206	u64 irq_offset;
    207	long rc;
    208	bool closed;
    209
    210	pr_debug("%s for context %d, command %s\n", __func__, ctx->pasid,
    211		CMD_STR(cmd));
    212
    213	mutex_lock(&ctx->status_mutex);
    214	closed = (ctx->status == CLOSED);
    215	mutex_unlock(&ctx->status_mutex);
    216
    217	if (closed)
    218		return -EIO;
    219
    220	switch (cmd) {
    221	case OCXL_IOCTL_ATTACH:
    222		rc = afu_ioctl_attach(ctx,
    223				(struct ocxl_ioctl_attach __user *) args);
    224		break;
    225
    226	case OCXL_IOCTL_IRQ_ALLOC:
    227		rc = ocxl_afu_irq_alloc(ctx, &irq_id);
    228		if (!rc) {
    229			irq_offset = ocxl_irq_id_to_offset(ctx, irq_id);
    230			rc = copy_to_user((u64 __user *) args, &irq_offset,
    231					sizeof(irq_offset));
    232			if (rc) {
    233				ocxl_afu_irq_free(ctx, irq_id);
    234				return -EFAULT;
    235			}
    236		}
    237		break;
    238
    239	case OCXL_IOCTL_IRQ_FREE:
    240		rc = copy_from_user(&irq_offset, (u64 __user *) args,
    241				sizeof(irq_offset));
    242		if (rc)
    243			return -EFAULT;
    244		irq_id = ocxl_irq_offset_to_id(ctx, irq_offset);
    245		rc = ocxl_afu_irq_free(ctx, irq_id);
    246		break;
    247
    248	case OCXL_IOCTL_IRQ_SET_FD:
    249		rc = copy_from_user(&irq_fd, (u64 __user *) args,
    250				sizeof(irq_fd));
    251		if (rc)
    252			return -EFAULT;
    253		if (irq_fd.reserved)
    254			return -EINVAL;
    255		irq_id = ocxl_irq_offset_to_id(ctx, irq_fd.irq_offset);
    256		ev_ctx = eventfd_ctx_fdget(irq_fd.eventfd);
    257		if (IS_ERR(ev_ctx))
    258			return PTR_ERR(ev_ctx);
    259		rc = ocxl_irq_set_handler(ctx, irq_id, irq_handler, irq_free, ev_ctx);
    260		break;
    261
    262	case OCXL_IOCTL_GET_METADATA:
    263		rc = afu_ioctl_get_metadata(ctx,
    264				(struct ocxl_ioctl_metadata __user *) args);
    265		break;
    266
    267#ifdef CONFIG_PPC64
    268	case OCXL_IOCTL_ENABLE_P9_WAIT:
    269		rc = afu_ioctl_enable_p9_wait(ctx,
    270				(struct ocxl_ioctl_p9_wait __user *) args);
    271		break;
    272#endif
    273
    274	case OCXL_IOCTL_GET_FEATURES:
    275		rc = afu_ioctl_get_features(ctx,
    276				(struct ocxl_ioctl_features __user *) args);
    277		break;
    278
    279	default:
    280		rc = -EINVAL;
    281	}
    282	return rc;
    283}
    284
    285static long afu_compat_ioctl(struct file *file, unsigned int cmd,
    286			unsigned long args)
    287{
    288	return afu_ioctl(file, cmd, args);
    289}
    290
    291static int afu_mmap(struct file *file, struct vm_area_struct *vma)
    292{
    293	struct ocxl_context *ctx = file->private_data;
    294
    295	pr_debug("%s for context %d\n", __func__, ctx->pasid);
    296	return ocxl_context_mmap(ctx, vma);
    297}
    298
    299static bool has_xsl_error(struct ocxl_context *ctx)
    300{
    301	bool ret;
    302
    303	mutex_lock(&ctx->xsl_error_lock);
    304	ret = !!ctx->xsl_error.addr;
    305	mutex_unlock(&ctx->xsl_error_lock);
    306
    307	return ret;
    308}
    309
    310/*
    311 * Are there any events pending on the AFU
    312 * ctx: The AFU context
    313 * Returns: true if there are events pending
    314 */
    315static bool afu_events_pending(struct ocxl_context *ctx)
    316{
    317	if (has_xsl_error(ctx))
    318		return true;
    319	return false;
    320}
    321
    322static unsigned int afu_poll(struct file *file, struct poll_table_struct *wait)
    323{
    324	struct ocxl_context *ctx = file->private_data;
    325	unsigned int mask = 0;
    326	bool closed;
    327
    328	pr_debug("%s for context %d\n", __func__, ctx->pasid);
    329
    330	poll_wait(file, &ctx->events_wq, wait);
    331
    332	mutex_lock(&ctx->status_mutex);
    333	closed = (ctx->status == CLOSED);
    334	mutex_unlock(&ctx->status_mutex);
    335
    336	if (afu_events_pending(ctx))
    337		mask = EPOLLIN | EPOLLRDNORM;
    338	else if (closed)
    339		mask = EPOLLERR;
    340
    341	return mask;
    342}
    343
    344/*
    345 * Populate the supplied buffer with a single XSL error
    346 * ctx:	The AFU context to report the error from
    347 * header: the event header to populate
    348 * buf: The buffer to write the body into (should be at least
    349 *      AFU_EVENT_BODY_XSL_ERROR_SIZE)
    350 * Return: the amount of buffer that was populated
    351 */
    352static ssize_t append_xsl_error(struct ocxl_context *ctx,
    353				struct ocxl_kernel_event_header *header,
    354				char __user *buf)
    355{
    356	struct ocxl_kernel_event_xsl_fault_error body;
    357
    358	memset(&body, 0, sizeof(body));
    359
    360	mutex_lock(&ctx->xsl_error_lock);
    361	if (!ctx->xsl_error.addr) {
    362		mutex_unlock(&ctx->xsl_error_lock);
    363		return 0;
    364	}
    365
    366	body.addr = ctx->xsl_error.addr;
    367	body.dsisr = ctx->xsl_error.dsisr;
    368	body.count = ctx->xsl_error.count;
    369
    370	ctx->xsl_error.addr = 0;
    371	ctx->xsl_error.dsisr = 0;
    372	ctx->xsl_error.count = 0;
    373
    374	mutex_unlock(&ctx->xsl_error_lock);
    375
    376	header->type = OCXL_AFU_EVENT_XSL_FAULT_ERROR;
    377
    378	if (copy_to_user(buf, &body, sizeof(body)))
    379		return -EFAULT;
    380
    381	return sizeof(body);
    382}
    383
    384#define AFU_EVENT_BODY_MAX_SIZE sizeof(struct ocxl_kernel_event_xsl_fault_error)
    385
    386/*
    387 * Reports events on the AFU
    388 * Format:
    389 *	Header (struct ocxl_kernel_event_header)
    390 *	Body (struct ocxl_kernel_event_*)
    391 *	Header...
    392 */
    393static ssize_t afu_read(struct file *file, char __user *buf, size_t count,
    394			loff_t *off)
    395{
    396	struct ocxl_context *ctx = file->private_data;
    397	struct ocxl_kernel_event_header header;
    398	ssize_t rc;
    399	ssize_t used = 0;
    400	DEFINE_WAIT(event_wait);
    401
    402	memset(&header, 0, sizeof(header));
    403
    404	/* Require offset to be 0 */
    405	if (*off != 0)
    406		return -EINVAL;
    407
    408	if (count < (sizeof(struct ocxl_kernel_event_header) +
    409			AFU_EVENT_BODY_MAX_SIZE))
    410		return -EINVAL;
    411
    412	for (;;) {
    413		prepare_to_wait(&ctx->events_wq, &event_wait,
    414				TASK_INTERRUPTIBLE);
    415
    416		if (afu_events_pending(ctx))
    417			break;
    418
    419		if (ctx->status == CLOSED)
    420			break;
    421
    422		if (file->f_flags & O_NONBLOCK) {
    423			finish_wait(&ctx->events_wq, &event_wait);
    424			return -EAGAIN;
    425		}
    426
    427		if (signal_pending(current)) {
    428			finish_wait(&ctx->events_wq, &event_wait);
    429			return -ERESTARTSYS;
    430		}
    431
    432		schedule();
    433	}
    434
    435	finish_wait(&ctx->events_wq, &event_wait);
    436
    437	if (has_xsl_error(ctx)) {
    438		used = append_xsl_error(ctx, &header, buf + sizeof(header));
    439		if (used < 0)
    440			return used;
    441	}
    442
    443	if (!afu_events_pending(ctx))
    444		header.flags |= OCXL_KERNEL_EVENT_FLAG_LAST;
    445
    446	if (copy_to_user(buf, &header, sizeof(header)))
    447		return -EFAULT;
    448
    449	used += sizeof(header);
    450
    451	rc = used;
    452	return rc;
    453}
    454
    455static int afu_release(struct inode *inode, struct file *file)
    456{
    457	struct ocxl_context *ctx = file->private_data;
    458	int rc;
    459
    460	pr_debug("%s for device %x\n", __func__, inode->i_rdev);
    461	rc = ocxl_context_detach(ctx);
    462	mutex_lock(&ctx->mapping_lock);
    463	ctx->mapping = NULL;
    464	mutex_unlock(&ctx->mapping_lock);
    465	wake_up_all(&ctx->events_wq);
    466	if (rc != -EBUSY)
    467		ocxl_context_free(ctx);
    468	return 0;
    469}
    470
    471static const struct file_operations ocxl_afu_fops = {
    472	.owner		= THIS_MODULE,
    473	.open           = afu_open,
    474	.unlocked_ioctl = afu_ioctl,
    475	.compat_ioctl   = afu_compat_ioctl,
    476	.mmap           = afu_mmap,
    477	.poll           = afu_poll,
    478	.read           = afu_read,
    479	.release        = afu_release,
    480};
    481
    482// Free the info struct
    483static void info_release(struct device *dev)
    484{
    485	struct ocxl_file_info *info = container_of(dev, struct ocxl_file_info, dev);
    486
    487	ocxl_afu_put(info->afu);
    488	kfree(info);
    489}
    490
    491static int ocxl_file_make_visible(struct ocxl_file_info *info)
    492{
    493	int rc;
    494
    495	cdev_init(&info->cdev, &ocxl_afu_fops);
    496	rc = cdev_add(&info->cdev, info->dev.devt, 1);
    497	if (rc) {
    498		dev_err(&info->dev, "Unable to add afu char device: %d\n", rc);
    499		return rc;
    500	}
    501
    502	return 0;
    503}
    504
    505static void ocxl_file_make_invisible(struct ocxl_file_info *info)
    506{
    507	cdev_del(&info->cdev);
    508}
    509
    510int ocxl_file_register_afu(struct ocxl_afu *afu)
    511{
    512	int minor;
    513	int rc;
    514	struct ocxl_file_info *info;
    515	struct ocxl_fn *fn = afu->fn;
    516	struct pci_dev *pci_dev = to_pci_dev(fn->dev.parent);
    517
    518	info = kzalloc(sizeof(*info), GFP_KERNEL);
    519	if (info == NULL)
    520		return -ENOMEM;
    521
    522	minor = allocate_minor(info);
    523	if (minor < 0) {
    524		kfree(info);
    525		return minor;
    526	}
    527
    528	info->dev.parent = &fn->dev;
    529	info->dev.devt = MKDEV(MAJOR(ocxl_dev), minor);
    530	info->dev.class = ocxl_class;
    531	info->dev.release = info_release;
    532
    533	info->afu = afu;
    534	ocxl_afu_get(afu);
    535
    536	rc = dev_set_name(&info->dev, "%s.%s.%hhu",
    537		afu->config.name, dev_name(&pci_dev->dev), afu->config.idx);
    538	if (rc)
    539		goto err_put;
    540
    541	rc = device_register(&info->dev);
    542	if (rc)
    543		goto err_put;
    544
    545	rc = ocxl_sysfs_register_afu(info);
    546	if (rc)
    547		goto err_unregister;
    548
    549	rc = ocxl_file_make_visible(info);
    550	if (rc)
    551		goto err_unregister;
    552
    553	ocxl_afu_set_private(afu, info);
    554
    555	return 0;
    556
    557err_unregister:
    558	ocxl_sysfs_unregister_afu(info); // safe to call even if register failed
    559	free_minor(info);
    560	device_unregister(&info->dev);
    561	return rc;
    562err_put:
    563	ocxl_afu_put(afu);
    564	free_minor(info);
    565	kfree(info);
    566	return rc;
    567}
    568
    569void ocxl_file_unregister_afu(struct ocxl_afu *afu)
    570{
    571	struct ocxl_file_info *info = ocxl_afu_get_private(afu);
    572
    573	if (!info)
    574		return;
    575
    576	ocxl_file_make_invisible(info);
    577	ocxl_sysfs_unregister_afu(info);
    578	free_minor(info);
    579	device_unregister(&info->dev);
    580}
    581
    582static char *ocxl_devnode(struct device *dev, umode_t *mode)
    583{
    584	return kasprintf(GFP_KERNEL, "ocxl/%s", dev_name(dev));
    585}
    586
    587int ocxl_file_init(void)
    588{
    589	int rc;
    590
    591	idr_init(&minors_idr);
    592
    593	rc = alloc_chrdev_region(&ocxl_dev, 0, OCXL_NUM_MINORS, "ocxl");
    594	if (rc) {
    595		pr_err("Unable to allocate ocxl major number: %d\n", rc);
    596		return rc;
    597	}
    598
    599	ocxl_class = class_create(THIS_MODULE, "ocxl");
    600	if (IS_ERR(ocxl_class)) {
    601		pr_err("Unable to create ocxl class\n");
    602		unregister_chrdev_region(ocxl_dev, OCXL_NUM_MINORS);
    603		return PTR_ERR(ocxl_class);
    604	}
    605
    606	ocxl_class->devnode = ocxl_devnode;
    607	return 0;
    608}
    609
    610void ocxl_file_exit(void)
    611{
    612	class_destroy(ocxl_class);
    613	unregister_chrdev_region(ocxl_dev, OCXL_NUM_MINORS);
    614	idr_destroy(&minors_idr);
    615}