1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */ 25cbbc3b1SGlauber Costa/* 35cbbc3b1SGlauber Costa * __put_user functions. 45cbbc3b1SGlauber Costa * 55cbbc3b1SGlauber Costa * (C) Copyright 2005 Linus Torvalds 65cbbc3b1SGlauber Costa * (C) Copyright 2005 Andi Kleen 75cbbc3b1SGlauber Costa * (C) Copyright 2008 Glauber Costa 85cbbc3b1SGlauber Costa * 95cbbc3b1SGlauber Costa * These functions have a non-standard call interface 105cbbc3b1SGlauber Costa * to make them more efficient, especially as they 115cbbc3b1SGlauber Costa * return an error value in addition to the "real" 125cbbc3b1SGlauber Costa * return value. 135cbbc3b1SGlauber Costa */ 145cbbc3b1SGlauber Costa#include <linux/linkage.h> 155cbbc3b1SGlauber Costa#include <asm/thread_info.h> 165cbbc3b1SGlauber Costa#include <asm/errno.h> 175cbbc3b1SGlauber Costa#include <asm/asm.h> 1863bcff2aSH. Peter Anvin#include <asm/smap.h> 19784d5699SAl Viro#include <asm/export.h> 205cbbc3b1SGlauber Costa 215cbbc3b1SGlauber Costa 225cbbc3b1SGlauber Costa/* 235cbbc3b1SGlauber Costa * __put_user_X 245cbbc3b1SGlauber Costa * 255cbbc3b1SGlauber Costa * Inputs: %eax[:%edx] contains the data 265cbbc3b1SGlauber Costa * %ecx contains the address 275cbbc3b1SGlauber Costa * 28d55564cfSLinus Torvalds * Outputs: %ecx is error code (0 or -EFAULT) 29d55564cfSLinus Torvalds * 30d55564cfSLinus Torvalds * Clobbers: %ebx needed for task pointer 315cbbc3b1SGlauber Costa * 325cbbc3b1SGlauber Costa * These functions should not modify any other registers, 335cbbc3b1SGlauber Costa * as they get called from within inline assembly. 345cbbc3b1SGlauber Costa */ 355cbbc3b1SGlauber Costa 36b19b74bcSKirill A. Shutemov.macro check_range size:req 37b19b74bcSKirill A. Shutemov.if IS_ENABLED(CONFIG_X86_64) 38b19b74bcSKirill A. Shutemov mov %rcx, %rbx 39b19b74bcSKirill A. Shutemov sar $63, %rbx 40b19b74bcSKirill A. Shutemov or %rbx, %rcx 41b19b74bcSKirill A. Shutemov.else 42b19b74bcSKirill A. Shutemov cmp $TASK_SIZE_MAX-\size+1, %ecx 43b19b74bcSKirill A. Shutemov jae .Lbad_put_user 44b19b74bcSKirill A. Shutemov.endif 45b19b74bcSKirill A. Shutemov.endm 465cbbc3b1SGlauber Costa 475cbbc3b1SGlauber Costa.text 486dcc5627SJiri SlabySYM_FUNC_START(__put_user_1) 49b19b74bcSKirill A. Shutemov check_range size=1 5063bcff2aSH. Peter Anvin ASM_STAC 515cbbc3b1SGlauber Costa1: movb %al,(%_ASM_CX) 52d55564cfSLinus Torvalds xor %ecx,%ecx 5382e844a6SJosh Poimboeuf ASM_CLAC 54f94909ceSPeter Zijlstra RET 556dcc5627SJiri SlabySYM_FUNC_END(__put_user_1) 56784d5699SAl ViroEXPORT_SYMBOL(__put_user_1) 57cb855971SThomas Gleixner 58cb855971SThomas GleixnerSYM_FUNC_START(__put_user_nocheck_1) 59cb855971SThomas Gleixner ASM_STAC 60cb855971SThomas Gleixner2: movb %al,(%_ASM_CX) 61cb855971SThomas Gleixner xor %ecx,%ecx 62cb855971SThomas Gleixner ASM_CLAC 63cb855971SThomas Gleixner RET 64cb855971SThomas GleixnerSYM_FUNC_END(__put_user_nocheck_1) 65d55564cfSLinus TorvaldsEXPORT_SYMBOL(__put_user_nocheck_1) 665cbbc3b1SGlauber Costa 676dcc5627SJiri SlabySYM_FUNC_START(__put_user_2) 68b19b74bcSKirill A. Shutemov check_range size=2 6963bcff2aSH. Peter Anvin ASM_STAC 70cb855971SThomas Gleixner3: movw %ax,(%_ASM_CX) 71d55564cfSLinus Torvalds xor %ecx,%ecx 7282e844a6SJosh Poimboeuf ASM_CLAC 73f94909ceSPeter Zijlstra RET 746dcc5627SJiri SlabySYM_FUNC_END(__put_user_2) 75784d5699SAl ViroEXPORT_SYMBOL(__put_user_2) 76cb855971SThomas Gleixner 77cb855971SThomas GleixnerSYM_FUNC_START(__put_user_nocheck_2) 78cb855971SThomas Gleixner ASM_STAC 79cb855971SThomas Gleixner4: movw %ax,(%_ASM_CX) 80cb855971SThomas Gleixner xor %ecx,%ecx 81cb855971SThomas Gleixner ASM_CLAC 82cb855971SThomas Gleixner RET 83cb855971SThomas GleixnerSYM_FUNC_END(__put_user_nocheck_2) 84d55564cfSLinus TorvaldsEXPORT_SYMBOL(__put_user_nocheck_2) 855cbbc3b1SGlauber Costa 866dcc5627SJiri SlabySYM_FUNC_START(__put_user_4) 87b19b74bcSKirill A. Shutemov check_range size=4 8863bcff2aSH. Peter Anvin ASM_STAC 89cb855971SThomas Gleixner5: movl %eax,(%_ASM_CX) 90d55564cfSLinus Torvalds xor %ecx,%ecx 9182e844a6SJosh Poimboeuf ASM_CLAC 92f94909ceSPeter Zijlstra RET 936dcc5627SJiri SlabySYM_FUNC_END(__put_user_4) 94784d5699SAl ViroEXPORT_SYMBOL(__put_user_4) 95cb855971SThomas Gleixner 96cb855971SThomas GleixnerSYM_FUNC_START(__put_user_nocheck_4) 97cb855971SThomas Gleixner ASM_STAC 98cb855971SThomas Gleixner6: movl %eax,(%_ASM_CX) 99cb855971SThomas Gleixner xor %ecx,%ecx 100cb855971SThomas Gleixner ASM_CLAC 101cb855971SThomas Gleixner RET 102cb855971SThomas GleixnerSYM_FUNC_END(__put_user_nocheck_4) 103d55564cfSLinus TorvaldsEXPORT_SYMBOL(__put_user_nocheck_4) 1045cbbc3b1SGlauber Costa 1056dcc5627SJiri SlabySYM_FUNC_START(__put_user_8) 106b19b74bcSKirill A. Shutemov check_range size=8 10763bcff2aSH. Peter Anvin ASM_STAC 108cb855971SThomas Gleixner7: mov %_ASM_AX,(%_ASM_CX) 1095cbbc3b1SGlauber Costa#ifdef CONFIG_X86_32 110cb855971SThomas Gleixner8: movl %edx,4(%_ASM_CX) 1115cbbc3b1SGlauber Costa#endif 112d55564cfSLinus Torvalds xor %ecx,%ecx 11382e844a6SJosh Poimboeuf ASM_CLAC 11482e844a6SJosh Poimboeuf RET 1156dcc5627SJiri SlabySYM_FUNC_END(__put_user_8) 116784d5699SAl ViroEXPORT_SYMBOL(__put_user_8) 117cb855971SThomas Gleixner 118cb855971SThomas GleixnerSYM_FUNC_START(__put_user_nocheck_8) 119cb855971SThomas Gleixner ASM_STAC 120cb855971SThomas Gleixner9: mov %_ASM_AX,(%_ASM_CX) 121cb855971SThomas Gleixner#ifdef CONFIG_X86_32 122cb855971SThomas Gleixner10: movl %edx,4(%_ASM_CX) 123cb855971SThomas Gleixner#endif 124cb855971SThomas Gleixner xor %ecx,%ecx 125cb855971SThomas Gleixner ASM_CLAC 126cb855971SThomas Gleixner RET 127cb855971SThomas GleixnerSYM_FUNC_END(__put_user_nocheck_8) 128d55564cfSLinus TorvaldsEXPORT_SYMBOL(__put_user_nocheck_8) 1295cbbc3b1SGlauber Costa 1305516c89dSNadav AmitSYM_CODE_START_LOCAL(__put_user_handle_exception) 13182e844a6SJosh Poimboeuf ASM_CLAC 13298ededb6SJiri Slaby.Lbad_put_user: 133d55564cfSLinus Torvalds movl $-EFAULT,%ecx 13482e844a6SJosh Poimboeuf RET 1355516c89dSNadav AmitSYM_CODE_END(__put_user_handle_exception) 1365cbbc3b1SGlauber Costa 137*2aed1b6cSQiuxu Zhuo _ASM_EXTABLE_UA(1b, __put_user_handle_exception) 138*2aed1b6cSQiuxu Zhuo _ASM_EXTABLE_UA(2b, __put_user_handle_exception) 139*2aed1b6cSQiuxu Zhuo _ASM_EXTABLE_UA(3b, __put_user_handle_exception) 140*2aed1b6cSQiuxu Zhuo _ASM_EXTABLE_UA(4b, __put_user_handle_exception) 141*2aed1b6cSQiuxu Zhuo _ASM_EXTABLE_UA(5b, __put_user_handle_exception) 142*2aed1b6cSQiuxu Zhuo _ASM_EXTABLE_UA(6b, __put_user_handle_exception) 143*2aed1b6cSQiuxu Zhuo _ASM_EXTABLE_UA(7b, __put_user_handle_exception) 144*2aed1b6cSQiuxu Zhuo _ASM_EXTABLE_UA(9b, __put_user_handle_exception) 145cb855971SThomas Gleixner#ifdef CONFIG_X86_32 146*2aed1b6cSQiuxu Zhuo _ASM_EXTABLE_UA(8b, __put_user_handle_exception) 147*2aed1b6cSQiuxu Zhuo _ASM_EXTABLE_UA(10b, __put_user_handle_exception) 1485cbbc3b1SGlauber Costa#endif 149