1d2912cb1SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */ 21da177e4SLinus Torvalds/* 31da177e4SLinus Torvalds * linux/arch/arm/lib/getuser.S 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (C) 2001 Russell King 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * Idea from x86 version, (C) Copyright 1998 Linus Torvalds 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * These functions have a non-standard call interface to make them more 101da177e4SLinus Torvalds * efficient, especially as they return an error value in addition to 111da177e4SLinus Torvalds * the "real" return value. 121da177e4SLinus Torvalds * 131da177e4SLinus Torvalds * __get_user_X 141da177e4SLinus Torvalds * 151da177e4SLinus Torvalds * Inputs: r0 contains the address 168404663fSRussell King * r1 contains the address limit, which must be preserved 171da177e4SLinus Torvalds * Outputs: r0 is the error code 18e38361d0SDaniel Thompson * r2, r3 contains the zero-extended value 191da177e4SLinus Torvalds * lr corrupted 201da177e4SLinus Torvalds * 214baa9922SRussell King * No other registers must be altered. (see <asm/uaccess.h> 221da177e4SLinus Torvalds * for specific ASM register usage). 231da177e4SLinus Torvalds * 241da177e4SLinus Torvalds * Note that ADDR_LIMIT is either 0 or 0xc0000000. 251da177e4SLinus Torvalds * Note also that it is intended that __get_user_bad is not global. 261da177e4SLinus Torvalds */ 2793ed3970SCatalin Marinas#include <linux/linkage.h> 288404663fSRussell King#include <asm/assembler.h> 291da177e4SLinus Torvalds#include <asm/errno.h> 30247055aaSCatalin Marinas#include <asm/domain.h> 311da177e4SLinus Torvalds 3293ed3970SCatalin MarinasENTRY(__get_user_1) 338404663fSRussell King check_uaccess r0, 1, r1, r2, __get_user_bad 344e7682d0SCatalin Marinas1: TUSER(ldrb) r2, [r0] 351da177e4SLinus Torvalds mov r0, #0 366ebbf2ceSRussell King ret lr 3793ed3970SCatalin MarinasENDPROC(__get_user_1) 380d73c3f8SMasami Hiramatsu_ASM_NOKPROBE(__get_user_1) 391da177e4SLinus Torvalds 4093ed3970SCatalin MarinasENTRY(__get_user_2) 418404663fSRussell King check_uaccess r0, 2, r1, r2, __get_user_bad 42344eb553SVincent Whitchurch#if __LINUX_ARM_ARCH__ >= 6 43344eb553SVincent Whitchurch 44344eb553SVincent Whitchurch2: TUSER(ldrh) r2, [r0] 45344eb553SVincent Whitchurch 46344eb553SVincent Whitchurch#else 47344eb553SVincent Whitchurch 488404663fSRussell King#ifdef CONFIG_CPU_USE_DOMAINS 498404663fSRussell Kingrb .req ip 508404663fSRussell King2: ldrbt r2, [r0], #1 518404663fSRussell King3: ldrbt rb, [r0], #0 528b592783SCatalin Marinas#else 538404663fSRussell Kingrb .req r0 548404663fSRussell King2: ldrb r2, [r0] 558404663fSRussell King3: ldrb rb, [r0, #1] 568b592783SCatalin Marinas#endif 571da177e4SLinus Torvalds#ifndef __ARMEB__ 588404663fSRussell King orr r2, r2, rb, lsl #8 591da177e4SLinus Torvalds#else 608404663fSRussell King orr r2, rb, r2, lsl #8 611da177e4SLinus Torvalds#endif 62344eb553SVincent Whitchurch 63344eb553SVincent Whitchurch#endif /* __LINUX_ARM_ARCH__ >= 6 */ 64344eb553SVincent Whitchurch 651da177e4SLinus Torvalds mov r0, #0 666ebbf2ceSRussell King ret lr 6793ed3970SCatalin MarinasENDPROC(__get_user_2) 680d73c3f8SMasami Hiramatsu_ASM_NOKPROBE(__get_user_2) 691da177e4SLinus Torvalds 7093ed3970SCatalin MarinasENTRY(__get_user_4) 718404663fSRussell King check_uaccess r0, 4, r1, r2, __get_user_bad 724e7682d0SCatalin Marinas4: TUSER(ldr) r2, [r0] 731da177e4SLinus Torvalds mov r0, #0 746ebbf2ceSRussell King ret lr 7593ed3970SCatalin MarinasENDPROC(__get_user_4) 760d73c3f8SMasami Hiramatsu_ASM_NOKPROBE(__get_user_4) 771da177e4SLinus Torvalds 78e38361d0SDaniel ThompsonENTRY(__get_user_8) 799e344048SKees Cook check_uaccess r0, 8, r1, r2, __get_user_bad8 80e38361d0SDaniel Thompson#ifdef CONFIG_THUMB2_KERNEL 81e38361d0SDaniel Thompson5: TUSER(ldr) r2, [r0] 82e38361d0SDaniel Thompson6: TUSER(ldr) r3, [r0, #4] 83e38361d0SDaniel Thompson#else 84e38361d0SDaniel Thompson5: TUSER(ldr) r2, [r0], #4 85e38361d0SDaniel Thompson6: TUSER(ldr) r3, [r0] 86e38361d0SDaniel Thompson#endif 87e38361d0SDaniel Thompson mov r0, #0 88e38361d0SDaniel Thompson ret lr 89e38361d0SDaniel ThompsonENDPROC(__get_user_8) 900d73c3f8SMasami Hiramatsu_ASM_NOKPROBE(__get_user_8) 91e38361d0SDaniel Thompson 92e38361d0SDaniel Thompson#ifdef __ARMEB__ 93d9981380SVictor KamenskyENTRY(__get_user_32t_8) 94e38361d0SDaniel Thompson check_uaccess r0, 8, r1, r2, __get_user_bad 95e38361d0SDaniel Thompson#ifdef CONFIG_CPU_USE_DOMAINS 96e38361d0SDaniel Thompson add r0, r0, #4 97e38361d0SDaniel Thompson7: ldrt r2, [r0] 98e38361d0SDaniel Thompson#else 99e38361d0SDaniel Thompson7: ldr r2, [r0, #4] 100e38361d0SDaniel Thompson#endif 101e38361d0SDaniel Thompson mov r0, #0 102e38361d0SDaniel Thompson ret lr 103d9981380SVictor KamenskyENDPROC(__get_user_32t_8) 1040d73c3f8SMasami Hiramatsu_ASM_NOKPROBE(__get_user_32t_8) 105d9981380SVictor Kamensky 106d9981380SVictor KamenskyENTRY(__get_user_64t_1) 107d9981380SVictor Kamensky check_uaccess r0, 1, r1, r2, __get_user_bad8 108d9981380SVictor Kamensky8: TUSER(ldrb) r3, [r0] 109d9981380SVictor Kamensky mov r0, #0 110d9981380SVictor Kamensky ret lr 111d9981380SVictor KamenskyENDPROC(__get_user_64t_1) 1120d73c3f8SMasami Hiramatsu_ASM_NOKPROBE(__get_user_64t_1) 113d9981380SVictor Kamensky 114d9981380SVictor KamenskyENTRY(__get_user_64t_2) 115d9981380SVictor Kamensky check_uaccess r0, 2, r1, r2, __get_user_bad8 116d9981380SVictor Kamensky#ifdef CONFIG_CPU_USE_DOMAINS 117d9981380SVictor Kamenskyrb .req ip 118d9981380SVictor Kamensky9: ldrbt r3, [r0], #1 119d9981380SVictor Kamensky10: ldrbt rb, [r0], #0 120d9981380SVictor Kamensky#else 121d9981380SVictor Kamenskyrb .req r0 122d9981380SVictor Kamensky9: ldrb r3, [r0] 123d9981380SVictor Kamensky10: ldrb rb, [r0, #1] 124d9981380SVictor Kamensky#endif 125d9981380SVictor Kamensky orr r3, rb, r3, lsl #8 126d9981380SVictor Kamensky mov r0, #0 127d9981380SVictor Kamensky ret lr 128d9981380SVictor KamenskyENDPROC(__get_user_64t_2) 1290d73c3f8SMasami Hiramatsu_ASM_NOKPROBE(__get_user_64t_2) 130d9981380SVictor Kamensky 131d9981380SVictor KamenskyENTRY(__get_user_64t_4) 132d9981380SVictor Kamensky check_uaccess r0, 4, r1, r2, __get_user_bad8 133d9981380SVictor Kamensky11: TUSER(ldr) r3, [r0] 134d9981380SVictor Kamensky mov r0, #0 135d9981380SVictor Kamensky ret lr 136d9981380SVictor KamenskyENDPROC(__get_user_64t_4) 1370d73c3f8SMasami Hiramatsu_ASM_NOKPROBE(__get_user_64t_4) 138e38361d0SDaniel Thompson#endif 139e38361d0SDaniel Thompson 140e38361d0SDaniel Thompson__get_user_bad8: 141e38361d0SDaniel Thompson mov r3, #0 1421da177e4SLinus Torvalds__get_user_bad: 1431da177e4SLinus Torvalds mov r2, #0 1441da177e4SLinus Torvalds mov r0, #-EFAULT 1456ebbf2ceSRussell King ret lr 14693ed3970SCatalin MarinasENDPROC(__get_user_bad) 147e38361d0SDaniel ThompsonENDPROC(__get_user_bad8) 1480d73c3f8SMasami Hiramatsu_ASM_NOKPROBE(__get_user_bad) 1490d73c3f8SMasami Hiramatsu_ASM_NOKPROBE(__get_user_bad8) 1501da177e4SLinus Torvalds 1514260415fSRussell King.pushsection __ex_table, "a" 1521da177e4SLinus Torvalds .long 1b, __get_user_bad 1531da177e4SLinus Torvalds .long 2b, __get_user_bad 154344eb553SVincent Whitchurch#if __LINUX_ARM_ARCH__ < 6 1551da177e4SLinus Torvalds .long 3b, __get_user_bad 156344eb553SVincent Whitchurch#endif 1571da177e4SLinus Torvalds .long 4b, __get_user_bad 158e38361d0SDaniel Thompson .long 5b, __get_user_bad8 159e38361d0SDaniel Thompson .long 6b, __get_user_bad8 160e38361d0SDaniel Thompson#ifdef __ARMEB__ 161e38361d0SDaniel Thompson .long 7b, __get_user_bad 162d9981380SVictor Kamensky .long 8b, __get_user_bad8 163d9981380SVictor Kamensky .long 9b, __get_user_bad8 164d9981380SVictor Kamensky .long 10b, __get_user_bad8 165d9981380SVictor Kamensky .long 11b, __get_user_bad8 166e38361d0SDaniel Thompson#endif 1674260415fSRussell King.popsection 168