From: "Andi Kleen" <ak@suse.de>

Give out of line get_user better calling conventions

Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/x86_64/lib/getuser.S    |   65 ++++++++++++++++++++---------------
 25-akpm/include/asm-x86_64/uaccess.h |   13 +++----
 2 files changed, 44 insertions(+), 34 deletions(-)

diff -puN arch/x86_64/lib/getuser.S~x86_64-give-out-of-line-get_user-better-calling arch/x86_64/lib/getuser.S
--- 25/arch/x86_64/lib/getuser.S~x86_64-give-out-of-line-get_user-better-calling	Wed Mar 23 15:38:41 2005
+++ 25-akpm/arch/x86_64/lib/getuser.S	Wed Mar 23 15:38:41 2005
@@ -2,6 +2,7 @@
  * __get_user functions.
  *
  * (C) Copyright 1998 Linus Torvalds
+ * (C) Copyright 2005 Andi Kleen
  *
  * These functions have a non-standard call interface
  * to make them more efficient, especially as they
@@ -12,12 +13,14 @@
 /*
  * __get_user_X
  *
- * Inputs:	%rax contains the address
+ * Inputs:	%rcx contains the address.
+ *		The register is modified, but all changes are undone
+ *		before returning because the C code doesn't know about it.
  *
  * Outputs:	%rax is error code (0 or -EFAULT)
  *		%rdx contains zero-extended value
  * 
- * %rbx is destroyed.
+ * %r8 is destroyed.
  *
  * These functions should not modify any other registers,
  * as they get called from within inline assembly.
@@ -33,52 +36,60 @@
 	.p2align 4
 .globl __get_user_1
 __get_user_1:	
-	GET_THREAD_INFO(%rbx)
-	cmpq threadinfo_addr_limit(%rbx),%rax
+	GET_THREAD_INFO(%r8)
+	cmpq threadinfo_addr_limit(%r8),%rcx
 	jae bad_get_user
-1:	movzb (%rax),%edx
-	xorq %rax,%rax
+1:	movzb (%rcx),%edx
+	xorl %eax,%eax
 	ret
 
 	.p2align 4
 .globl __get_user_2
 __get_user_2:
-	GET_THREAD_INFO(%rbx) 
-	addq $1,%rax
-	jc bad_get_user
-	cmpq threadinfo_addr_limit(%rbx),%rax 
-	jae	 bad_get_user
-2:	movzwl -1(%rax),%edx
-	xorq %rax,%rax
+	GET_THREAD_INFO(%r8)
+	addq $1,%rcx
+	jc 20f
+	cmpq threadinfo_addr_limit(%r8),%rcx
+	jae 20f
+	decq   %rcx
+2:	movzwl (%rcx),%edx
+	xorl %eax,%eax
 	ret
+20:	decq    %rcx
+	jmp	bad_get_user
 
 	.p2align 4
 .globl __get_user_4
 __get_user_4:
-	GET_THREAD_INFO(%rbx) 
-	addq $3,%rax
-	jc bad_get_user
-	cmpq threadinfo_addr_limit(%rbx),%rax 
-	jae bad_get_user
-3:	movl -3(%rax),%edx
-	xorq %rax,%rax
+	GET_THREAD_INFO(%r8)
+	addq $3,%rcx
+	jc 30f
+	cmpq threadinfo_addr_limit(%r8),%rcx
+	jae 30f
+	subq $3,%rcx
+3:	movl (%rcx),%edx
+	xorl %eax,%eax
 	ret
+30:	subq $3,%rcx
+	jmp bad_get_user
 
 	.p2align 4
 .globl __get_user_8
 __get_user_8:
-	GET_THREAD_INFO(%rbx) 
-	addq $7,%rax
+	GET_THREAD_INFO(%r8)
+	addq $7,%rcx
 	jc bad_get_user
-	cmpq threadinfo_addr_limit(%rbx),%rax
+	cmpq threadinfo_addr_limit(%r8),%rcx
 	jae	bad_get_user
-4:	movq -7(%rax),%rdx
-	xorq %rax,%rax
+	subq	$7,%rcx
+4:	movq (%rcx),%rdx
+	xorl %eax,%eax
 	ret
+40:	subq $7,%rcx
+	jmp bad_get_user
 
-ENTRY(bad_get_user)
 bad_get_user:
-	xorq %rdx,%rdx
+	xorl %edx,%edx
 	movq $(-EFAULT),%rax
 	ret
 
diff -puN include/asm-x86_64/uaccess.h~x86_64-give-out-of-line-get_user-better-calling include/asm-x86_64/uaccess.h
--- 25/include/asm-x86_64/uaccess.h~x86_64-give-out-of-line-get_user-better-calling	Wed Mar 23 15:38:41 2005
+++ 25-akpm/include/asm-x86_64/uaccess.h	Wed Mar 23 15:38:41 2005
@@ -91,16 +91,11 @@ struct exception_table_entry
  * accesses to the same area of user memory).
  */
 
-extern void __get_user_1(void);
-extern void __get_user_2(void);
-extern void __get_user_4(void);
-extern void __get_user_8(void);
-
 #define __get_user_x(size,ret,x,ptr) \
 	__asm__ __volatile__("call __get_user_" #size \
 		:"=a" (ret),"=d" (x) \
-		:"0" (ptr) \
-		:"rbx")
+		:"c" (ptr) \
+		:"r8")
 
 /* Careful: we have to cast the result to the type of the pointer for sign reasons */
 #define get_user(x,ptr)							\
@@ -210,6 +205,10 @@ struct __large_struct { unsigned long bu
 	__gu_err;						\
 })
 
+extern int __get_user_1(void);
+extern int __get_user_2(void);
+extern int __get_user_4(void);
+extern int __get_user_8(void);
 extern int __get_user_bad(void);
 
 #define __get_user_size(x,ptr,size,retval)				\
_