1/* 2 * linux/arch/arm/lib/getuser.S 3 * 4 * Copyright (C) 2001 Russell King 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * Idea from x86 version, (C) Copyright 1998 Linus Torvalds 11 * 12 * These functions have a non-standard call interface to make them more 13 * efficient, especially as they return an error value in addition to 14 * the "real" return value. 15 * 16 * __get_user_X 17 * 18 * Inputs: r0 contains the address 19 * r1 contains the address limit, which must be preserved 20 * Outputs: r0 is the error code 21 * r2, r3 contains the zero-extended value 22 * lr corrupted 23 * 24 * No other registers must be altered. (see <asm/uaccess.h> 25 * for specific ASM register usage). 26 * 27 * Note that ADDR_LIMIT is either 0 or 0xc0000000. 28 * Note also that it is intended that __get_user_bad is not global. 29 */ 30#include <linux/linkage.h> 31#include <asm/assembler.h> 32#include <asm/errno.h> 33#include <asm/domain.h> 34 35ENTRY(__get_user_1) 36 check_uaccess r0, 1, r1, r2, __get_user_bad 371: TUSER(ldrb) r2, [r0] 38 mov r0, #0 39 ret lr 40ENDPROC(__get_user_1) 41_ASM_NOKPROBE(__get_user_1) 42 43ENTRY(__get_user_2) 44 check_uaccess r0, 2, r1, r2, __get_user_bad 45#if __LINUX_ARM_ARCH__ >= 6 46 472: TUSER(ldrh) r2, [r0] 48 49#else 50 51#ifdef CONFIG_CPU_USE_DOMAINS 52rb .req ip 532: ldrbt r2, [r0], #1 543: ldrbt rb, [r0], #0 55#else 56rb .req r0 572: ldrb r2, [r0] 583: ldrb rb, [r0, #1] 59#endif 60#ifndef __ARMEB__ 61 orr r2, r2, rb, lsl #8 62#else 63 orr r2, rb, r2, lsl #8 64#endif 65 66#endif /* __LINUX_ARM_ARCH__ >= 6 */ 67 68 mov r0, #0 69 ret lr 70ENDPROC(__get_user_2) 71_ASM_NOKPROBE(__get_user_2) 72 73ENTRY(__get_user_4) 74 check_uaccess r0, 4, r1, r2, __get_user_bad 754: TUSER(ldr) r2, [r0] 76 mov r0, #0 77 ret lr 78ENDPROC(__get_user_4) 79_ASM_NOKPROBE(__get_user_4) 80 81ENTRY(__get_user_8) 82 check_uaccess r0, 8, r1, r2, __get_user_bad8 83#ifdef CONFIG_THUMB2_KERNEL 845: TUSER(ldr) r2, [r0] 856: TUSER(ldr) r3, [r0, #4] 86#else 875: TUSER(ldr) r2, [r0], #4 886: TUSER(ldr) r3, [r0] 89#endif 90 mov r0, #0 91 ret lr 92ENDPROC(__get_user_8) 93_ASM_NOKPROBE(__get_user_8) 94 95#ifdef __ARMEB__ 96ENTRY(__get_user_32t_8) 97 check_uaccess r0, 8, r1, r2, __get_user_bad 98#ifdef CONFIG_CPU_USE_DOMAINS 99 add r0, r0, #4 1007: ldrt r2, [r0] 101#else 1027: ldr r2, [r0, #4] 103#endif 104 mov r0, #0 105 ret lr 106ENDPROC(__get_user_32t_8) 107_ASM_NOKPROBE(__get_user_32t_8) 108 109ENTRY(__get_user_64t_1) 110 check_uaccess r0, 1, r1, r2, __get_user_bad8 1118: TUSER(ldrb) r3, [r0] 112 mov r0, #0 113 ret lr 114ENDPROC(__get_user_64t_1) 115_ASM_NOKPROBE(__get_user_64t_1) 116 117ENTRY(__get_user_64t_2) 118 check_uaccess r0, 2, r1, r2, __get_user_bad8 119#ifdef CONFIG_CPU_USE_DOMAINS 120rb .req ip 1219: ldrbt r3, [r0], #1 12210: ldrbt rb, [r0], #0 123#else 124rb .req r0 1259: ldrb r3, [r0] 12610: ldrb rb, [r0, #1] 127#endif 128 orr r3, rb, r3, lsl #8 129 mov r0, #0 130 ret lr 131ENDPROC(__get_user_64t_2) 132_ASM_NOKPROBE(__get_user_64t_2) 133 134ENTRY(__get_user_64t_4) 135 check_uaccess r0, 4, r1, r2, __get_user_bad8 13611: TUSER(ldr) r3, [r0] 137 mov r0, #0 138 ret lr 139ENDPROC(__get_user_64t_4) 140_ASM_NOKPROBE(__get_user_64t_4) 141#endif 142 143__get_user_bad8: 144 mov r3, #0 145__get_user_bad: 146 mov r2, #0 147 mov r0, #-EFAULT 148 ret lr 149ENDPROC(__get_user_bad) 150ENDPROC(__get_user_bad8) 151_ASM_NOKPROBE(__get_user_bad) 152_ASM_NOKPROBE(__get_user_bad8) 153 154.pushsection __ex_table, "a" 155 .long 1b, __get_user_bad 156 .long 2b, __get_user_bad 157#if __LINUX_ARM_ARCH__ < 6 158 .long 3b, __get_user_bad 159#endif 160 .long 4b, __get_user_bad 161 .long 5b, __get_user_bad8 162 .long 6b, __get_user_bad8 163#ifdef __ARMEB__ 164 .long 7b, __get_user_bad 165 .long 8b, __get_user_bad8 166 .long 9b, __get_user_bad8 167 .long 10b, __get_user_bad8 168 .long 11b, __get_user_bad8 169#endif 170.popsection 171