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 | |