1194676Sthompsa/* SPDX-License-Identifier: GPL-2.0-only */ 2194676Sthompsa/* 3194676Sthompsa * linux/arch/arm/lib/putuser.S 4194676Sthompsa * 5194676Sthompsa * Copyright (C) 2001 Russell King 6194676Sthompsa * 7194676Sthompsa * Idea from x86 version, (C) Copyright 1998 Linus Torvalds 8194676Sthompsa * 9194676Sthompsa * These functions have a non-standard call interface to make 10194676Sthompsa * them more efficient, especially as they return an error 11194676Sthompsa * value in addition to the "real" return value. 12194676Sthompsa * 13194676Sthompsa * __put_user_X 14194676Sthompsa * 15194676Sthompsa * Inputs: r0 contains the address 16194676Sthompsa * r1 contains the address limit, which must be preserved 17194676Sthompsa * r2, r3 contains the value 18194676Sthompsa * Outputs: r0 is the error code 19194676Sthompsa * lr corrupted 20194676Sthompsa * 21194676Sthompsa * No other registers must be altered. (see <asm/uaccess.h> 22194676Sthompsa * for specific ASM register usage). 23194676Sthompsa * 24194676Sthompsa * Note that ADDR_LIMIT is either 0 or 0xc0000000 25194676Sthompsa * Note also that it is intended that __put_user_bad is not global. 26194676Sthompsa */ 27194676Sthompsa#include <linux/linkage.h> 28194676Sthompsa#include <asm/assembler.h> 29194676Sthompsa#include <asm/errno.h> 30194676Sthompsa#include <asm/domain.h> 31194676Sthompsa 32194676SthompsaENTRY(__put_user_1) 33194676Sthompsa check_uaccess r0, 1, r1, ip, __put_user_bad 34194676Sthompsa1: TUSER(strb) r2, [r0] 35194676Sthompsa mov r0, #0 36194676Sthompsa ret lr 37194676SthompsaENDPROC(__put_user_1) 38194676Sthompsa 39194676SthompsaENTRY(__put_user_2) 40194676Sthompsa check_uaccess r0, 2, r1, ip, __put_user_bad 41194676Sthompsa#if __LINUX_ARM_ARCH__ >= 6 42194676Sthompsa 43194676Sthompsa2: TUSER(strh) r2, [r0] 44194676Sthompsa 45194676Sthompsa#else 46194676Sthompsa 47194676Sthompsa mov ip, r2, lsr #8 48194676Sthompsa#ifndef __ARMEB__ 49194676Sthompsa2: TUSER(strb) r2, [r0], #1 50194676Sthompsa3: TUSER(strb) ip, [r0] 51194676Sthompsa#else 52194676Sthompsa2: TUSER(strb) ip, [r0], #1 53194676Sthompsa3: TUSER(strb) r2, [r0] 54194676Sthompsa#endif 55194676Sthompsa 56194676Sthompsa#endif /* __LINUX_ARM_ARCH__ >= 6 */ 57194676Sthompsa mov r0, #0 58194676Sthompsa ret lr 59194676SthompsaENDPROC(__put_user_2) 60194676Sthompsa 61194676SthompsaENTRY(__put_user_4) 62194676Sthompsa check_uaccess r0, 4, r1, ip, __put_user_bad 63194676Sthompsa4: TUSER(str) r2, [r0] 64194676Sthompsa mov r0, #0 65194676Sthompsa ret lr 66194676SthompsaENDPROC(__put_user_4) 67194676Sthompsa 68194676SthompsaENTRY(__put_user_8) 69194676Sthompsa check_uaccess r0, 8, r1, ip, __put_user_bad 70194676Sthompsa#ifdef CONFIG_THUMB2_KERNEL 71194676Sthompsa5: TUSER(str) r2, [r0] 72194676Sthompsa6: TUSER(str) r3, [r0, #4] 73194676Sthompsa#else 74194676Sthompsa5: TUSER(str) r2, [r0], #4 75194676Sthompsa6: TUSER(str) r3, [r0] 76194676Sthompsa#endif 77194676Sthompsa mov r0, #0 78194676Sthompsa ret lr 79194676SthompsaENDPROC(__put_user_8) 80194676Sthompsa 81194676Sthompsa__put_user_bad: 82194676Sthompsa mov r0, #-EFAULT 83194676Sthompsa ret lr 84194676SthompsaENDPROC(__put_user_bad) 85194676Sthompsa 86194676Sthompsa.pushsection __ex_table, "a" 87194676Sthompsa .long 1b, __put_user_bad 88194676Sthompsa .long 2b, __put_user_bad 89194676Sthompsa#if __LINUX_ARM_ARCH__ < 6 90194676Sthompsa .long 3b, __put_user_bad 91194676Sthompsa#endif 92194676Sthompsa .long 4b, __put_user_bad 93194676Sthompsa .long 5b, __put_user_bad 94194676Sthompsa .long 6b, __put_user_bad 95194676Sthompsa.popsection 96194676Sthompsa