1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __M68KNOMMU_UACCESS_H
3 #define __M68KNOMMU_UACCESS_H
4 
5 /*
6  * User space memory access functions
7  */
8 #include <linux/mm.h>
9 #include <linux/string.h>
10 
11 #include <asm/segment.h>
12 
13 #define access_ok(type,addr,size)	_access_ok((unsigned long)(addr),(size))
14 
15 /*
16  * It is not enough to just have access_ok check for a real RAM address.
17  * This would disallow the case of code/ro-data running XIP in flash/rom.
18  * Ideally we would check the possible flash ranges too, but that is
19  * currently not so easy.
20  */
_access_ok(unsigned long addr,unsigned long size)21 static inline int _access_ok(unsigned long addr, unsigned long size)
22 {
23 	return 1;
24 }
25 
26 /*
27  * These are the main single-value transfer routines.  They automatically
28  * use the right size if we just have the right pointer type.
29  */
30 
31 #define put_user(x, ptr)				\
32 ({							\
33     int __pu_err = 0;					\
34     typeof(*(ptr)) __pu_val = (x);			\
35     switch (sizeof (*(ptr))) {				\
36     case 1:						\
37 	__put_user_asm(__pu_err, __pu_val, ptr, b);	\
38 	break;						\
39     case 2:						\
40 	__put_user_asm(__pu_err, __pu_val, ptr, w);	\
41 	break;						\
42     case 4:						\
43 	__put_user_asm(__pu_err, __pu_val, ptr, l);	\
44 	break;						\
45     case 8:						\
46 	memcpy(ptr, &__pu_val, sizeof (*(ptr))); \
47 	break;						\
48     default:						\
49 	__pu_err = __put_user_bad();			\
50 	break;						\
51     }							\
52     __pu_err;						\
53 })
54 #define __put_user(x, ptr) put_user(x, ptr)
55 
56 extern int __put_user_bad(void);
57 
58 /*
59  * Tell gcc we read from memory instead of writing: this is because
60  * we do not write to any memory gcc knows about, so there are no
61  * aliasing issues.
62  */
63 
64 #define __ptr(x) ((unsigned long *)(x))
65 
66 #define __put_user_asm(err,x,ptr,bwl)				\
67 	__asm__ ("move" #bwl " %0,%1"				\
68 		: /* no outputs */						\
69 		:"d" (x),"m" (*__ptr(ptr)) : "memory")
70 
71 #define get_user(x, ptr)					\
72 ({								\
73     int __gu_err = 0;						\
74     typeof(x) __gu_val = 0;					\
75     switch (sizeof(*(ptr))) {					\
76     case 1:							\
77 	__get_user_asm(__gu_err, __gu_val, ptr, b, "=d");	\
78 	break;							\
79     case 2:							\
80 	__get_user_asm(__gu_err, __gu_val, ptr, w, "=r");	\
81 	break;							\
82     case 4:							\
83 	__get_user_asm(__gu_err, __gu_val, ptr, l, "=r");	\
84 	break;							\
85     case 8:							\
86 	memcpy((void *) &__gu_val, ptr, sizeof (*(ptr)));	\
87 	break;							\
88     default:							\
89 	__gu_val = 0;						\
90 	__gu_err = __get_user_bad();				\
91 	break;							\
92     }								\
93     (x) = (typeof(*(ptr))) __gu_val;				\
94     __gu_err;							\
95 })
96 #define __get_user(x, ptr) get_user(x, ptr)
97 
98 extern int __get_user_bad(void);
99 
100 #define __get_user_asm(err,x,ptr,bwl,reg)			\
101 	__asm__ ("move" #bwl " %1,%0"				\
102 		 : "=d" (x)					\
103 		 : "m" (*__ptr(ptr)))
104 
105 static inline unsigned long
raw_copy_from_user(void * to,const void __user * from,unsigned long n)106 raw_copy_from_user(void *to, const void __user *from, unsigned long n)
107 {
108 	memcpy(to, (__force const void *)from, n);
109 	return 0;
110 }
111 
112 static inline unsigned long
raw_copy_to_user(void __user * to,const void * from,unsigned long n)113 raw_copy_to_user(void __user *to, const void *from, unsigned long n)
114 {
115 	memcpy((__force void *)to, from, n);
116 	return 0;
117 }
118 #define INLINE_COPY_FROM_USER
119 #define INLINE_COPY_TO_USER
120 
121 /*
122  * Copy a null terminated string from userspace.
123  */
124 
125 static inline long
strncpy_from_user(char * dst,const char * src,long count)126 strncpy_from_user(char *dst, const char *src, long count)
127 {
128 	char *tmp;
129 	strncpy(dst, src, count);
130 	for (tmp = dst; *tmp && count > 0; tmp++, count--)
131 		;
132 	return(tmp - dst); /* DAVIDM should we count a NUL ?  check getname */
133 }
134 
135 /*
136  * Return the size of a string (including the ending 0)
137  *
138  * Return 0 on exception, a value greater than N if too long
139  */
strnlen_user(const char * src,long n)140 static inline long strnlen_user(const char *src, long n)
141 {
142 	return(strlen(src) + 1); /* DAVIDM make safer */
143 }
144 
145 /*
146  * Zero Userspace
147  */
148 
149 static inline unsigned long
__clear_user(void * to,unsigned long n)150 __clear_user(void *to, unsigned long n)
151 {
152 	memset(to, 0, n);
153 	return 0;
154 }
155 
156 #define	clear_user(to,n)	__clear_user(to,n)
157 
158 #endif /* _M68KNOMMU_UACCESS_H */
159