xref: /openbmc/linux/arch/loongarch/lib/copy_user.S (revision f3531d1a)
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4 */
5
6#include <asm/alternative-asm.h>
7#include <asm/asm.h>
8#include <asm/asmmacro.h>
9#include <asm/asm-extable.h>
10#include <asm/cpu.h>
11#include <asm/export.h>
12#include <asm/regdef.h>
13
14.irp to, 0, 1, 2, 3, 4, 5, 6, 7
15.L_fixup_handle_\to\():
16	addi.d	a0, a2, (\to) * (-8)
17	jr	ra
18.endr
19
20SYM_FUNC_START(__copy_user)
21	/*
22	 * Some CPUs support hardware unaligned access
23	 */
24	ALTERNATIVE	"b __copy_user_generic",	\
25			"b __copy_user_fast", CPU_FEATURE_UAL
26SYM_FUNC_END(__copy_user)
27
28EXPORT_SYMBOL(__copy_user)
29
30/*
31 * unsigned long __copy_user_generic(void *to, const void *from, size_t n)
32 *
33 * a0: to
34 * a1: from
35 * a2: n
36 */
37SYM_FUNC_START(__copy_user_generic)
38	beqz	a2, 3f
39
401:	ld.b	t0, a1, 0
412:	st.b	t0, a0, 0
42	addi.d	a0, a0, 1
43	addi.d	a1, a1, 1
44	addi.d	a2, a2, -1
45	bgtz	a2, 1b
46
473:	move	a0, a2
48	jr	ra
49
50	_asm_extable 1b, .L_fixup_handle_0
51	_asm_extable 2b, .L_fixup_handle_0
52SYM_FUNC_END(__copy_user_generic)
53
54/*
55 * unsigned long __copy_user_fast(void *to, const void *from, unsigned long n)
56 *
57 * a0: to
58 * a1: from
59 * a2: n
60 */
61SYM_FUNC_START(__copy_user_fast)
62	beqz	a2, 19f
63
64	ori	a3, zero, 64
65	blt	a2, a3, 17f
66
67	/* copy 64 bytes at a time */
681:	ld.d	t0, a1, 0
692:	ld.d	t1, a1, 8
703:	ld.d	t2, a1, 16
714:	ld.d	t3, a1, 24
725:	ld.d	t4, a1, 32
736:	ld.d	t5, a1, 40
747:	ld.d	t6, a1, 48
758:	ld.d	t7, a1, 56
769:	st.d	t0, a0, 0
7710:	st.d	t1, a0, 8
7811:	st.d	t2, a0, 16
7912:	st.d	t3, a0, 24
8013:	st.d	t4, a0, 32
8114:	st.d	t5, a0, 40
8215:	st.d	t6, a0, 48
8316:	st.d	t7, a0, 56
84
85	addi.d	a0, a0, 64
86	addi.d	a1, a1, 64
87	addi.d	a2, a2, -64
88	bge	a2, a3, 1b
89
90	beqz	a2, 19f
91
92	/* copy the remaining bytes */
9317:	ld.b	t0, a1, 0
9418:	st.b	t0, a0, 0
95	addi.d	a0, a0, 1
96	addi.d	a1, a1, 1
97	addi.d	a2, a2, -1
98	bgt	a2, zero, 17b
99
100	/* return */
10119:	move	a0, a2
102	jr	ra
103
104	/* fixup and ex_table */
105	_asm_extable 1b, .L_fixup_handle_0
106	_asm_extable 2b, .L_fixup_handle_1
107	_asm_extable 3b, .L_fixup_handle_2
108	_asm_extable 4b, .L_fixup_handle_3
109	_asm_extable 5b, .L_fixup_handle_4
110	_asm_extable 6b, .L_fixup_handle_5
111	_asm_extable 7b, .L_fixup_handle_6
112	_asm_extable 8b, .L_fixup_handle_7
113	_asm_extable 9b, .L_fixup_handle_0
114	_asm_extable 10b, .L_fixup_handle_1
115	_asm_extable 11b, .L_fixup_handle_2
116	_asm_extable 12b, .L_fixup_handle_3
117	_asm_extable 13b, .L_fixup_handle_4
118	_asm_extable 14b, .L_fixup_handle_5
119	_asm_extable 15b, .L_fixup_handle_6
120	_asm_extable 16b, .L_fixup_handle_7
121	_asm_extable 17b, .L_fixup_handle_0
122	_asm_extable 18b, .L_fixup_handle_0
123SYM_FUNC_END(__copy_user_fast)
124