1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * __put_user functions. 4 * 5 * (C) Copyright 2005 Linus Torvalds 6 * (C) Copyright 2005 Andi Kleen 7 * (C) Copyright 2008 Glauber Costa 8 * 9 * These functions have a non-standard call interface 10 * to make them more efficient, especially as they 11 * return an error value in addition to the "real" 12 * return value. 13 */ 14#include <linux/linkage.h> 15#include <asm/thread_info.h> 16#include <asm/errno.h> 17#include <asm/asm.h> 18#include <asm/smap.h> 19#include <asm/export.h> 20 21 22/* 23 * __put_user_X 24 * 25 * Inputs: %eax[:%edx] contains the data 26 * %ecx contains the address 27 * 28 * Outputs: %ecx is error code (0 or -EFAULT) 29 * 30 * Clobbers: %ebx needed for task pointer 31 * 32 * These functions should not modify any other registers, 33 * as they get called from within inline assembly. 34 */ 35 36#define ENTER mov PER_CPU_VAR(current_task), %_ASM_BX 37 38.text 39SYM_FUNC_START(__put_user_1) 40 ENTER 41 cmp TASK_addr_limit(%_ASM_BX),%_ASM_CX 42 jae .Lbad_put_user 43SYM_INNER_LABEL(__put_user_nocheck_1, SYM_L_GLOBAL) 44 ASM_STAC 451: movb %al,(%_ASM_CX) 46 xor %ecx,%ecx 47 ASM_CLAC 48 ret 49SYM_FUNC_END(__put_user_1) 50EXPORT_SYMBOL(__put_user_1) 51EXPORT_SYMBOL(__put_user_nocheck_1) 52 53SYM_FUNC_START(__put_user_2) 54 ENTER 55 mov TASK_addr_limit(%_ASM_BX),%_ASM_BX 56 sub $1,%_ASM_BX 57 cmp %_ASM_BX,%_ASM_CX 58 jae .Lbad_put_user 59SYM_INNER_LABEL(__put_user_nocheck_2, SYM_L_GLOBAL) 60 ASM_STAC 612: movw %ax,(%_ASM_CX) 62 xor %ecx,%ecx 63 ASM_CLAC 64 ret 65SYM_FUNC_END(__put_user_2) 66EXPORT_SYMBOL(__put_user_2) 67EXPORT_SYMBOL(__put_user_nocheck_2) 68 69SYM_FUNC_START(__put_user_4) 70 ENTER 71 mov TASK_addr_limit(%_ASM_BX),%_ASM_BX 72 sub $3,%_ASM_BX 73 cmp %_ASM_BX,%_ASM_CX 74 jae .Lbad_put_user 75SYM_INNER_LABEL(__put_user_nocheck_4, SYM_L_GLOBAL) 76 ASM_STAC 773: movl %eax,(%_ASM_CX) 78 xor %ecx,%ecx 79 ASM_CLAC 80 ret 81SYM_FUNC_END(__put_user_4) 82EXPORT_SYMBOL(__put_user_4) 83EXPORT_SYMBOL(__put_user_nocheck_4) 84 85SYM_FUNC_START(__put_user_8) 86 ENTER 87 mov TASK_addr_limit(%_ASM_BX),%_ASM_BX 88 sub $7,%_ASM_BX 89 cmp %_ASM_BX,%_ASM_CX 90 jae .Lbad_put_user 91SYM_INNER_LABEL(__put_user_nocheck_8, SYM_L_GLOBAL) 92 ASM_STAC 934: mov %_ASM_AX,(%_ASM_CX) 94#ifdef CONFIG_X86_32 955: movl %edx,4(%_ASM_CX) 96#endif 97 xor %ecx,%ecx 98 ASM_CLAC 99 RET 100SYM_FUNC_END(__put_user_8) 101EXPORT_SYMBOL(__put_user_8) 102EXPORT_SYMBOL(__put_user_nocheck_8) 103 104SYM_CODE_START_LOCAL(.Lbad_put_user_clac) 105 ASM_CLAC 106.Lbad_put_user: 107 movl $-EFAULT,%ecx 108 RET 109SYM_CODE_END(.Lbad_put_user_clac) 110 111 _ASM_EXTABLE_UA(1b, .Lbad_put_user_clac) 112 _ASM_EXTABLE_UA(2b, .Lbad_put_user_clac) 113 _ASM_EXTABLE_UA(3b, .Lbad_put_user_clac) 114 _ASM_EXTABLE_UA(4b, .Lbad_put_user_clac) 115#ifdef CONFIG_X86_32 116 _ASM_EXTABLE_UA(5b, .Lbad_put_user_clac) 117#endif 118