xref: /openbmc/linux/arch/arm/lib/copy_to_user.S (revision c67e8ec0)
1/*
2 *  linux/arch/arm/lib/copy_to_user.S
3 *
4 *  Author:	Nicolas Pitre
5 *  Created:	Sep 29, 2005
6 *  Copyright:	MontaVista Software, Inc.
7 *
8 *  This program is free software; you can redistribute it and/or modify
9 *  it under the terms of the GNU General Public License version 2 as
10 *  published by the Free Software Foundation.
11 */
12
13#include <linux/linkage.h>
14#include <asm/assembler.h>
15#include <asm/unwind.h>
16
17/*
18 * Prototype:
19 *
20 *	size_t arm_copy_to_user(void *to, const void *from, size_t n)
21 *
22 * Purpose:
23 *
24 *	copy a block to user memory from kernel memory
25 *
26 * Params:
27 *
28 *	to = user memory
29 *	from = kernel memory
30 *	n = number of bytes to copy
31 *
32 * Return value:
33 *
34 *	Number of bytes NOT copied.
35 */
36
37#define LDR1W_SHIFT	0
38
39	.macro ldr1w ptr reg abort
40	W(ldr) \reg, [\ptr], #4
41	.endm
42
43	.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
44	ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4}
45	.endm
46
47	.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
48	ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
49	.endm
50
51	.macro ldr1b ptr reg cond=al abort
52	ldr\cond\()b \reg, [\ptr], #1
53	.endm
54
55#ifdef CONFIG_CPU_USE_DOMAINS
56
57#ifndef CONFIG_THUMB2_KERNEL
58#define STR1W_SHIFT	0
59#else
60#define STR1W_SHIFT	1
61#endif
62
63	.macro str1w ptr reg abort
64	strusr	\reg, \ptr, 4, abort=\abort
65	.endm
66
67	.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
68	str1w \ptr, \reg1, \abort
69	str1w \ptr, \reg2, \abort
70	str1w \ptr, \reg3, \abort
71	str1w \ptr, \reg4, \abort
72	str1w \ptr, \reg5, \abort
73	str1w \ptr, \reg6, \abort
74	str1w \ptr, \reg7, \abort
75	str1w \ptr, \reg8, \abort
76	.endm
77
78#else
79
80#define STR1W_SHIFT	0
81
82	.macro str1w ptr reg abort
83	USERL(\abort, W(str) \reg, [\ptr], #4)
84	.endm
85
86	.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
87	USERL(\abort, stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8})
88	.endm
89
90#endif /* CONFIG_CPU_USE_DOMAINS */
91
92	.macro str1b ptr reg cond=al abort
93	strusr	\reg, \ptr, 1, \cond, abort=\abort
94	.endm
95
96	.macro enter reg1 reg2
97	mov	r3, #0
98	stmdb	sp!, {r0, r2, r3, \reg1, \reg2}
99	.endm
100
101	.macro usave reg1 reg2
102	UNWIND(	.save {r0, r2, r3, \reg1, \reg2}	)
103	.endm
104
105	.macro exit reg1 reg2
106	add	sp, sp, #8
107	ldmfd	sp!, {r0, \reg1, \reg2}
108	.endm
109
110	.text
111
112ENTRY(__copy_to_user_std)
113WEAK(arm_copy_to_user)
114#ifdef CONFIG_CPU_SPECTRE
115	get_thread_info r3
116	ldr	r3, [r3, #TI_ADDR_LIMIT]
117	uaccess_mask_range_ptr r0, r2, r3, ip
118#endif
119
120#include "copy_template.S"
121
122ENDPROC(arm_copy_to_user)
123ENDPROC(__copy_to_user_std)
124
125	.pushsection .text.fixup,"ax"
126	.align 0
127	copy_abort_preamble
128	ldmfd	sp!, {r1, r2, r3}
129	sub	r0, r0, r1
130	rsb	r0, r0, r2
131	copy_abort_end
132	.popsection
133