xref: /openbmc/linux/arch/x86/lib/putuser.S (revision 8957261c)
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/linkage.h>
15#include <asm/thread_info.h>
16#include <asm/errno.h>
17#include <asm/asm.h>
18#include <asm/smap.h>
19#include <asm/export.h>
20
21
22/*
23 * __put_user_X
24 *
25 * Inputs:	%eax[:%edx] contains the data
26 *		%ecx contains the address
27 *
28 * Outputs:	%ecx is error code (0 or -EFAULT)
29 *
30 * Clobbers:	%ebx needed for task pointer
31 *
32 * These functions should not modify any other registers,
33 * as they get called from within inline assembly.
34 */
35
36.macro check_range size:req
37.if IS_ENABLED(CONFIG_X86_64)
38	mov %rcx, %rbx
39	sar $63, %rbx
40	or %rbx, %rcx
41.else
42	cmp $TASK_SIZE_MAX-\size+1, %ecx
43	jae .Lbad_put_user
44.endif
45.endm
46
47.text
48SYM_FUNC_START(__put_user_1)
49	check_range size=1
50	ASM_STAC
511:	movb %al,(%_ASM_CX)
52	xor %ecx,%ecx
53	ASM_CLAC
54	RET
55SYM_FUNC_END(__put_user_1)
56EXPORT_SYMBOL(__put_user_1)
57
58SYM_FUNC_START(__put_user_nocheck_1)
59	ASM_STAC
602:	movb %al,(%_ASM_CX)
61	xor %ecx,%ecx
62	ASM_CLAC
63	RET
64SYM_FUNC_END(__put_user_nocheck_1)
65EXPORT_SYMBOL(__put_user_nocheck_1)
66
67SYM_FUNC_START(__put_user_2)
68	check_range size=2
69	ASM_STAC
703:	movw %ax,(%_ASM_CX)
71	xor %ecx,%ecx
72	ASM_CLAC
73	RET
74SYM_FUNC_END(__put_user_2)
75EXPORT_SYMBOL(__put_user_2)
76
77SYM_FUNC_START(__put_user_nocheck_2)
78	ASM_STAC
794:	movw %ax,(%_ASM_CX)
80	xor %ecx,%ecx
81	ASM_CLAC
82	RET
83SYM_FUNC_END(__put_user_nocheck_2)
84EXPORT_SYMBOL(__put_user_nocheck_2)
85
86SYM_FUNC_START(__put_user_4)
87	check_range size=4
88	ASM_STAC
895:	movl %eax,(%_ASM_CX)
90	xor %ecx,%ecx
91	ASM_CLAC
92	RET
93SYM_FUNC_END(__put_user_4)
94EXPORT_SYMBOL(__put_user_4)
95
96SYM_FUNC_START(__put_user_nocheck_4)
97	ASM_STAC
986:	movl %eax,(%_ASM_CX)
99	xor %ecx,%ecx
100	ASM_CLAC
101	RET
102SYM_FUNC_END(__put_user_nocheck_4)
103EXPORT_SYMBOL(__put_user_nocheck_4)
104
105SYM_FUNC_START(__put_user_8)
106	check_range size=8
107	ASM_STAC
1087:	mov %_ASM_AX,(%_ASM_CX)
109#ifdef CONFIG_X86_32
1108:	movl %edx,4(%_ASM_CX)
111#endif
112	xor %ecx,%ecx
113	ASM_CLAC
114	RET
115SYM_FUNC_END(__put_user_8)
116EXPORT_SYMBOL(__put_user_8)
117
118SYM_FUNC_START(__put_user_nocheck_8)
119	ASM_STAC
1209:	mov %_ASM_AX,(%_ASM_CX)
121#ifdef CONFIG_X86_32
12210:	movl %edx,4(%_ASM_CX)
123#endif
124	xor %ecx,%ecx
125	ASM_CLAC
126	RET
127SYM_FUNC_END(__put_user_nocheck_8)
128EXPORT_SYMBOL(__put_user_nocheck_8)
129
130SYM_CODE_START_LOCAL(__put_user_handle_exception)
131	ASM_CLAC
132.Lbad_put_user:
133	movl $-EFAULT,%ecx
134	RET
135SYM_CODE_END(__put_user_handle_exception)
136
137	_ASM_EXTABLE(1b, __put_user_handle_exception)
138	_ASM_EXTABLE(2b, __put_user_handle_exception)
139	_ASM_EXTABLE(3b, __put_user_handle_exception)
140	_ASM_EXTABLE(4b, __put_user_handle_exception)
141	_ASM_EXTABLE(5b, __put_user_handle_exception)
142	_ASM_EXTABLE(6b, __put_user_handle_exception)
143	_ASM_EXTABLE(7b, __put_user_handle_exception)
144	_ASM_EXTABLE(9b, __put_user_handle_exception)
145#ifdef CONFIG_X86_32
146	_ASM_EXTABLE(8b, __put_user_handle_exception)
147	_ASM_EXTABLE(10b, __put_user_handle_exception)
148#endif
149