blob: d75adcd231480c09f57b7ee144b7d8ba2ab5b5aa [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
#include <linux/atomic.h>
#include <linux/compiler.h>
#include <linux/errno.h>
#include <linux/arm-smccc.h>
#include <linux/export.h>
#include <linux/types.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/hashtable.h>
#include <linux/init.h>
#include <linux/kmsan-checks.h>
#include <linux/mm.h>
#include <linux/preempt.h>
#include <linux/printk.h>
#include <linux/spinlock.h>
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <linux/kcov.h>
#include <linux/refcount.h>
#include <linux/log2.h>
#include <linux/uaccess.h>
#include <asm/setup.h>
#include <asm/kvm_asm.h>
#define PKVM_PROXY_HVC_IOC_TYPE 0
#define PKVM_PROXY_HELPER_IOC_TYPE 0
#define HVC_PROXY_IOCTL(hvcnum, numarg) \
_IOC(_IOC_WRITE, PKVM_PROXY_HVC_IOC_TYPE, hvcnum, 8 * numarg)
static int pkvm_proxy_open(struct inode *inode, struct file *filep)
{
return nonseekable_open(inode, filep);
}
static long pkvm_proxy_ioctl(struct file *filep, unsigned int cmd,
unsigned long uarg)
{
uint args_size;
u64 args[7] = {};
int id;
struct arm_smccc_res res;
switch (_IOC_TYPE(cmd)) {
case PKVM_PROXY_HVC_IOC_TYPE:
id = _IOC_NR(cmd);
args_size = ALIGN(_IOC_SIZE(cmd), sizeof(u64));
if (args_size > 7 * sizeof(u64))
return -EINVAL;
if (copy_from_user(args, (void*)uarg, args_size)) {
return -EACCES;
}
arm_smccc_1_1_hvc(KVM_HOST_SMCCC_ID(id), args[0], args[1],
args[2], args[3], args[4], args[5], args[6],
&res);
if(res.a0 != SMCCC_RET_SUCCESS)
return -EINVAL;
return res.a1;
default:
return -ENOSYS;
}
}
static int pkvm_proxy_close(struct inode *inode, struct file *filep)
{
return 0;
}
static const struct file_operations pkvm_proxy_fops = {
.open = pkvm_proxy_open,
.unlocked_ioctl = pkvm_proxy_ioctl,
.compat_ioctl = pkvm_proxy_ioctl,
/* .mmap = pkvm_proxy_mmap, */
.release = pkvm_proxy_close,
};
static int __init pkvm_proxy_init(void)
{
/*
* The pkvm_proxy debugfs file won't ever get removed and thus,
* there is no need to protect it against removal races. The
* use of debugfs_create_file_unsafe() is actually safe here.
*/
debugfs_create_file_unsafe("pkvm_proxy", 0600, NULL, NULL, &pkvm_proxy_fops);
return 0;
}
device_initcall(pkvm_proxy_init);