root/arch/csky/include/asm/uaccess.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. access_ok

   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
   3 
   4 #ifndef __ASM_CSKY_UACCESS_H
   5 #define __ASM_CSKY_UACCESS_H
   6 
   7 /*
   8  * User space memory access functions
   9  */
  10 #include <linux/compiler.h>
  11 #include <linux/errno.h>
  12 #include <linux/types.h>
  13 #include <linux/sched.h>
  14 #include <linux/mm.h>
  15 #include <linux/string.h>
  16 #include <linux/version.h>
  17 #include <asm/segment.h>
  18 
  19 static inline int access_ok(const void *addr, unsigned long size)
  20 {
  21         unsigned long limit = current_thread_info()->addr_limit.seg;
  22 
  23         return (((unsigned long)addr < limit) &&
  24                 ((unsigned long)(addr + size) < limit));
  25 }
  26 
  27 #define __addr_ok(addr) (access_ok(addr, 0))
  28 
  29 extern int __put_user_bad(void);
  30 
  31 /*
  32  * Tell gcc we read from memory instead of writing: this is because
  33  * we do not write to any memory gcc knows about, so there are no
  34  * aliasing issues.
  35  */
  36 
  37 /*
  38  * These are the main single-value transfer routines.  They automatically
  39  * use the right size if we just have the right pointer type.
  40  *
  41  * This gets kind of ugly. We want to return _two_ values in "get_user()"
  42  * and yet we don't want to do any pointers, because that is too much
  43  * of a performance impact. Thus we have a few rather ugly macros here,
  44  * and hide all the ugliness from the user.
  45  *
  46  * The "__xxx" versions of the user access functions are versions that
  47  * do not verify the address space, that must have been done previously
  48  * with a separate "access_ok()" call (this is used when we do multiple
  49  * accesses to the same area of user memory).
  50  *
  51  * As we use the same address space for kernel and user data on
  52  * Ckcore, we can just do these as direct assignments.  (Of course, the
  53  * exception handling means that it's no longer "just"...)
  54  */
  55 
  56 #define put_user(x, ptr) \
  57         __put_user_check((x), (ptr), sizeof(*(ptr)))
  58 
  59 #define __put_user(x, ptr) \
  60         __put_user_nocheck((x), (ptr), sizeof(*(ptr)))
  61 
  62 #define __ptr(x) ((unsigned long *)(x))
  63 
  64 #define get_user(x, ptr) \
  65         __get_user_check((x), (ptr), sizeof(*(ptr)))
  66 
  67 #define __get_user(x, ptr) \
  68         __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
  69 
  70 #define __put_user_nocheck(x, ptr, size)                                \
  71 ({                                                                      \
  72         long __pu_err = 0;                                              \
  73         typeof(*(ptr)) *__pu_addr = (ptr);                              \
  74         typeof(*(ptr)) __pu_val = (typeof(*(ptr)))(x);                  \
  75         if (__pu_addr)                                                  \
  76                 __put_user_size(__pu_val, (__pu_addr), (size),          \
  77                                 __pu_err);                              \
  78         __pu_err;                                                       \
  79 })
  80 
  81 #define __put_user_check(x, ptr, size)                                  \
  82 ({                                                                      \
  83         long __pu_err = -EFAULT;                                        \
  84         typeof(*(ptr)) *__pu_addr = (ptr);                              \
  85         typeof(*(ptr)) __pu_val = (typeof(*(ptr)))(x);                  \
  86         if (access_ok(__pu_addr, size) && __pu_addr)    \
  87                 __put_user_size(__pu_val, __pu_addr, (size), __pu_err); \
  88         __pu_err;                                                       \
  89 })
  90 
  91 #define __put_user_size(x, ptr, size, retval)           \
  92 do {                                                    \
  93         retval = 0;                                     \
  94         switch (size) {                                 \
  95         case 1:                                         \
  96                 __put_user_asm_b(x, ptr, retval);       \
  97                 break;                                  \
  98         case 2:                                         \
  99                 __put_user_asm_h(x, ptr, retval);       \
 100                 break;                                  \
 101         case 4:                                         \
 102                 __put_user_asm_w(x, ptr, retval);       \
 103                 break;                                  \
 104         case 8:                                         \
 105                 __put_user_asm_64(x, ptr, retval);      \
 106                 break;                                  \
 107         default:                                        \
 108                 __put_user_bad();                       \
 109         }                                               \
 110 } while (0)
 111 
 112 /*
 113  * We don't tell gcc that we are accessing memory, but this is OK
 114  * because we do not write to any memory gcc knows about, so there
 115  * are no aliasing issues.
 116  *
 117  * Note that PC at a fault is the address *after* the faulting
 118  * instruction.
 119  */
 120 #define __put_user_asm_b(x, ptr, err)                   \
 121 do {                                                    \
 122         int errcode;                                    \
 123         asm volatile(                                   \
 124         "1:     stb   %1, (%2,0)        \n"             \
 125         "       br    3f                \n"             \
 126         "2:     mov   %0, %3            \n"             \
 127         "       br    3f                \n"             \
 128         ".section __ex_table, \"a\"     \n"             \
 129         ".align   2                     \n"             \
 130         ".long    1b,2b                 \n"             \
 131         ".previous                      \n"             \
 132         "3:                             \n"             \
 133         : "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode)  \
 134         : "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT)      \
 135         : "memory");                                    \
 136 } while (0)
 137 
 138 #define __put_user_asm_h(x, ptr, err)                   \
 139 do {                                                    \
 140         int errcode;                                    \
 141         asm volatile(                                   \
 142         "1:     sth   %1, (%2,0)        \n"             \
 143         "       br    3f                \n"             \
 144         "2:     mov   %0, %3            \n"             \
 145         "       br    3f                \n"             \
 146         ".section __ex_table, \"a\"     \n"             \
 147         ".align   2                     \n"             \
 148         ".long    1b,2b                 \n"             \
 149         ".previous                      \n"             \
 150         "3:                             \n"             \
 151         : "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode)  \
 152         : "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT)      \
 153         : "memory");                                    \
 154 } while (0)
 155 
 156 #define __put_user_asm_w(x, ptr, err)                   \
 157 do {                                                    \
 158         int errcode;                                    \
 159         asm volatile(                                   \
 160         "1:     stw   %1, (%2,0)        \n"             \
 161         "       br    3f                \n"             \
 162         "2:     mov   %0, %3            \n"             \
 163         "       br    3f                \n"             \
 164         ".section __ex_table,\"a\"      \n"             \
 165         ".align   2                     \n"             \
 166         ".long    1b, 2b                \n"             \
 167         ".previous                      \n"             \
 168         "3:                             \n"             \
 169         : "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode)  \
 170         : "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT)      \
 171         : "memory");                                    \
 172 } while (0)
 173 
 174 #define __put_user_asm_64(x, ptr, err)                          \
 175 do {                                                            \
 176         int tmp;                                                \
 177         int errcode;                                            \
 178         typeof(*(ptr))src = (typeof(*(ptr)))x;                  \
 179         typeof(*(ptr))*psrc = &src;                             \
 180                                                                 \
 181         asm volatile(                                           \
 182         "     ldw     %3, (%1, 0)     \n"                       \
 183         "1:   stw     %3, (%2, 0)     \n"                       \
 184         "     ldw     %3, (%1, 4)     \n"                       \
 185         "2:   stw     %3, (%2, 4)     \n"                       \
 186         "     br      4f              \n"                       \
 187         "3:   mov     %0, %4          \n"                       \
 188         "     br      4f              \n"                       \
 189         ".section __ex_table, \"a\"   \n"                       \
 190         ".align   2                   \n"                       \
 191         ".long    1b, 3b              \n"                       \
 192         ".long    2b, 3b              \n"                       \
 193         ".previous                    \n"                       \
 194         "4:                           \n"                       \
 195         : "=r"(err), "=r"(psrc), "=r"(ptr),                     \
 196           "=r"(tmp), "=r"(errcode)                              \
 197         : "0"(err), "1"(psrc), "2"(ptr), "3"(0), "4"(-EFAULT)   \
 198         : "memory");                                            \
 199 } while (0)
 200 
 201 #define __get_user_nocheck(x, ptr, size)                        \
 202 ({                                                              \
 203         long  __gu_err;                                         \
 204         __get_user_size(x, (ptr), (size), __gu_err);            \
 205         __gu_err;                                               \
 206 })
 207 
 208 #define __get_user_check(x, ptr, size)                          \
 209 ({                                                              \
 210         int __gu_err = -EFAULT;                                 \
 211         const __typeof__(*(ptr)) __user *__gu_ptr = (ptr);      \
 212         if (access_ok(__gu_ptr, size) && __gu_ptr)      \
 213                 __get_user_size(x, __gu_ptr, size, __gu_err);   \
 214         __gu_err;                                               \
 215 })
 216 
 217 #define __get_user_size(x, ptr, size, retval)                   \
 218 do {                                                            \
 219         switch (size) {                                         \
 220         case 1:                                                 \
 221                 __get_user_asm_common((x), ptr, "ldb", retval); \
 222                 break;                                          \
 223         case 2:                                                 \
 224                 __get_user_asm_common((x), ptr, "ldh", retval); \
 225                 break;                                          \
 226         case 4:                                                 \
 227                 __get_user_asm_common((x), ptr, "ldw", retval); \
 228                 break;                                          \
 229         default:                                                \
 230                 x = 0;                                          \
 231                 (retval) = __get_user_bad();                    \
 232         }                                                       \
 233 } while (0)
 234 
 235 #define __get_user_asm_common(x, ptr, ins, err)                 \
 236 do {                                                            \
 237         int errcode;                                            \
 238         asm volatile(                                           \
 239         "1:   " ins " %1, (%4,0)        \n"                     \
 240         "       br    3f                \n"                     \
 241         /* Fix up codes */                                      \
 242         "2:     mov   %0, %2            \n"                     \
 243         "       movi  %1, 0             \n"                     \
 244         "       br    3f                \n"                     \
 245         ".section __ex_table,\"a\"      \n"                     \
 246         ".align   2                     \n"                     \
 247         ".long    1b, 2b                \n"                     \
 248         ".previous                      \n"                     \
 249         "3:                             \n"                     \
 250         : "=r"(err), "=r"(x), "=r"(errcode)                     \
 251         : "0"(0), "r"(ptr), "2"(-EFAULT)                        \
 252         : "memory");                                            \
 253 } while (0)
 254 
 255 extern int __get_user_bad(void);
 256 
 257 #define ___copy_to_user(to, from, n)                    \
 258 do {                                                    \
 259         int w0, w1, w2, w3;                             \
 260         asm volatile(                                   \
 261         "0:     cmpnei  %1, 0           \n"             \
 262         "       bf      8f              \n"             \
 263         "       mov     %3, %1          \n"             \
 264         "       or      %3, %2          \n"             \
 265         "       andi    %3, 3           \n"             \
 266         "       cmpnei  %3, 0           \n"             \
 267         "       bf      1f              \n"             \
 268         "       br      5f              \n"             \
 269         "1:     cmplti  %0, 16          \n" /* 4W */    \
 270         "       bt      3f              \n"             \
 271         "       ldw     %3, (%2, 0)     \n"             \
 272         "       ldw     %4, (%2, 4)     \n"             \
 273         "       ldw     %5, (%2, 8)     \n"             \
 274         "       ldw     %6, (%2, 12)    \n"             \
 275         "2:     stw     %3, (%1, 0)     \n"             \
 276         "9:     stw     %4, (%1, 4)     \n"             \
 277         "10:    stw     %5, (%1, 8)     \n"             \
 278         "11:    stw     %6, (%1, 12)    \n"             \
 279         "       addi    %2, 16          \n"             \
 280         "       addi    %1, 16          \n"             \
 281         "       subi    %0, 16          \n"             \
 282         "       br      1b              \n"             \
 283         "3:     cmplti  %0, 4           \n" /* 1W */    \
 284         "       bt      5f              \n"             \
 285         "       ldw     %3, (%2, 0)     \n"             \
 286         "4:     stw     %3, (%1, 0)     \n"             \
 287         "       addi    %2, 4           \n"             \
 288         "       addi    %1, 4           \n"             \
 289         "       subi    %0, 4           \n"             \
 290         "       br      3b              \n"             \
 291         "5:     cmpnei  %0, 0           \n"  /* 1B */   \
 292         "       bf      13f             \n"             \
 293         "       ldb     %3, (%2, 0)     \n"             \
 294         "6:     stb     %3, (%1, 0)     \n"             \
 295         "       addi    %2,  1          \n"             \
 296         "       addi    %1,  1          \n"             \
 297         "       subi    %0,  1          \n"             \
 298         "       br      5b              \n"             \
 299         "7:     subi    %0,  4          \n"             \
 300         "8:     subi    %0,  4          \n"             \
 301         "12:    subi    %0,  4          \n"             \
 302         "       br      13f             \n"             \
 303         ".section __ex_table, \"a\"     \n"             \
 304         ".align   2                     \n"             \
 305         ".long    2b, 13f               \n"             \
 306         ".long    4b, 13f               \n"             \
 307         ".long    6b, 13f               \n"             \
 308         ".long    9b, 12b               \n"             \
 309         ".long   10b, 8b                \n"             \
 310         ".long   11b, 7b                \n"             \
 311         ".previous                      \n"             \
 312         "13:                            \n"             \
 313         : "=r"(n), "=r"(to), "=r"(from), "=r"(w0),      \
 314           "=r"(w1), "=r"(w2), "=r"(w3)                  \
 315         : "0"(n), "1"(to), "2"(from)                    \
 316         : "memory");                                    \
 317 } while (0)
 318 
 319 #define ___copy_from_user(to, from, n)                  \
 320 do {                                                    \
 321         int tmp;                                        \
 322         int nsave;                                      \
 323         asm volatile(                                   \
 324         "0:     cmpnei  %1, 0           \n"             \
 325         "       bf      7f              \n"             \
 326         "       mov     %3, %1          \n"             \
 327         "       or      %3, %2          \n"             \
 328         "       andi    %3, 3           \n"             \
 329         "       cmpnei  %3, 0           \n"             \
 330         "       bf      1f              \n"             \
 331         "       br      5f              \n"             \
 332         "1:     cmplti  %0, 16          \n"             \
 333         "       bt      3f              \n"             \
 334         "2:     ldw     %3, (%2, 0)     \n"             \
 335         "10:    ldw     %4, (%2, 4)     \n"             \
 336         "       stw     %3, (%1, 0)     \n"             \
 337         "       stw     %4, (%1, 4)     \n"             \
 338         "11:    ldw     %3, (%2, 8)     \n"             \
 339         "12:    ldw     %4, (%2, 12)    \n"             \
 340         "       stw     %3, (%1, 8)     \n"             \
 341         "       stw     %4, (%1, 12)    \n"             \
 342         "       addi    %2, 16          \n"             \
 343         "       addi    %1, 16          \n"             \
 344         "       subi    %0, 16          \n"             \
 345         "       br      1b              \n"             \
 346         "3:     cmplti  %0, 4           \n"             \
 347         "       bt      5f              \n"             \
 348         "4:     ldw     %3, (%2, 0)     \n"             \
 349         "       stw     %3, (%1, 0)     \n"             \
 350         "       addi    %2, 4           \n"             \
 351         "       addi    %1, 4           \n"             \
 352         "       subi    %0, 4           \n"             \
 353         "       br      3b              \n"             \
 354         "5:     cmpnei  %0, 0           \n"             \
 355         "       bf      7f              \n"             \
 356         "6:     ldb     %3, (%2, 0)     \n"             \
 357         "       stb     %3, (%1, 0)     \n"             \
 358         "       addi    %2,  1          \n"             \
 359         "       addi    %1,  1          \n"             \
 360         "       subi    %0,  1          \n"             \
 361         "       br      5b              \n"             \
 362         "8:     stw     %3, (%1, 0)     \n"             \
 363         "       subi    %0, 4           \n"             \
 364         "       bf      7f              \n"             \
 365         "9:     subi    %0, 8           \n"             \
 366         "       bf      7f              \n"             \
 367         "13:    stw     %3, (%1, 8)     \n"             \
 368         "       subi    %0, 12          \n"             \
 369         "       bf      7f              \n"             \
 370         ".section __ex_table, \"a\"     \n"             \
 371         ".align   2                     \n"             \
 372         ".long    2b, 7f                \n"             \
 373         ".long    4b, 7f                \n"             \
 374         ".long    6b, 7f                \n"             \
 375         ".long   10b, 8b                \n"             \
 376         ".long   11b, 9b                \n"             \
 377         ".long   12b,13b                \n"             \
 378         ".previous                      \n"             \
 379         "7:                             \n"             \
 380         : "=r"(n), "=r"(to), "=r"(from), "=r"(nsave),   \
 381           "=r"(tmp)                                     \
 382         : "0"(n), "1"(to), "2"(from)                    \
 383         : "memory");                                    \
 384 } while (0)
 385 
 386 unsigned long raw_copy_from_user(void *to, const void *from, unsigned long n);
 387 unsigned long raw_copy_to_user(void *to, const void *from, unsigned long n);
 388 
 389 unsigned long clear_user(void *to, unsigned long n);
 390 unsigned long __clear_user(void __user *to, unsigned long n);
 391 
 392 long strncpy_from_user(char *dst, const char *src, long count);
 393 long __strncpy_from_user(char *dst, const char *src, long count);
 394 
 395 /*
 396  * Return the size of a string (including the ending 0)
 397  *
 398  * Return 0 on exception, a value greater than N if too long
 399  */
 400 long strnlen_user(const char *src, long n);
 401 
 402 #define strlen_user(str) strnlen_user(str, 32767)
 403 
 404 struct exception_table_entry {
 405         unsigned long insn;
 406         unsigned long nextinsn;
 407 };
 408 
 409 extern int fixup_exception(struct pt_regs *regs);
 410 
 411 #endif /* __ASM_CSKY_UACCESS_H */

/* [<][>][^][v][top][bottom][index][help] */