blob: e33388419b7b235cbb0eb20a02c2c708f58a69cf [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
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 * __get_user_X
15 *
Glauber Costa40faf462008-06-24 11:37:57 -030016 * Inputs: %rax contains the address.
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 * The register is modified, but all changes are undone
18 * before returning because the C code doesn't know about it.
19 *
20 * Outputs: %rax is error code (0 or -EFAULT)
21 * %rdx contains zero-extended value
22 *
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>
Jan Beulich8d379da2006-09-26 10:52:32 +020029#include <asm/dwarf2.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <asm/page.h>
31#include <asm/errno.h>
Sam Ravnborge2d5df92005-09-09 21:28:48 +020032#include <asm/asm-offsets.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <asm/thread_info.h>
Glauber Costa40faf462008-06-24 11:37:57 -030034#include <asm/asm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
36 .text
Jan Beulich8d379da2006-09-26 10:52:32 +020037ENTRY(__get_user_1)
38 CFI_STARTPROC
Glauber Costa40faf462008-06-24 11:37:57 -030039 GET_THREAD_INFO(%_ASM_DX)
40 cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 jae bad_get_user
Glauber Costa40faf462008-06-24 11:37:57 -0300421: movzb (%_ASM_AX),%edx
Glauber Costaef8c1a22008-06-24 11:21:53 -030043 xor %eax,%eax
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 ret
Jan Beulich8d379da2006-09-26 10:52:32 +020045 CFI_ENDPROC
46ENDPROC(__get_user_1)
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
Jan Beulich8d379da2006-09-26 10:52:32 +020048ENTRY(__get_user_2)
49 CFI_STARTPROC
Glauber Costa40faf462008-06-24 11:37:57 -030050 add $1,%_ASM_AX
Glauber Costa92628752008-06-24 11:13:16 -030051 jc bad_get_user
Glauber Costa40faf462008-06-24 11:37:57 -030052 GET_THREAD_INFO(%_ASM_DX)
53 cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
Glauber Costa92628752008-06-24 11:13:16 -030054 jae bad_get_user
Glauber Costa40faf462008-06-24 11:37:57 -0300552: movzwl -1(%_ASM_AX),%edx
Glauber Costaef8c1a22008-06-24 11:21:53 -030056 xor %eax,%eax
Linus Torvalds1da177e2005-04-16 15:20:36 -070057 ret
Jan Beulich8d379da2006-09-26 10:52:32 +020058 CFI_ENDPROC
59ENDPROC(__get_user_2)
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
Jan Beulich8d379da2006-09-26 10:52:32 +020061ENTRY(__get_user_4)
62 CFI_STARTPROC
Glauber Costa40faf462008-06-24 11:37:57 -030063 add $3,%_ASM_AX
Glauber Costa92628752008-06-24 11:13:16 -030064 jc bad_get_user
Glauber Costa40faf462008-06-24 11:37:57 -030065 GET_THREAD_INFO(%_ASM_DX)
66 cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
Glauber Costa92628752008-06-24 11:13:16 -030067 jae bad_get_user
Glauber Costa40faf462008-06-24 11:37:57 -0300683: mov -3(%_ASM_AX),%edx
Glauber Costaef8c1a22008-06-24 11:21:53 -030069 xor %eax,%eax
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 ret
Jan Beulich8d379da2006-09-26 10:52:32 +020071 CFI_ENDPROC
72ENDPROC(__get_user_4)
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
Jan Beulich8d379da2006-09-26 10:52:32 +020074ENTRY(__get_user_8)
75 CFI_STARTPROC
Glauber Costa40faf462008-06-24 11:37:57 -030076 add $7,%_ASM_AX
Glauber Costa92628752008-06-24 11:13:16 -030077 jc bad_get_user
Glauber Costa40faf462008-06-24 11:37:57 -030078 GET_THREAD_INFO(%_ASM_DX)
79 cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
Glauber Costa92628752008-06-24 11:13:16 -030080 jae bad_get_user
Glauber Costa40faf462008-06-24 11:37:57 -0300814: movq -7(%_ASM_AX),%_ASM_DX
Glauber Costaef8c1a22008-06-24 11:21:53 -030082 xor %eax,%eax
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 ret
Jan Beulich8d379da2006-09-26 10:52:32 +020084 CFI_ENDPROC
85ENDPROC(__get_user_8)
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87bad_get_user:
Jan Beulich8d379da2006-09-26 10:52:32 +020088 CFI_STARTPROC
Glauber Costaef8c1a22008-06-24 11:21:53 -030089 xor %edx,%edx
Glauber Costa40faf462008-06-24 11:37:57 -030090 mov $(-EFAULT),%_ASM_AX
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 ret
Jan Beulich8d379da2006-09-26 10:52:32 +020092 CFI_ENDPROC
93END(bad_get_user)
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
95.section __ex_table,"a"
Glauber Costa87e2f1e2008-06-24 12:02:44 -030096 _ASM_PTR 1b,bad_get_user
97 _ASM_PTR 2b,bad_get_user
98 _ASM_PTR 3b,bad_get_user
99 _ASM_PTR 4b,bad_get_user
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100.previous