Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6
[linux-2.6] / arch / x86_64 / lib / putuser.S
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
35 ENTRY(__put_user_1)
36         CFI_STARTPROC
37         GET_THREAD_INFO(%r8)
38         cmpq threadinfo_addr_limit(%r8),%rcx
39         jae bad_put_user
40 1:      movb %dl,(%rcx)
41         xorl %eax,%eax
42         ret
43         CFI_ENDPROC
44 ENDPROC(__put_user_1)
45
46 ENTRY(__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
54 2:      movw %dx,(%rcx)
55         xorl %eax,%eax
56         ret
57 20:     decq %rcx
58         jmp bad_put_user
59         CFI_ENDPROC
60 ENDPROC(__put_user_2)
61
62 ENTRY(__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
70 3:      movl %edx,(%rcx)
71         xorl %eax,%eax
72         ret
73 30:     subq $3,%rcx
74         jmp bad_put_user
75         CFI_ENDPROC
76 ENDPROC(__put_user_4)
77
78 ENTRY(__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
86 4:      movq %rdx,(%rcx)
87         xorl %eax,%eax
88         ret
89 40:     subq $7,%rcx
90         jmp bad_put_user
91         CFI_ENDPROC
92 ENDPROC(__put_user_8)
93
94 bad_put_user:
95         CFI_STARTPROC
96         movq $(-EFAULT),%rax
97         ret
98         CFI_ENDPROC
99 END(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