xref: /OK3568_Linux_fs/kernel/arch/arm/lib/getuser.S (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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