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