linux/arch/cris/include/arch-v32/arch/uaccess.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * Authors:    Hans-Peter Nilsson (hp@axis.com)
   4 *
   5 */
   6#ifndef _CRIS_ARCH_UACCESS_H
   7#define _CRIS_ARCH_UACCESS_H
   8
   9/*
  10 * We don't tell gcc that we are accessing memory, but this is OK
  11 * because we do not write to any memory gcc knows about, so there
  12 * are no aliasing issues.
  13 *
  14 * Note that PC at a fault is the address *at* the faulting
  15 * instruction for CRISv32.
  16 */
  17#define __put_user_asm(x, addr, err, op)                        \
  18        __asm__ __volatile__(                                   \
  19                "2:     "op" %1,[%2]\n"                         \
  20                "4:\n"                                          \
  21                "       .section .fixup,\"ax\"\n"               \
  22                "3:     move.d %3,%0\n"                         \
  23                "       jump 4b\n"                              \
  24                "       nop\n"                                  \
  25                "       .previous\n"                            \
  26                "       .section __ex_table,\"a\"\n"            \
  27                "       .dword 2b,3b\n"                         \
  28                "       .previous\n"                            \
  29                : "=r" (err)                                    \
  30                : "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
  31
  32#define __put_user_asm_64(x, addr, err) do {                    \
  33        int dummy_for_put_user_asm_64_;                         \
  34        __asm__ __volatile__(                                   \
  35                "2:     move.d %M2,[%1+]\n"                     \
  36                "4:     move.d %H2,[%1]\n"                      \
  37                "5:\n"                                          \
  38                "       .section .fixup,\"ax\"\n"               \
  39                "3:     move.d %4,%0\n"                         \
  40                "       jump 5b\n"                              \
  41                "       .previous\n"                            \
  42                "       .section __ex_table,\"a\"\n"            \
  43                "       .dword 2b,3b\n"                         \
  44                "       .dword 4b,3b\n"                         \
  45                "       .previous\n"                            \
  46                : "=r" (err), "=b" (dummy_for_put_user_asm_64_) \
  47                : "r" (x), "1" (addr), "g" (-EFAULT),           \
  48                  "0" (err));                                   \
  49        } while (0)
  50
  51/* See comment before __put_user_asm.  */
  52
  53#define __get_user_asm(x, addr, err, op)                \
  54        __asm__ __volatile__(                           \
  55                "2:     "op" [%2],%1\n"                 \
  56                "4:\n"                                  \
  57                "       .section .fixup,\"ax\"\n"       \
  58                "3:     move.d %3,%0\n"                 \
  59                "       jump 4b\n"                      \
  60                "       moveq 0,%1\n"                   \
  61                "       .previous\n"                    \
  62                "       .section __ex_table,\"a\"\n"    \
  63                "       .dword 2b,3b\n"                 \
  64                "       .previous\n"                    \
  65                : "=r" (err), "=r" (x)                  \
  66                : "r" (addr), "g" (-EFAULT), "0" (err))
  67
  68#define __get_user_asm_64(x, addr, err) do {            \
  69        int dummy_for_get_user_asm_64_;                 \
  70        __asm__ __volatile__(                           \
  71                "2:     move.d [%2+],%M1\n"             \
  72                "4:     move.d [%2],%H1\n"              \
  73                "5:\n"                                  \
  74                "       .section .fixup,\"ax\"\n"       \
  75                "3:     move.d %4,%0\n"                 \
  76                "       jump 5b\n"                      \
  77                "       moveq 0,%1\n"                   \
  78                "       .previous\n"                    \
  79                "       .section __ex_table,\"a\"\n"    \
  80                "       .dword 2b,3b\n"                 \
  81                "       .dword 4b,3b\n"                 \
  82                "       .previous\n"                    \
  83                : "=r" (err), "=r" (x),                 \
  84                  "=b" (dummy_for_get_user_asm_64_)     \
  85                : "2" (addr), "g" (-EFAULT), "0" (err));\
  86        } while (0)
  87
  88/*
  89 * Copy a null terminated string from userspace.
  90 *
  91 * Must return:
  92 * -EFAULT              for an exception
  93 * count                if we hit the buffer limit
  94 * bytes copied         if we hit a null byte
  95 * (without the null byte)
  96 */
  97static inline long
  98__do_strncpy_from_user(char *dst, const char *src, long count)
  99{
 100        long res;
 101
 102        if (count == 0)
 103                return 0;
 104
 105        /*
 106         * Currently, in 2.4.0-test9, most ports use a simple byte-copy loop.
 107         *  So do we.
 108         *
 109         *  This code is deduced from:
 110         *
 111         *      char tmp2;
 112         *      long tmp1, tmp3;
 113         *      tmp1 = count;
 114         *      while ((*dst++ = (tmp2 = *src++)) != 0
 115         *             && --tmp1)
 116         *        ;
 117         *
 118         *      res = count - tmp1;
 119         *
 120         *  with tweaks.
 121         */
 122
 123        __asm__ __volatile__ (
 124                "       move.d %3,%0\n"
 125                "5:     move.b [%2+],$acr\n"
 126                "1:     beq 6f\n"
 127                "       move.b $acr,[%1+]\n"
 128
 129                "       subq 1,%0\n"
 130                "2:     bne 1b\n"
 131                "       move.b [%2+],$acr\n"
 132
 133                "6:     sub.d %3,%0\n"
 134                "       neg.d %0,%0\n"
 135                "3:\n"
 136                "       .section .fixup,\"ax\"\n"
 137                "4:     move.d %7,%0\n"
 138                "       jump 3b\n"
 139                "       nop\n"
 140
 141                /* The address for a fault at the first move is trivial.
 142                   The address for a fault at the second move is that of
 143                   the preceding branch insn, since the move insn is in
 144                   its delay-slot.  Just so you don't get confused...  */
 145                "       .previous\n"
 146                "       .section __ex_table,\"a\"\n"
 147                "       .dword 5b,4b\n"
 148                "       .dword 2b,4b\n"
 149                "       .previous"
 150                : "=r" (res), "=b" (dst), "=b" (src), "=r" (count)
 151                : "3" (count), "1" (dst), "2" (src), "g" (-EFAULT)
 152                : "acr");
 153
 154        return res;
 155}
 156
 157/* A few copy asms to build up the more complex ones from.
 158
 159   Note again, a post-increment is performed regardless of whether a bus
 160   fault occurred in that instruction, and PC for a faulted insn is the
 161   address for the insn, or for the preceding branch when in a delay-slot.  */
 162
 163#define __asm_copy_user_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 164        __asm__ __volatile__ (                          \
 165                        COPY                            \
 166                "1:\n"                                  \
 167                "       .section .fixup,\"ax\"\n"       \
 168                        FIXUP                           \
 169                "       .previous\n"                    \
 170                "       .section __ex_table,\"a\"\n"    \
 171                        TENTRY                          \
 172                "       .previous\n"                    \
 173                : "=b" (to), "=b" (from), "=r" (ret)    \
 174                : "0" (to), "1" (from), "2" (ret)       \
 175                : "acr", "memory")
 176
 177#define __asm_copy_from_user_1(to, from, ret) \
 178        __asm_copy_user_cont(to, from, ret,     \
 179                "2:     move.b [%1+],$acr\n"    \
 180                "       move.b $acr,[%0+]\n",   \
 181                "3:     addq 1,%2\n"            \
 182                "       jump 1b\n",             \
 183                "       .dword 2b,3b\n")
 184
 185#define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 186        __asm_copy_user_cont(to, from, ret,             \
 187                        COPY                            \
 188                "2:     move.w [%1+],$acr\n"            \
 189                "       move.w $acr,[%0+]\n",           \
 190                        FIXUP                           \
 191                "3:     addq 2,%2\n"                    \
 192                "       jump 1b\n",                     \
 193                        TENTRY                          \
 194                "       .dword 2b,3b\n")
 195
 196#define __asm_copy_from_user_2(to, from, ret) \
 197        __asm_copy_from_user_2x_cont(to, from, ret, "", "", "")
 198
 199#define __asm_copy_from_user_3(to, from, ret)           \
 200        __asm_copy_from_user_2x_cont(to, from, ret,     \
 201                "4:     move.b [%1+],$acr\n"            \
 202                "       move.b $acr,[%0+]\n",           \
 203                "5:     addq 1,%2\n",                   \
 204                "       .dword 4b,5b\n")
 205
 206#define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 207        __asm_copy_user_cont(to, from, ret,             \
 208                        COPY                            \
 209                "2:     move.d [%1+],$acr\n"            \
 210                "       move.d $acr,[%0+]\n",           \
 211                        FIXUP                           \
 212                "3:     addq 4,%2\n"                    \
 213                "       jump 1b\n",                     \
 214                        TENTRY                          \
 215                "       .dword 2b,3b\n")
 216
 217#define __asm_copy_from_user_4(to, from, ret) \
 218        __asm_copy_from_user_4x_cont(to, from, ret, "", "", "")
 219
 220#define __asm_copy_from_user_5(to, from, ret) \
 221        __asm_copy_from_user_4x_cont(to, from, ret,     \
 222                "4:     move.b [%1+],$acr\n"            \
 223                "       move.b $acr,[%0+]\n",           \
 224                "5:     addq 1,%2\n",                   \
 225                "       .dword 4b,5b\n")
 226
 227#define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 228        __asm_copy_from_user_4x_cont(to, from, ret,     \
 229                        COPY                            \
 230                "4:     move.w [%1+],$acr\n"            \
 231                "       move.w $acr,[%0+]\n",           \
 232                        FIXUP                           \
 233                "5:     addq 2,%2\n",                   \
 234                        TENTRY                          \
 235                "       .dword 4b,5b\n")
 236
 237#define __asm_copy_from_user_6(to, from, ret) \
 238        __asm_copy_from_user_6x_cont(to, from, ret, "", "", "")
 239
 240#define __asm_copy_from_user_7(to, from, ret) \
 241        __asm_copy_from_user_6x_cont(to, from, ret,     \
 242                "6:     move.b [%1+],$acr\n"            \
 243                "       move.b $acr,[%0+]\n",           \
 244                "7:     addq 1,%2\n",                   \
 245                "       .dword 6b,7b\n")
 246
 247#define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 248        __asm_copy_from_user_4x_cont(to, from, ret,     \
 249                        COPY                            \
 250                "4:     move.d [%1+],$acr\n"            \
 251                "       move.d $acr,[%0+]\n",           \
 252                        FIXUP                           \
 253                "5:     addq 4,%2\n",                   \
 254                        TENTRY                          \
 255                "       .dword 4b,5b\n")
 256
 257#define __asm_copy_from_user_8(to, from, ret) \
 258        __asm_copy_from_user_8x_cont(to, from, ret, "", "", "")
 259
 260#define __asm_copy_from_user_9(to, from, ret) \
 261        __asm_copy_from_user_8x_cont(to, from, ret,     \
 262                "6:     move.b [%1+],$acr\n"            \
 263                "       move.b $acr,[%0+]\n",           \
 264                "7:     addq 1,%2\n",                   \
 265                "       .dword 6b,7b\n")
 266
 267#define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 268        __asm_copy_from_user_8x_cont(to, from, ret,     \
 269                        COPY                            \
 270                "6:     move.w [%1+],$acr\n"            \
 271                "       move.w $acr,[%0+]\n",           \
 272                        FIXUP                           \
 273                "7:     addq 2,%2\n",                   \
 274                        TENTRY                          \
 275                "       .dword 6b,7b\n")
 276
 277#define __asm_copy_from_user_10(to, from, ret) \
 278        __asm_copy_from_user_10x_cont(to, from, ret, "", "", "")
 279
 280#define __asm_copy_from_user_11(to, from, ret)          \
 281        __asm_copy_from_user_10x_cont(to, from, ret,    \
 282                "8:     move.b [%1+],$acr\n"            \
 283                "       move.b $acr,[%0+]\n",           \
 284                "9:     addq 1,%2\n",                   \
 285                "       .dword 8b,9b\n")
 286
 287#define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 288        __asm_copy_from_user_8x_cont(to, from, ret,     \
 289                        COPY                            \
 290                "6:     move.d [%1+],$acr\n"            \
 291                "       move.d $acr,[%0+]\n",           \
 292                        FIXUP                           \
 293                "7:     addq 4,%2\n",                   \
 294                        TENTRY                          \
 295                "       .dword 6b,7b\n")
 296
 297#define __asm_copy_from_user_12(to, from, ret) \
 298        __asm_copy_from_user_12x_cont(to, from, ret, "", "", "")
 299
 300#define __asm_copy_from_user_13(to, from, ret) \
 301        __asm_copy_from_user_12x_cont(to, from, ret,    \
 302                "8:     move.b [%1+],$acr\n"            \
 303                "       move.b $acr,[%0+]\n",           \
 304                "9:     addq 1,%2\n",                   \
 305                "       .dword 8b,9b\n")
 306
 307#define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 308        __asm_copy_from_user_12x_cont(to, from, ret,    \
 309                        COPY                            \
 310                "8:     move.w [%1+],$acr\n"            \
 311                "       move.w $acr,[%0+]\n",           \
 312                        FIXUP                           \
 313                "9:     addq 2,%2\n",                   \
 314                        TENTRY                          \
 315                "       .dword 8b,9b\n")
 316
 317#define __asm_copy_from_user_14(to, from, ret) \
 318        __asm_copy_from_user_14x_cont(to, from, ret, "", "", "")
 319
 320#define __asm_copy_from_user_15(to, from, ret) \
 321        __asm_copy_from_user_14x_cont(to, from, ret,    \
 322                "10:    move.b [%1+],$acr\n"            \
 323                "       move.b $acr,[%0+]\n",           \
 324                "11:    addq 1,%2\n",                   \
 325                "       .dword 10b,11b\n")
 326
 327#define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 328        __asm_copy_from_user_12x_cont(to, from, ret,    \
 329                        COPY                            \
 330                "8:     move.d [%1+],$acr\n"            \
 331                "       move.d $acr,[%0+]\n",           \
 332                        FIXUP                           \
 333                "9:     addq 4,%2\n",                   \
 334                        TENTRY                          \
 335                "       .dword 8b,9b\n")
 336
 337#define __asm_copy_from_user_16(to, from, ret) \
 338        __asm_copy_from_user_16x_cont(to, from, ret, "", "", "")
 339
 340#define __asm_copy_from_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 341        __asm_copy_from_user_16x_cont(to, from, ret,    \
 342                        COPY                            \
 343                "10:    move.d [%1+],$acr\n"            \
 344                "       move.d $acr,[%0+]\n",           \
 345                        FIXUP                           \
 346                "11:    addq 4,%2\n",                   \
 347                        TENTRY                          \
 348                "       .dword 10b,11b\n")
 349
 350#define __asm_copy_from_user_20(to, from, ret) \
 351        __asm_copy_from_user_20x_cont(to, from, ret, "", "", "")
 352
 353#define __asm_copy_from_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 354        __asm_copy_from_user_20x_cont(to, from, ret,    \
 355                        COPY                            \
 356                "12:    move.d [%1+],$acr\n"            \
 357                "       move.d $acr,[%0+]\n",           \
 358                        FIXUP                           \
 359                "13:    addq 4,%2\n",                   \
 360                        TENTRY                          \
 361                "       .dword 12b,13b\n")
 362
 363#define __asm_copy_from_user_24(to, from, ret) \
 364        __asm_copy_from_user_24x_cont(to, from, ret, "", "", "")
 365
 366/* And now, the to-user ones.  */
 367
 368#define __asm_copy_to_user_1(to, from, ret)     \
 369        __asm_copy_user_cont(to, from, ret,     \
 370                "       move.b [%1+],$acr\n"    \
 371                "2:     move.b $acr,[%0+]\n",   \
 372                "3:     jump 1b\n"              \
 373                "       addq 1,%2\n",           \
 374                "       .dword 2b,3b\n")
 375
 376#define __asm_copy_to_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 377        __asm_copy_user_cont(to, from, ret,             \
 378                        COPY                            \
 379                "       move.w [%1+],$acr\n"            \
 380                "2:     move.w $acr,[%0+]\n",           \
 381                        FIXUP                           \
 382                "3:     jump 1b\n"                      \
 383                "       addq 2,%2\n",                   \
 384                        TENTRY                          \
 385                "       .dword 2b,3b\n")
 386
 387#define __asm_copy_to_user_2(to, from, ret) \
 388        __asm_copy_to_user_2x_cont(to, from, ret, "", "", "")
 389
 390#define __asm_copy_to_user_3(to, from, ret) \
 391        __asm_copy_to_user_2x_cont(to, from, ret,       \
 392                "       move.b [%1+],$acr\n"            \
 393                "4:     move.b $acr,[%0+]\n",           \
 394                "5:     addq 1,%2\n",                   \
 395                "       .dword 4b,5b\n")
 396
 397#define __asm_copy_to_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 398        __asm_copy_user_cont(to, from, ret,             \
 399                        COPY                            \
 400                "       move.d [%1+],$acr\n"            \
 401                "2:     move.d $acr,[%0+]\n",           \
 402                        FIXUP                           \
 403                "3:     jump 1b\n"                      \
 404                "       addq 4,%2\n",                   \
 405                        TENTRY                          \
 406                "       .dword 2b,3b\n")
 407
 408#define __asm_copy_to_user_4(to, from, ret) \
 409        __asm_copy_to_user_4x_cont(to, from, ret, "", "", "")
 410
 411#define __asm_copy_to_user_5(to, from, ret) \
 412        __asm_copy_to_user_4x_cont(to, from, ret,       \
 413                "       move.b [%1+],$acr\n"            \
 414                "4:     move.b $acr,[%0+]\n",           \
 415                "5:     addq 1,%2\n",                   \
 416                "       .dword 4b,5b\n")
 417
 418#define __asm_copy_to_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 419        __asm_copy_to_user_4x_cont(to, from, ret,       \
 420                        COPY                            \
 421                "       move.w [%1+],$acr\n"            \
 422                "4:     move.w $acr,[%0+]\n",           \
 423                        FIXUP                           \
 424                "5:     addq 2,%2\n",                   \
 425                        TENTRY                          \
 426                "       .dword 4b,5b\n")
 427
 428#define __asm_copy_to_user_6(to, from, ret) \
 429        __asm_copy_to_user_6x_cont(to, from, ret, "", "", "")
 430
 431#define __asm_copy_to_user_7(to, from, ret) \
 432        __asm_copy_to_user_6x_cont(to, from, ret,       \
 433                "       move.b [%1+],$acr\n"            \
 434                "6:     move.b $acr,[%0+]\n",           \
 435                "7:     addq 1,%2\n",                   \
 436                "       .dword 6b,7b\n")
 437
 438#define __asm_copy_to_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 439        __asm_copy_to_user_4x_cont(to, from, ret,       \
 440                        COPY                            \
 441                "       move.d [%1+],$acr\n"            \
 442                "4:     move.d $acr,[%0+]\n",           \
 443                        FIXUP                           \
 444                "5:     addq 4,%2\n",                   \
 445                        TENTRY                          \
 446                "       .dword 4b,5b\n")
 447
 448#define __asm_copy_to_user_8(to, from, ret) \
 449        __asm_copy_to_user_8x_cont(to, from, ret, "", "", "")
 450
 451#define __asm_copy_to_user_9(to, from, ret) \
 452        __asm_copy_to_user_8x_cont(to, from, ret,       \
 453                "       move.b [%1+],$acr\n"            \
 454                "6:     move.b $acr,[%0+]\n",           \
 455                "7:     addq 1,%2\n",                   \
 456                "       .dword 6b,7b\n")
 457
 458#define __asm_copy_to_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 459        __asm_copy_to_user_8x_cont(to, from, ret,       \
 460                        COPY                            \
 461                "       move.w [%1+],$acr\n"            \
 462                "6:     move.w $acr,[%0+]\n",           \
 463                        FIXUP                           \
 464                "7:     addq 2,%2\n",                   \
 465                        TENTRY                          \
 466                "       .dword 6b,7b\n")
 467
 468#define __asm_copy_to_user_10(to, from, ret) \
 469        __asm_copy_to_user_10x_cont(to, from, ret, "", "", "")
 470
 471#define __asm_copy_to_user_11(to, from, ret) \
 472        __asm_copy_to_user_10x_cont(to, from, ret,      \
 473                "       move.b [%1+],$acr\n"            \
 474                "8:     move.b $acr,[%0+]\n",           \
 475                "9:     addq 1,%2\n",                   \
 476                "       .dword 8b,9b\n")
 477
 478#define __asm_copy_to_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 479        __asm_copy_to_user_8x_cont(to, from, ret,       \
 480                        COPY                            \
 481                "       move.d [%1+],$acr\n"            \
 482                "6:     move.d $acr,[%0+]\n",           \
 483                        FIXUP                           \
 484                "7:     addq 4,%2\n",                   \
 485                        TENTRY                          \
 486                "       .dword 6b,7b\n")
 487
 488#define __asm_copy_to_user_12(to, from, ret) \
 489        __asm_copy_to_user_12x_cont(to, from, ret, "", "", "")
 490
 491#define __asm_copy_to_user_13(to, from, ret) \
 492        __asm_copy_to_user_12x_cont(to, from, ret,      \
 493                "       move.b [%1+],$acr\n"            \
 494                "8:     move.b $acr,[%0+]\n",           \
 495                "9:     addq 1,%2\n",                   \
 496                "       .dword 8b,9b\n")
 497
 498#define __asm_copy_to_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 499        __asm_copy_to_user_12x_cont(to, from, ret,      \
 500                        COPY                            \
 501                "       move.w [%1+],$acr\n"            \
 502                "8:     move.w $acr,[%0+]\n",           \
 503                        FIXUP                           \
 504                "9:     addq 2,%2\n",                   \
 505                        TENTRY                          \
 506                "       .dword 8b,9b\n")
 507
 508#define __asm_copy_to_user_14(to, from, ret)    \
 509        __asm_copy_to_user_14x_cont(to, from, ret, "", "", "")
 510
 511#define __asm_copy_to_user_15(to, from, ret) \
 512        __asm_copy_to_user_14x_cont(to, from, ret,      \
 513                "       move.b [%1+],$acr\n"            \
 514                "10:    move.b $acr,[%0+]\n",           \
 515                "11:    addq 1,%2\n",                   \
 516                "       .dword 10b,11b\n")
 517
 518#define __asm_copy_to_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 519        __asm_copy_to_user_12x_cont(to, from, ret,      \
 520                        COPY                            \
 521                "       move.d [%1+],$acr\n"            \
 522                "8:     move.d $acr,[%0+]\n",           \
 523                        FIXUP                           \
 524                "9:     addq 4,%2\n",                   \
 525                        TENTRY                          \
 526                "       .dword 8b,9b\n")
 527
 528#define __asm_copy_to_user_16(to, from, ret) \
 529        __asm_copy_to_user_16x_cont(to, from, ret, "", "", "")
 530
 531#define __asm_copy_to_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 532        __asm_copy_to_user_16x_cont(to, from, ret,      \
 533                        COPY                            \
 534                "       move.d [%1+],$acr\n"            \
 535                "10:    move.d $acr,[%0+]\n",           \
 536                        FIXUP                           \
 537                "11:    addq 4,%2\n",                   \
 538                        TENTRY                          \
 539                "       .dword 10b,11b\n")
 540
 541#define __asm_copy_to_user_20(to, from, ret) \
 542        __asm_copy_to_user_20x_cont(to, from, ret, "", "", "")
 543
 544#define __asm_copy_to_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 545        __asm_copy_to_user_20x_cont(to, from, ret,      \
 546                        COPY                            \
 547                "       move.d [%1+],$acr\n"            \
 548                "12:    move.d $acr,[%0+]\n",           \
 549                        FIXUP                           \
 550                "13:    addq 4,%2\n",                   \
 551                        TENTRY                          \
 552                "       .dword 12b,13b\n")
 553
 554#define __asm_copy_to_user_24(to, from, ret)    \
 555        __asm_copy_to_user_24x_cont(to, from, ret, "", "", "")
 556
 557/* Define a few clearing asms with exception handlers.  */
 558
 559/* This frame-asm is like the __asm_copy_user_cont one, but has one less
 560   input.  */
 561
 562#define __asm_clear(to, ret, CLEAR, FIXUP, TENTRY) \
 563        __asm__ __volatile__ (                          \
 564                        CLEAR                           \
 565                "1:\n"                                  \
 566                "       .section .fixup,\"ax\"\n"       \
 567                        FIXUP                           \
 568                "       .previous\n"                    \
 569                "       .section __ex_table,\"a\"\n"    \
 570                        TENTRY                          \
 571                "       .previous"                      \
 572                : "=b" (to), "=r" (ret)                 \
 573                : "0" (to), "1" (ret)                   \
 574                : "memory")
 575
 576#define __asm_clear_1(to, ret) \
 577        __asm_clear(to, ret,                    \
 578                "2:     clear.b [%0+]\n",       \
 579                "3:     jump 1b\n"              \
 580                "       addq 1,%1\n",           \
 581                "       .dword 2b,3b\n")
 582
 583#define __asm_clear_2(to, ret) \
 584        __asm_clear(to, ret,                    \
 585                "2:     clear.w [%0+]\n",       \
 586                "3:     jump 1b\n"              \
 587                "       addq 2,%1\n",           \
 588                "       .dword 2b,3b\n")
 589
 590#define __asm_clear_3(to, ret) \
 591     __asm_clear(to, ret,                       \
 592                 "2:    clear.w [%0+]\n"        \
 593                 "3:    clear.b [%0+]\n",       \
 594                 "4:    addq 2,%1\n"            \
 595                 "5:    jump 1b\n"              \
 596                 "      addq 1,%1\n",           \
 597                 "      .dword 2b,4b\n"         \
 598                 "      .dword 3b,5b\n")
 599
 600#define __asm_clear_4x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
 601        __asm_clear(to, ret,                            \
 602                        CLEAR                           \
 603                "2:     clear.d [%0+]\n",               \
 604                        FIXUP                           \
 605                "3:     jump 1b\n"                      \
 606                "       addq 4,%1\n",                   \
 607                        TENTRY                          \
 608                "       .dword 2b,3b\n")
 609
 610#define __asm_clear_4(to, ret) \
 611        __asm_clear_4x_cont(to, ret, "", "", "")
 612
 613#define __asm_clear_8x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
 614        __asm_clear_4x_cont(to, ret,                    \
 615                        CLEAR                           \
 616                "4:     clear.d [%0+]\n",               \
 617                        FIXUP                           \
 618                "5:     addq 4,%1\n",                   \
 619                        TENTRY                          \
 620                "       .dword 4b,5b\n")
 621
 622#define __asm_clear_8(to, ret) \
 623        __asm_clear_8x_cont(to, ret, "", "", "")
 624
 625#define __asm_clear_12x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
 626        __asm_clear_8x_cont(to, ret,                    \
 627                        CLEAR                           \
 628                "6:     clear.d [%0+]\n",               \
 629                        FIXUP                           \
 630                "7:     addq 4,%1\n",                   \
 631                        TENTRY                          \
 632                "       .dword 6b,7b\n")
 633
 634#define __asm_clear_12(to, ret) \
 635        __asm_clear_12x_cont(to, ret, "", "", "")
 636
 637#define __asm_clear_16x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
 638        __asm_clear_12x_cont(to, ret,                   \
 639                        CLEAR                           \
 640                "8:     clear.d [%0+]\n",               \
 641                        FIXUP                           \
 642                "9:     addq 4,%1\n",                   \
 643                        TENTRY                          \
 644                "       .dword 8b,9b\n")
 645
 646#define __asm_clear_16(to, ret) \
 647        __asm_clear_16x_cont(to, ret, "", "", "")
 648
 649#define __asm_clear_20x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
 650        __asm_clear_16x_cont(to, ret,                   \
 651                        CLEAR                           \
 652                "10:    clear.d [%0+]\n",               \
 653                        FIXUP                           \
 654                "11:    addq 4,%1\n",                   \
 655                        TENTRY                          \
 656                "       .dword 10b,11b\n")
 657
 658#define __asm_clear_20(to, ret) \
 659        __asm_clear_20x_cont(to, ret, "", "", "")
 660
 661#define __asm_clear_24x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
 662        __asm_clear_20x_cont(to, ret,                   \
 663                        CLEAR                           \
 664                "12:    clear.d [%0+]\n",               \
 665                        FIXUP                           \
 666                "13:    addq 4,%1\n",                   \
 667                        TENTRY                          \
 668                "       .dword 12b,13b\n")
 669
 670#define __asm_clear_24(to, ret) \
 671        __asm_clear_24x_cont(to, ret, "", "", "")
 672
 673/*
 674 * Return the size of a string (including the ending 0)
 675 *
 676 * Return length of string in userspace including terminating 0
 677 * or 0 for error.  Return a value greater than N if too long.
 678 */
 679
 680static inline long
 681strnlen_user(const char *s, long n)
 682{
 683        long res, tmp1;
 684
 685        if (!access_ok(VERIFY_READ, s, 0))
 686                return 0;
 687
 688        /*
 689         * This code is deduced from:
 690         *
 691         *      tmp1 = n;
 692         *      while (tmp1-- > 0 && *s++)
 693         *        ;
 694         *
 695         *      res = n - tmp1;
 696         *
 697         *  (with tweaks).
 698         */
 699
 700        __asm__ __volatile__ (
 701                "       move.d %1,$acr\n"
 702                "       cmpq 0,$acr\n"
 703                "0:\n"
 704                "       ble 1f\n"
 705                "       subq 1,$acr\n"
 706
 707                "4:     test.b [%0+]\n"
 708                "       bne 0b\n"
 709                "       cmpq 0,$acr\n"
 710                "1:\n"
 711                "       move.d %1,%0\n"
 712                "       sub.d $acr,%0\n"
 713                "2:\n"
 714                "       .section .fixup,\"ax\"\n"
 715
 716                "3:     jump 2b\n"
 717                "       clear.d %0\n"
 718
 719                "       .previous\n"
 720                "       .section __ex_table,\"a\"\n"
 721                "       .dword 4b,3b\n"
 722                "       .previous\n"
 723                : "=r" (res), "=r" (tmp1)
 724                : "0" (s), "1" (n)
 725                : "acr");
 726
 727        return res;
 728}
 729
 730#endif
 731