1 /* $OpenBSD: uaccess.h,v 1.7 2022/02/01 04:09:14 jsg Exp $ */
2 /*
3 * Copyright (c) 2015 Mark Kettenis
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #ifndef _LINUX_UACCESS_H
19 #define _LINUX_UACCESS_H
20
21 #include <sys/param.h>
22 #include <sys/systm.h>
23 #include <uvm/uvm_extern.h>
24
25 #include <linux/sched.h>
26
27 static inline unsigned long
__copy_to_user(void * to,const void * from,unsigned long len)28 __copy_to_user(void *to, const void *from, unsigned long len)
29 {
30 if (copyout(from, to, len))
31 return len;
32 return 0;
33 }
34
35 static inline unsigned long
copy_to_user(void * to,const void * from,unsigned long len)36 copy_to_user(void *to, const void *from, unsigned long len)
37 {
38 return __copy_to_user(to, from, len);
39 }
40
41 static inline unsigned long
__copy_from_user(void * to,const void * from,unsigned long len)42 __copy_from_user(void *to, const void *from, unsigned long len)
43 {
44 if (copyin(from, to, len))
45 return len;
46 return 0;
47 }
48
49 static inline unsigned long
copy_from_user(void * to,const void * from,unsigned long len)50 copy_from_user(void *to, const void *from, unsigned long len)
51 {
52 return __copy_from_user(to, from, len);
53 }
54
55 #define get_user(x, ptr) -copyin(ptr, &(x), sizeof(x))
56 #define put_user(x, ptr) ({ \
57 __typeof((x)) __tmp = (x); \
58 -copyout(&(__tmp), ptr, sizeof(__tmp)); \
59 })
60 #define __get_user(x, ptr) get_user((x), (ptr))
61 #define __put_user(x, ptr) put_user((x), (ptr))
62
63 #define unsafe_put_user(x, ptr, err) ({ \
64 __typeof((x)) __tmp = (x); \
65 if (copyout(&(__tmp), ptr, sizeof(__tmp)) != 0) \
66 goto err; \
67 })
68
69 static inline int
access_ok(const void * addr,unsigned long size)70 access_ok(const void *addr, unsigned long size)
71 {
72 vaddr_t startva = (vaddr_t)addr;
73 vaddr_t endva = ((vaddr_t)addr) + size;
74 return (startva >= VM_MIN_ADDRESS && endva >= VM_MIN_ADDRESS) &&
75 (startva <= VM_MAXUSER_ADDRESS && endva <= VM_MAXUSER_ADDRESS);
76 }
77
78 #define user_access_begin(addr, size) access_ok(addr, size)
79 #define user_access_end()
80
81 #define user_write_access_begin(addr, size) access_ok(addr, size)
82 #define user_write_access_end()
83
84 #if defined(__i386__) || defined(__amd64__)
85
86 static inline void
pagefault_disable(void)87 pagefault_disable(void)
88 {
89 curcpu()->ci_inatomic++;
90 KASSERT(curcpu()->ci_inatomic > 0);
91 }
92
93 static inline void
pagefault_enable(void)94 pagefault_enable(void)
95 {
96 KASSERT(curcpu()->ci_inatomic > 0);
97 curcpu()->ci_inatomic--;
98 }
99
100 static inline int
pagefault_disabled(void)101 pagefault_disabled(void)
102 {
103 return curcpu()->ci_inatomic;
104 }
105
106 static inline unsigned long
__copy_to_user_inatomic(void * to,const void * from,unsigned long len)107 __copy_to_user_inatomic(void *to, const void *from, unsigned long len)
108 {
109 struct cpu_info *ci = curcpu();
110 int inatomic = ci->ci_inatomic;
111 int error;
112
113 ci->ci_inatomic = 1;
114 error = copyout(from, to, len);
115 ci->ci_inatomic = inatomic;
116
117 return (error ? len : 0);
118 }
119
120 static inline unsigned long
__copy_from_user_inatomic(void * to,const void * from,unsigned long len)121 __copy_from_user_inatomic(void *to, const void *from, unsigned long len)
122 {
123 struct cpu_info *ci = curcpu();
124 int inatomic = ci->ci_inatomic;
125 int error;
126
127 ci->ci_inatomic = 1;
128 error = copyin(from, to, len);
129 ci->ci_inatomic = inatomic;
130
131 return (error ? len : 0);
132 }
133
134 static inline unsigned long
__copy_from_user_inatomic_nocache(void * to,const void * from,unsigned long len)135 __copy_from_user_inatomic_nocache(void *to, const void *from, unsigned long len)
136 {
137 return __copy_from_user_inatomic(to, from, len);
138 }
139
140 #endif /* defined(__i386__) || defined(__amd64__) */
141
142 #endif
143