xref: /openbmc/linux/arch/x86/lib/putuser.S (revision 95e9fd10)
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/dwarf2.h>
15#include <asm/thread_info.h>
16#include <asm/errno.h>
17#include <asm/asm.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	CFI_STARTPROC ; \
33		GET_THREAD_INFO(%_ASM_BX)
34#define EXIT	ret ; \
35		CFI_ENDPROC
36
37.text
38ENTRY(__put_user_1)
39	ENTER
40	cmp TI_addr_limit(%_ASM_BX),%_ASM_CX
41	jae bad_put_user
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
532:	movw %ax,(%_ASM_CX)
54	xor %eax,%eax
55	EXIT
56ENDPROC(__put_user_2)
57
58ENTRY(__put_user_4)
59	ENTER
60	mov TI_addr_limit(%_ASM_BX),%_ASM_BX
61	sub $3,%_ASM_BX
62	cmp %_ASM_BX,%_ASM_CX
63	jae bad_put_user
643:	movl %eax,(%_ASM_CX)
65	xor %eax,%eax
66	EXIT
67ENDPROC(__put_user_4)
68
69ENTRY(__put_user_8)
70	ENTER
71	mov TI_addr_limit(%_ASM_BX),%_ASM_BX
72	sub $7,%_ASM_BX
73	cmp %_ASM_BX,%_ASM_CX
74	jae bad_put_user
754:	mov %_ASM_AX,(%_ASM_CX)
76#ifdef CONFIG_X86_32
775:	movl %edx,4(%_ASM_CX)
78#endif
79	xor %eax,%eax
80	EXIT
81ENDPROC(__put_user_8)
82
83bad_put_user:
84	CFI_STARTPROC
85	movl $-EFAULT,%eax
86	EXIT
87END(bad_put_user)
88
89	_ASM_EXTABLE(1b,bad_put_user)
90	_ASM_EXTABLE(2b,bad_put_user)
91	_ASM_EXTABLE(3b,bad_put_user)
92	_ASM_EXTABLE(4b,bad_put_user)
93#ifdef CONFIG_X86_32
94	_ASM_EXTABLE(5b,bad_put_user)
95#endif
96