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