1/*
2 * __put_user functions.
3 *
4 * (C) Copyright 1998 Linus Torvalds
5 * (C) Copyright 2005 Andi Kleen
6 *
7 * These functions have a non-standard call interface
8 * to make them more efficient, especially as they
9 * return an error value in addition to the "real"
10 * return value.
11 */
12
13/*
14 * __put_user_X
15 *
16 * Inputs:	%rcx contains the address
17 *		%rdx contains new value
18 *
19 * Outputs:	%rax is error code (0 or -EFAULT)
20 *
21 * %r8 is destroyed.
22 *
23 * These functions should not modify any other registers,
24 * as they get called from within inline assembly.
25 */
26
27#include <linux/linkage.h>
28#include <asm/dwarf2.h>
29#include <asm/page.h>
30#include <asm/errno.h>
31#include <asm/asm-offsets.h>
32#include <asm/thread_info.h>
33
34	.text
35ENTRY(__put_user_1)
36	CFI_STARTPROC
37	GET_THREAD_INFO(%r8)
38	cmpq threadinfo_addr_limit(%r8),%rcx
39	jae bad_put_user
401:	movb %dl,(%rcx)
41	xorl %eax,%eax
42	ret
43	CFI_ENDPROC
44ENDPROC(__put_user_1)
45
46ENTRY(__put_user_2)
47	CFI_STARTPROC
48	GET_THREAD_INFO(%r8)
49	addq $1,%rcx
50	jc 20f
51	cmpq threadinfo_addr_limit(%r8),%rcx
52	jae 20f
53	decq %rcx
542:	movw %dx,(%rcx)
55	xorl %eax,%eax
56	ret
5720:	decq %rcx
58	jmp bad_put_user
59	CFI_ENDPROC
60ENDPROC(__put_user_2)
61
62ENTRY(__put_user_4)
63	CFI_STARTPROC
64	GET_THREAD_INFO(%r8)
65	addq $3,%rcx
66	jc 30f
67	cmpq threadinfo_addr_limit(%r8),%rcx
68	jae 30f
69	subq $3,%rcx
703:	movl %edx,(%rcx)
71	xorl %eax,%eax
72	ret
7330:	subq $3,%rcx
74	jmp bad_put_user
75	CFI_ENDPROC
76ENDPROC(__put_user_4)
77
78ENTRY(__put_user_8)
79	CFI_STARTPROC
80	GET_THREAD_INFO(%r8)
81	addq $7,%rcx
82	jc 40f
83	cmpq threadinfo_addr_limit(%r8),%rcx
84	jae 40f
85	subq $7,%rcx
864:	movq %rdx,(%rcx)
87	xorl %eax,%eax
88	ret
8940:	subq $7,%rcx
90	jmp bad_put_user
91	CFI_ENDPROC
92ENDPROC(__put_user_8)
93
94bad_put_user:
95	CFI_STARTPROC
96	movq $(-EFAULT),%rax
97	ret
98	CFI_ENDPROC
99END(bad_put_user)
100
101.section __ex_table,"a"
102	.quad 1b,bad_put_user
103	.quad 2b,bad_put_user
104	.quad 3b,bad_put_user
105	.quad 4b,bad_put_user
106.previous
107