xref: /OK3568_Linux_fs/kernel/arch/sh/include/asm/uaccess.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun #ifndef __ASM_SH_UACCESS_H
3*4882a593Smuzhiyun #define __ASM_SH_UACCESS_H
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun #include <asm/segment.h>
6*4882a593Smuzhiyun #include <asm/extable.h>
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #define __addr_ok(addr) \
9*4882a593Smuzhiyun 	((unsigned long __force)(addr) < current_thread_info()->addr_limit.seg)
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun /*
12*4882a593Smuzhiyun  * __access_ok: Check if address with size is OK or not.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * Uhhuh, this needs 33-bit arithmetic. We have a carry..
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * sum := addr + size;  carry? --> flag = true;
17*4882a593Smuzhiyun  * if (sum >= addr_limit) flag = true;
18*4882a593Smuzhiyun  */
19*4882a593Smuzhiyun #define __access_ok(addr, size)	({				\
20*4882a593Smuzhiyun 	unsigned long __ao_a = (addr), __ao_b = (size);		\
21*4882a593Smuzhiyun 	unsigned long __ao_end = __ao_a + __ao_b - !!__ao_b;	\
22*4882a593Smuzhiyun 	__ao_end >= __ao_a && __addr_ok(__ao_end); })
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #define access_ok(addr, size)	\
25*4882a593Smuzhiyun 	(__chk_user_ptr(addr),		\
26*4882a593Smuzhiyun 	 __access_ok((unsigned long __force)(addr), (size)))
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #define user_addr_max()	(current_thread_info()->addr_limit.seg)
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun /*
31*4882a593Smuzhiyun  * Uh, these should become the main single-value transfer routines ...
32*4882a593Smuzhiyun  * They automatically use the right size if we just have the right
33*4882a593Smuzhiyun  * pointer type ...
34*4882a593Smuzhiyun  *
35*4882a593Smuzhiyun  * As SuperH uses the same address space for kernel and user data, we
36*4882a593Smuzhiyun  * can just do these as direct assignments.
37*4882a593Smuzhiyun  *
38*4882a593Smuzhiyun  * Careful to not
39*4882a593Smuzhiyun  * (a) re-use the arguments for side effects (sizeof is ok)
40*4882a593Smuzhiyun  * (b) require any knowledge of processes at this stage
41*4882a593Smuzhiyun  */
42*4882a593Smuzhiyun #define put_user(x,ptr)		__put_user_check((x), (ptr), sizeof(*(ptr)))
43*4882a593Smuzhiyun #define get_user(x,ptr)		__get_user_check((x), (ptr), sizeof(*(ptr)))
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun /*
46*4882a593Smuzhiyun  * The "__xxx" versions do not do address space checking, useful when
47*4882a593Smuzhiyun  * doing multiple accesses to the same area (the user has to do the
48*4882a593Smuzhiyun  * checks by hand with "access_ok()")
49*4882a593Smuzhiyun  */
50*4882a593Smuzhiyun #define __put_user(x,ptr)	__put_user_nocheck((x), (ptr), sizeof(*(ptr)))
51*4882a593Smuzhiyun #define __get_user(x,ptr)	__get_user_nocheck((x), (ptr), sizeof(*(ptr)))
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun struct __large_struct { unsigned long buf[100]; };
54*4882a593Smuzhiyun #define __m(x) (*(struct __large_struct __user *)(x))
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun #define __get_user_nocheck(x,ptr,size)				\
57*4882a593Smuzhiyun ({								\
58*4882a593Smuzhiyun 	long __gu_err;						\
59*4882a593Smuzhiyun 	unsigned long __gu_val;					\
60*4882a593Smuzhiyun 	const __typeof__(*(ptr)) __user *__gu_addr = (ptr);	\
61*4882a593Smuzhiyun 	__chk_user_ptr(ptr);					\
62*4882a593Smuzhiyun 	__get_user_size(__gu_val, __gu_addr, (size), __gu_err);	\
63*4882a593Smuzhiyun 	(x) = (__force __typeof__(*(ptr)))__gu_val;		\
64*4882a593Smuzhiyun 	__gu_err;						\
65*4882a593Smuzhiyun })
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun #define __get_user_check(x,ptr,size)					\
68*4882a593Smuzhiyun ({									\
69*4882a593Smuzhiyun 	long __gu_err = -EFAULT;					\
70*4882a593Smuzhiyun 	unsigned long __gu_val = 0;					\
71*4882a593Smuzhiyun 	const __typeof__(*(ptr)) *__gu_addr = (ptr);			\
72*4882a593Smuzhiyun 	if (likely(access_ok(__gu_addr, (size))))		\
73*4882a593Smuzhiyun 		__get_user_size(__gu_val, __gu_addr, (size), __gu_err);	\
74*4882a593Smuzhiyun 	(x) = (__force __typeof__(*(ptr)))__gu_val;			\
75*4882a593Smuzhiyun 	__gu_err;							\
76*4882a593Smuzhiyun })
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun #define __put_user_nocheck(x,ptr,size)				\
79*4882a593Smuzhiyun ({								\
80*4882a593Smuzhiyun 	long __pu_err;						\
81*4882a593Smuzhiyun 	__typeof__(*(ptr)) __user *__pu_addr = (ptr);		\
82*4882a593Smuzhiyun 	__typeof__(*(ptr)) __pu_val = x;			\
83*4882a593Smuzhiyun 	__chk_user_ptr(ptr);					\
84*4882a593Smuzhiyun 	__put_user_size(__pu_val, __pu_addr, (size), __pu_err);	\
85*4882a593Smuzhiyun 	__pu_err;						\
86*4882a593Smuzhiyun })
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun #define __put_user_check(x,ptr,size)				\
89*4882a593Smuzhiyun ({								\
90*4882a593Smuzhiyun 	long __pu_err = -EFAULT;				\
91*4882a593Smuzhiyun 	__typeof__(*(ptr)) __user *__pu_addr = (ptr);		\
92*4882a593Smuzhiyun 	__typeof__(*(ptr)) __pu_val = x;			\
93*4882a593Smuzhiyun 	if (likely(access_ok(__pu_addr, size)))	\
94*4882a593Smuzhiyun 		__put_user_size(__pu_val, __pu_addr, (size),	\
95*4882a593Smuzhiyun 				__pu_err);			\
96*4882a593Smuzhiyun 	__pu_err;						\
97*4882a593Smuzhiyun })
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun # include <asm/uaccess_32.h>
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun extern long strncpy_from_user(char *dest, const char __user *src, long count);
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun extern __must_check long strnlen_user(const char __user *str, long n);
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun /* Generic arbitrary sized copy.  */
106*4882a593Smuzhiyun /* Return the number of bytes NOT copied */
107*4882a593Smuzhiyun __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun static __always_inline unsigned long
raw_copy_from_user(void * to,const void __user * from,unsigned long n)110*4882a593Smuzhiyun raw_copy_from_user(void *to, const void __user *from, unsigned long n)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun 	return __copy_user(to, (__force void *)from, n);
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun static __always_inline unsigned long __must_check
raw_copy_to_user(void __user * to,const void * from,unsigned long n)116*4882a593Smuzhiyun raw_copy_to_user(void __user *to, const void *from, unsigned long n)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun 	return __copy_user((__force void *)to, from, n);
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun #define INLINE_COPY_FROM_USER
121*4882a593Smuzhiyun #define INLINE_COPY_TO_USER
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun /*
124*4882a593Smuzhiyun  * Clear the area and return remaining number of bytes
125*4882a593Smuzhiyun  * (on failure.  Usually it's 0.)
126*4882a593Smuzhiyun  */
127*4882a593Smuzhiyun __kernel_size_t __clear_user(void *addr, __kernel_size_t size);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun #define clear_user(addr,n)						\
130*4882a593Smuzhiyun ({									\
131*4882a593Smuzhiyun 	void __user * __cl_addr = (addr);				\
132*4882a593Smuzhiyun 	unsigned long __cl_size = (n);					\
133*4882a593Smuzhiyun 									\
134*4882a593Smuzhiyun 	if (__cl_size && access_ok(__cl_addr, __cl_size))		\
135*4882a593Smuzhiyun 		__cl_size = __clear_user(__cl_addr, __cl_size);		\
136*4882a593Smuzhiyun 									\
137*4882a593Smuzhiyun 	__cl_size;							\
138*4882a593Smuzhiyun })
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun extern void *set_exception_table_vec(unsigned int vec, void *handler);
141*4882a593Smuzhiyun 
set_exception_table_evt(unsigned int evt,void * handler)142*4882a593Smuzhiyun static inline void *set_exception_table_evt(unsigned int evt, void *handler)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun 	return set_exception_table_vec(evt >> 5, handler);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun struct mem_access {
148*4882a593Smuzhiyun 	unsigned long (*from)(void *dst, const void __user *src, unsigned long cnt);
149*4882a593Smuzhiyun 	unsigned long (*to)(void __user *dst, const void *src, unsigned long cnt);
150*4882a593Smuzhiyun };
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
153*4882a593Smuzhiyun 			    struct mem_access *ma, int, unsigned long address);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun #endif /* __ASM_SH_UACCESS_H */
156