Merge branch 'for-4.19/upstream' into for-linus
[sfrench/cifs-2.6.git] / arch / riscv / lib / uaccess.S
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
16 ENTRY(__asm_copy_to_user)
17 ENTRY(__asm_copy_from_user)
18
19         /* Enable access to user memory */
20         li t6, SR_SUM
21         csrs 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
39 1:
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
45 2:
46         bltu a1, a3, 5f
47
48 3:
49         /* Disable access to user memory */
50         csrc sstatus, t6
51         li a0, 0
52         ret
53 4: /* 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
60 5: /* 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
67 ENDPROC(__asm_copy_to_user)
68 ENDPROC(__asm_copy_from_user)
69
70
71 ENTRY(__clear_user)
72
73         /* Enable access to user memory */
74         li t6, SR_SUM
75         csrs 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
88 1:
89         fixup REG_S, zero, (a0), 11f
90         addi a0, a0, SZREG
91         bltu a0, t1, 1b
92 2:
93         bltu a0, a3, 5f
94
95 3:
96         /* Disable access to user memory */
97         csrc sstatus, t6
98         li a0, 0
99         ret
100 4: /* Edge case: unalignment */
101         fixup sb, zero, (a0), 11f
102         addi a0, a0, 1
103         bltu a0, t0, 4b
104         j 1b
105 5: /* Edge case: remainder */
106         fixup sb, zero, (a0), 11f
107         addi a0, a0, 1
108         bltu a0, a3, 5b
109         j 3b
110 ENDPROC(__clear_user)
111
112         .section .fixup,"ax"
113         .balign 4
114         /* Fixup code for __copy_user(10) and __clear_user(11) */
115 10:
116         /* Disable access to user memory */
117         csrs sstatus, t6
118         mv a0, a2
119         ret
120 11:
121         csrs sstatus, t6
122         mv a0, a1
123         ret
124         .previous