linux/arch/arm/lib/getuser.S
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 *  linux/arch/arm/lib/getuser.S
   4 *
   5 *  Copyright (C) 2001 Russell King
   6 *
   7 *  Idea from x86 version, (C) Copyright 1998 Linus Torvalds
   8 *
   9 * These functions have a non-standard call interface to make them more
  10 * efficient, especially as they return an error value in addition to
  11 * the "real" return value.
  12 *
  13 * __get_user_X
  14 *
  15 * Inputs:      r0 contains the address
  16 *              r1 contains the address limit, which must be preserved
  17 * Outputs:     r0 is the error code
  18 *              r2, r3 contains the zero-extended value
  19 *              lr corrupted
  20 *
  21 * No other registers must be altered.  (see <asm/uaccess.h>
  22 * for specific ASM register usage).
  23 *
  24 * Note that ADDR_LIMIT is either 0 or 0xc0000000.
  25 * Note also that it is intended that __get_user_bad is not global.
  26 */
  27#include <linux/linkage.h>
  28#include <asm/assembler.h>
  29#include <asm/errno.h>
  30#include <asm/domain.h>
  31
  32ENTRY(__get_user_1)
  33        check_uaccess r0, 1, r1, r2, __get_user_bad
  341: TUSER(ldrb)  r2, [r0]
  35        mov     r0, #0
  36        ret     lr
  37ENDPROC(__get_user_1)
  38_ASM_NOKPROBE(__get_user_1)
  39
  40ENTRY(__get_user_2)
  41        check_uaccess r0, 2, r1, r2, __get_user_bad
  42#if __LINUX_ARM_ARCH__ >= 6
  43
  442: TUSER(ldrh)  r2, [r0]
  45
  46#else
  47
  48#ifdef CONFIG_CPU_USE_DOMAINS
  49rb      .req    ip
  502:      ldrbt   r2, [r0], #1
  513:      ldrbt   rb, [r0], #0
  52#else
  53rb      .req    r0
  542:      ldrb    r2, [r0]
  553:      ldrb    rb, [r0, #1]
  56#endif
  57#ifndef __ARMEB__
  58        orr     r2, r2, rb, lsl #8
  59#else
  60        orr     r2, rb, r2, lsl #8
  61#endif
  62
  63#endif /* __LINUX_ARM_ARCH__ >= 6 */
  64
  65        mov     r0, #0
  66        ret     lr
  67ENDPROC(__get_user_2)
  68_ASM_NOKPROBE(__get_user_2)
  69
  70ENTRY(__get_user_4)
  71        check_uaccess r0, 4, r1, r2, __get_user_bad
  724: TUSER(ldr)   r2, [r0]
  73        mov     r0, #0
  74        ret     lr
  75ENDPROC(__get_user_4)
  76_ASM_NOKPROBE(__get_user_4)
  77
  78ENTRY(__get_user_8)
  79        check_uaccess r0, 8, r1, r2, __get_user_bad8
  80#ifdef CONFIG_THUMB2_KERNEL
  815: TUSER(ldr)   r2, [r0]
  826: TUSER(ldr)   r3, [r0, #4]
  83#else
  845: TUSER(ldr)   r2, [r0], #4
  856: TUSER(ldr)   r3, [r0]
  86#endif
  87        mov     r0, #0
  88        ret     lr
  89ENDPROC(__get_user_8)
  90_ASM_NOKPROBE(__get_user_8)
  91
  92#ifdef __ARMEB__
  93ENTRY(__get_user_32t_8)
  94        check_uaccess r0, 8, r1, r2, __get_user_bad
  95#ifdef CONFIG_CPU_USE_DOMAINS
  96        add     r0, r0, #4
  977:      ldrt    r2, [r0]
  98#else
  997:      ldr     r2, [r0, #4]
 100#endif
 101        mov     r0, #0
 102        ret     lr
 103ENDPROC(__get_user_32t_8)
 104_ASM_NOKPROBE(__get_user_32t_8)
 105
 106ENTRY(__get_user_64t_1)
 107        check_uaccess r0, 1, r1, r2, __get_user_bad8
 1088: TUSER(ldrb)  r3, [r0]
 109        mov     r0, #0
 110        ret     lr
 111ENDPROC(__get_user_64t_1)
 112_ASM_NOKPROBE(__get_user_64t_1)
 113
 114ENTRY(__get_user_64t_2)
 115        check_uaccess r0, 2, r1, r2, __get_user_bad8
 116#ifdef CONFIG_CPU_USE_DOMAINS
 117rb      .req    ip
 1189:      ldrbt   r3, [r0], #1
 11910:     ldrbt   rb, [r0], #0
 120#else
 121rb      .req    r0
 1229:      ldrb    r3, [r0]
 12310:     ldrb    rb, [r0, #1]
 124#endif
 125        orr     r3, rb, r3, lsl #8
 126        mov     r0, #0
 127        ret     lr
 128ENDPROC(__get_user_64t_2)
 129_ASM_NOKPROBE(__get_user_64t_2)
 130
 131ENTRY(__get_user_64t_4)
 132        check_uaccess r0, 4, r1, r2, __get_user_bad8
 13311: TUSER(ldr)  r3, [r0]
 134        mov     r0, #0
 135        ret     lr
 136ENDPROC(__get_user_64t_4)
 137_ASM_NOKPROBE(__get_user_64t_4)
 138#endif
 139
 140__get_user_bad8:
 141        mov     r3, #0
 142__get_user_bad:
 143        mov     r2, #0
 144        mov     r0, #-EFAULT
 145        ret     lr
 146ENDPROC(__get_user_bad)
 147ENDPROC(__get_user_bad8)
 148_ASM_NOKPROBE(__get_user_bad)
 149_ASM_NOKPROBE(__get_user_bad8)
 150
 151.pushsection __ex_table, "a"
 152        .long   1b, __get_user_bad
 153        .long   2b, __get_user_bad
 154#if __LINUX_ARM_ARCH__ < 6
 155        .long   3b, __get_user_bad
 156#endif
 157        .long   4b, __get_user_bad
 158        .long   5b, __get_user_bad8
 159        .long   6b, __get_user_bad8
 160#ifdef __ARMEB__
 161        .long   7b, __get_user_bad
 162        .long   8b, __get_user_bad8
 163        .long   9b, __get_user_bad8
 164        .long   10b, __get_user_bad8
 165        .long   11b, __get_user_bad8
 166#endif
 167.popsection
 168