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/extable.h> 31#include <asm/domain.h> 32 33ENTRY(__get_user_1) 34 check_uaccess r0, 1, r1, r2, __get_user_bad 351: TUSER(ldrb) r2, [r0] 36 mov r0, #0 37 ret lr 38ENDPROC(__get_user_1) 39_ASM_NOKPROBE(__get_user_1) 40 41ENTRY(__get_user_2) 42 check_uaccess r0, 2, r1, r2, __get_user_bad 43#if __LINUX_ARM_ARCH__ >= 6 44 452: TUSER(ldrh) r2, [r0] 46 47#else 48 49#ifdef CONFIG_CPU_USE_DOMAINS 50rb .req ip 512: ldrbt r2, [r0], #1 523: ldrbt rb, [r0], #0 53#else 54rb .req r0 552: ldrb r2, [r0] 563: ldrb rb, [r0, #1] 57#endif 58#ifndef __ARMEB__ 59 orr r2, r2, rb, lsl #8 60#else 61 orr r2, rb, r2, lsl #8 62#endif 63 64#endif /* __LINUX_ARM_ARCH__ >= 6 */ 65 66 mov r0, #0 67 ret lr 68ENDPROC(__get_user_2) 69_ASM_NOKPROBE(__get_user_2) 70 71ENTRY(__get_user_4) 72 check_uaccess r0, 4, r1, r2, __get_user_bad 734: TUSER(ldr) r2, [r0] 74 mov r0, #0 75 ret lr 76ENDPROC(__get_user_4) 77_ASM_NOKPROBE(__get_user_4) 78 79ENTRY(__get_user_8) 80 check_uaccess r0, 8, r1, r2, __get_user_bad8 81#ifdef CONFIG_THUMB2_KERNEL 825: TUSER(ldr) r2, [r0] 836: TUSER(ldr) r3, [r0, #4] 84#else 855: TUSER(ldr) r2, [r0], #4 866: TUSER(ldr) r3, [r0] 87#endif 88 mov r0, #0 89 ret lr 90ENDPROC(__get_user_8) 91_ASM_NOKPROBE(__get_user_8) 92 93#ifdef __ARMEB__ 94ENTRY(__get_user_32t_8) 95 check_uaccess r0, 8, r1, r2, __get_user_bad 96#ifdef CONFIG_CPU_USE_DOMAINS 97 add r0, r0, #4 987: ldrt r2, [r0] 99#else 1007: ldr r2, [r0, #4] 101#endif 102 mov r0, #0 103 ret lr 104ENDPROC(__get_user_32t_8) 105_ASM_NOKPROBE(__get_user_32t_8) 106 107ENTRY(__get_user_64t_1) 108 check_uaccess r0, 1, r1, r2, __get_user_bad8 1098: TUSER(ldrb) r3, [r0] 110 mov r0, #0 111 ret lr 112ENDPROC(__get_user_64t_1) 113_ASM_NOKPROBE(__get_user_64t_1) 114 115ENTRY(__get_user_64t_2) 116 check_uaccess r0, 2, r1, r2, __get_user_bad8 117#ifdef CONFIG_CPU_USE_DOMAINS 118rb .req ip 1199: ldrbt r3, [r0], #1 12010: ldrbt rb, [r0], #0 121#else 122rb .req r0 1239: ldrb r3, [r0] 12410: ldrb rb, [r0, #1] 125#endif 126 orr r3, rb, r3, lsl #8 127 mov r0, #0 128 ret lr 129ENDPROC(__get_user_64t_2) 130_ASM_NOKPROBE(__get_user_64t_2) 131 132ENTRY(__get_user_64t_4) 133 check_uaccess r0, 4, r1, r2, __get_user_bad8 13411: TUSER(ldr) r3, [r0] 135 mov r0, #0 136 ret lr 137ENDPROC(__get_user_64t_4) 138_ASM_NOKPROBE(__get_user_64t_4) 139#endif 140 141__get_user_bad8: 142 mov r3, #0 143__get_user_bad: 144 mov r2, #0 145 mov r0, #-EFAULT 146 ret lr 147ENDPROC(__get_user_bad) 148ENDPROC(__get_user_bad8) 149_ASM_NOKPROBE(__get_user_bad) 150_ASM_NOKPROBE(__get_user_bad8) 151 152.pushsection __ex_table, "a" 153 ex_entry 1b, __get_user_bad 154 ex_entry 2b, __get_user_bad 155#if __LINUX_ARM_ARCH__ < 6 156 ex_entry 3b, __get_user_bad 157#endif 158 ex_entry 4b, __get_user_bad 159 ex_entry 5b, __get_user_bad8 160 ex_entry 6b, __get_user_bad8 161#ifdef __ARMEB__ 162 ex_entry 7b, __get_user_bad 163 ex_entry 8b, __get_user_bad8 164 ex_entry 9b, __get_user_bad8 165 ex_entry 10b, __get_user_bad8 166 ex_entry 11b, __get_user_bad8 167#endif 168