xref: /openbmc/linux/arch/arm/lib/getuser.S (revision d2912cb1)
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