Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-2.6-microblaze.git] / arch / riscv / lib / uaccess.S
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
7 100:
8         \op \reg, \addr
9         .section __ex_table,"a"
10         .balign RISCV_SZPTR
11         RISCV_PTR 100b, \lbl
12         .previous
13         .endm
14
15 ENTRY(__asm_copy_to_user)
16 ENTRY(__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
38 1:
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
44 2:
45         bltu a1, a3, 5f
46
47 3:
48         /* Disable access to user memory */
49         csrc CSR_STATUS, t6
50         li a0, 0
51         ret
52 4: /* 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
59 5: /* 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
66 ENDPROC(__asm_copy_to_user)
67 ENDPROC(__asm_copy_from_user)
68 EXPORT_SYMBOL(__asm_copy_to_user)
69 EXPORT_SYMBOL(__asm_copy_from_user)
70
71
72 ENTRY(__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
89 1:
90         fixup REG_S, zero, (a0), 11f
91         addi a0, a0, SZREG
92         bltu a0, t1, 1b
93 2:
94         bltu a0, a3, 5f
95
96 3:
97         /* Disable access to user memory */
98         csrc CSR_STATUS, t6
99         li a0, 0
100         ret
101 4: /* Edge case: unalignment */
102         fixup sb, zero, (a0), 11f
103         addi a0, a0, 1
104         bltu a0, t0, 4b
105         j 1b
106 5: /* Edge case: remainder */
107         fixup sb, zero, (a0), 11f
108         addi a0, a0, 1
109         bltu a0, a3, 5b
110         j 3b
111 ENDPROC(__clear_user)
112 EXPORT_SYMBOL(__clear_user)
113
114         .section .fixup,"ax"
115         .balign 4
116         /* Fixup code for __copy_user(10) and __clear_user(11) */
117 10:
118         /* Disable access to user memory */
119         csrs CSR_STATUS, t6
120         mv a0, a2
121         ret
122 11:
123         csrs CSR_STATUS, t6
124         mv a0, a1
125         ret
126         .previous