xref: /openbmc/linux/arch/riscv/lib/uaccess.S (revision e2c75e76)
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(__copy_user)
17
18	/* Enable access to user memory */
19	li t6, SR_SUM
20	csrs sstatus, 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 sstatus, 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(__copy_user)
67
68
69ENTRY(__clear_user)
70
71	/* Enable access to user memory */
72	li t6, SR_SUM
73	csrs sstatus, t6
74
75	add a3, a0, a1
76	addi t0, a0, SZREG-1
77	andi t1, a3, ~(SZREG-1)
78	andi t0, t0, ~(SZREG-1)
79	/*
80	 * a3: terminal address of target region
81	 * t0: lowest doubleword-aligned address in target region
82	 * t1: highest doubleword-aligned address in target region
83	 */
84	bgeu t0, t1, 2f
85	bltu a0, t0, 4f
861:
87	fixup REG_S, zero, (a0), 10f
88	addi a0, a0, SZREG
89	bltu a0, t1, 1b
902:
91	bltu a0, a3, 5f
92
933:
94	/* Disable access to user memory */
95	csrc sstatus, t6
96	li a0, 0
97	ret
984: /* Edge case: unalignment */
99	fixup sb, zero, (a0), 10f
100	addi a0, a0, 1
101	bltu a0, t0, 4b
102	j 1b
1035: /* Edge case: remainder */
104	fixup sb, zero, (a0), 10f
105	addi a0, a0, 1
106	bltu a0, a3, 5b
107	j 3b
108ENDPROC(__clear_user)
109
110	.section .fixup,"ax"
111	.balign 4
11210:
113	/* Disable access to user memory */
114	csrs sstatus, t6
115	sub a0, a3, a0
116	ret
117	.previous
118