1/* SPDX-License-Identifier: GPL-2.0 */
2// Copyright (C) 2005-2017 Andes Technology Corporation
3
4#ifndef _ASMANDES_UACCESS_H
5#define _ASMANDES_UACCESS_H
6
7/*
8 * User space memory access functions
9 */
10#include <linux/sched.h>
11#include <asm/errno.h>
12#include <asm/memory.h>
13#include <asm/types.h>
14
15#define __asmeq(x, y)  ".ifnc " x "," y " ; .err ; .endif\n\t"
16
17/*
18 * The exception table consists of pairs of addresses: the first is the
19 * address of an instruction that is allowed to fault, and the second is
20 * the address at which the program should continue.  No registers are
21 * modified, so it is entirely up to the continuation code to figure out
22 * what to do.
23 *
24 * All the routines below use bits of fixup code that are out of line
25 * with the main instruction path.  This means when everything is well,
26 * we don't even have to jump over them.  Further, they do not intrude
27 * on our cache or tlb entries.
28 */
29
30struct exception_table_entry {
31	unsigned long insn, fixup;
32};
33
34extern int fixup_exception(struct pt_regs *regs);
35
36#define KERNEL_DS 	((mm_segment_t) { ~0UL })
37#define USER_DS		((mm_segment_t) {TASK_SIZE - 1})
38
39#define get_fs()	(current_thread_info()->addr_limit)
40#define user_addr_max	get_fs
41
42static inline void set_fs(mm_segment_t fs)
43{
44	current_thread_info()->addr_limit = fs;
45}
46
47#define uaccess_kernel()	(get_fs() == KERNEL_DS)
48
49#define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs() -size))
50
51#define access_ok(addr, size)	\
52	__range_ok((unsigned long)addr, (unsigned long)size)
53/*
54 * Single-value transfer routines.  They automatically use the right
55 * size if we just have the right pointer type.  Note that the functions
56 * which read from user space (*get_*) need to take care not to leak
57 * kernel data even if the calling code is buggy and fails to check
58 * the return value.  This means zeroing out the destination variable
59 * or buffer on error.  Normally this is done out of line by the
60 * fixup code, but there are a few places where it intrudes on the
61 * main code path.  When we only write to user space, there is no
62 * problem.
63 *
64 * The "__xxx" versions of the user access functions do not verify the
65 * address space - it must have been done previously with a separate
66 * "access_ok()" call.
67 *
68 * The "xxx_error" versions set the third argument to EFAULT if an
69 * error occurs, and leave it unchanged on success.  Note that these
70 * versions are void (ie, don't return a value as such).
71 */
72
73#define get_user(x, ptr)						\
74({									\
75	long __gu_err = 0;						\
76	__get_user_check((x), (ptr), __gu_err);				\
77	__gu_err;							\
78})
79
80#define __get_user_error(x, ptr, err)					\
81({									\
82	__get_user_check((x), (ptr), (err));				\
83	(void)0;							\
84})
85
86#define __get_user(x, ptr)						\
87({									\
88	long __gu_err = 0;						\
89	const __typeof__(*(ptr)) __user *__p = (ptr);			\
90	__get_user_err((x), __p, (__gu_err));				\
91	__gu_err;							\
92})
93
94#define __get_user_check(x, ptr, err)					\
95({									\
96	const __typeof__(*(ptr)) __user *__p = (ptr);			\
97	might_fault();							\
98	if (access_ok(__p, sizeof(*__p))) {		\
99		__get_user_err((x), __p, (err));			\
100	} else {							\
101		(x) = 0; (err) = -EFAULT;				\
102	}								\
103})
104
105#define __get_user_err(x, ptr, err)					\
106do {									\
107	unsigned long __gu_val;						\
108	__chk_user_ptr(ptr);						\
109	switch (sizeof(*(ptr))) {					\
110	case 1:								\
111		__get_user_asm("lbi", __gu_val, (ptr), (err));		\
112		break;							\
113	case 2:								\
114		__get_user_asm("lhi", __gu_val, (ptr), (err));		\
115		break;							\
116	case 4:								\
117		__get_user_asm("lwi", __gu_val, (ptr), (err));		\
118		break;							\
119	case 8:								\
120		__get_user_asm_dword(__gu_val, (ptr), (err));		\
121		break;							\
122	default:							\
123		BUILD_BUG(); 						\
124		break;							\
125	}								\
126	(x) = (__force __typeof__(*(ptr)))__gu_val;			\
127} while (0)
128
129#define __get_user_asm(inst, x, addr, err)				\
130	__asm__ __volatile__ (						\
131		"1:	"inst"	%1,[%2]\n"				\
132		"2:\n"							\
133		"	.section .fixup,\"ax\"\n"			\
134		"	.align	2\n"					\
135		"3:	move %0, %3\n"					\
136		"	move %1, #0\n"					\
137		"	b	2b\n"					\
138		"	.previous\n"					\
139		"	.section __ex_table,\"a\"\n"			\
140		"	.align	3\n"					\
141		"	.long	1b, 3b\n"				\
142		"	.previous"					\
143		: "+r" (err), "=&r" (x)					\
144		: "r" (addr), "i" (-EFAULT)				\
145		: "cc")
146
147#ifdef __NDS32_EB__
148#define __gu_reg_oper0 "%H1"
149#define __gu_reg_oper1 "%L1"
150#else
151#define __gu_reg_oper0 "%L1"
152#define __gu_reg_oper1 "%H1"
153#endif
154
155#define __get_user_asm_dword(x, addr, err) 				\
156	__asm__ __volatile__ (						\
157		"\n1:\tlwi " __gu_reg_oper0 ",[%2]\n"			\
158		"\n2:\tlwi " __gu_reg_oper1 ",[%2+4]\n"			\
159		"3:\n"							\
160		"	.section .fixup,\"ax\"\n"			\
161		"	.align	2\n"					\
162		"4:	move	%0, %3\n"				\
163		"	b	3b\n"					\
164		"	.previous\n"					\
165		"	.section __ex_table,\"a\"\n"			\
166		"	.align	3\n"					\
167		"	.long	1b, 4b\n"				\
168		"	.long	2b, 4b\n"				\
169		"	.previous"					\
170		: "+r"(err), "=&r"(x)					\
171		: "r"(addr), "i"(-EFAULT)				\
172		: "cc")
173
174#define put_user(x, ptr)						\
175({									\
176	long __pu_err = 0;						\
177	__put_user_check((x), (ptr), __pu_err);				\
178	__pu_err;							\
179})
180
181#define __put_user(x, ptr)						\
182({									\
183	long __pu_err = 0;						\
184	__typeof__(*(ptr)) __user *__p = (ptr);				\
185	__put_user_err((x), __p, __pu_err);				\
186	__pu_err;							\
187})
188
189#define __put_user_error(x, ptr, err)					\
190({									\
191	__put_user_err((x), (ptr), (err));				\
192	(void)0;							\
193})
194
195#define __put_user_check(x, ptr, err)					\
196({									\
197	__typeof__(*(ptr)) __user *__p = (ptr);				\
198	might_fault();							\
199	if (access_ok(__p, sizeof(*__p))) {		\
200		__put_user_err((x), __p, (err));			\
201	} else	{							\
202		(err) = -EFAULT;					\
203	}								\
204})
205
206#define __put_user_err(x, ptr, err)					\
207do {									\
208	__typeof__(*(ptr)) __pu_val = (x);				\
209	__chk_user_ptr(ptr);						\
210	switch (sizeof(*(ptr))) {					\
211	case 1:								\
212		__put_user_asm("sbi", __pu_val, (ptr), (err));		\
213		break;							\
214	case 2: 							\
215		__put_user_asm("shi", __pu_val, (ptr), (err));		\
216		break;							\
217	case 4: 							\
218		__put_user_asm("swi", __pu_val, (ptr), (err));		\
219		break;							\
220	case 8:								\
221		__put_user_asm_dword(__pu_val, (ptr), (err));		\
222		break;							\
223	default:							\
224		BUILD_BUG(); 						\
225		break;							\
226	}								\
227} while (0)
228
229#define __put_user_asm(inst, x, addr, err)				\
230	__asm__ __volatile__ (						\
231		"1:	"inst"	%1,[%2]\n"				\
232		"2:\n"							\
233		"	.section .fixup,\"ax\"\n"			\
234		"	.align	2\n"					\
235		"3:	move	%0, %3\n"				\
236		"	b	2b\n"					\
237		"	.previous\n"					\
238		"	.section __ex_table,\"a\"\n"			\
239		"	.align	3\n"					\
240		"	.long	1b, 3b\n"				\
241		"	.previous"					\
242		: "+r" (err)						\
243		: "r" (x), "r" (addr), "i" (-EFAULT)			\
244		: "cc")
245
246#ifdef __NDS32_EB__
247#define __pu_reg_oper0 "%H2"
248#define __pu_reg_oper1 "%L2"
249#else
250#define __pu_reg_oper0 "%L2"
251#define __pu_reg_oper1 "%H2"
252#endif
253
254#define __put_user_asm_dword(x, addr, err) 				\
255	__asm__ __volatile__ (						\
256		"\n1:\tswi " __pu_reg_oper0 ",[%1]\n"			\
257		"\n2:\tswi " __pu_reg_oper1 ",[%1+4]\n"			\
258		"3:\n"							\
259		"	.section .fixup,\"ax\"\n"			\
260		"	.align	2\n"					\
261		"4:	move	%0, %3\n"				\
262		"	b	3b\n"					\
263		"	.previous\n"					\
264		"	.section __ex_table,\"a\"\n"			\
265		"	.align	3\n"					\
266		"	.long	1b, 4b\n"				\
267		"	.long	2b, 4b\n"				\
268		"	.previous"					\
269		: "+r"(err)						\
270		: "r"(addr), "r"(x), "i"(-EFAULT)			\
271		: "cc")
272
273extern unsigned long __arch_clear_user(void __user * addr, unsigned long n);
274extern long strncpy_from_user(char *dest, const char __user * src, long count);
275extern __must_check long strlen_user(const char __user * str);
276extern __must_check long strnlen_user(const char __user * str, long n);
277extern unsigned long __arch_copy_from_user(void *to, const void __user * from,
278                                           unsigned long n);
279extern unsigned long __arch_copy_to_user(void __user * to, const void *from,
280                                         unsigned long n);
281
282#define raw_copy_from_user __arch_copy_from_user
283#define raw_copy_to_user __arch_copy_to_user
284
285#define INLINE_COPY_FROM_USER
286#define INLINE_COPY_TO_USER
287static inline unsigned long clear_user(void __user * to, unsigned long n)
288{
289	if (access_ok(to, n))
290		n = __arch_clear_user(to, n);
291	return n;
292}
293
294static inline unsigned long __clear_user(void __user * to, unsigned long n)
295{
296	return __arch_clear_user(to, n);
297}
298
299#endif /* _ASMNDS32_UACCESS_H */
300