]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/riscv/riscv/support.S
MFV r326007: less v529.
[FreeBSD/FreeBSD.git] / sys / riscv / riscv / support.S
1 /*-
2  * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
3  * All rights reserved.
4  *
5  * Portions of this software were developed by SRI International and the
6  * University of Cambridge Computer Laboratory under DARPA/AFRL contract
7  * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
8  *
9  * Portions of this software were developed by the University of Cambridge
10  * Computer Laboratory as part of the CTSRD Project, with support from the
11  * UK Higher Education Innovation Fund (HEIF).
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 #include <machine/asm.h>
36 __FBSDID("$FreeBSD$");
37
38 #include <machine/setjmp.h>
39
40 #include "assym.s"
41
42 /*
43  * One of the fu* or su* functions failed, return -1.
44  */
45 ENTRY(fsu_fault)
46         SET_FAULT_HANDLER(x0, a1)       /* Reset the handler function */
47 fsu_fault_nopcb:
48         li      a0, -1
49         ret
50 END(fsu_fault)
51
52 /*
53  * int casueword32(volatile uint32_t *, uint32_t, uint32_t *, uint32_t)
54  */
55 ENTRY(casueword32)
56         li      a4, (VM_MAXUSER_ADDRESS-3)
57         bgt     a0, a4, fsu_fault_nopcb
58         la      a6, fsu_fault           /* Load the fault handler */
59         SET_FAULT_HANDLER(a6, a4)       /* And set it */
60 1:      lr.w    a4, 0(a0)               /* Load-exclusive the data */
61         bne     a4, a1, 2f              /* If not equal then exit */
62         sc.w    a5, a3, 0(a0)           /* Store the new data */
63         bnez    a5, 1b                  /* Retry on failure */
64 2:      SET_FAULT_HANDLER(x0, a5)       /* Reset the fault handler */
65         sw      a4, 0(a2)               /* Store the read data */
66         li      a0, 0                   /* Success */
67         ret                             /* Return */
68 END(casueword32)
69
70 /*
71  * int casueword(volatile u_long *, u_long, u_long *, u_long)
72  */
73 ENTRY(casueword)
74         li      a4, (VM_MAXUSER_ADDRESS-7)
75         bgt     a0, a4, fsu_fault_nopcb
76         la      a6, fsu_fault           /* Load the fault handler */
77         SET_FAULT_HANDLER(a6, a4)       /* And set it */
78 1:      lr.d    a4, 0(a0)               /* Load-exclusive the data */
79         bne     a4, a1, 2f              /* If not equal then exit */
80         sc.d    a5, a3, 0(a0)           /* Store the new data */
81         bnez    a5, 1b                  /* Retry on failure */
82 2:      SET_FAULT_HANDLER(x0, a5)       /* Reset the fault handler */
83         sd      a4, 0(a2)               /* Store the read data */
84         li      a0, 0                   /* Success */
85         ret                             /* Return */
86 END(casueword)
87
88 /*
89  * int fubyte(volatile const void *)
90  */
91 ENTRY(fubyte)
92         li      a1, VM_MAXUSER_ADDRESS
93         bgt     a0, a1, fsu_fault_nopcb
94         la      a6, fsu_fault           /* Load the fault handler */
95         SET_FAULT_HANDLER(a6, a1)       /* And set it */
96         lb      a0, 0(a0)               /* Try loading the data */
97         SET_FAULT_HANDLER(x0, a1)       /* Reset the fault handler */
98         ret                             /* Return */
99 END(fubyte)
100
101 /*
102  * int fuword(volatile const void *)
103  */
104 ENTRY(fuword16)
105         li      a1, (VM_MAXUSER_ADDRESS-1)
106         bgt     a0, a1, fsu_fault_nopcb
107         la      a6, fsu_fault           /* Load the fault handler */
108         SET_FAULT_HANDLER(a6, a1)       /* And set it */
109         lh      a0, 0(a0)               /* Try loading the data */
110         SET_FAULT_HANDLER(x0, a1)       /* Reset the fault handler */
111         ret                             /* Return */
112 END(fuword16)
113
114 /*
115  * int32_t fueword32(volatile const void *, int32_t *)
116  */
117 ENTRY(fueword32)
118         li      a2, (VM_MAXUSER_ADDRESS-3)
119         bgt     a0, a2, fsu_fault_nopcb
120         la      a6, fsu_fault           /* Load the fault handler */
121         SET_FAULT_HANDLER(a6, a2)       /* And set it */
122         lw      a0, 0(a0)               /* Try loading the data */
123         SET_FAULT_HANDLER(x0, a2)       /* Reset the fault handler */
124         sw      a0, 0(a1)               /* Save the data in kernel space */
125         li      a0, 0                   /* Success */
126         ret                             /* Return */
127 END(fueword32)
128
129 /*
130  * long fueword(volatile const void *, int64_t *)
131  * int64_t fueword64(volatile const void *, int64_t *)
132  */
133 ENTRY(fueword)
134 EENTRY(fueword64)
135         li      a2, (VM_MAXUSER_ADDRESS-7)
136         bgt     a0, a2, fsu_fault_nopcb
137         la      a6, fsu_fault           /* Load the fault handler */
138         SET_FAULT_HANDLER(a6, a2)       /* And set it */
139         ld      a0, 0(a0)               /* Try loading the data */
140         SET_FAULT_HANDLER(x0, a2)       /* Reset the fault handler */
141         sd      a0, 0(a1)               /* Save the data in kernel space */
142         li      a0, 0                   /* Success */
143         ret                             /* Return */
144 EEND(fueword64)
145 END(fueword)
146
147 /*
148  * int subyte(volatile void *, int)
149  */
150 ENTRY(subyte)
151         li      a2, VM_MAXUSER_ADDRESS
152         bgt     a0, a2, fsu_fault_nopcb
153         la      a6, fsu_fault           /* Load the fault handler */
154         SET_FAULT_HANDLER(a6, a2)       /* And set it */
155         sb      a1, 0(a0)               /* Try storing the data */
156         SET_FAULT_HANDLER(x0, a2)       /* Reset the fault handler */
157         li      a0, 0                   /* Success */
158         ret                             /* Return */
159 END(subyte)
160
161 /*
162  * int suword16(volatile void *, int)
163  */
164 ENTRY(suword16)
165         li      a2, (VM_MAXUSER_ADDRESS-1)
166         bgt     a0, a2, fsu_fault_nopcb
167         la      a6, fsu_fault           /* Load the fault handler */
168         SET_FAULT_HANDLER(a6, a2)       /* And set it */
169         sh      a1, 0(a0)               /* Try storing the data */
170         SET_FAULT_HANDLER(x0, a2)       /* Reset the fault handler */
171         li      a0, 0                   /* Success */
172         ret                             /* Return */
173 END(suword16)
174
175 /*
176  * int suword32(volatile void *, int)
177  */
178 ENTRY(suword32)
179         li      a2, (VM_MAXUSER_ADDRESS-3)
180         bgt     a0, a2, fsu_fault_nopcb
181         la      a6, fsu_fault           /* Load the fault handler */
182         SET_FAULT_HANDLER(a6, a2)       /* And set it */
183         sw      a1, 0(a0)               /* Try storing the data */
184         SET_FAULT_HANDLER(x0, a2)       /* Reset the fault handler */
185         li      a0, 0                   /* Success */
186         ret                             /* Return */
187 END(suword32)
188
189 /*
190  * int suword(volatile void *, long)
191  */
192 ENTRY(suword)
193 EENTRY(suword64)
194         li      a2, (VM_MAXUSER_ADDRESS-7)
195         bgt     a0, a2, fsu_fault_nopcb
196         la      a6, fsu_fault           /* Load the fault handler */
197         SET_FAULT_HANDLER(a6, a2)       /* And set it */
198         sd      a1, 0(a0)               /* Try storing the data */
199         SET_FAULT_HANDLER(x0, a2)       /* Reset the fault handler */
200         li      a0, 0                   /* Success */
201         ret                             /* Return */
202 EEND(suword64)
203 END(suword)
204
205 /*
206  * fuswintr and suswintr are just like fusword and susword except that if
207  * the page is not in memory or would cause a trap, then we return an error.
208  * The important thing is to prevent sleep() and switch().
209  */
210
211 /*
212  * Special handler so the trap code knows not to sleep.
213  */
214 ENTRY(fsu_intr_fault)
215         SET_FAULT_HANDLER(x0, a1)       /* Reset the handler function */
216         li      a0, -1
217         ret
218 END(fsu_fault)
219
220 /*
221  * int fuswintr(void *)
222  */
223 ENTRY(fuswintr)
224         li      a1, (VM_MAXUSER_ADDRESS-3)
225         bgt     a0, a1, fsu_fault_nopcb
226         la      a6, fsu_intr_fault      /* Load the fault handler */
227         SET_FAULT_HANDLER(a6, a1)       /* And set it */
228         lw      a0, 0(a0)               /* Try loading the data */
229         SET_FAULT_HANDLER(x0, x1)       /* Reset the fault handler */
230         ret                             /* Return */
231 END(fuswintr)
232
233 /*
234  * int suswintr(void *base, int word)
235  */
236 ENTRY(suswintr)
237         li      a2, (VM_MAXUSER_ADDRESS-3)
238         bgt     a0, a2, fsu_fault_nopcb
239         la      a6, fsu_intr_fault      /* Load the fault handler */
240         SET_FAULT_HANDLER(a6, a2)       /* And set it */
241         sw      a1, 0(a0)               /* Try storing the data */
242         SET_FAULT_HANDLER(x0, a2)       /* Reset the fault handler */
243         li      a0, 0                   /* Success */
244         ret                             /* Return */
245 END(suswintr)
246
247 ENTRY(setjmp)
248         /* Store the stack pointer */
249         sd      sp, 0(a0)
250         addi    a0, a0, 8
251
252         /* Store the general purpose registers and ra */
253         sd      s0, (0 * 8)(a0)
254         sd      s1, (1 * 8)(a0)
255         sd      s2, (2 * 8)(a0)
256         sd      s3, (3 * 8)(a0)
257         sd      s4, (4 * 8)(a0)
258         sd      s5, (5 * 8)(a0)
259         sd      s6, (6 * 8)(a0)
260         sd      s7, (7 * 8)(a0)
261         sd      s8, (8 * 8)(a0)
262         sd      s9, (9 * 8)(a0)
263         sd      s10, (10 * 8)(a0)
264         sd      s11, (11 * 8)(a0)
265         sd      ra, (12 * 8)(a0)
266
267         /* Return value */
268         li      a0, 0
269         ret
270 END(setjmp)
271
272 ENTRY(longjmp)
273         /* Restore the stack pointer */
274         ld      sp, 0(a0)
275         addi    a0, a0, 8
276
277         /* Restore the general purpose registers and ra */
278         ld      s0, (0 * 8)(a0)
279         ld      s1, (1 * 8)(a0)
280         ld      s2, (2 * 8)(a0)
281         ld      s3, (3 * 8)(a0)
282         ld      s4, (4 * 8)(a0)
283         ld      s5, (5 * 8)(a0)
284         ld      s6, (6 * 8)(a0)
285         ld      s7, (7 * 8)(a0)
286         ld      s8, (8 * 8)(a0)
287         ld      s9, (9 * 8)(a0)
288         ld      s10, (10 * 8)(a0)
289         ld      s11, (11 * 8)(a0)
290         ld      ra, (12 * 8)(a0)
291
292         /* Load the return value */
293         mv      a0, a1
294         ret
295 END(longjmp)