xref: /openbmc/linux/arch/riscv/lib/uaccess.S (revision bef7a78d)
1#include <linux/linkage.h>
2#include <asm-generic/export.h>
3#include <asm/asm.h>
4#include <asm/csr.h>
5
6	.macro fixup op reg addr lbl
7100:
8	\op \reg, \addr
9	.section __ex_table,"a"
10	.balign RISCV_SZPTR
11	RISCV_PTR 100b, \lbl
12	.previous
13	.endm
14
15ENTRY(__asm_copy_to_user)
16ENTRY(__asm_copy_from_user)
17
18	/* Enable access to user memory */
19	li t6, SR_SUM
20	csrs CSR_STATUS, t6
21
22	add a3, a1, a2
23	/* Use word-oriented copy only if low-order bits match */
24	andi t0, a0, SZREG-1
25	andi t1, a1, SZREG-1
26	bne t0, t1, 2f
27
28	addi t0, a1, SZREG-1
29	andi t1, a3, ~(SZREG-1)
30	andi t0, t0, ~(SZREG-1)
31	/*
32	 * a3: terminal address of source region
33	 * t0: lowest XLEN-aligned address in source
34	 * t1: highest XLEN-aligned address in source
35	 */
36	bgeu t0, t1, 2f
37	bltu a1, t0, 4f
381:
39	fixup REG_L, t2, (a1), 10f
40	fixup REG_S, t2, (a0), 10f
41	addi a1, a1, SZREG
42	addi a0, a0, SZREG
43	bltu a1, t1, 1b
442:
45	bltu a1, a3, 5f
46
473:
48	/* Disable access to user memory */
49	csrc CSR_STATUS, t6
50	li a0, 0
51	ret
524: /* Edge case: unalignment */
53	fixup lbu, t2, (a1), 10f
54	fixup sb, t2, (a0), 10f
55	addi a1, a1, 1
56	addi a0, a0, 1
57	bltu a1, t0, 4b
58	j 1b
595: /* Edge case: remainder */
60	fixup lbu, t2, (a1), 10f
61	fixup sb, t2, (a0), 10f
62	addi a1, a1, 1
63	addi a0, a0, 1
64	bltu a1, a3, 5b
65	j 3b
66ENDPROC(__asm_copy_to_user)
67ENDPROC(__asm_copy_from_user)
68EXPORT_SYMBOL(__asm_copy_to_user)
69EXPORT_SYMBOL(__asm_copy_from_user)
70
71
72ENTRY(__clear_user)
73
74	/* Enable access to user memory */
75	li t6, SR_SUM
76	csrs CSR_STATUS, t6
77
78	add a3, a0, a1
79	addi t0, a0, SZREG-1
80	andi t1, a3, ~(SZREG-1)
81	andi t0, t0, ~(SZREG-1)
82	/*
83	 * a3: terminal address of target region
84	 * t0: lowest doubleword-aligned address in target region
85	 * t1: highest doubleword-aligned address in target region
86	 */
87	bgeu t0, t1, 2f
88	bltu a0, t0, 4f
891:
90	fixup REG_S, zero, (a0), 11f
91	addi a0, a0, SZREG
92	bltu a0, t1, 1b
932:
94	bltu a0, a3, 5f
95
963:
97	/* Disable access to user memory */
98	csrc CSR_STATUS, t6
99	li a0, 0
100	ret
1014: /* Edge case: unalignment */
102	fixup sb, zero, (a0), 11f
103	addi a0, a0, 1
104	bltu a0, t0, 4b
105	j 1b
1065: /* Edge case: remainder */
107	fixup sb, zero, (a0), 11f
108	addi a0, a0, 1
109	bltu a0, a3, 5b
110	j 3b
111ENDPROC(__clear_user)
112EXPORT_SYMBOL(__clear_user)
113
114	.section .fixup,"ax"
115	.balign 4
116	/* Fixup code for __copy_user(10) and __clear_user(11) */
11710:
118	/* Disable access to user memory */
119	csrs CSR_STATUS, t6
120	mv a0, a2
121	ret
12211:
123	csrs CSR_STATUS, t6
124	mv a0, a1
125	ret
126	.previous
127