xref: /linux/arch/x86/lib/putuser.S (revision c0e297dc61f8d4453e07afbea1fa8d0e67cd4a34)
1/*
2 * __put_user functions.
3 *
4 * (C) Copyright 2005 Linus Torvalds
5 * (C) Copyright 2005 Andi Kleen
6 * (C) Copyright 2008 Glauber Costa
7 *
8 * These functions have a non-standard call interface
9 * to make them more efficient, especially as they
10 * return an error value in addition to the "real"
11 * return value.
12 */
13#include <linux/linkage.h>
14#include <asm/thread_info.h>
15#include <asm/errno.h>
16#include <asm/asm.h>
17#include <asm/smap.h>
18
19
20/*
21 * __put_user_X
22 *
23 * Inputs:	%eax[:%edx] contains the data
24 *		%ecx contains the address
25 *
26 * Outputs:	%eax is error code (0 or -EFAULT)
27 *
28 * These functions should not modify any other registers,
29 * as they get called from within inline assembly.
30 */
31
32#define ENTER	GET_THREAD_INFO(%_ASM_BX)
33#define EXIT	ASM_CLAC ;	\
34		ret
35
36.text
37ENTRY(__put_user_1)
38	ENTER
39	cmp TI_addr_limit(%_ASM_BX),%_ASM_CX
40	jae bad_put_user
41	ASM_STAC
421:	movb %al,(%_ASM_CX)
43	xor %eax,%eax
44	EXIT
45ENDPROC(__put_user_1)
46
47ENTRY(__put_user_2)
48	ENTER
49	mov TI_addr_limit(%_ASM_BX),%_ASM_BX
50	sub $1,%_ASM_BX
51	cmp %_ASM_BX,%_ASM_CX
52	jae bad_put_user
53	ASM_STAC
542:	movw %ax,(%_ASM_CX)
55	xor %eax,%eax
56	EXIT
57ENDPROC(__put_user_2)
58
59ENTRY(__put_user_4)
60	ENTER
61	mov TI_addr_limit(%_ASM_BX),%_ASM_BX
62	sub $3,%_ASM_BX
63	cmp %_ASM_BX,%_ASM_CX
64	jae bad_put_user
65	ASM_STAC
663:	movl %eax,(%_ASM_CX)
67	xor %eax,%eax
68	EXIT
69ENDPROC(__put_user_4)
70
71ENTRY(__put_user_8)
72	ENTER
73	mov TI_addr_limit(%_ASM_BX),%_ASM_BX
74	sub $7,%_ASM_BX
75	cmp %_ASM_BX,%_ASM_CX
76	jae bad_put_user
77	ASM_STAC
784:	mov %_ASM_AX,(%_ASM_CX)
79#ifdef CONFIG_X86_32
805:	movl %edx,4(%_ASM_CX)
81#endif
82	xor %eax,%eax
83	EXIT
84ENDPROC(__put_user_8)
85
86bad_put_user:
87	movl $-EFAULT,%eax
88	EXIT
89END(bad_put_user)
90
91	_ASM_EXTABLE(1b,bad_put_user)
92	_ASM_EXTABLE(2b,bad_put_user)
93	_ASM_EXTABLE(3b,bad_put_user)
94	_ASM_EXTABLE(4b,bad_put_user)
95#ifdef CONFIG_X86_32
96	_ASM_EXTABLE(5b,bad_put_user)
97#endif
98