1/* 2 * __put_user functions. 3 * 4 * (C) Copyright 2005 Linus Torvalds 5 * (C) Copyright 2005 Andi Kleen 6 * (C) Copyright 2008 Glauber Costa 7 * 8 * These functions have a non-standard call interface 9 * to make them more efficient, especially as they 10 * return an error value in addition to the "real" 11 * return value. 12 */ 13#include <linux/linkage.h> 14#include <asm/thread_info.h> 15#include <asm/errno.h> 16#include <asm/asm.h> 17#include <asm/smap.h> 18#include <asm/export.h> 19 20 21/* 22 * __put_user_X 23 * 24 * Inputs: %eax[:%edx] contains the data 25 * %ecx contains the address 26 * 27 * Outputs: %eax is error code (0 or -EFAULT) 28 * 29 * These functions should not modify any other registers, 30 * as they get called from within inline assembly. 31 */ 32 33#define ENTER mov PER_CPU_VAR(current_task), %_ASM_BX 34#define EXIT ASM_CLAC ; \ 35 ret 36 37.text 38ENTRY(__put_user_1) 39 ENTER 40 cmp TASK_addr_limit(%_ASM_BX),%_ASM_CX 41 jae bad_put_user 42 ASM_STAC 431: movb %al,(%_ASM_CX) 44 xor %eax,%eax 45 EXIT 46ENDPROC(__put_user_1) 47EXPORT_SYMBOL(__put_user_1) 48 49ENTRY(__put_user_2) 50 ENTER 51 mov TASK_addr_limit(%_ASM_BX),%_ASM_BX 52 sub $1,%_ASM_BX 53 cmp %_ASM_BX,%_ASM_CX 54 jae bad_put_user 55 ASM_STAC 562: movw %ax,(%_ASM_CX) 57 xor %eax,%eax 58 EXIT 59ENDPROC(__put_user_2) 60EXPORT_SYMBOL(__put_user_2) 61 62ENTRY(__put_user_4) 63 ENTER 64 mov TASK_addr_limit(%_ASM_BX),%_ASM_BX 65 sub $3,%_ASM_BX 66 cmp %_ASM_BX,%_ASM_CX 67 jae bad_put_user 68 ASM_STAC 693: movl %eax,(%_ASM_CX) 70 xor %eax,%eax 71 EXIT 72ENDPROC(__put_user_4) 73EXPORT_SYMBOL(__put_user_4) 74 75ENTRY(__put_user_8) 76 ENTER 77 mov TASK_addr_limit(%_ASM_BX),%_ASM_BX 78 sub $7,%_ASM_BX 79 cmp %_ASM_BX,%_ASM_CX 80 jae bad_put_user 81 ASM_STAC 824: mov %_ASM_AX,(%_ASM_CX) 83#ifdef CONFIG_X86_32 845: movl %edx,4(%_ASM_CX) 85#endif 86 xor %eax,%eax 87 EXIT 88ENDPROC(__put_user_8) 89EXPORT_SYMBOL(__put_user_8) 90 91bad_put_user: 92 movl $-EFAULT,%eax 93 EXIT 94END(bad_put_user) 95 96 _ASM_EXTABLE(1b,bad_put_user) 97 _ASM_EXTABLE(2b,bad_put_user) 98 _ASM_EXTABLE(3b,bad_put_user) 99 _ASM_EXTABLE(4b,bad_put_user) 100#ifdef CONFIG_X86_32 101 _ASM_EXTABLE(5b,bad_put_user) 102#endif 103