Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * __put_user functions.
0004  *
0005  * (C) Copyright 2005 Linus Torvalds
0006  * (C) Copyright 2005 Andi Kleen
0007  * (C) Copyright 2008 Glauber Costa
0008  *
0009  * These functions have a non-standard call interface
0010  * to make them more efficient, especially as they
0011  * return an error value in addition to the "real"
0012  * return value.
0013  */
0014 #include <linux/linkage.h>
0015 #include <asm/thread_info.h>
0016 #include <asm/errno.h>
0017 #include <asm/asm.h>
0018 #include <asm/smap.h>
0019 #include <asm/export.h>
0020 
0021 
0022 /*
0023  * __put_user_X
0024  *
0025  * Inputs:  %eax[:%edx] contains the data
0026  *      %ecx contains the address
0027  *
0028  * Outputs: %ecx is error code (0 or -EFAULT)
0029  *
0030  * Clobbers:    %ebx needed for task pointer
0031  *
0032  * These functions should not modify any other registers,
0033  * as they get called from within inline assembly.
0034  */
0035 
0036 #ifdef CONFIG_X86_5LEVEL
0037 #define LOAD_TASK_SIZE_MINUS_N(n) \
0038     ALTERNATIVE __stringify(mov $((1 << 47) - 4096 - (n)),%rbx), \
0039             __stringify(mov $((1 << 56) - 4096 - (n)),%rbx), X86_FEATURE_LA57
0040 #else
0041 #define LOAD_TASK_SIZE_MINUS_N(n) \
0042     mov $(TASK_SIZE_MAX - (n)),%_ASM_BX
0043 #endif
0044 
0045 .text
0046 SYM_FUNC_START(__put_user_1)
0047     LOAD_TASK_SIZE_MINUS_N(0)
0048     cmp %_ASM_BX,%_ASM_CX
0049     jae .Lbad_put_user
0050 SYM_INNER_LABEL(__put_user_nocheck_1, SYM_L_GLOBAL)
0051     ENDBR
0052     ASM_STAC
0053 1:  movb %al,(%_ASM_CX)
0054     xor %ecx,%ecx
0055     ASM_CLAC
0056     RET
0057 SYM_FUNC_END(__put_user_1)
0058 EXPORT_SYMBOL(__put_user_1)
0059 EXPORT_SYMBOL(__put_user_nocheck_1)
0060 
0061 SYM_FUNC_START(__put_user_2)
0062     LOAD_TASK_SIZE_MINUS_N(1)
0063     cmp %_ASM_BX,%_ASM_CX
0064     jae .Lbad_put_user
0065 SYM_INNER_LABEL(__put_user_nocheck_2, SYM_L_GLOBAL)
0066     ENDBR
0067     ASM_STAC
0068 2:  movw %ax,(%_ASM_CX)
0069     xor %ecx,%ecx
0070     ASM_CLAC
0071     RET
0072 SYM_FUNC_END(__put_user_2)
0073 EXPORT_SYMBOL(__put_user_2)
0074 EXPORT_SYMBOL(__put_user_nocheck_2)
0075 
0076 SYM_FUNC_START(__put_user_4)
0077     LOAD_TASK_SIZE_MINUS_N(3)
0078     cmp %_ASM_BX,%_ASM_CX
0079     jae .Lbad_put_user
0080 SYM_INNER_LABEL(__put_user_nocheck_4, SYM_L_GLOBAL)
0081     ENDBR
0082     ASM_STAC
0083 3:  movl %eax,(%_ASM_CX)
0084     xor %ecx,%ecx
0085     ASM_CLAC
0086     RET
0087 SYM_FUNC_END(__put_user_4)
0088 EXPORT_SYMBOL(__put_user_4)
0089 EXPORT_SYMBOL(__put_user_nocheck_4)
0090 
0091 SYM_FUNC_START(__put_user_8)
0092     LOAD_TASK_SIZE_MINUS_N(7)
0093     cmp %_ASM_BX,%_ASM_CX
0094     jae .Lbad_put_user
0095 SYM_INNER_LABEL(__put_user_nocheck_8, SYM_L_GLOBAL)
0096     ENDBR
0097     ASM_STAC
0098 4:  mov %_ASM_AX,(%_ASM_CX)
0099 #ifdef CONFIG_X86_32
0100 5:  movl %edx,4(%_ASM_CX)
0101 #endif
0102     xor %ecx,%ecx
0103     ASM_CLAC
0104     RET
0105 SYM_FUNC_END(__put_user_8)
0106 EXPORT_SYMBOL(__put_user_8)
0107 EXPORT_SYMBOL(__put_user_nocheck_8)
0108 
0109 SYM_CODE_START_LOCAL(.Lbad_put_user_clac)
0110     ASM_CLAC
0111 .Lbad_put_user:
0112     movl $-EFAULT,%ecx
0113     RET
0114 SYM_CODE_END(.Lbad_put_user_clac)
0115 
0116     _ASM_EXTABLE_UA(1b, .Lbad_put_user_clac)
0117     _ASM_EXTABLE_UA(2b, .Lbad_put_user_clac)
0118     _ASM_EXTABLE_UA(3b, .Lbad_put_user_clac)
0119     _ASM_EXTABLE_UA(4b, .Lbad_put_user_clac)
0120 #ifdef CONFIG_X86_32
0121     _ASM_EXTABLE_UA(5b, .Lbad_put_user_clac)
0122 #endif