xref: /openbmc/linux/arch/x86/lib/putuser.S (revision 7af6fbdd)
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#define ENTER	mov PER_CPU_VAR(current_task), %_ASM_BX
37
38.text
39SYM_FUNC_START(__put_user_1)
40	ENTER
41	cmp TASK_addr_limit(%_ASM_BX),%_ASM_CX
42	jae .Lbad_put_user
43SYM_INNER_LABEL(__put_user_nocheck_1, SYM_L_GLOBAL)
44	ASM_STAC
451:	movb %al,(%_ASM_CX)
46	xor %ecx,%ecx
47	ASM_CLAC
48	ret
49SYM_FUNC_END(__put_user_1)
50EXPORT_SYMBOL(__put_user_1)
51EXPORT_SYMBOL(__put_user_nocheck_1)
52
53SYM_FUNC_START(__put_user_2)
54	ENTER
55	mov TASK_addr_limit(%_ASM_BX),%_ASM_BX
56	sub $1,%_ASM_BX
57	cmp %_ASM_BX,%_ASM_CX
58	jae .Lbad_put_user
59SYM_INNER_LABEL(__put_user_nocheck_2, SYM_L_GLOBAL)
60	ASM_STAC
612:	movw %ax,(%_ASM_CX)
62	xor %ecx,%ecx
63	ASM_CLAC
64	ret
65SYM_FUNC_END(__put_user_2)
66EXPORT_SYMBOL(__put_user_2)
67EXPORT_SYMBOL(__put_user_nocheck_2)
68
69SYM_FUNC_START(__put_user_4)
70	ENTER
71	mov TASK_addr_limit(%_ASM_BX),%_ASM_BX
72	sub $3,%_ASM_BX
73	cmp %_ASM_BX,%_ASM_CX
74	jae .Lbad_put_user
75SYM_INNER_LABEL(__put_user_nocheck_4, SYM_L_GLOBAL)
76	ASM_STAC
773:	movl %eax,(%_ASM_CX)
78	xor %ecx,%ecx
79	ASM_CLAC
80	ret
81SYM_FUNC_END(__put_user_4)
82EXPORT_SYMBOL(__put_user_4)
83EXPORT_SYMBOL(__put_user_nocheck_4)
84
85SYM_FUNC_START(__put_user_8)
86	ENTER
87	mov TASK_addr_limit(%_ASM_BX),%_ASM_BX
88	sub $7,%_ASM_BX
89	cmp %_ASM_BX,%_ASM_CX
90	jae .Lbad_put_user
91SYM_INNER_LABEL(__put_user_nocheck_8, SYM_L_GLOBAL)
92	ASM_STAC
934:	mov %_ASM_AX,(%_ASM_CX)
94#ifdef CONFIG_X86_32
955:	movl %edx,4(%_ASM_CX)
96#endif
97	xor %ecx,%ecx
98	ASM_CLAC
99	RET
100SYM_FUNC_END(__put_user_8)
101EXPORT_SYMBOL(__put_user_8)
102EXPORT_SYMBOL(__put_user_nocheck_8)
103
104SYM_CODE_START_LOCAL(.Lbad_put_user_clac)
105	ASM_CLAC
106.Lbad_put_user:
107	movl $-EFAULT,%ecx
108	RET
109SYM_CODE_END(.Lbad_put_user_clac)
110
111	_ASM_EXTABLE_UA(1b, .Lbad_put_user_clac)
112	_ASM_EXTABLE_UA(2b, .Lbad_put_user_clac)
113	_ASM_EXTABLE_UA(3b, .Lbad_put_user_clac)
114	_ASM_EXTABLE_UA(4b, .Lbad_put_user_clac)
115#ifdef CONFIG_X86_32
116	_ASM_EXTABLE_UA(5b, .Lbad_put_user_clac)
117#endif
118