• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2023 Huawei Device Co., Ltd.
4  */
5 
6 #include "xpm_misc.h"
7 
8 #include <linux/mm.h>
9 #include <linux/mman.h>
10 #include <linux/file.h>
11 #include <linux/compat.h>
12 #include <linux/mm_types.h>
13 #include <linux/miscdevice.h>
14 #include <linux/xpm_types.h>
15 #include "xpm_log.h"
16 #include "xpm_report.h"
17 
18 #define XPM_SET_REGION _IOW('x', 0x01, struct xpm_region_info)
19 
xpm_set_region(unsigned long addr_base,unsigned long length)20 static int xpm_set_region(unsigned long addr_base, unsigned long length)
21 {
22 	int ret = 0;
23 	unsigned long addr;
24 	struct mm_struct *mm = current->mm;
25 
26 	if (!mm)
27 		return -EINVAL;
28 
29 	if (mmap_write_lock_killable(mm))
30 		return -EINTR;
31 
32 	if ((mm->xpm_region.addr_start != 0) ||
33 		(mm->xpm_region.addr_end != 0)) {
34 		xpm_log_info("xpm region has been set");
35 		goto exit;
36 	}
37 
38 	addr = get_unmapped_area(NULL, addr_base, length, 0, 0);
39 	if (IS_ERR_VALUE(addr) || (ULONG_MAX - addr_base < length)) {
40 		xpm_log_error("xpm get unmmaped area failed");
41 		ret = -EINVAL;
42 		goto exit;
43 	}
44 
45 	mm->xpm_region.addr_start = addr;
46 	mm->xpm_region.addr_end = addr + length;
47 exit:
48 	mmap_write_unlock(mm);
49 	return ret;
50 }
51 
xpm_ioctl(struct file * file,unsigned int cmd,unsigned long arg)52 static long xpm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
53 {
54 	int ret;
55 	struct xpm_region_info info = {0};
56 
57 	if (unlikely(copy_from_user(&info, (void __user *)(uintptr_t)arg,
58 		sizeof(struct xpm_region_info))))
59 		return -EFAULT;
60 
61 	switch (cmd) {
62 	case XPM_SET_REGION:
63 		ret = xpm_set_region(info.addr_base, info.length);
64 		break;
65 	default:
66 		xpm_log_error("xpm ioctl cmd error, cmd = %d", cmd);
67 		ret = -EINVAL;
68 		break;
69 	}
70 
71 	return ret;
72 }
73 
74 #ifdef CONFIG_COMPAT
xpm_compat_ioctl(struct file * file,unsigned int cmd,unsigned long arg)75 static long xpm_compat_ioctl(struct file *file, unsigned int cmd,
76 	unsigned long arg)
77 {
78 	return 0;
79 }
80 #endif
81 
xpm_open(struct inode * inode,struct file * file)82 static int xpm_open(struct inode *inode, struct file *file)
83 {
84 	return 0;
85 }
86 
xpm_release(struct inode * inode,struct file * file)87 static int xpm_release(struct inode *inode, struct file *file)
88 {
89 	return 0;
90 }
91 
92 static const struct file_operations xpm_fops = {
93 	.owner          = THIS_MODULE,
94 	.open           = xpm_open,
95 	.release        = xpm_release,
96 	.unlocked_ioctl = xpm_ioctl,
97 #ifdef CONFIG_COMPAT
98 	.compat_ioctl   = xpm_compat_ioctl,
99 #endif
100 };
101 
102 static struct miscdevice xpm_misc = {
103 	.minor = MISC_DYNAMIC_MINOR,
104 	.name  = "xpm",
105 	.fops  = &xpm_fops,
106 };
107 
xpm_register_misc_device(void)108 int xpm_register_misc_device(void)
109 {
110 	return misc_register(&xpm_misc);
111 }
112 
xpm_deregister_misc_device(void)113 void xpm_deregister_misc_device(void)
114 {
115 	misc_deregister(&xpm_misc);
116 }
117