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