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