1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  *  linux/arch/arm/lib/putuser.S
4  *
5  *  Copyright (C) 2001 Russell King
6  *
7  *  Idea from x86 version, (C) Copyright 1998 Linus Torvalds
8  *
9  * These functions have a non-standard call interface to make
10  * them more efficient, especially as they return an error
11  * value in addition to the "real" return value.
12  *
13  * __put_user_X
14  *
15  * Inputs:	r0 contains the address
16  *		r1 contains the address limit, which must be preserved
17  *		r2, r3 contains the value
18  * Outputs:	r0 is the error code
19  *		lr corrupted
20  *
21  * No other registers must be altered.  (see <asm/uaccess.h>
22  * for specific ASM register usage).
23  *
24  * Note that ADDR_LIMIT is either 0 or 0xc0000000
25  * Note also that it is intended that __put_user_bad is not global.
26  */
27 #include <linux/linkage.h>
28 #include <asm/assembler.h>
29 #include <asm/errno.h>
30 #include <asm/domain.h>
31 
32 ENTRY(__put_user_1)
33 	check_uaccess r0, 1, r1, ip, __put_user_bad
34 1: TUSER(strb)	r2, [r0]
35 	mov	r0, #0
36 	ret	lr
37 ENDPROC(__put_user_1)
38 
39 ENTRY(__put_user_2)
40 	check_uaccess r0, 2, r1, ip, __put_user_bad
41 #if __LINUX_ARM_ARCH__ >= 6
42 
43 2: TUSER(strh)	r2, [r0]
44 
45 #else
46 
47 	mov	ip, r2, lsr #8
48 #ifndef __ARMEB__
49 2: TUSER(strb)	r2, [r0], #1
50 3: TUSER(strb)	ip, [r0]
51 #else
52 2: TUSER(strb)	ip, [r0], #1
53 3: TUSER(strb)	r2, [r0]
54 #endif
55 
56 #endif /* __LINUX_ARM_ARCH__ >= 6 */
57 	mov	r0, #0
58 	ret	lr
59 ENDPROC(__put_user_2)
60 
61 ENTRY(__put_user_4)
62 	check_uaccess r0, 4, r1, ip, __put_user_bad
63 4: TUSER(str)	r2, [r0]
64 	mov	r0, #0
65 	ret	lr
66 ENDPROC(__put_user_4)
67 
68 ENTRY(__put_user_8)
69 	check_uaccess r0, 8, r1, ip, __put_user_bad
70 #ifdef CONFIG_THUMB2_KERNEL
71 5: TUSER(str)	r2, [r0]
72 6: TUSER(str)	r3, [r0, #4]
73 #else
74 5: TUSER(str)	r2, [r0], #4
75 6: TUSER(str)	r3, [r0]
76 #endif
77 	mov	r0, #0
78 	ret	lr
79 ENDPROC(__put_user_8)
80 
81 __put_user_bad:
82 	mov	r0, #-EFAULT
83 	ret	lr
84 ENDPROC(__put_user_bad)
85 
86 .pushsection __ex_table, "a"
87 	.long	1b, __put_user_bad
88 	.long	2b, __put_user_bad
89 #if __LINUX_ARM_ARCH__ < 6
90 	.long	3b, __put_user_bad
91 #endif
92 	.long	4b, __put_user_bad
93 	.long	5b, __put_user_bad
94 	.long	6b, __put_user_bad
95 .popsection
96