xref: /linux/arch/arm64/lib/copy_from_user.S (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
1caab277bSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
20aea86a2SCatalin Marinas/*
30aea86a2SCatalin Marinas * Copyright (C) 2012 ARM Ltd.
40aea86a2SCatalin Marinas */
50aea86a2SCatalin Marinas
60aea86a2SCatalin Marinas#include <linux/linkage.h>
7338d4f49SJames Morse
8b4b8664dSAl Viro#include <asm/asm-uaccess.h>
956c08ec5SMark Rutland#include <asm/assembler.h>
1056c08ec5SMark Rutland#include <asm/cache.h>
110aea86a2SCatalin Marinas
120aea86a2SCatalin Marinas/*
130aea86a2SCatalin Marinas * Copy from user space to a kernel buffer (alignment handled by the hardware)
140aea86a2SCatalin Marinas *
150aea86a2SCatalin Marinas * Parameters:
160aea86a2SCatalin Marinas *	x0 - to
170aea86a2SCatalin Marinas *	x1 - from
180aea86a2SCatalin Marinas *	x2 - n
190aea86a2SCatalin Marinas * Returns:
200aea86a2SCatalin Marinas *	x0 - bytes not copied
210aea86a2SCatalin Marinas */
2240426882SFeng Kan
23ada66f18SCatalin Marinas	.macro ldrb1 reg, ptr, val
247b90dc40SMark Rutland	user_ldst 9998f, ldtrb, \reg, \ptr, \val
2540426882SFeng Kan	.endm
2640426882SFeng Kan
27ada66f18SCatalin Marinas	.macro strb1 reg, ptr, val
28ada66f18SCatalin Marinas	strb \reg, [\ptr], \val
2940426882SFeng Kan	.endm
3040426882SFeng Kan
31ada66f18SCatalin Marinas	.macro ldrh1 reg, ptr, val
32295cf156SRobin Murphy	user_ldst 9997f, ldtrh, \reg, \ptr, \val
3340426882SFeng Kan	.endm
3440426882SFeng Kan
35ada66f18SCatalin Marinas	.macro strh1 reg, ptr, val
36ada66f18SCatalin Marinas	strh \reg, [\ptr], \val
3740426882SFeng Kan	.endm
3840426882SFeng Kan
39ada66f18SCatalin Marinas	.macro ldr1 reg, ptr, val
40295cf156SRobin Murphy	user_ldst 9997f, ldtr, \reg, \ptr, \val
4140426882SFeng Kan	.endm
4240426882SFeng Kan
43ada66f18SCatalin Marinas	.macro str1 reg, ptr, val
44ada66f18SCatalin Marinas	str \reg, [\ptr], \val
4540426882SFeng Kan	.endm
4640426882SFeng Kan
47ada66f18SCatalin Marinas	.macro ldp1 reg1, reg2, ptr, val
48295cf156SRobin Murphy	user_ldp 9997f, \reg1, \reg2, \ptr, \val
4940426882SFeng Kan	.endm
5040426882SFeng Kan
51ada66f18SCatalin Marinas	.macro stp1 reg1, reg2, ptr, val
52ada66f18SCatalin Marinas	stp \reg1, \reg2, [\ptr], \val
5340426882SFeng Kan	.endm
5440426882SFeng Kan
5540426882SFeng Kanend	.req	x5
56295cf156SRobin Murphysrcin	.req	x15
573ac0f452SMark BrownSYM_FUNC_START(__arch_copy_from_user)
5840426882SFeng Kan	add	end, x0, x2
59295cf156SRobin Murphy	mov	srcin, x1
6040426882SFeng Kan#include "copy_template.S"
6140426882SFeng Kan	mov	x0, #0				// Nothing to copy
620aea86a2SCatalin Marinas	ret
630aea86a2SCatalin Marinas
64*4012e0e2SMark Rutland	// Exception fixups
65295cf156SRobin Murphy9997:	cmp	dst, dstin
66295cf156SRobin Murphy	b.ne	9998f
67295cf156SRobin Murphy	// Before being absolutely sure we couldn't copy anything, try harder
68295cf156SRobin MurphyUSER(9998f, ldtrb tmp1w, [srcin])
69295cf156SRobin Murphy	strb	tmp1w, [dst], #1
704855bd25SAl Viro9998:	sub	x0, end, dst			// bytes not copied
710aea86a2SCatalin Marinas	ret
72*4012e0e2SMark RutlandSYM_FUNC_END(__arch_copy_from_user)
73*4012e0e2SMark RutlandEXPORT_SYMBOL(__arch_copy_from_user)
74