162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  linux/arch/arm/lib/copy_from_user.S
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Author:	Nicolas Pitre
662306a36Sopenharmony_ci *  Created:	Sep 29, 2005
762306a36Sopenharmony_ci *  Copyright:	MontaVista Software, Inc.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/linkage.h>
1162306a36Sopenharmony_ci#include <asm/assembler.h>
1262306a36Sopenharmony_ci#include <asm/unwind.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci/*
1562306a36Sopenharmony_ci * Prototype:
1662306a36Sopenharmony_ci *
1762306a36Sopenharmony_ci *	size_t arm_copy_from_user(void *to, const void *from, size_t n)
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * Purpose:
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci *	copy a block to kernel memory from user memory
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * Params:
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci *	to = kernel memory
2662306a36Sopenharmony_ci *	from = user memory
2762306a36Sopenharmony_ci *	n = number of bytes to copy
2862306a36Sopenharmony_ci *
2962306a36Sopenharmony_ci * Return value:
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci *	Number of bytes NOT copied.
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#ifdef CONFIG_CPU_USE_DOMAINS
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#ifndef CONFIG_THUMB2_KERNEL
3762306a36Sopenharmony_ci#define LDR1W_SHIFT	0
3862306a36Sopenharmony_ci#else
3962306a36Sopenharmony_ci#define LDR1W_SHIFT	1
4062306a36Sopenharmony_ci#endif
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	.macro ldr1w ptr reg abort
4362306a36Sopenharmony_ci	ldrusr	\reg, \ptr, 4, abort=\abort
4462306a36Sopenharmony_ci	.endm
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
4762306a36Sopenharmony_ci	ldr1w \ptr, \reg1, \abort
4862306a36Sopenharmony_ci	ldr1w \ptr, \reg2, \abort
4962306a36Sopenharmony_ci	ldr1w \ptr, \reg3, \abort
5062306a36Sopenharmony_ci	ldr1w \ptr, \reg4, \abort
5162306a36Sopenharmony_ci	.endm
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
5462306a36Sopenharmony_ci	ldr4w \ptr, \reg1, \reg2, \reg3, \reg4, \abort
5562306a36Sopenharmony_ci	ldr4w \ptr, \reg5, \reg6, \reg7, \reg8, \abort
5662306a36Sopenharmony_ci	.endm
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci#else
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#define LDR1W_SHIFT	0
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	.macro ldr1w ptr reg abort
6362306a36Sopenharmony_ci	USERL(\abort, W(ldr) \reg, [\ptr], #4)
6462306a36Sopenharmony_ci	.endm
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
6762306a36Sopenharmony_ci	USERL(\abort, ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4})
6862306a36Sopenharmony_ci	.endm
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
7162306a36Sopenharmony_ci	USERL(\abort, ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8})
7262306a36Sopenharmony_ci	.endm
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci#endif /* CONFIG_CPU_USE_DOMAINS */
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	.macro ldr1b ptr reg cond=al abort
7762306a36Sopenharmony_ci	ldrusr	\reg, \ptr, 1, \cond, abort=\abort
7862306a36Sopenharmony_ci	.endm
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci#define STR1W_SHIFT	0
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	.macro str1w ptr reg abort
8362306a36Sopenharmony_ci	W(str) \reg, [\ptr], #4
8462306a36Sopenharmony_ci	.endm
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
8762306a36Sopenharmony_ci	stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
8862306a36Sopenharmony_ci	.endm
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	.macro str1b ptr reg cond=al abort
9162306a36Sopenharmony_ci	strb\cond \reg, [\ptr], #1
9262306a36Sopenharmony_ci	.endm
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	.macro enter regs:vararg
9562306a36Sopenharmony_ci	mov	r3, #0
9662306a36Sopenharmony_ciUNWIND( .save	{r0, r2, r3, \regs}		)
9762306a36Sopenharmony_ci	stmdb	sp!, {r0, r2, r3, \regs}
9862306a36Sopenharmony_ci	.endm
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	.macro exit regs:vararg
10162306a36Sopenharmony_ci	add	sp, sp, #8
10262306a36Sopenharmony_ci	ldmfd	sp!, {r0, \regs}
10362306a36Sopenharmony_ci	.endm
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	.text
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ciENTRY(arm_copy_from_user)
10862306a36Sopenharmony_ci#ifdef CONFIG_CPU_SPECTRE
10962306a36Sopenharmony_ci	ldr	r3, =TASK_SIZE
11062306a36Sopenharmony_ci	uaccess_mask_range_ptr r1, r2, r3, ip
11162306a36Sopenharmony_ci#endif
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci#include "copy_template.S"
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ciENDPROC(arm_copy_from_user)
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	.pushsection .text.fixup,"ax"
11862306a36Sopenharmony_ci	.align 0
11962306a36Sopenharmony_ci	copy_abort_preamble
12062306a36Sopenharmony_ci	ldmfd	sp!, {r1, r2, r3}
12162306a36Sopenharmony_ci	sub	r0, r0, r1
12262306a36Sopenharmony_ci	rsb	r0, r0, r2
12362306a36Sopenharmony_ci	copy_abort_end
12462306a36Sopenharmony_ci	.popsection
12562306a36Sopenharmony_ci
126