blob: e0817a12d32362b4e69687c7b09e424580616e5d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * __put_user functions.
3 *
4 * (C) Copyright 2005 Linus Torvalds
Glauber Costa5cbbc3b2008-06-24 17:40:14 -03005 * (C) Copyright 2005 Andi Kleen
6 * (C) Copyright 2008 Glauber Costa
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 *
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 */
Jan Beulich00e065e2007-05-02 19:27:05 +020013#include <linux/linkage.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <asm/thread_info.h>
Glauber Costa5cbbc3b2008-06-24 17:40:14 -030015#include <asm/errno.h>
Glauber Costa2528de42008-06-24 17:36:31 -030016#include <asm/asm.h>
H. Peter Anvin63bcff22012-09-21 12:43:12 -070017#include <asm/smap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
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
Ingo Molnar131484c2015-05-28 12:21:47 +020032#define ENTER GET_THREAD_INFO(%_ASM_BX)
H. Peter Anvin63bcff22012-09-21 12:43:12 -070033#define EXIT ASM_CLAC ; \
Ingo Molnar131484c2015-05-28 12:21:47 +020034 ret
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
36.text
Jan Beulich00e065e2007-05-02 19:27:05 +020037ENTRY(__put_user_1)
Linus Torvalds1da177e2005-04-16 15:20:36 -070038 ENTER
Glauber Costa2528de42008-06-24 17:36:31 -030039 cmp TI_addr_limit(%_ASM_BX),%_ASM_CX
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 jae bad_put_user
H. Peter Anvin63bcff22012-09-21 12:43:12 -070041 ASM_STAC
Glauber Costa2528de42008-06-24 17:36:31 -0300421: movb %al,(%_ASM_CX)
Glauber Costaefea5052008-06-24 16:59:05 -030043 xor %eax,%eax
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 EXIT
Jan Beulich00e065e2007-05-02 19:27:05 +020045ENDPROC(__put_user_1)
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
Jan Beulich00e065e2007-05-02 19:27:05 +020047ENTRY(__put_user_2)
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 ENTER
Glauber Costa2528de42008-06-24 17:36:31 -030049 mov TI_addr_limit(%_ASM_BX),%_ASM_BX
50 sub $1,%_ASM_BX
51 cmp %_ASM_BX,%_ASM_CX
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 jae bad_put_user
H. Peter Anvin63bcff22012-09-21 12:43:12 -070053 ASM_STAC
Glauber Costa2528de42008-06-24 17:36:31 -0300542: movw %ax,(%_ASM_CX)
Glauber Costaefea5052008-06-24 16:59:05 -030055 xor %eax,%eax
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 EXIT
Jan Beulich00e065e2007-05-02 19:27:05 +020057ENDPROC(__put_user_2)
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
Jan Beulich00e065e2007-05-02 19:27:05 +020059ENTRY(__put_user_4)
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 ENTER
Glauber Costa2528de42008-06-24 17:36:31 -030061 mov TI_addr_limit(%_ASM_BX),%_ASM_BX
62 sub $3,%_ASM_BX
63 cmp %_ASM_BX,%_ASM_CX
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 jae bad_put_user
H. Peter Anvin63bcff22012-09-21 12:43:12 -070065 ASM_STAC
Glauber Costa2528de42008-06-24 17:36:31 -0300663: movl %eax,(%_ASM_CX)
Glauber Costaefea5052008-06-24 16:59:05 -030067 xor %eax,%eax
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 EXIT
Jan Beulich00e065e2007-05-02 19:27:05 +020069ENDPROC(__put_user_4)
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
Jan Beulich00e065e2007-05-02 19:27:05 +020071ENTRY(__put_user_8)
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 ENTER
Glauber Costa2528de42008-06-24 17:36:31 -030073 mov TI_addr_limit(%_ASM_BX),%_ASM_BX
74 sub $7,%_ASM_BX
75 cmp %_ASM_BX,%_ASM_CX
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 jae bad_put_user
H. Peter Anvin63bcff22012-09-21 12:43:12 -070077 ASM_STAC
Glauber Costa5cbbc3b2008-06-24 17:40:14 -0300784: mov %_ASM_AX,(%_ASM_CX)
79#ifdef CONFIG_X86_32
Glauber Costa2528de42008-06-24 17:36:31 -0300805: movl %edx,4(%_ASM_CX)
Glauber Costa5cbbc3b2008-06-24 17:40:14 -030081#endif
Glauber Costaefea5052008-06-24 16:59:05 -030082 xor %eax,%eax
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 EXIT
Jan Beulich00e065e2007-05-02 19:27:05 +020084ENDPROC(__put_user_8)
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
86bad_put_user:
Glauber Costa5cbbc3b2008-06-24 17:40:14 -030087 movl $-EFAULT,%eax
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 EXIT
Jan Beulich00e065e2007-05-02 19:27:05 +020089END(bad_put_user)
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
H. Peter Anvina53a96e2012-04-20 12:19:52 -070091 _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)
Glauber Costa5cbbc3b2008-06-24 17:40:14 -030095#ifdef CONFIG_X86_32
H. Peter Anvina53a96e2012-04-20 12:19:52 -070096 _ASM_EXTABLE(5b,bad_put_user)
Glauber Costa5cbbc3b2008-06-24 17:40:14 -030097#endif