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.macro check_range size:req 37.if IS_ENABLED(CONFIG_X86_64) 38 mov %rcx, %rbx 39 sar $63, %rbx 40 or %rbx, %rcx 41.else 42 cmp $TASK_SIZE_MAX-\size+1, %ecx 43 jae .Lbad_put_user 44.endif 45.endm 46 47.text 48SYM_FUNC_START(__put_user_1) 49 check_range size=1 50 ASM_STAC 511: movb %al,(%_ASM_CX) 52 xor %ecx,%ecx 53 ASM_CLAC 54 RET 55SYM_FUNC_END(__put_user_1) 56EXPORT_SYMBOL(__put_user_1) 57 58SYM_FUNC_START(__put_user_nocheck_1) 59 ASM_STAC 602: movb %al,(%_ASM_CX) 61 xor %ecx,%ecx 62 ASM_CLAC 63 RET 64SYM_FUNC_END(__put_user_nocheck_1) 65EXPORT_SYMBOL(__put_user_nocheck_1) 66 67SYM_FUNC_START(__put_user_2) 68 check_range size=2 69 ASM_STAC 703: movw %ax,(%_ASM_CX) 71 xor %ecx,%ecx 72 ASM_CLAC 73 RET 74SYM_FUNC_END(__put_user_2) 75EXPORT_SYMBOL(__put_user_2) 76 77SYM_FUNC_START(__put_user_nocheck_2) 78 ASM_STAC 794: movw %ax,(%_ASM_CX) 80 xor %ecx,%ecx 81 ASM_CLAC 82 RET 83SYM_FUNC_END(__put_user_nocheck_2) 84EXPORT_SYMBOL(__put_user_nocheck_2) 85 86SYM_FUNC_START(__put_user_4) 87 check_range size=4 88 ASM_STAC 895: movl %eax,(%_ASM_CX) 90 xor %ecx,%ecx 91 ASM_CLAC 92 RET 93SYM_FUNC_END(__put_user_4) 94EXPORT_SYMBOL(__put_user_4) 95 96SYM_FUNC_START(__put_user_nocheck_4) 97 ASM_STAC 986: movl %eax,(%_ASM_CX) 99 xor %ecx,%ecx 100 ASM_CLAC 101 RET 102SYM_FUNC_END(__put_user_nocheck_4) 103EXPORT_SYMBOL(__put_user_nocheck_4) 104 105SYM_FUNC_START(__put_user_8) 106 check_range size=8 107 ASM_STAC 1087: mov %_ASM_AX,(%_ASM_CX) 109#ifdef CONFIG_X86_32 1108: movl %edx,4(%_ASM_CX) 111#endif 112 xor %ecx,%ecx 113 ASM_CLAC 114 RET 115SYM_FUNC_END(__put_user_8) 116EXPORT_SYMBOL(__put_user_8) 117 118SYM_FUNC_START(__put_user_nocheck_8) 119 ASM_STAC 1209: mov %_ASM_AX,(%_ASM_CX) 121#ifdef CONFIG_X86_32 12210: movl %edx,4(%_ASM_CX) 123#endif 124 xor %ecx,%ecx 125 ASM_CLAC 126 RET 127SYM_FUNC_END(__put_user_nocheck_8) 128EXPORT_SYMBOL(__put_user_nocheck_8) 129 130SYM_CODE_START_LOCAL(__put_user_handle_exception) 131 ASM_CLAC 132.Lbad_put_user: 133 movl $-EFAULT,%ecx 134 RET 135SYM_CODE_END(__put_user_handle_exception) 136 137 _ASM_EXTABLE(1b, __put_user_handle_exception) 138 _ASM_EXTABLE(2b, __put_user_handle_exception) 139 _ASM_EXTABLE(3b, __put_user_handle_exception) 140 _ASM_EXTABLE(4b, __put_user_handle_exception) 141 _ASM_EXTABLE(5b, __put_user_handle_exception) 142 _ASM_EXTABLE(6b, __put_user_handle_exception) 143 _ASM_EXTABLE(7b, __put_user_handle_exception) 144 _ASM_EXTABLE(9b, __put_user_handle_exception) 145#ifdef CONFIG_X86_32 146 _ASM_EXTABLE(8b, __put_user_handle_exception) 147 _ASM_EXTABLE(10b, __put_user_handle_exception) 148#endif 149