getuser.S 2.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/*
 * __get_user functions.
 *
 * (C) Copyright 1998 Linus Torvalds
 * (C) Copyright 2005 Andi Kleen
6
 * (C) Copyright 2008 Glauber Costa
L
Linus Torvalds 已提交
7 8 9 10 11 12 13 14 15 16
 *
 * These functions have a non-standard call interface
 * to make them more efficient, especially as they
 * return an error value in addition to the "real"
 * return value.
 */

/*
 * __get_user_X
 *
17
 * Inputs:	%[r|e]ax contains the address.
L
Linus Torvalds 已提交
18
 *
19 20
 * Outputs:	%[r|e]ax is error code (0 or -EFAULT)
 *		%[r|e]dx contains zero-extended value
21
 *		%ecx contains the high half for 32-bit __get_user_8
22
 *
L
Linus Torvalds 已提交
23 24 25 26 27 28
 *
 * These functions should not modify any other registers,
 * as they get called from within inline assembly.
 */

#include <linux/linkage.h>
29
#include <asm/page_types.h>
L
Linus Torvalds 已提交
30
#include <asm/errno.h>
31
#include <asm/asm-offsets.h>
L
Linus Torvalds 已提交
32
#include <asm/thread_info.h>
G
Glauber Costa 已提交
33
#include <asm/asm.h>
34
#include <asm/smap.h>
L
Linus Torvalds 已提交
35 36

	.text
37
ENTRY(__get_user_1)
G
Glauber Costa 已提交
38 39
	GET_THREAD_INFO(%_ASM_DX)
	cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
L
Linus Torvalds 已提交
40
	jae bad_get_user
41
	ASM_STAC
42
1:	movzbl (%_ASM_AX),%edx
43
	xor %eax,%eax
44
	ASM_CLAC
L
Linus Torvalds 已提交
45
	ret
46
ENDPROC(__get_user_1)
L
Linus Torvalds 已提交
47

48
ENTRY(__get_user_2)
G
Glauber Costa 已提交
49
	add $1,%_ASM_AX
50
	jc bad_get_user
G
Glauber Costa 已提交
51 52
	GET_THREAD_INFO(%_ASM_DX)
	cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
53
	jae bad_get_user
54
	ASM_STAC
G
Glauber Costa 已提交
55
2:	movzwl -1(%_ASM_AX),%edx
56
	xor %eax,%eax
57
	ASM_CLAC
L
Linus Torvalds 已提交
58
	ret
59
ENDPROC(__get_user_2)
L
Linus Torvalds 已提交
60

61
ENTRY(__get_user_4)
G
Glauber Costa 已提交
62
	add $3,%_ASM_AX
63
	jc bad_get_user
G
Glauber Costa 已提交
64 65
	GET_THREAD_INFO(%_ASM_DX)
	cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
66
	jae bad_get_user
67
	ASM_STAC
68
3:	movl -3(%_ASM_AX),%edx
69
	xor %eax,%eax
70
	ASM_CLAC
L
Linus Torvalds 已提交
71
	ret
72
ENDPROC(__get_user_4)
L
Linus Torvalds 已提交
73

74
ENTRY(__get_user_8)
75
#ifdef CONFIG_X86_64
G
Glauber Costa 已提交
76
	add $7,%_ASM_AX
77
	jc bad_get_user
G
Glauber Costa 已提交
78 79
	GET_THREAD_INFO(%_ASM_DX)
	cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
80
	jae bad_get_user
81
	ASM_STAC
82
4:	movq -7(%_ASM_AX),%rdx
83
	xor %eax,%eax
84
	ASM_CLAC
L
Linus Torvalds 已提交
85
	ret
86 87 88 89 90 91 92
#else
	add $7,%_ASM_AX
	jc bad_get_user_8
	GET_THREAD_INFO(%_ASM_DX)
	cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
	jae bad_get_user_8
	ASM_STAC
93 94
4:	movl -7(%_ASM_AX),%edx
5:	movl -3(%_ASM_AX),%ecx
95 96 97 98
	xor %eax,%eax
	ASM_CLAC
	ret
#endif
99
ENDPROC(__get_user_8)
100

L
Linus Torvalds 已提交
101 102

bad_get_user:
103
	xor %edx,%edx
G
Glauber Costa 已提交
104
	mov $(-EFAULT),%_ASM_AX
105
	ASM_CLAC
L
Linus Torvalds 已提交
106
	ret
107
END(bad_get_user)
L
Linus Torvalds 已提交
108

109 110 111 112 113 114 115 116 117 118
#ifdef CONFIG_X86_32
bad_get_user_8:
	xor %edx,%edx
	xor %ecx,%ecx
	mov $(-EFAULT),%_ASM_AX
	ASM_CLAC
	ret
END(bad_get_user_8)
#endif

119 120 121
	_ASM_EXTABLE(1b,bad_get_user)
	_ASM_EXTABLE(2b,bad_get_user)
	_ASM_EXTABLE(3b,bad_get_user)
122
#ifdef CONFIG_X86_64
123
	_ASM_EXTABLE(4b,bad_get_user)
124 125 126
#else
	_ASM_EXTABLE(4b,bad_get_user_8)
	_ASM_EXTABLE(5b,bad_get_user_8)
127
#endif