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

intel_scu_ipcutil.c (3448B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Driver for the Intel SCU IPC mechanism
      4 *
      5 * (C) Copyright 2008-2010 Intel Corporation
      6 * Author: Sreedhara DS (sreedhara.ds@intel.com)
      7 *
      8 * This driver provides IOCTL interfaces to call Intel SCU IPC driver API.
      9 */
     10
     11#include <linux/errno.h>
     12#include <linux/fcntl.h>
     13#include <linux/fs.h>
     14#include <linux/kernel.h>
     15#include <linux/module.h>
     16#include <linux/sched.h>
     17#include <linux/slab.h>
     18#include <linux/types.h>
     19#include <linux/uaccess.h>
     20
     21#include <asm/intel_scu_ipc.h>
     22
     23static int major;
     24
     25struct intel_scu_ipc_dev *scu;
     26static DEFINE_MUTEX(scu_lock);
     27
     28/* IOCTL commands */
     29#define	INTE_SCU_IPC_REGISTER_READ	0
     30#define INTE_SCU_IPC_REGISTER_WRITE	1
     31#define INTE_SCU_IPC_REGISTER_UPDATE	2
     32
     33struct scu_ipc_data {
     34	u32     count;  /* No. of registers */
     35	u16     addr[5]; /* Register addresses */
     36	u8      data[5]; /* Register data */
     37	u8      mask; /* Valid for read-modify-write */
     38};
     39
     40/**
     41 *	scu_reg_access		-	implement register access ioctls
     42 *	@cmd: command we are doing (read/write/update)
     43 *	@data: kernel copy of ioctl data
     44 *
     45 *	Allow the user to perform register accesses on the SCU via the
     46 *	kernel interface
     47 */
     48
     49static int scu_reg_access(u32 cmd, struct scu_ipc_data  *data)
     50{
     51	unsigned int count = data->count;
     52
     53	if (count == 0 || count == 3 || count > 4)
     54		return -EINVAL;
     55
     56	switch (cmd) {
     57	case INTE_SCU_IPC_REGISTER_READ:
     58		return intel_scu_ipc_dev_readv(scu, data->addr, data->data, count);
     59	case INTE_SCU_IPC_REGISTER_WRITE:
     60		return intel_scu_ipc_dev_writev(scu, data->addr, data->data, count);
     61	case INTE_SCU_IPC_REGISTER_UPDATE:
     62		return intel_scu_ipc_dev_update(scu, data->addr[0], data->data[0],
     63						data->mask);
     64	default:
     65		return -ENOTTY;
     66	}
     67}
     68
     69/**
     70 *	scu_ipc_ioctl		-	control ioctls for the SCU
     71 *	@fp: file handle of the SCU device
     72 *	@cmd: ioctl coce
     73 *	@arg: pointer to user passed structure
     74 *
     75 *	Support the I/O and firmware flashing interfaces of the SCU
     76 */
     77static long scu_ipc_ioctl(struct file *fp, unsigned int cmd,
     78							unsigned long arg)
     79{
     80	int ret;
     81	struct scu_ipc_data  data;
     82	void __user *argp = (void __user *)arg;
     83
     84	if (!capable(CAP_SYS_RAWIO))
     85		return -EPERM;
     86
     87	if (copy_from_user(&data, argp, sizeof(struct scu_ipc_data)))
     88		return -EFAULT;
     89	ret = scu_reg_access(cmd, &data);
     90	if (ret < 0)
     91		return ret;
     92	if (copy_to_user(argp, &data, sizeof(struct scu_ipc_data)))
     93		return -EFAULT;
     94	return 0;
     95}
     96
     97static int scu_ipc_open(struct inode *inode, struct file *file)
     98{
     99	int ret = 0;
    100
    101	/* Only single open at the time */
    102	mutex_lock(&scu_lock);
    103	if (scu) {
    104		ret = -EBUSY;
    105		goto unlock;
    106	}
    107
    108	scu = intel_scu_ipc_dev_get();
    109	if (!scu)
    110		ret = -ENODEV;
    111
    112unlock:
    113	mutex_unlock(&scu_lock);
    114	return ret;
    115}
    116
    117static int scu_ipc_release(struct inode *inode, struct file *file)
    118{
    119	mutex_lock(&scu_lock);
    120	intel_scu_ipc_dev_put(scu);
    121	scu = NULL;
    122	mutex_unlock(&scu_lock);
    123
    124	return 0;
    125}
    126
    127static const struct file_operations scu_ipc_fops = {
    128	.unlocked_ioctl = scu_ipc_ioctl,
    129	.open = scu_ipc_open,
    130	.release = scu_ipc_release,
    131};
    132
    133static int __init ipc_module_init(void)
    134{
    135	major = register_chrdev(0, "intel_mid_scu", &scu_ipc_fops);
    136	if (major < 0)
    137		return major;
    138
    139	return 0;
    140}
    141
    142static void __exit ipc_module_exit(void)
    143{
    144	unregister_chrdev(major, "intel_mid_scu");
    145}
    146
    147module_init(ipc_module_init);
    148module_exit(ipc_module_exit);
    149
    150MODULE_LICENSE("GPL v2");
    151MODULE_DESCRIPTION("Utility driver for intel scu ipc");
    152MODULE_AUTHOR("Sreedhara <sreedhara.ds@intel.com>");