linux/arch/mips/include/asm/uaccess.h
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 03, 04 by Ralf Baechle
   7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
   8 * Copyright (C) 2007  Maciej W. Rozycki
   9 * Copyright (C) 2014, Imagination Technologies Ltd.
  10 */
  11#ifndef _ASM_UACCESS_H
  12#define _ASM_UACCESS_H
  13
  14#include <linux/kernel.h>
  15#include <linux/string.h>
  16#include <asm/asm-eva.h>
  17#include <asm/extable.h>
  18
  19#ifdef CONFIG_32BIT
  20
  21#define __UA_LIMIT 0x80000000UL
  22
  23#define __UA_ADDR       ".word"
  24#define __UA_LA         "la"
  25#define __UA_ADDU       "addu"
  26#define __UA_t0         "$8"
  27#define __UA_t1         "$9"
  28
  29#endif /* CONFIG_32BIT */
  30
  31#ifdef CONFIG_64BIT
  32
  33extern u64 __ua_limit;
  34
  35#define __UA_LIMIT      __ua_limit
  36
  37#define __UA_ADDR       ".dword"
  38#define __UA_LA         "dla"
  39#define __UA_ADDU       "daddu"
  40#define __UA_t0         "$12"
  41#define __UA_t1         "$13"
  42
  43#endif /* CONFIG_64BIT */
  44
  45/*
  46 * Is a address valid? This does a straightforward calculation rather
  47 * than tests.
  48 *
  49 * Address valid if:
  50 *  - "addr" doesn't have any high-bits set
  51 *  - AND "size" doesn't have any high-bits set
  52 *  - AND "addr+size" doesn't have any high-bits set
  53 *  - OR we are in kernel mode.
  54 *
  55 * __ua_size() is a trick to avoid runtime checking of positive constant
  56 * sizes; for those we already know at compile time that the size is ok.
  57 */
  58#define __ua_size(size)                                                 \
  59        ((__builtin_constant_p(size) && (signed long) (size) > 0) ? 0 : (size))
  60
  61/*
  62 * access_ok: - Checks if a user space pointer is valid
  63 * @addr: User space pointer to start of block to check
  64 * @size: Size of block to check
  65 *
  66 * Context: User context only. This function may sleep if pagefaults are
  67 *          enabled.
  68 *
  69 * Checks if a pointer to a block of memory in user space is valid.
  70 *
  71 * Returns true (nonzero) if the memory block may be valid, false (zero)
  72 * if it is definitely invalid.
  73 *
  74 * Note that, depending on architecture, this function probably just
  75 * checks that the pointer is in the user space range - after calling
  76 * this function, memory access functions may still return -EFAULT.
  77 */
  78
  79static inline int __access_ok(const void __user *p, unsigned long size)
  80{
  81        unsigned long addr = (unsigned long)p;
  82        unsigned long end = addr + size - !!size;
  83
  84        return (__UA_LIMIT & (addr | end | __ua_size(size))) == 0;
  85}
  86
  87#define access_ok(addr, size)                                   \
  88        likely(__access_ok((addr), (size)))
  89
  90/*
  91 * put_user: - Write a simple value into user space.
  92 * @x:   Value to copy to user space.
  93 * @ptr: Destination address, in user space.
  94 *
  95 * Context: User context only. This function may sleep if pagefaults are
  96 *          enabled.
  97 *
  98 * This macro copies a single simple value from kernel space to user
  99 * space.  It supports simple types like char and int, but not larger
 100 * data types like structures or arrays.
 101 *
 102 * @ptr must have pointer-to-simple-variable type, and @x must be assignable
 103 * to the result of dereferencing @ptr.
 104 *
 105 * Returns zero on success, or -EFAULT on error.
 106 */
 107#define put_user(x, ptr)                                                \
 108({                                                                      \
 109        __typeof__(*(ptr)) __user *__p = (ptr);                         \
 110                                                                        \
 111        might_fault();                                                  \
 112        access_ok(__p, sizeof(*__p)) ? __put_user((x), __p) : -EFAULT;  \
 113})
 114
 115/*
 116 * get_user: - Get a simple variable from user space.
 117 * @x:   Variable to store result.
 118 * @ptr: Source address, in user space.
 119 *
 120 * Context: User context only. This function may sleep if pagefaults are
 121 *          enabled.
 122 *
 123 * This macro copies a single simple variable from user space to kernel
 124 * space.  It supports simple types like char and int, but not larger
 125 * data types like structures or arrays.
 126 *
 127 * @ptr must have pointer-to-simple-variable type, and the result of
 128 * dereferencing @ptr must be assignable to @x without a cast.
 129 *
 130 * Returns zero on success, or -EFAULT on error.
 131 * On error, the variable @x is set to zero.
 132 */
 133#define get_user(x, ptr)                                                \
 134({                                                                      \
 135        const __typeof__(*(ptr)) __user *__p = (ptr);                   \
 136                                                                        \
 137        might_fault();                                                  \
 138        access_ok(__p, sizeof(*__p)) ? __get_user((x), __p) :           \
 139                                       ((x) = 0, -EFAULT);              \
 140})
 141
 142/*
 143 * __put_user: - Write a simple value into user space, with less checking.
 144 * @x:   Value to copy to user space.
 145 * @ptr: Destination address, in user space.
 146 *
 147 * Context: User context only. This function may sleep if pagefaults are
 148 *          enabled.
 149 *
 150 * This macro copies a single simple value from kernel space to user
 151 * space.  It supports simple types like char and int, but not larger
 152 * data types like structures or arrays.
 153 *
 154 * @ptr must have pointer-to-simple-variable type, and @x must be assignable
 155 * to the result of dereferencing @ptr.
 156 *
 157 * Caller must check the pointer with access_ok() before calling this
 158 * function.
 159 *
 160 * Returns zero on success, or -EFAULT on error.
 161 */
 162#define __put_user(x, ptr)                                              \
 163({                                                                      \
 164        __typeof__(*(ptr)) __user *__pu_ptr = (ptr);                    \
 165        __typeof__(*(ptr)) __pu_val = (x);                              \
 166        int __pu_err = 0;                                               \
 167                                                                        \
 168        __chk_user_ptr(__pu_ptr);                                       \
 169        switch (sizeof(*__pu_ptr)) {                                    \
 170        case 1:                                                         \
 171                __put_data_asm(user_sb, __pu_ptr);                      \
 172                break;                                                  \
 173        case 2:                                                         \
 174                __put_data_asm(user_sh, __pu_ptr);                      \
 175                break;                                                  \
 176        case 4:                                                         \
 177                __put_data_asm(user_sw, __pu_ptr);                      \
 178                break;                                                  \
 179        case 8:                                                         \
 180                __PUT_DW(user_sd, __pu_ptr);                            \
 181                break;                                                  \
 182        default:                                                        \
 183                BUILD_BUG();                                            \
 184        }                                                               \
 185                                                                        \
 186        __pu_err;                                                       \
 187})
 188
 189/*
 190 * __get_user: - Get a simple variable from user space, with less checking.
 191 * @x:   Variable to store result.
 192 * @ptr: Source address, in user space.
 193 *
 194 * Context: User context only. This function may sleep if pagefaults are
 195 *          enabled.
 196 *
 197 * This macro copies a single simple variable from user space to kernel
 198 * space.  It supports simple types like char and int, but not larger
 199 * data types like structures or arrays.
 200 *
 201 * @ptr must have pointer-to-simple-variable type, and the result of
 202 * dereferencing @ptr must be assignable to @x without a cast.
 203 *
 204 * Caller must check the pointer with access_ok() before calling this
 205 * function.
 206 *
 207 * Returns zero on success, or -EFAULT on error.
 208 * On error, the variable @x is set to zero.
 209 */
 210#define __get_user(x, ptr)                                              \
 211({                                                                      \
 212        const __typeof__(*(ptr)) __user *__gu_ptr = (ptr);              \
 213        int __gu_err = 0;                                               \
 214                                                                        \
 215        __chk_user_ptr(__gu_ptr);                                       \
 216        switch (sizeof(*__gu_ptr)) {                                    \
 217        case 1:                                                         \
 218                __get_data_asm((x), user_lb, __gu_ptr);                 \
 219                break;                                                  \
 220        case 2:                                                         \
 221                __get_data_asm((x), user_lh, __gu_ptr);                 \
 222                break;                                                  \
 223        case 4:                                                         \
 224                __get_data_asm((x), user_lw, __gu_ptr);                 \
 225                break;                                                  \
 226        case 8:                                                         \
 227                __GET_DW((x), user_ld, __gu_ptr);                       \
 228                break;                                                  \
 229        default:                                                        \
 230                BUILD_BUG();                                            \
 231        }                                                               \
 232                                                                        \
 233        __gu_err;                                                       \
 234})
 235
 236struct __large_struct { unsigned long buf[100]; };
 237#define __m(x) (*(struct __large_struct __user *)(x))
 238
 239#ifdef CONFIG_32BIT
 240#define __GET_DW(val, insn, ptr) __get_data_asm_ll32(val, insn, ptr)
 241#endif
 242#ifdef CONFIG_64BIT
 243#define __GET_DW(val, insn, ptr) __get_data_asm(val, insn, ptr)
 244#endif
 245
 246#define __get_data_asm(val, insn, addr)                                 \
 247{                                                                       \
 248        long __gu_tmp;                                                  \
 249                                                                        \
 250        __asm__ __volatile__(                                           \
 251        "1:     "insn("%1", "%3")"                              \n"     \
 252        "2:                                                     \n"     \
 253        "       .insn                                           \n"     \
 254        "       .section .fixup,\"ax\"                          \n"     \
 255        "3:     li      %0, %4                                  \n"     \
 256        "       move    %1, $0                                  \n"     \
 257        "       j       2b                                      \n"     \
 258        "       .previous                                       \n"     \
 259        "       .section __ex_table,\"a\"                       \n"     \
 260        "       "__UA_ADDR "\t1b, 3b                            \n"     \
 261        "       .previous                                       \n"     \
 262        : "=r" (__gu_err), "=r" (__gu_tmp)                              \
 263        : "0" (0), "o" (__m(addr)), "i" (-EFAULT));                     \
 264                                                                        \
 265        (val) = (__typeof__(*(addr))) __gu_tmp;                         \
 266}
 267
 268/*
 269 * Get a long long 64 using 32 bit registers.
 270 */
 271#define __get_data_asm_ll32(val, insn, addr)                            \
 272{                                                                       \
 273        union {                                                         \
 274                unsigned long long      l;                              \
 275                __typeof__(*(addr))     t;                              \
 276        } __gu_tmp;                                                     \
 277                                                                        \
 278        __asm__ __volatile__(                                           \
 279        "1:     " insn("%1", "(%3)")"                           \n"     \
 280        "2:     " insn("%D1", "4(%3)")"                         \n"     \
 281        "3:                                                     \n"     \
 282        "       .insn                                           \n"     \
 283        "       .section        .fixup,\"ax\"                   \n"     \
 284        "4:     li      %0, %4                                  \n"     \
 285        "       move    %1, $0                                  \n"     \
 286        "       move    %D1, $0                                 \n"     \
 287        "       j       3b                                      \n"     \
 288        "       .previous                                       \n"     \
 289        "       .section        __ex_table,\"a\"                \n"     \
 290        "       " __UA_ADDR "   1b, 4b                          \n"     \
 291        "       " __UA_ADDR "   2b, 4b                          \n"     \
 292        "       .previous                                       \n"     \
 293        : "=r" (__gu_err), "=&r" (__gu_tmp.l)                           \
 294        : "0" (0), "r" (addr), "i" (-EFAULT));                          \
 295                                                                        \
 296        (val) = __gu_tmp.t;                                             \
 297}
 298
 299#define HAVE_GET_KERNEL_NOFAULT
 300
 301#define __get_kernel_nofault(dst, src, type, err_label)                 \
 302do {                                                                    \
 303        int __gu_err;                                                   \
 304                                                                        \
 305        switch (sizeof(type)) {                                         \
 306        case 1:                                                         \
 307                __get_data_asm(*(type *)(dst), kernel_lb,               \
 308                               (__force type *)(src));                  \
 309                break;                                                  \
 310        case 2:                                                         \
 311                __get_data_asm(*(type *)(dst), kernel_lh,               \
 312                               (__force type *)(src));                  \
 313                break;                                                  \
 314        case 4:                                                         \
 315                 __get_data_asm(*(type *)(dst), kernel_lw,              \
 316                               (__force type *)(src));                  \
 317                break;                                                  \
 318        case 8:                                                         \
 319                __GET_DW(*(type *)(dst), kernel_ld,                     \
 320                         (__force type *)(src));                        \
 321                break;                                                  \
 322        default:                                                        \
 323                BUILD_BUG();                                            \
 324                break;                                                  \
 325        }                                                               \
 326        if (unlikely(__gu_err))                                         \
 327                goto err_label;                                         \
 328} while (0)
 329
 330/*
 331 * Yuck.  We need two variants, one for 64bit operation and one
 332 * for 32 bit mode and old iron.
 333 */
 334#ifdef CONFIG_32BIT
 335#define __PUT_DW(insn, ptr) __put_data_asm_ll32(insn, ptr)
 336#endif
 337#ifdef CONFIG_64BIT
 338#define __PUT_DW(insn, ptr) __put_data_asm(insn, ptr)
 339#endif
 340
 341#define __put_data_asm(insn, ptr)                                       \
 342{                                                                       \
 343        __asm__ __volatile__(                                           \
 344        "1:     "insn("%z2", "%3")"     # __put_data_asm        \n"     \
 345        "2:                                                     \n"     \
 346        "       .insn                                           \n"     \
 347        "       .section        .fixup,\"ax\"                   \n"     \
 348        "3:     li      %0, %4                                  \n"     \
 349        "       j       2b                                      \n"     \
 350        "       .previous                                       \n"     \
 351        "       .section        __ex_table,\"a\"                \n"     \
 352        "       " __UA_ADDR "   1b, 3b                          \n"     \
 353        "       .previous                                       \n"     \
 354        : "=r" (__pu_err)                                               \
 355        : "0" (0), "Jr" (__pu_val), "o" (__m(ptr)),                     \
 356          "i" (-EFAULT));                                               \
 357}
 358
 359#define __put_data_asm_ll32(insn, ptr)                                  \
 360{                                                                       \
 361        __asm__ __volatile__(                                           \
 362        "1:     "insn("%2", "(%3)")"    # __put_data_asm_ll32   \n"     \
 363        "2:     "insn("%D2", "4(%3)")"                          \n"     \
 364        "3:                                                     \n"     \
 365        "       .insn                                           \n"     \
 366        "       .section        .fixup,\"ax\"                   \n"     \
 367        "4:     li      %0, %4                                  \n"     \
 368        "       j       3b                                      \n"     \
 369        "       .previous                                       \n"     \
 370        "       .section        __ex_table,\"a\"                \n"     \
 371        "       " __UA_ADDR "   1b, 4b                          \n"     \
 372        "       " __UA_ADDR "   2b, 4b                          \n"     \
 373        "       .previous"                                              \
 374        : "=r" (__pu_err)                                               \
 375        : "0" (0), "r" (__pu_val), "r" (ptr),                           \
 376          "i" (-EFAULT));                                               \
 377}
 378
 379#define __put_kernel_nofault(dst, src, type, err_label)                 \
 380do {                                                                    \
 381        type __pu_val;                                  \
 382        int __pu_err = 0;                                               \
 383                                                                        \
 384        __pu_val = *(__force type *)(src);                              \
 385        switch (sizeof(type)) {                                         \
 386        case 1:                                                         \
 387                __put_data_asm(kernel_sb, (type *)(dst));               \
 388                break;                                                  \
 389        case 2:                                                         \
 390                __put_data_asm(kernel_sh, (type *)(dst));               \
 391                break;                                                  \
 392        case 4:                                                         \
 393                __put_data_asm(kernel_sw, (type *)(dst))                \
 394                break;                                                  \
 395        case 8:                                                         \
 396                __PUT_DW(kernel_sd, (type *)(dst));                     \
 397                break;                                                  \
 398        default:                                                        \
 399                BUILD_BUG();                                            \
 400                break;                                                  \
 401        }                                                               \
 402        if (unlikely(__pu_err))                                         \
 403                goto err_label;                                         \
 404} while (0)
 405
 406
 407/*
 408 * We're generating jump to subroutines which will be outside the range of
 409 * jump instructions
 410 */
 411#ifdef MODULE
 412#define __MODULE_JAL(destination)                                       \
 413        ".set\tnoat\n\t"                                                \
 414        __UA_LA "\t$1, " #destination "\n\t"                            \
 415        "jalr\t$1\n\t"                                                  \
 416        ".set\tat\n\t"
 417#else
 418#define __MODULE_JAL(destination)                                       \
 419        "jal\t" #destination "\n\t"
 420#endif
 421
 422#if defined(CONFIG_CPU_DADDI_WORKAROUNDS) || (defined(CONFIG_EVA) &&    \
 423                                              defined(CONFIG_CPU_HAS_PREFETCH))
 424#define DADDI_SCRATCH "$3"
 425#else
 426#define DADDI_SCRATCH "$0"
 427#endif
 428
 429extern size_t __raw_copy_from_user(void *__to, const void *__from, size_t __n);
 430extern size_t __raw_copy_to_user(void *__to, const void *__from, size_t __n);
 431extern size_t __raw_copy_in_user(void *__to, const void *__from, size_t __n);
 432
 433static inline unsigned long
 434raw_copy_from_user(void *to, const void __user *from, unsigned long n)
 435{
 436        register void *__cu_to_r __asm__("$4");
 437        register const void __user *__cu_from_r __asm__("$5");
 438        register long __cu_len_r __asm__("$6");
 439
 440        __cu_to_r = to;
 441        __cu_from_r = from;
 442        __cu_len_r = n;
 443
 444        __asm__ __volatile__(
 445                ".set\tnoreorder\n\t"
 446                __MODULE_JAL(__raw_copy_from_user)
 447                ".set\tnoat\n\t"
 448                __UA_ADDU "\t$1, %1, %2\n\t"
 449                ".set\tat\n\t"
 450                ".set\treorder"
 451                : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)
 452                :
 453                : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31",
 454                  DADDI_SCRATCH, "memory");
 455
 456        return __cu_len_r;
 457}
 458
 459static inline unsigned long
 460raw_copy_to_user(void __user *to, const void *from, unsigned long n)
 461{
 462        register void __user *__cu_to_r __asm__("$4");
 463        register const void *__cu_from_r __asm__("$5");
 464        register long __cu_len_r __asm__("$6");
 465
 466        __cu_to_r = (to);
 467        __cu_from_r = (from);
 468        __cu_len_r = (n);
 469
 470        __asm__ __volatile__(
 471                __MODULE_JAL(__raw_copy_to_user)
 472                : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)
 473                :
 474                : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31",
 475                  DADDI_SCRATCH, "memory");
 476
 477        return __cu_len_r;
 478}
 479
 480#define INLINE_COPY_FROM_USER
 481#define INLINE_COPY_TO_USER
 482
 483static inline unsigned long
 484raw_copy_in_user(void __user *to, const void __user *from, unsigned long n)
 485{
 486        register void __user *__cu_to_r __asm__("$4");
 487        register const void __user *__cu_from_r __asm__("$5");
 488        register long __cu_len_r __asm__("$6");
 489
 490        __cu_to_r = to;
 491        __cu_from_r = from;
 492        __cu_len_r = n;
 493
 494        __asm__ __volatile__(
 495                ".set\tnoreorder\n\t"
 496                __MODULE_JAL(__raw_copy_in_user)
 497                ".set\tnoat\n\t"
 498                __UA_ADDU "\t$1, %1, %2\n\t"
 499                ".set\tat\n\t"
 500                ".set\treorder"
 501                : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)
 502                :
 503                : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31",
 504                  DADDI_SCRATCH, "memory");
 505        return __cu_len_r;
 506}
 507
 508extern __kernel_size_t __bzero(void __user *addr, __kernel_size_t size);
 509
 510/*
 511 * __clear_user: - Zero a block of memory in user space, with less checking.
 512 * @to:   Destination address, in user space.
 513 * @n:    Number of bytes to zero.
 514 *
 515 * Zero a block of memory in user space.  Caller must check
 516 * the specified block with access_ok() before calling this function.
 517 *
 518 * Returns number of bytes that could not be cleared.
 519 * On success, this will be zero.
 520 */
 521static inline __kernel_size_t
 522__clear_user(void __user *addr, __kernel_size_t size)
 523{
 524        __kernel_size_t res;
 525
 526#ifdef CONFIG_CPU_MICROMIPS
 527/* micromips memset / bzero also clobbers t7 & t8 */
 528#define bzero_clobbers "$4", "$5", "$6", __UA_t0, __UA_t1, "$15", "$24", "$31"
 529#else
 530#define bzero_clobbers "$4", "$5", "$6", __UA_t0, __UA_t1, "$31"
 531#endif /* CONFIG_CPU_MICROMIPS */
 532
 533        might_fault();
 534        __asm__ __volatile__(
 535                "move\t$4, %1\n\t"
 536                "move\t$5, $0\n\t"
 537                "move\t$6, %2\n\t"
 538                __MODULE_JAL(__bzero)
 539                "move\t%0, $6"
 540                : "=r" (res)
 541                : "r" (addr), "r" (size)
 542                : bzero_clobbers);
 543
 544        return res;
 545}
 546
 547#define clear_user(addr,n)                                              \
 548({                                                                      \
 549        void __user * __cl_addr = (addr);                               \
 550        unsigned long __cl_size = (n);                                  \
 551        if (__cl_size && access_ok(__cl_addr, __cl_size))               \
 552                __cl_size = __clear_user(__cl_addr, __cl_size);         \
 553        __cl_size;                                                      \
 554})
 555
 556extern long __strncpy_from_user_asm(char *__to, const char __user *__from, long __len);
 557
 558/*
 559 * strncpy_from_user: - Copy a NUL terminated string from userspace.
 560 * @dst:   Destination address, in kernel space.  This buffer must be at
 561 *         least @count bytes long.
 562 * @src:   Source address, in user space.
 563 * @count: Maximum number of bytes to copy, including the trailing NUL.
 564 *
 565 * Copies a NUL-terminated string from userspace to kernel space.
 566 *
 567 * On success, returns the length of the string (not including the trailing
 568 * NUL).
 569 *
 570 * If access to userspace fails, returns -EFAULT (some data may have been
 571 * copied).
 572 *
 573 * If @count is smaller than the length of the string, copies @count bytes
 574 * and returns @count.
 575 */
 576static inline long
 577strncpy_from_user(char *__to, const char __user *__from, long __len)
 578{
 579        long res;
 580
 581        if (!access_ok(__from, __len))
 582                return -EFAULT;
 583
 584        might_fault();
 585        __asm__ __volatile__(
 586                "move\t$4, %1\n\t"
 587                "move\t$5, %2\n\t"
 588                "move\t$6, %3\n\t"
 589                __MODULE_JAL(__strncpy_from_user_asm)
 590                "move\t%0, $2"
 591                : "=r" (res)
 592                : "r" (__to), "r" (__from), "r" (__len)
 593                : "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
 594
 595        return res;
 596}
 597
 598extern long __strnlen_user_asm(const char __user *s, long n);
 599
 600/*
 601 * strnlen_user: - Get the size of a string in user space.
 602 * @str: The string to measure.
 603 *
 604 * Context: User context only. This function may sleep if pagefaults are
 605 *          enabled.
 606 *
 607 * Get the size of a NUL-terminated string in user space.
 608 *
 609 * Returns the size of the string INCLUDING the terminating NUL.
 610 * On exception, returns 0.
 611 * If the string is too long, returns a value greater than @n.
 612 */
 613static inline long strnlen_user(const char __user *s, long n)
 614{
 615        long res;
 616
 617        if (!access_ok(s, 1))
 618                return 0;
 619
 620        might_fault();
 621        __asm__ __volatile__(
 622                "move\t$4, %1\n\t"
 623                "move\t$5, %2\n\t"
 624                __MODULE_JAL(__strnlen_user_asm)
 625                "move\t%0, $2"
 626                : "=r" (res)
 627                : "r" (s), "r" (n)
 628                : "$2", "$4", "$5", __UA_t0, "$31");
 629
 630        return res;
 631}
 632
 633#endif /* _ASM_UACCESS_H */
 634