X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fx86_64%2Flib%2Fputuser.S;h=4989f5a8fa9b2fa1cd3903017ae409002a1e8195;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=4d287ceeab73c1056cfb68a205d27ccc3211363d;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/arch/x86_64/lib/putuser.S b/arch/x86_64/lib/putuser.S index 4d287ceea..4989f5a8f 100644 --- a/arch/x86_64/lib/putuser.S +++ b/arch/x86_64/lib/putuser.S @@ -2,87 +2,105 @@ * __put_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. + * to make them more efficient, especially as they + * return an error value in addition to the "real" + * return value. */ /* * __put_user_X * - * Inputs: %rax contains the address - * %rdx contains the value + * Inputs: %rcx contains the address + * %rdx contains new value * * Outputs: %rax is error code (0 or -EFAULT) - * %rbx is corrupted (will contain "current_task"). + * + * %r8 is destroyed. * * These functions should not modify any other registers, * as they get called from within inline assembly. */ -/* FIXME: putuser.S should be really merged with getuser.S, and preprocessor should be used to keep code duplication lower */ - #include +#include #include #include -#include +#include #include -.text -.p2align -.globl __put_user_1 -__put_user_1: - GET_THREAD_INFO(%rbx) - cmpq threadinfo_addr_limit(%rbx),%rax + .text +ENTRY(__put_user_1) + CFI_STARTPROC + GET_THREAD_INFO(%r8) + cmpq threadinfo_addr_limit(%r8),%rcx jae bad_put_user -1: movb %dl,(%rax) - xorq %rax,%rax +1: movb %dl,(%rcx) + xorl %eax,%eax ret + CFI_ENDPROC +ENDPROC(__put_user_1) -.p2align -.globl __put_user_2 -__put_user_2: - GET_THREAD_INFO(%rbx) - addq $1,%rax - jc bad_put_user - cmpq threadinfo_addr_limit(%rbx),%rax - jae bad_put_user -2: movw %dx,-1(%rax) - xorq %rax,%rax +ENTRY(__put_user_2) + CFI_STARTPROC + GET_THREAD_INFO(%r8) + addq $1,%rcx + jc 20f + cmpq threadinfo_addr_limit(%r8),%rcx + jae 20f + decq %rcx +2: movw %dx,(%rcx) + xorl %eax,%eax ret +20: decq %rcx + jmp bad_put_user + CFI_ENDPROC +ENDPROC(__put_user_2) -.p2align -.globl __put_user_4 -__put_user_4: - GET_THREAD_INFO(%rbx) - addq $3,%rax - jc bad_put_user - cmpq threadinfo_addr_limit(%rbx),%rax - jae bad_put_user -3: movl %edx,-3(%rax) - xorq %rax,%rax +ENTRY(__put_user_4) + CFI_STARTPROC + GET_THREAD_INFO(%r8) + addq $3,%rcx + jc 30f + cmpq threadinfo_addr_limit(%r8),%rcx + jae 30f + subq $3,%rcx +3: movl %edx,(%rcx) + xorl %eax,%eax ret +30: subq $3,%rcx + jmp bad_put_user + CFI_ENDPROC +ENDPROC(__put_user_4) -.p2align -.globl __put_user_8 -__put_user_8: - GET_THREAD_INFO(%rbx) - addq $7,%rax - jc bad_put_user - cmpq threadinfo_addr_limit(%rbx),%rax - jae bad_put_user -4: movq %rdx,-7(%rax) - xorq %rax,%rax +ENTRY(__put_user_8) + CFI_STARTPROC + GET_THREAD_INFO(%r8) + addq $7,%rcx + jc 40f + cmpq threadinfo_addr_limit(%r8),%rcx + jae 40f + subq $7,%rcx +4: movq %rdx,(%rcx) + xorl %eax,%eax ret +40: subq $7,%rcx + jmp bad_put_user + CFI_ENDPROC +ENDPROC(__put_user_8) -ENTRY(bad_put_user) bad_put_user: + CFI_STARTPROC movq $(-EFAULT),%rax ret + CFI_ENDPROC +END(bad_put_user) .section __ex_table,"a" .quad 1b,bad_put_user .quad 2b,bad_put_user .quad 3b,bad_put_user - .quad 4b,bad_put_user + .quad 4b,bad_put_user .previous