| // 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); |