~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/m68k/include/asm/uaccess.h

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 #ifndef __M68K_UACCESS_H
  3 #define __M68K_UACCESS_H
  4 
  5 #ifdef CONFIG_MMU
  6 
  7 /*
  8  * User space memory access functions
  9  */
 10 #include <linux/compiler.h>
 11 #include <linux/types.h>
 12 #include <asm/extable.h>
 13 #include <asm-generic/access_ok.h>
 14 
 15 /*
 16  * Not all varients of the 68k family support the notion of address spaces.
 17  * The traditional 680x0 parts do, and they use the sfc/dfc registers and
 18  * the "moves" instruction to access user space from kernel space. Other
 19  * family members like ColdFire don't support this, and only have a single
 20  * address space, and use the usual "move" instruction for user space access.
 21  *
 22  * Outside of this difference the user space access functions are the same.
 23  * So lets keep the code simple and just define in what we need to use.
 24  */
 25 #ifdef CONFIG_CPU_HAS_ADDRESS_SPACES
 26 #define MOVES   "moves"
 27 #else
 28 #define MOVES   "move"
 29 #endif
 30 
 31 #define __put_user_asm(inst, res, x, ptr, bwl, reg, err) \
 32 asm volatile ("\n"                                      \
 33         "1:     "inst"."#bwl"   %2,%1\n"                \
 34         "2:\n"                                          \
 35         "       .section .fixup,\"ax\"\n"               \
 36         "       .even\n"                                \
 37         "10:    moveq.l %3,%0\n"                        \
 38         "       jra 2b\n"                               \
 39         "       .previous\n"                            \
 40         "\n"                                            \
 41         "       .section __ex_table,\"a\"\n"            \
 42         "       .align  4\n"                            \
 43         "       .long   1b,10b\n"                       \
 44         "       .long   2b,10b\n"                       \
 45         "       .previous"                              \
 46         : "+d" (res), "=m" (*(ptr))                     \
 47         : #reg (x), "i" (err))
 48 
 49 #define __put_user_asm8(inst, res, x, ptr)                      \
 50 do {                                                            \
 51         const void *__pu_ptr = (const void __force *)(ptr);     \
 52                                                                 \
 53         asm volatile ("\n"                                      \
 54                 "1:     "inst".l %2,(%1)+\n"                    \
 55                 "2:     "inst".l %R2,(%1)\n"                    \
 56                 "3:\n"                                          \
 57                 "       .section .fixup,\"ax\"\n"               \
 58                 "       .even\n"                                \
 59                 "10:    movel %3,%0\n"                          \
 60                 "       jra 3b\n"                               \
 61                 "       .previous\n"                            \
 62                 "\n"                                            \
 63                 "       .section __ex_table,\"a\"\n"            \
 64                 "       .align 4\n"                             \
 65                 "       .long 1b,10b\n"                         \
 66                 "       .long 2b,10b\n"                         \
 67                 "       .long 3b,10b\n"                         \
 68                 "       .previous"                              \
 69                 : "+d" (res), "+a" (__pu_ptr)                   \
 70                 : "r" (x), "i" (-EFAULT)                        \
 71                 : "memory");                                    \
 72 } while (0)
 73 
 74 /*
 75  * These are the main single-value transfer routines.  They automatically
 76  * use the right size if we just have the right pointer type.
 77  */
 78 
 79 #define __put_user(x, ptr)                                              \
 80 ({                                                                      \
 81         typeof(*(ptr)) __pu_val = (x);                                  \
 82         int __pu_err = 0;                                               \
 83         __chk_user_ptr(ptr);                                            \
 84         switch (sizeof (*(ptr))) {                                      \
 85         case 1:                                                         \
 86                 __put_user_asm(MOVES, __pu_err, __pu_val, ptr, b, d, -EFAULT); \
 87                 break;                                                  \
 88         case 2:                                                         \
 89                 __put_user_asm(MOVES, __pu_err, __pu_val, ptr, w, r, -EFAULT); \
 90                 break;                                                  \
 91         case 4:                                                         \
 92                 __put_user_asm(MOVES, __pu_err, __pu_val, ptr, l, r, -EFAULT); \
 93                 break;                                                  \
 94         case 8:                                                         \
 95                 __put_user_asm8(MOVES, __pu_err, __pu_val, ptr);        \
 96                 break;                                                  \
 97         default:                                                        \
 98                 BUILD_BUG();                                            \
 99         }                                                               \
100         __pu_err;                                                       \
101 })
102 #define put_user(x, ptr)        __put_user(x, ptr)
103 
104 
105 #define __get_user_asm(inst, res, x, ptr, type, bwl, reg, err) ({       \
106         type __gu_val;                                                  \
107         asm volatile ("\n"                                              \
108                 "1:     "inst"."#bwl"   %2,%1\n"                        \
109                 "2:\n"                                                  \
110                 "       .section .fixup,\"ax\"\n"                       \
111                 "       .even\n"                                        \
112                 "10:    move.l  %3,%0\n"                                \
113                 "       sub.l   %1,%1\n"                                \
114                 "       jra     2b\n"                                   \
115                 "       .previous\n"                                    \
116                 "\n"                                                    \
117                 "       .section __ex_table,\"a\"\n"                    \
118                 "       .align  4\n"                                    \
119                 "       .long   1b,10b\n"                               \
120                 "       .previous"                                      \
121                 : "+d" (res), "=&" #reg (__gu_val)                      \
122                 : "m" (*(ptr)), "i" (err));                             \
123         (x) = (__force typeof(*(ptr)))(__force unsigned long)__gu_val;  \
124 })
125 
126 #define __get_user_asm8(inst, res, x, ptr)                              \
127 do {                                                                    \
128         const void *__gu_ptr = (const void __force *)(ptr);             \
129         union {                                                         \
130                 u64 l;                                                  \
131                 __typeof__(*(ptr)) t;                                   \
132         } __gu_val;                                                     \
133                                                                         \
134         asm volatile ("\n"                                              \
135                 "1:     "inst".l (%2)+,%1\n"                            \
136                 "2:     "inst".l (%2),%R1\n"                            \
137                 "3:\n"                                                  \
138                 "       .section .fixup,\"ax\"\n"                       \
139                 "       .even\n"                                        \
140                 "10:    move.l  %3,%0\n"                                \
141                 "       sub.l   %1,%1\n"                                \
142                 "       sub.l   %R1,%R1\n"                              \
143                 "       jra     3b\n"                                   \
144                 "       .previous\n"                                    \
145                 "\n"                                                    \
146                 "       .section __ex_table,\"a\"\n"                    \
147                 "       .align  4\n"                                    \
148                 "       .long   1b,10b\n"                               \
149                 "       .long   2b,10b\n"                               \
150                 "       .previous"                                      \
151                 : "+d" (res), "=&r" (__gu_val.l),                       \
152                   "+a" (__gu_ptr)                                       \
153                 : "i" (-EFAULT)                                         \
154                 : "memory");                                            \
155         (x) = __gu_val.t;                                               \
156 } while (0)
157 
158 #define __get_user(x, ptr)                                              \
159 ({                                                                      \
160         int __gu_err = 0;                                               \
161         __chk_user_ptr(ptr);                                            \
162         switch (sizeof(*(ptr))) {                                       \
163         case 1:                                                         \
164                 __get_user_asm(MOVES, __gu_err, x, ptr, u8, b, d, -EFAULT); \
165                 break;                                                  \
166         case 2:                                                         \
167                 __get_user_asm(MOVES, __gu_err, x, ptr, u16, w, r, -EFAULT); \
168                 break;                                                  \
169         case 4:                                                         \
170                 __get_user_asm(MOVES, __gu_err, x, ptr, u32, l, r, -EFAULT); \
171                 break;                                                  \
172         case 8:                                                         \
173                 __get_user_asm8(MOVES, __gu_err, x, ptr);               \
174                 break;                                                  \
175         default:                                                        \
176                 BUILD_BUG();                                            \
177         }                                                               \
178         __gu_err;                                                       \
179 })
180 #define get_user(x, ptr) __get_user(x, ptr)
181 
182 unsigned long __generic_copy_from_user(void *to, const void __user *from, unsigned long n);
183 unsigned long __generic_copy_to_user(void __user *to, const void *from, unsigned long n);
184 
185 #define __suffix0
186 #define __suffix1 b
187 #define __suffix2 w
188 #define __suffix4 l
189 
190 #define ____constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3, s1, s2, s3)\
191         asm volatile ("\n"                                              \
192                 "1:     "MOVES"."#s1"   (%2)+,%3\n"                     \
193                 "       move."#s1"      %3,(%1)+\n"                     \
194                 "       .ifnc   \""#s2"\",\"\"\n"                       \
195                 "2:     "MOVES"."#s2"   (%2)+,%3\n"                     \
196                 "       move."#s2"      %3,(%1)+\n"                     \
197                 "       .ifnc   \""#s3"\",\"\"\n"                       \
198                 "3:     "MOVES"."#s3"   (%2)+,%3\n"                     \
199                 "       move."#s3"      %3,(%1)+\n"                     \
200                 "       .endif\n"                                       \
201                 "       .endif\n"                                       \
202                 "4:\n"                                                  \
203                 "       .section __ex_table,\"a\"\n"                    \
204                 "       .align  4\n"                                    \
205                 "       .long   1b,10f\n"                               \
206                 "       .ifnc   \""#s2"\",\"\"\n"                       \
207                 "       .long   2b,20f\n"                               \
208                 "       .ifnc   \""#s3"\",\"\"\n"                       \
209                 "       .long   3b,30f\n"                               \
210                 "       .endif\n"                                       \
211                 "       .endif\n"                                       \
212                 "       .previous\n"                                    \
213                 "\n"                                                    \
214                 "       .section .fixup,\"ax\"\n"                       \
215                 "       .even\n"                                        \
216                 "10:    addq.l #"#n1",%0\n"                             \
217                 "       .ifnc   \""#s2"\",\"\"\n"                       \
218                 "20:    addq.l #"#n2",%0\n"                             \
219                 "       .ifnc   \""#s3"\",\"\"\n"                       \
220                 "30:    addq.l #"#n3",%0\n"                             \
221                 "       .endif\n"                                       \
222                 "       .endif\n"                                       \
223                 "       jra     4b\n"                                   \
224                 "       .previous\n"                                    \
225                 : "+d" (res), "+&a" (to), "+a" (from), "=&d" (tmp)      \
226                 : : "memory")
227 
228 #define ___constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3, s1, s2, s3)\
229         ____constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3, s1, s2, s3)
230 #define __constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3)   \
231         ___constant_copy_from_user_asm(res, to, from, tmp, n1, n2, n3,  \
232                                         __suffix##n1, __suffix##n2, __suffix##n3)
233 
234 static __always_inline unsigned long
235 __constant_copy_from_user(void *to, const void __user *from, unsigned long n)
236 {
237         unsigned long res = 0, tmp;
238 
239         switch (n) {
240         case 1:
241                 __constant_copy_from_user_asm(res, to, from, tmp, 1, 0, 0);
242                 break;
243         case 2:
244                 __constant_copy_from_user_asm(res, to, from, tmp, 2, 0, 0);
245                 break;
246         case 3:
247                 __constant_copy_from_user_asm(res, to, from, tmp, 2, 1, 0);
248                 break;
249         case 4:
250                 __constant_copy_from_user_asm(res, to, from, tmp, 4, 0, 0);
251                 break;
252         case 5:
253                 __constant_copy_from_user_asm(res, to, from, tmp, 4, 1, 0);
254                 break;
255         case 6:
256                 __constant_copy_from_user_asm(res, to, from, tmp, 4, 2, 0);
257                 break;
258         case 7:
259                 __constant_copy_from_user_asm(res, to, from, tmp, 4, 2, 1);
260                 break;
261         case 8:
262                 __constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 0);
263                 break;
264         case 9:
265                 __constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 1);
266                 break;
267         case 10:
268                 __constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 2);
269                 break;
270         case 12:
271                 __constant_copy_from_user_asm(res, to, from, tmp, 4, 4, 4);
272                 break;
273         default:
274                 /* we limit the inlined version to 3 moves */
275                 return __generic_copy_from_user(to, from, n);
276         }
277 
278         return res;
279 }
280 
281 #define __constant_copy_to_user_asm(res, to, from, tmp, n, s1, s2, s3)  \
282         asm volatile ("\n"                                              \
283                 "       move."#s1"      (%2)+,%3\n"                     \
284                 "11:    "MOVES"."#s1"   %3,(%1)+\n"                     \
285                 "12:    move."#s2"      (%2)+,%3\n"                     \
286                 "21:    "MOVES"."#s2"   %3,(%1)+\n"                     \
287                 "22:\n"                                                 \
288                 "       .ifnc   \""#s3"\",\"\"\n"                       \
289                 "       move."#s3"      (%2)+,%3\n"                     \
290                 "31:    "MOVES"."#s3"   %3,(%1)+\n"                     \
291                 "32:\n"                                                 \
292                 "       .endif\n"                                       \
293                 "4:\n"                                                  \
294                 "\n"                                                    \
295                 "       .section __ex_table,\"a\"\n"                    \
296                 "       .align  4\n"                                    \
297                 "       .long   11b,5f\n"                               \
298                 "       .long   12b,5f\n"                               \
299                 "       .long   21b,5f\n"                               \
300                 "       .long   22b,5f\n"                               \
301                 "       .ifnc   \""#s3"\",\"\"\n"                       \
302                 "       .long   31b,5f\n"                               \
303                 "       .long   32b,5f\n"                               \
304                 "       .endif\n"                                       \
305                 "       .previous\n"                                    \
306                 "\n"                                                    \
307                 "       .section .fixup,\"ax\"\n"                       \
308                 "       .even\n"                                        \
309                 "5:     moveq.l #"#n",%0\n"                             \
310                 "       jra     4b\n"                                   \
311                 "       .previous\n"                                    \
312                 : "+d" (res), "+a" (to), "+a" (from), "=&d" (tmp)       \
313                 : : "memory")
314 
315 static __always_inline unsigned long
316 __constant_copy_to_user(void __user *to, const void *from, unsigned long n)
317 {
318         unsigned long res = 0, tmp;
319 
320         switch (n) {
321         case 1:
322                 __put_user_asm(MOVES, res, *(u8 *)from, (u8 __user *)to,
323                                 b, d, 1);
324                 break;
325         case 2:
326                 __put_user_asm(MOVES, res, *(u16 *)from, (u16 __user *)to,
327                                 w, r, 2);
328                 break;
329         case 3:
330                 __constant_copy_to_user_asm(res, to, from, tmp, 3, w, b,);
331                 break;
332         case 4:
333                 __put_user_asm(MOVES, res, *(u32 *)from, (u32 __user *)to,
334                                 l, r, 4);
335                 break;
336         case 5:
337                 __constant_copy_to_user_asm(res, to, from, tmp, 5, l, b,);
338                 break;
339         case 6:
340                 __constant_copy_to_user_asm(res, to, from, tmp, 6, l, w,);
341                 break;
342         case 7:
343                 __constant_copy_to_user_asm(res, to, from, tmp, 7, l, w, b);
344                 break;
345         case 8:
346                 __constant_copy_to_user_asm(res, to, from, tmp, 8, l, l,);
347                 break;
348         case 9:
349                 __constant_copy_to_user_asm(res, to, from, tmp, 9, l, l, b);
350                 break;
351         case 10:
352                 __constant_copy_to_user_asm(res, to, from, tmp, 10, l, l, w);
353                 break;
354         case 12:
355                 __constant_copy_to_user_asm(res, to, from, tmp, 12, l, l, l);
356                 break;
357         default:
358                 /* limit the inlined version to 3 moves */
359                 return __generic_copy_to_user(to, from, n);
360         }
361 
362         return res;
363 }
364 
365 static inline unsigned long
366 raw_copy_from_user(void *to, const void __user *from, unsigned long n)
367 {
368         if (__builtin_constant_p(n))
369                 return __constant_copy_from_user(to, from, n);
370         return __generic_copy_from_user(to, from, n);
371 }
372 
373 static inline unsigned long
374 raw_copy_to_user(void __user *to, const void *from, unsigned long n)
375 {
376         if (__builtin_constant_p(n))
377                 return __constant_copy_to_user(to, from, n);
378         return __generic_copy_to_user(to, from, n);
379 }
380 #define INLINE_COPY_FROM_USER
381 #define INLINE_COPY_TO_USER
382 
383 #define __get_kernel_nofault(dst, src, type, err_label)                 \
384 do {                                                                    \
385         type *__gk_dst = (type *)(dst);                                 \
386         type *__gk_src = (type *)(src);                                 \
387         int __gk_err = 0;                                               \
388                                                                         \
389         switch (sizeof(type)) {                                         \
390         case 1:                                                         \
391                 __get_user_asm("move", __gk_err, *__gk_dst, __gk_src,   \
392                                 u8, b, d, -EFAULT);                     \
393                 break;                                                  \
394         case 2:                                                         \
395                 __get_user_asm("move", __gk_err, *__gk_dst, __gk_src,   \
396                                 u16, w, r, -EFAULT);                    \
397                 break;                                                  \
398         case 4:                                                         \
399                 __get_user_asm("move", __gk_err, *__gk_dst, __gk_src,   \
400                                 u32, l, r, -EFAULT);                    \
401                 break;                                                  \
402         case 8:                                                         \
403                 __get_user_asm8("move", __gk_err, *__gk_dst, __gk_src); \
404                 break;                                                  \
405         default:                                                        \
406                 BUILD_BUG();                                            \
407         }                                                               \
408         if (unlikely(__gk_err))                                         \
409                 goto err_label;                                         \
410 } while (0)
411 
412 #define __put_kernel_nofault(dst, src, type, err_label)                 \
413 do {                                                                    \
414         type __pk_src = *(type *)(src);                                 \
415         type *__pk_dst = (type *)(dst);                                 \
416         int __pk_err = 0;                                               \
417                                                                         \
418         switch (sizeof(type)) {                                         \
419         case 1:                                                         \
420                 __put_user_asm("move", __pk_err, __pk_src, __pk_dst,    \
421                                 b, d, -EFAULT);                         \
422                 break;                                                  \
423         case 2:                                                         \
424                 __put_user_asm("move", __pk_err, __pk_src, __pk_dst,    \
425                                 w, r, -EFAULT);                         \
426                 break;                                                  \
427         case 4:                                                         \
428                 __put_user_asm("move", __pk_err, __pk_src, __pk_dst,    \
429                                 l, r, -EFAULT);                         \
430                 break;                                                  \
431         case 8:                                                         \
432                 __put_user_asm8("move", __pk_err, __pk_src, __pk_dst);  \
433                 break;                                                  \
434         default:                                                        \
435                 BUILD_BUG();                                            \
436         }                                                               \
437         if (unlikely(__pk_err))                                         \
438                 goto err_label;                                         \
439 } while (0)
440 
441 extern long strncpy_from_user(char *dst, const char __user *src, long count);
442 extern __must_check long strnlen_user(const char __user *str, long n);
443 
444 unsigned long __clear_user(void __user *to, unsigned long n);
445 
446 #define clear_user      __clear_user
447 
448 #else /* !CONFIG_MMU */
449 #include <asm-generic/uaccess.h>
450 #endif
451 
452 #endif /* _M68K_UACCESS_H */
453 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php