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/export.h> 15#include <linux/linkage.h> 16#include <asm/thread_info.h> 17#include <asm/errno.h> 18#include <asm/asm.h> 19#include <asm/smap.h> 20 21/* 22 * __put_user_X 23 * 24 * Inputs: %eax[:%edx] contains the data 25 * %ecx contains the address 26 * 27 * Outputs: %ecx is error code (0 or -EFAULT) 28 * 29 * Clobbers: %ebx needed for task pointer 30 * 31 * These functions should not modify any other registers, 32 * as they get called from within inline assembly. 33 */ 34 35.macro check_range size:req 36.if IS_ENABLED(CONFIG_X86_64) 37 mov %rcx, %rbx 38 sar $63, %rbx 39 or %rbx, %rcx 40.else 41 cmp $TASK_SIZE_MAX-\size+1, %ecx 42 jae .Lbad_put_user 43.endif 44.endm 45 46.text 47SYM_FUNC_START(__put_user_1) 48 check_range size=1 49 ASM_STAC 501: movb %al,(%_ASM_CX) 51 xor %ecx,%ecx 52 ASM_CLAC 53 RET 54SYM_FUNC_END(__put_user_1) 55EXPORT_SYMBOL(__put_user_1) 56 57SYM_FUNC_START(__put_user_nocheck_1) 58 ASM_STAC 592: movb %al,(%_ASM_CX) 60 xor %ecx,%ecx 61 ASM_CLAC 62 RET 63SYM_FUNC_END(__put_user_nocheck_1) 64EXPORT_SYMBOL(__put_user_nocheck_1) 65 66SYM_FUNC_START(__put_user_2) 67 check_range size=2 68 ASM_STAC 693: movw %ax,(%_ASM_CX) 70 xor %ecx,%ecx 71 ASM_CLAC 72 RET 73SYM_FUNC_END(__put_user_2) 74EXPORT_SYMBOL(__put_user_2) 75 76SYM_FUNC_START(__put_user_nocheck_2) 77 ASM_STAC 784: movw %ax,(%_ASM_CX) 79 xor %ecx,%ecx 80 ASM_CLAC 81 RET 82SYM_FUNC_END(__put_user_nocheck_2) 83EXPORT_SYMBOL(__put_user_nocheck_2) 84 85SYM_FUNC_START(__put_user_4) 86 check_range size=4 87 ASM_STAC 885: movl %eax,(%_ASM_CX) 89 xor %ecx,%ecx 90 ASM_CLAC 91 RET 92SYM_FUNC_END(__put_user_4) 93EXPORT_SYMBOL(__put_user_4) 94 95SYM_FUNC_START(__put_user_nocheck_4) 96 ASM_STAC 976: movl %eax,(%_ASM_CX) 98 xor %ecx,%ecx 99 ASM_CLAC 100 RET 101SYM_FUNC_END(__put_user_nocheck_4) 102EXPORT_SYMBOL(__put_user_nocheck_4) 103 104SYM_FUNC_START(__put_user_8) 105 check_range size=8 106 ASM_STAC 1077: mov %_ASM_AX,(%_ASM_CX) 108#ifdef CONFIG_X86_32 1098: movl %edx,4(%_ASM_CX) 110#endif 111 xor %ecx,%ecx 112 ASM_CLAC 113 RET 114SYM_FUNC_END(__put_user_8) 115EXPORT_SYMBOL(__put_user_8) 116 117SYM_FUNC_START(__put_user_nocheck_8) 118 ASM_STAC 1199: mov %_ASM_AX,(%_ASM_CX) 120#ifdef CONFIG_X86_32 12110: movl %edx,4(%_ASM_CX) 122#endif 123 xor %ecx,%ecx 124 ASM_CLAC 125 RET 126SYM_FUNC_END(__put_user_nocheck_8) 127EXPORT_SYMBOL(__put_user_nocheck_8) 128 129SYM_CODE_START_LOCAL(__put_user_handle_exception) 130 ASM_CLAC 131.Lbad_put_user: 132 movl $-EFAULT,%ecx 133 RET 134SYM_CODE_END(__put_user_handle_exception) 135 136 _ASM_EXTABLE_UA(1b, __put_user_handle_exception) 137 _ASM_EXTABLE_UA(2b, __put_user_handle_exception) 138 _ASM_EXTABLE_UA(3b, __put_user_handle_exception) 139 _ASM_EXTABLE_UA(4b, __put_user_handle_exception) 140 _ASM_EXTABLE_UA(5b, __put_user_handle_exception) 141 _ASM_EXTABLE_UA(6b, __put_user_handle_exception) 142 _ASM_EXTABLE_UA(7b, __put_user_handle_exception) 143 _ASM_EXTABLE_UA(9b, __put_user_handle_exception) 144#ifdef CONFIG_X86_32 145 _ASM_EXTABLE_UA(8b, __put_user_handle_exception) 146 _ASM_EXTABLE_UA(10b, __put_user_handle_exception) 147#endif 148