blob: 0ef5128c2de8b05ce60e8beac1e43f53adcba2ba [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * __get_user functions.
3 *
4 * (C) Copyright 1998 Linus Torvalds
5 * (C) Copyright 2005 Andi Kleen
Glauber Costa6c2d4582008-06-24 12:05:11 -03006 * (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 */
13
14/*
15 * __get_user_X
16 *
Glauber Costa6c2d4582008-06-24 12:05:11 -030017 * Inputs: %[r|e]ax contains the address.
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 *
Glauber Costa6c2d4582008-06-24 12:05:11 -030019 * Outputs: %[r|e]ax is error code (0 or -EFAULT)
20 * %[r|e]dx contains zero-extended value
Ville Syrjälä96477b42012-12-12 13:34:03 +020021 * %ecx contains the high half for 32-bit __get_user_8
Glauber Costa6c2d4582008-06-24 12:05:11 -030022 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070023 *
24 * These functions should not modify any other registers,
25 * as they get called from within inline assembly.
26 */
27
28#include <linux/linkage.h>
Jeremy Fitzhardinge0341c142009-02-13 11:14:01 -080029#include <asm/page_types.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#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>
Glauber Costa40faf462008-06-24 11:37:57 -030033#include <asm/asm.h>
H. Peter Anvin63bcff22012-09-21 12:43:12 -070034#include <asm/smap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
36 .text
Jan Beulich8d379da2006-09-26 10:52:32 +020037ENTRY(__get_user_1)
Andy Lutomirski13d4ea02016-07-14 13:22:57 -070038 mov PER_CPU_VAR(current_task), %_ASM_DX
39 cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 jae bad_get_user
H. Peter Anvin63bcff22012-09-21 12:43:12 -070041 ASM_STAC
H. Peter Anvin16640162013-02-11 23:14:48 -0800421: movzbl (%_ASM_AX),%edx
Glauber Costaef8c1a22008-06-24 11:21:53 -030043 xor %eax,%eax
H. Peter Anvin63bcff22012-09-21 12:43:12 -070044 ASM_CLAC
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 ret
Jan Beulich8d379da2006-09-26 10:52:32 +020046ENDPROC(__get_user_1)
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
Jan Beulich8d379da2006-09-26 10:52:32 +020048ENTRY(__get_user_2)
Glauber Costa40faf462008-06-24 11:37:57 -030049 add $1,%_ASM_AX
Glauber Costa92628752008-06-24 11:13:16 -030050 jc bad_get_user
Andy Lutomirski13d4ea02016-07-14 13:22:57 -070051 mov PER_CPU_VAR(current_task), %_ASM_DX
52 cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
Glauber Costa92628752008-06-24 11:13:16 -030053 jae bad_get_user
H. Peter Anvin63bcff22012-09-21 12:43:12 -070054 ASM_STAC
Glauber Costa40faf462008-06-24 11:37:57 -0300552: movzwl -1(%_ASM_AX),%edx
Glauber Costaef8c1a22008-06-24 11:21:53 -030056 xor %eax,%eax
H. Peter Anvin63bcff22012-09-21 12:43:12 -070057 ASM_CLAC
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 ret
Jan Beulich8d379da2006-09-26 10:52:32 +020059ENDPROC(__get_user_2)
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
Jan Beulich8d379da2006-09-26 10:52:32 +020061ENTRY(__get_user_4)
Glauber Costa40faf462008-06-24 11:37:57 -030062 add $3,%_ASM_AX
Glauber Costa92628752008-06-24 11:13:16 -030063 jc bad_get_user
Andy Lutomirski13d4ea02016-07-14 13:22:57 -070064 mov PER_CPU_VAR(current_task), %_ASM_DX
65 cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
Glauber Costa92628752008-06-24 11:13:16 -030066 jae bad_get_user
H. Peter Anvin63bcff22012-09-21 12:43:12 -070067 ASM_STAC
H. Peter Anvin16640162013-02-11 23:14:48 -0800683: movl -3(%_ASM_AX),%edx
Glauber Costaef8c1a22008-06-24 11:21:53 -030069 xor %eax,%eax
H. Peter Anvin63bcff22012-09-21 12:43:12 -070070 ASM_CLAC
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 ret
Jan Beulich8d379da2006-09-26 10:52:32 +020072ENDPROC(__get_user_4)
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
Jan Beulich8d379da2006-09-26 10:52:32 +020074ENTRY(__get_user_8)
Ville Syrjälä96477b42012-12-12 13:34:03 +020075#ifdef CONFIG_X86_64
Glauber Costa40faf462008-06-24 11:37:57 -030076 add $7,%_ASM_AX
Glauber Costa92628752008-06-24 11:13:16 -030077 jc bad_get_user
Andy Lutomirski13d4ea02016-07-14 13:22:57 -070078 mov PER_CPU_VAR(current_task), %_ASM_DX
79 cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
Ville Syrjälä96477b42012-12-12 13:34:03 +020080 jae bad_get_user
H. Peter Anvin63bcff22012-09-21 12:43:12 -070081 ASM_STAC
H. Peter Anvin16640162013-02-11 23:14:48 -0800824: movq -7(%_ASM_AX),%rdx
Glauber Costaef8c1a22008-06-24 11:21:53 -030083 xor %eax,%eax
H. Peter Anvin63bcff22012-09-21 12:43:12 -070084 ASM_CLAC
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 ret
Ville Syrjälä96477b42012-12-12 13:34:03 +020086#else
87 add $7,%_ASM_AX
88 jc bad_get_user_8
Andy Lutomirski13d4ea02016-07-14 13:22:57 -070089 mov PER_CPU_VAR(current_task), %_ASM_DX
90 cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
Ville Syrjälä96477b42012-12-12 13:34:03 +020091 jae bad_get_user_8
92 ASM_STAC
H. Peter Anvin16640162013-02-11 23:14:48 -0800934: movl -7(%_ASM_AX),%edx
945: movl -3(%_ASM_AX),%ecx
Ville Syrjälä96477b42012-12-12 13:34:03 +020095 xor %eax,%eax
96 ASM_CLAC
97 ret
98#endif
Jan Beulich8d379da2006-09-26 10:52:32 +020099ENDPROC(__get_user_8)
Ville Syrjälä96477b42012-12-12 13:34:03 +0200100
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
102bad_get_user:
Glauber Costaef8c1a22008-06-24 11:21:53 -0300103 xor %edx,%edx
Glauber Costa40faf462008-06-24 11:37:57 -0300104 mov $(-EFAULT),%_ASM_AX
H. Peter Anvin63bcff22012-09-21 12:43:12 -0700105 ASM_CLAC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 ret
Jan Beulich8d379da2006-09-26 10:52:32 +0200107END(bad_get_user)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
Ville Syrjälä96477b42012-12-12 13:34:03 +0200109#ifdef CONFIG_X86_32
110bad_get_user_8:
Ville Syrjälä96477b42012-12-12 13:34:03 +0200111 xor %edx,%edx
112 xor %ecx,%ecx
113 mov $(-EFAULT),%_ASM_AX
114 ASM_CLAC
115 ret
Ville Syrjälä96477b42012-12-12 13:34:03 +0200116END(bad_get_user_8)
117#endif
118
H. Peter Anvin1a27bc02012-04-20 12:19:51 -0700119 _ASM_EXTABLE(1b,bad_get_user)
120 _ASM_EXTABLE(2b,bad_get_user)
121 _ASM_EXTABLE(3b,bad_get_user)
Glauber Costa6c2d4582008-06-24 12:05:11 -0300122#ifdef CONFIG_X86_64
H. Peter Anvin1a27bc02012-04-20 12:19:51 -0700123 _ASM_EXTABLE(4b,bad_get_user)
Ville Syrjälä96477b42012-12-12 13:34:03 +0200124#else
125 _ASM_EXTABLE(4b,bad_get_user_8)
126 _ASM_EXTABLE(5b,bad_get_user_8)
Glauber Costa6c2d4582008-06-24 12:05:11 -0300127#endif