1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * __put_user functions. |
4 | * |
5 | * (C) Copyright 2005 Linus Torvalds |
6 | * (C) Copyright 2005 Andi Kleen |
7 | * (C) Copyright 2008 Glauber Costa |
8 | * |
9 | * These functions have a non-standard call interface |
10 | * to make them more efficient, especially as they |
11 | * return an error value in addition to the "real" |
12 | * return value. |
13 | */ |
14 | #include <linux/export.h> |
15 | #include <linux/linkage.h> |
16 | #include <asm/thread_info.h> |
17 | #include <asm/errno.h> |
18 | #include <asm/asm.h> |
19 | #include <asm/smap.h> |
20 | |
21 | /* |
22 | * __put_user_X |
23 | * |
24 | * Inputs: %eax[:%edx] contains the data |
25 | * %ecx contains the address |
26 | * |
27 | * Outputs: %ecx is error code (0 or -EFAULT) |
28 | * |
29 | * Clobbers: %ebx needed for task pointer |
30 | * |
31 | * These functions should not modify any other registers, |
32 | * as they get called from within inline assembly. |
33 | */ |
34 | |
35 | .macro check_range size:req |
36 | .if IS_ENABLED(CONFIG_X86_64) |
37 | mov %rcx, %rbx |
38 | sar $63, %rbx |
39 | or %rbx, %rcx |
40 | .else |
41 | cmp $TASK_SIZE_MAX-\size+1, %ecx |
42 | jae .Lbad_put_user |
43 | .endif |
44 | .endm |
45 | |
46 | .text |
47 | SYM_FUNC_START(__put_user_1) |
48 | check_range size=1 |
49 | ASM_STAC |
50 | 1: movb %al,(%_ASM_CX) |
51 | xor %ecx,%ecx |
52 | ASM_CLAC |
53 | RET |
54 | SYM_FUNC_END(__put_user_1) |
55 | EXPORT_SYMBOL(__put_user_1) |
56 | |
57 | SYM_FUNC_START(__put_user_nocheck_1) |
58 | ASM_STAC |
59 | 2: movb %al,(%_ASM_CX) |
60 | xor %ecx,%ecx |
61 | ASM_CLAC |
62 | RET |
63 | SYM_FUNC_END(__put_user_nocheck_1) |
64 | EXPORT_SYMBOL(__put_user_nocheck_1) |
65 | |
66 | SYM_FUNC_START(__put_user_2) |
67 | check_range size=2 |
68 | ASM_STAC |
69 | 3: movw %ax,(%_ASM_CX) |
70 | xor %ecx,%ecx |
71 | ASM_CLAC |
72 | RET |
73 | SYM_FUNC_END(__put_user_2) |
74 | EXPORT_SYMBOL(__put_user_2) |
75 | |
76 | SYM_FUNC_START(__put_user_nocheck_2) |
77 | ASM_STAC |
78 | 4: movw %ax,(%_ASM_CX) |
79 | xor %ecx,%ecx |
80 | ASM_CLAC |
81 | RET |
82 | SYM_FUNC_END(__put_user_nocheck_2) |
83 | EXPORT_SYMBOL(__put_user_nocheck_2) |
84 | |
85 | SYM_FUNC_START(__put_user_4) |
86 | check_range size=4 |
87 | ASM_STAC |
88 | 5: movl %eax,(%_ASM_CX) |
89 | xor %ecx,%ecx |
90 | ASM_CLAC |
91 | RET |
92 | SYM_FUNC_END(__put_user_4) |
93 | EXPORT_SYMBOL(__put_user_4) |
94 | |
95 | SYM_FUNC_START(__put_user_nocheck_4) |
96 | ASM_STAC |
97 | 6: movl %eax,(%_ASM_CX) |
98 | xor %ecx,%ecx |
99 | ASM_CLAC |
100 | RET |
101 | SYM_FUNC_END(__put_user_nocheck_4) |
102 | EXPORT_SYMBOL(__put_user_nocheck_4) |
103 | |
104 | SYM_FUNC_START(__put_user_8) |
105 | check_range size=8 |
106 | ASM_STAC |
107 | 7: mov %_ASM_AX,(%_ASM_CX) |
108 | #ifdef CONFIG_X86_32 |
109 | 8: movl %edx,4(%_ASM_CX) |
110 | #endif |
111 | xor %ecx,%ecx |
112 | ASM_CLAC |
113 | RET |
114 | SYM_FUNC_END(__put_user_8) |
115 | EXPORT_SYMBOL(__put_user_8) |
116 | |
117 | SYM_FUNC_START(__put_user_nocheck_8) |
118 | ASM_STAC |
119 | 9: mov %_ASM_AX,(%_ASM_CX) |
120 | #ifdef CONFIG_X86_32 |
121 | 10: movl %edx,4(%_ASM_CX) |
122 | #endif |
123 | xor %ecx,%ecx |
124 | ASM_CLAC |
125 | RET |
126 | SYM_FUNC_END(__put_user_nocheck_8) |
127 | EXPORT_SYMBOL(__put_user_nocheck_8) |
128 | |
129 | SYM_CODE_START_LOCAL(__put_user_handle_exception) |
130 | ASM_CLAC |
131 | .Lbad_put_user: |
132 | movl $-EFAULT,%ecx |
133 | RET |
134 | SYM_CODE_END(__put_user_handle_exception) |
135 | |
136 | _ASM_EXTABLE_UA(1b, __put_user_handle_exception) |
137 | _ASM_EXTABLE_UA(2b, __put_user_handle_exception) |
138 | _ASM_EXTABLE_UA(3b, __put_user_handle_exception) |
139 | _ASM_EXTABLE_UA(4b, __put_user_handle_exception) |
140 | _ASM_EXTABLE_UA(5b, __put_user_handle_exception) |
141 | _ASM_EXTABLE_UA(6b, __put_user_handle_exception) |
142 | _ASM_EXTABLE_UA(7b, __put_user_handle_exception) |
143 | _ASM_EXTABLE_UA(9b, __put_user_handle_exception) |
144 | #ifdef CONFIG_X86_32 |
145 | _ASM_EXTABLE_UA(8b, __put_user_handle_exception) |
146 | _ASM_EXTABLE_UA(10b, __put_user_handle_exception) |
147 | #endif |
148 | |