xref: /kernel/linux/linux-6.6/arch/arm/lib/putuser.S (revision 62306a36)
162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  linux/arch/arm/lib/putuser.S
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright (C) 2001 Russell King
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *  Idea from x86 version, (C) Copyright 1998 Linus Torvalds
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * These functions have a non-standard call interface to make
1062306a36Sopenharmony_ci * them more efficient, especially as they return an error
1162306a36Sopenharmony_ci * value in addition to the "real" return value.
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * __put_user_X
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * Inputs:	r0 contains the address
1662306a36Sopenharmony_ci *		r1 contains the address limit, which must be preserved
1762306a36Sopenharmony_ci *		r2, r3 contains the value
1862306a36Sopenharmony_ci * Outputs:	r0 is the error code
1962306a36Sopenharmony_ci *		lr corrupted
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci * No other registers must be altered.  (see <asm/uaccess.h>
2262306a36Sopenharmony_ci * for specific ASM register usage).
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * Note that ADDR_LIMIT is either 0 or 0xc0000000
2562306a36Sopenharmony_ci * Note also that it is intended that __put_user_bad is not global.
2662306a36Sopenharmony_ci */
2762306a36Sopenharmony_ci#include <linux/linkage.h>
2862306a36Sopenharmony_ci#include <asm/assembler.h>
2962306a36Sopenharmony_ci#include <asm/errno.h>
3062306a36Sopenharmony_ci#include <asm/domain.h>
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ciENTRY(__put_user_1)
3362306a36Sopenharmony_ci	check_uaccess r0, 1, r1, ip, __put_user_bad
3462306a36Sopenharmony_ci1: TUSER(strb)	r2, [r0]
3562306a36Sopenharmony_ci	mov	r0, #0
3662306a36Sopenharmony_ci	ret	lr
3762306a36Sopenharmony_ciENDPROC(__put_user_1)
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ciENTRY(__put_user_2)
4062306a36Sopenharmony_ci	check_uaccess r0, 2, r1, ip, __put_user_bad
4162306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 6
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci2: TUSER(strh)	r2, [r0]
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#else
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	mov	ip, r2, lsr #8
4862306a36Sopenharmony_ci#ifndef __ARMEB__
4962306a36Sopenharmony_ci2: TUSER(strb)	r2, [r0], #1
5062306a36Sopenharmony_ci3: TUSER(strb)	ip, [r0]
5162306a36Sopenharmony_ci#else
5262306a36Sopenharmony_ci2: TUSER(strb)	ip, [r0], #1
5362306a36Sopenharmony_ci3: TUSER(strb)	r2, [r0]
5462306a36Sopenharmony_ci#endif
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci#endif /* __LINUX_ARM_ARCH__ >= 6 */
5762306a36Sopenharmony_ci	mov	r0, #0
5862306a36Sopenharmony_ci	ret	lr
5962306a36Sopenharmony_ciENDPROC(__put_user_2)
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ciENTRY(__put_user_4)
6262306a36Sopenharmony_ci	check_uaccess r0, 4, r1, ip, __put_user_bad
6362306a36Sopenharmony_ci4: TUSER(str)	r2, [r0]
6462306a36Sopenharmony_ci	mov	r0, #0
6562306a36Sopenharmony_ci	ret	lr
6662306a36Sopenharmony_ciENDPROC(__put_user_4)
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ciENTRY(__put_user_8)
6962306a36Sopenharmony_ci	check_uaccess r0, 8, r1, ip, __put_user_bad
7062306a36Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL
7162306a36Sopenharmony_ci5: TUSER(str)	r2, [r0]
7262306a36Sopenharmony_ci6: TUSER(str)	r3, [r0, #4]
7362306a36Sopenharmony_ci#else
7462306a36Sopenharmony_ci5: TUSER(str)	r2, [r0], #4
7562306a36Sopenharmony_ci6: TUSER(str)	r3, [r0]
7662306a36Sopenharmony_ci#endif
7762306a36Sopenharmony_ci	mov	r0, #0
7862306a36Sopenharmony_ci	ret	lr
7962306a36Sopenharmony_ciENDPROC(__put_user_8)
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci__put_user_bad:
8262306a36Sopenharmony_ci	mov	r0, #-EFAULT
8362306a36Sopenharmony_ci	ret	lr
8462306a36Sopenharmony_ciENDPROC(__put_user_bad)
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci.pushsection __ex_table, "a"
8762306a36Sopenharmony_ci	.long	1b, __put_user_bad
8862306a36Sopenharmony_ci	.long	2b, __put_user_bad
8962306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ < 6
9062306a36Sopenharmony_ci	.long	3b, __put_user_bad
9162306a36Sopenharmony_ci#endif
9262306a36Sopenharmony_ci	.long	4b, __put_user_bad
9362306a36Sopenharmony_ci	.long	5b, __put_user_bad
9462306a36Sopenharmony_ci	.long	6b, __put_user_bad
9562306a36Sopenharmony_ci.popsection
96