/*1* __put_user functions.2*3* (C) Copyright 2005 Linus Torvalds4* (C) Copyright 2005 Andi Kleen5* (C) Copyright 2008 Glauber Costa6*7* These functions have a non-standard call interface8* to make them more efficient, especially as they9* return an error value in addition to the "real"10* return value.11*/12#include <linux/linkage.h>13#include <asm/dwarf2.h>14#include <asm/thread_info.h>15#include <asm/errno.h>16#include <asm/asm.h>171819/*20* __put_user_X21*22* Inputs: %eax[:%edx] contains the data23* %ecx contains the address24*25* Outputs: %eax is error code (0 or -EFAULT)26*27* These functions should not modify any other registers,28* as they get called from within inline assembly.29*/3031#define ENTER CFI_STARTPROC ; \32GET_THREAD_INFO(%_ASM_BX)33#define EXIT ret ; \34CFI_ENDPROC3536.text37ENTRY(__put_user_1)38ENTER39cmp TI_addr_limit(%_ASM_BX),%_ASM_CX40jae bad_put_user411: movb %al,(%_ASM_CX)42xor %eax,%eax43EXIT44ENDPROC(__put_user_1)4546ENTRY(__put_user_2)47ENTER48mov TI_addr_limit(%_ASM_BX),%_ASM_BX49sub $1,%_ASM_BX50cmp %_ASM_BX,%_ASM_CX51jae bad_put_user522: movw %ax,(%_ASM_CX)53xor %eax,%eax54EXIT55ENDPROC(__put_user_2)5657ENTRY(__put_user_4)58ENTER59mov TI_addr_limit(%_ASM_BX),%_ASM_BX60sub $3,%_ASM_BX61cmp %_ASM_BX,%_ASM_CX62jae bad_put_user633: movl %eax,(%_ASM_CX)64xor %eax,%eax65EXIT66ENDPROC(__put_user_4)6768ENTRY(__put_user_8)69ENTER70mov TI_addr_limit(%_ASM_BX),%_ASM_BX71sub $7,%_ASM_BX72cmp %_ASM_BX,%_ASM_CX73jae bad_put_user744: mov %_ASM_AX,(%_ASM_CX)75#ifdef CONFIG_X86_32765: movl %edx,4(%_ASM_CX)77#endif78xor %eax,%eax79EXIT80ENDPROC(__put_user_8)8182bad_put_user:83CFI_STARTPROC84movl $-EFAULT,%eax85EXIT86END(bad_put_user)8788.section __ex_table,"a"89_ASM_PTR 1b,bad_put_user90_ASM_PTR 2b,bad_put_user91_ASM_PTR 3b,bad_put_user92_ASM_PTR 4b,bad_put_user93#ifdef CONFIG_X86_3294_ASM_PTR 5b,bad_put_user95#endif96.previous979899