blob: 4989f5a8fa9b2fa1cd3903017ae409002a1e8195 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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>
Jan Beulich8d379da2006-09-26 10:52:32 +020028#include <asm/dwarf2.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <asm/page.h>
30#include <asm/errno.h>
Sam Ravnborge2d5df92005-09-09 21:28:48 +020031#include <asm/asm-offsets.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <asm/thread_info.h>
33
34 .text
Jan Beulich8d379da2006-09-26 10:52:32 +020035ENTRY(__put_user_1)
36 CFI_STARTPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -070037 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
Jan Beulich8d379da2006-09-26 10:52:32 +020043 CFI_ENDPROC
44ENDPROC(__put_user_1)
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
Jan Beulich8d379da2006-09-26 10:52:32 +020046ENTRY(__put_user_2)
47 CFI_STARTPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 GET_THREAD_INFO(%r8)
49 addq $1,%rcx
Alexander Nyberg3a6fd752005-04-21 07:59:51 -070050 jc 20f
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 cmpq threadinfo_addr_limit(%r8),%rcx
Alexander Nyberg3a6fd752005-04-21 07:59:51 -070052 jae 20f
Alexander Nybergefab7732005-04-22 10:22:07 -070053 decq %rcx
542: movw %dx,(%rcx)
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 xorl %eax,%eax
56 ret
Alexander Nyberg3a6fd752005-04-21 07:59:51 -07005720: decq %rcx
58 jmp bad_put_user
Jan Beulich8d379da2006-09-26 10:52:32 +020059 CFI_ENDPROC
60ENDPROC(__put_user_2)
Linus Torvalds1da177e2005-04-16 15:20:36 -070061
Jan Beulich8d379da2006-09-26 10:52:32 +020062ENTRY(__put_user_4)
63 CFI_STARTPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 GET_THREAD_INFO(%r8)
65 addq $3,%rcx
Alexander Nyberg3a6fd752005-04-21 07:59:51 -070066 jc 30f
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 cmpq threadinfo_addr_limit(%r8),%rcx
Alexander Nyberg3a6fd752005-04-21 07:59:51 -070068 jae 30f
Alexander Nybergefab7732005-04-22 10:22:07 -070069 subq $3,%rcx
703: movl %edx,(%rcx)
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 xorl %eax,%eax
72 ret
Alexander Nyberg3a6fd752005-04-21 07:59:51 -07007330: subq $3,%rcx
74 jmp bad_put_user
Jan Beulich8d379da2006-09-26 10:52:32 +020075 CFI_ENDPROC
76ENDPROC(__put_user_4)
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
Jan Beulich8d379da2006-09-26 10:52:32 +020078ENTRY(__put_user_8)
79 CFI_STARTPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 GET_THREAD_INFO(%r8)
81 addq $7,%rcx
Alexander Nyberg3a6fd752005-04-21 07:59:51 -070082 jc 40f
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 cmpq threadinfo_addr_limit(%r8),%rcx
Alexander Nyberg3a6fd752005-04-21 07:59:51 -070084 jae 40f
Alexander Nybergefab7732005-04-22 10:22:07 -070085 subq $7,%rcx
864: movq %rdx,(%rcx)
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 xorl %eax,%eax
88 ret
Alexander Nyberg3a6fd752005-04-21 07:59:51 -07008940: subq $7,%rcx
90 jmp bad_put_user
Jan Beulich8d379da2006-09-26 10:52:32 +020091 CFI_ENDPROC
92ENDPROC(__put_user_8)
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
94bad_put_user:
Jan Beulich8d379da2006-09-26 10:52:32 +020095 CFI_STARTPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 movq $(-EFAULT),%rax
97 ret
Jan Beulich8d379da2006-09-26 10:52:32 +020098 CFI_ENDPROC
99END(bad_put_user)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
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