1#include <linux/linkage.h>
2#include <asm/asm.h>
3#include <asm/csr.h>
4
5	.altmacro
6	.macro fixup op reg addr lbl
7	LOCAL _epc
8_epc:
9	\op \reg, \addr
10	.section __ex_table,"a"
11	.balign RISCV_SZPTR
12	RISCV_PTR _epc, \lbl
13	.previous
14	.endm
15
16ENTRY(__asm_copy_to_user)
17ENTRY(__asm_copy_from_user)
18
19	/* Enable access to user memory */
20	li t6, SR_SUM
21	csrs CSR_SSTATUS, t6
22
23	add a3, a1, a2
24	/* Use word-oriented copy only if low-order bits match */
25	andi t0, a0, SZREG-1
26	andi t1, a1, SZREG-1
27	bne t0, t1, 2f
28
29	addi t0, a1, SZREG-1
30	andi t1, a3, ~(SZREG-1)
31	andi t0, t0, ~(SZREG-1)
32	/*
33	 * a3: terminal address of source region
34	 * t0: lowest XLEN-aligned address in source
35	 * t1: highest XLEN-aligned address in source
36	 */
37	bgeu t0, t1, 2f
38	bltu a1, t0, 4f
391:
40	fixup REG_L, t2, (a1), 10f
41	fixup REG_S, t2, (a0), 10f
42	addi a1, a1, SZREG
43	addi a0, a0, SZREG
44	bltu a1, t1, 1b
452:
46	bltu a1, a3, 5f
47
483:
49	/* Disable access to user memory */
50	csrc CSR_SSTATUS, t6
51	li a0, 0
52	ret
534: /* Edge case: unalignment */
54	fixup lbu, t2, (a1), 10f
55	fixup sb, t2, (a0), 10f
56	addi a1, a1, 1
57	addi a0, a0, 1
58	bltu a1, t0, 4b
59	j 1b
605: /* Edge case: remainder */
61	fixup lbu, t2, (a1), 10f
62	fixup sb, t2, (a0), 10f
63	addi a1, a1, 1
64	addi a0, a0, 1
65	bltu a1, a3, 5b
66	j 3b
67ENDPROC(__asm_copy_to_user)
68ENDPROC(__asm_copy_from_user)
69
70
71ENTRY(__clear_user)
72
73	/* Enable access to user memory */
74	li t6, SR_SUM
75	csrs CSR_SSTATUS, t6
76
77	add a3, a0, a1
78	addi t0, a0, SZREG-1
79	andi t1, a3, ~(SZREG-1)
80	andi t0, t0, ~(SZREG-1)
81	/*
82	 * a3: terminal address of target region
83	 * t0: lowest doubleword-aligned address in target region
84	 * t1: highest doubleword-aligned address in target region
85	 */
86	bgeu t0, t1, 2f
87	bltu a0, t0, 4f
881:
89	fixup REG_S, zero, (a0), 11f
90	addi a0, a0, SZREG
91	bltu a0, t1, 1b
922:
93	bltu a0, a3, 5f
94
953:
96	/* Disable access to user memory */
97	csrc CSR_SSTATUS, t6
98	li a0, 0
99	ret
1004: /* Edge case: unalignment */
101	fixup sb, zero, (a0), 11f
102	addi a0, a0, 1
103	bltu a0, t0, 4b
104	j 1b
1055: /* Edge case: remainder */
106	fixup sb, zero, (a0), 11f
107	addi a0, a0, 1
108	bltu a0, a3, 5b
109	j 3b
110ENDPROC(__clear_user)
111
112	.section .fixup,"ax"
113	.balign 4
114	/* Fixup code for __copy_user(10) and __clear_user(11) */
11510:
116	/* Disable access to user memory */
117	csrs CSR_SSTATUS, t6
118	mv a0, a2
119	ret
12011:
121	csrs CSR_SSTATUS, t6
122	mv a0, a1
123	ret
124	.previous
125