xref: /openbmc/linux/arch/riscv/lib/uaccess.S (revision dc6a81c3)
1#include <linux/linkage.h>
2#include <asm-generic/export.h>
3#include <asm/asm.h>
4#include <asm/csr.h>
5
6	.altmacro
7	.macro fixup op reg addr lbl
8	LOCAL _epc
9_epc:
10	\op \reg, \addr
11	.section __ex_table,"a"
12	.balign RISCV_SZPTR
13	RISCV_PTR _epc, \lbl
14	.previous
15	.endm
16
17ENTRY(__asm_copy_to_user)
18ENTRY(__asm_copy_from_user)
19
20	/* Enable access to user memory */
21	li t6, SR_SUM
22	csrs CSR_STATUS, t6
23
24	add a3, a1, a2
25	/* Use word-oriented copy only if low-order bits match */
26	andi t0, a0, SZREG-1
27	andi t1, a1, SZREG-1
28	bne t0, t1, 2f
29
30	addi t0, a1, SZREG-1
31	andi t1, a3, ~(SZREG-1)
32	andi t0, t0, ~(SZREG-1)
33	/*
34	 * a3: terminal address of source region
35	 * t0: lowest XLEN-aligned address in source
36	 * t1: highest XLEN-aligned address in source
37	 */
38	bgeu t0, t1, 2f
39	bltu a1, t0, 4f
401:
41	fixup REG_L, t2, (a1), 10f
42	fixup REG_S, t2, (a0), 10f
43	addi a1, a1, SZREG
44	addi a0, a0, SZREG
45	bltu a1, t1, 1b
462:
47	bltu a1, a3, 5f
48
493:
50	/* Disable access to user memory */
51	csrc CSR_STATUS, t6
52	li a0, 0
53	ret
544: /* Edge case: unalignment */
55	fixup lbu, t2, (a1), 10f
56	fixup sb, t2, (a0), 10f
57	addi a1, a1, 1
58	addi a0, a0, 1
59	bltu a1, t0, 4b
60	j 1b
615: /* Edge case: remainder */
62	fixup lbu, t2, (a1), 10f
63	fixup sb, t2, (a0), 10f
64	addi a1, a1, 1
65	addi a0, a0, 1
66	bltu a1, a3, 5b
67	j 3b
68ENDPROC(__asm_copy_to_user)
69ENDPROC(__asm_copy_from_user)
70EXPORT_SYMBOL(__asm_copy_to_user)
71EXPORT_SYMBOL(__asm_copy_from_user)
72
73
74ENTRY(__clear_user)
75
76	/* Enable access to user memory */
77	li t6, SR_SUM
78	csrs CSR_STATUS, t6
79
80	add a3, a0, a1
81	addi t0, a0, SZREG-1
82	andi t1, a3, ~(SZREG-1)
83	andi t0, t0, ~(SZREG-1)
84	/*
85	 * a3: terminal address of target region
86	 * t0: lowest doubleword-aligned address in target region
87	 * t1: highest doubleword-aligned address in target region
88	 */
89	bgeu t0, t1, 2f
90	bltu a0, t0, 4f
911:
92	fixup REG_S, zero, (a0), 11f
93	addi a0, a0, SZREG
94	bltu a0, t1, 1b
952:
96	bltu a0, a3, 5f
97
983:
99	/* Disable access to user memory */
100	csrc CSR_STATUS, t6
101	li a0, 0
102	ret
1034: /* Edge case: unalignment */
104	fixup sb, zero, (a0), 11f
105	addi a0, a0, 1
106	bltu a0, t0, 4b
107	j 1b
1085: /* Edge case: remainder */
109	fixup sb, zero, (a0), 11f
110	addi a0, a0, 1
111	bltu a0, a3, 5b
112	j 3b
113ENDPROC(__clear_user)
114EXPORT_SYMBOL(__clear_user)
115
116	.section .fixup,"ax"
117	.balign 4
118	/* Fixup code for __copy_user(10) and __clear_user(11) */
11910:
120	/* Disable access to user memory */
121	csrs CSR_STATUS, t6
122	mv a0, a2
123	ret
12411:
125	csrs CSR_STATUS, t6
126	mv a0, a1
127	ret
128	.previous
129