1#ifndef __METAG_UACCESS_H
2#define __METAG_UACCESS_H
3
4
5
6
7
8
9
10
11
12
13
14
15
16#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
17
18#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
19#define USER_DS MAKE_MM_SEG(PAGE_OFFSET)
20
21#define get_ds() (KERNEL_DS)
22#define get_fs() (current_thread_info()->addr_limit)
23#define set_fs(x) (current_thread_info()->addr_limit = (x))
24
25#define segment_eq(a, b) ((a).seg == (b).seg)
26
27static inline int __access_ok(unsigned long addr, unsigned long size)
28{
29
30
31
32
33
34
35 if (likely(addr >= META_MEMORY_BASE && addr < get_fs().seg &&
36 size <= get_fs().seg - addr))
37 return true;
38
39
40
41
42
43
44
45 if (!addr)
46 return true;
47
48 if (addr >= LINCORE_CODE_BASE && addr <= LINCORE_CODE_LIMIT &&
49 size <= LINCORE_CODE_LIMIT + 1 - addr)
50 return true;
51
52 return false;
53}
54
55#define access_ok(type, addr, size) __access_ok((unsigned long)(addr), \
56 (unsigned long)(size))
57
58#include <asm/extable.h>
59
60
61
62
63
64
65#define put_user(x, ptr) \
66 __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
67#define __put_user(x, ptr) \
68 __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
69
70extern void __put_user_bad(void);
71
72#define __put_user_nocheck(x, ptr, size) \
73({ \
74 long __pu_err; \
75 __put_user_size((x), (ptr), (size), __pu_err); \
76 __pu_err; \
77})
78
79#define __put_user_check(x, ptr, size) \
80({ \
81 long __pu_err = -EFAULT; \
82 __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
83 if (access_ok(VERIFY_WRITE, __pu_addr, size)) \
84 __put_user_size((x), __pu_addr, (size), __pu_err); \
85 __pu_err; \
86})
87
88extern long __put_user_asm_b(unsigned int x, void __user *addr);
89extern long __put_user_asm_w(unsigned int x, void __user *addr);
90extern long __put_user_asm_d(unsigned int x, void __user *addr);
91extern long __put_user_asm_l(unsigned long long x, void __user *addr);
92
93#define __put_user_size(x, ptr, size, retval) \
94do { \
95 retval = 0; \
96 switch (size) { \
97 case 1: \
98 retval = __put_user_asm_b((__force unsigned int)x, ptr);\
99 break; \
100 case 2: \
101 retval = __put_user_asm_w((__force unsigned int)x, ptr);\
102 break; \
103 case 4: \
104 retval = __put_user_asm_d((__force unsigned int)x, ptr);\
105 break; \
106 case 8: \
107 retval = __put_user_asm_l((__force unsigned long long)x,\
108 ptr); \
109 break; \
110 default: \
111 __put_user_bad(); \
112 } \
113} while (0)
114
115#define get_user(x, ptr) \
116 __get_user_check((x), (ptr), sizeof(*(ptr)))
117#define __get_user(x, ptr) \
118 __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
119
120extern long __get_user_bad(void);
121
122#define __get_user_nocheck(x, ptr, size) \
123({ \
124 long __gu_err; \
125 long long __gu_val; \
126 __get_user_size(__gu_val, (ptr), (size), __gu_err); \
127 (x) = (__force __typeof__(*(ptr)))__gu_val; \
128 __gu_err; \
129})
130
131#define __get_user_check(x, ptr, size) \
132({ \
133 long __gu_err = -EFAULT; \
134 long long __gu_val = 0; \
135 const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
136 if (access_ok(VERIFY_READ, __gu_addr, size)) \
137 __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
138 (x) = (__force __typeof__(*(ptr)))__gu_val; \
139 __gu_err; \
140})
141
142extern unsigned char __get_user_asm_b(const void __user *addr, long *err);
143extern unsigned short __get_user_asm_w(const void __user *addr, long *err);
144extern unsigned int __get_user_asm_d(const void __user *addr, long *err);
145extern unsigned long long __get_user_asm_l(const void __user *addr, long *err);
146
147#define __get_user_size(x, ptr, size, retval) \
148do { \
149 retval = 0; \
150 switch (size) { \
151 case 1: \
152 x = __get_user_asm_b(ptr, &retval); break; \
153 case 2: \
154 x = __get_user_asm_w(ptr, &retval); break; \
155 case 4: \
156 x = __get_user_asm_d(ptr, &retval); break; \
157 case 8: \
158 x = __get_user_asm_l(ptr, &retval); break; \
159 default: \
160 (x) = __get_user_bad(); \
161 } \
162} while (0)
163
164
165
166
167
168
169
170
171
172
173
174extern long __must_check __strncpy_from_user(char *dst, const char __user *src,
175 long count);
176
177static inline long
178strncpy_from_user(char *dst, const char __user *src, long count)
179{
180 if (!access_ok(VERIFY_READ, src, 1))
181 return -EFAULT;
182 return __strncpy_from_user(dst, src, count);
183}
184
185
186
187
188
189extern long __must_check strnlen_user(const char __user *src, long count);
190
191extern unsigned long raw_copy_from_user(void *to, const void __user *from,
192 unsigned long n);
193extern unsigned long raw_copy_to_user(void __user *to, const void *from,
194 unsigned long n);
195
196
197
198
199
200extern unsigned long __must_check __do_clear_user(void __user *to,
201 unsigned long n);
202
203static inline unsigned long clear_user(void __user *to, unsigned long n)
204{
205 if (access_ok(VERIFY_WRITE, to, n))
206 return __do_clear_user(to, n);
207 return n;
208}
209
210#define __clear_user(to, n) __do_clear_user(to, n)
211
212#endif
213