xref: /openbmc/linux/arch/x86/lib/putuser.S (revision 695c312ec5a68e4373d063ee649c7b925ffb5da7)
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