]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/riscv/riscv/support.S
Upgrade to version 3.1.4
[FreeBSD/FreeBSD.git] / sys / riscv / riscv / support.S
1 /*-
2  * Copyright (c) 2015-2020 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 #include <machine/riscvreg.h>
40
41 #include "assym.inc"
42
43 /*
44  * One of the fu* or su* functions failed, return -1.
45  */
46 ENTRY(fsu_fault)
47         SET_FAULT_HANDLER(x0, a1)       /* Reset the handler function */
48         EXIT_USER_ACCESS(a1)
49 fsu_fault_nopcb:
50         li      a0, -1
51         ret
52 END(fsu_fault)
53
54 /*
55  * int casueword32(volatile uint32_t *, uint32_t, uint32_t *, uint32_t)
56  */
57 ENTRY(casueword32)
58         li      a4, (VM_MAXUSER_ADDRESS-3)
59         bgt     a0, a4, fsu_fault_nopcb
60         la      a6, fsu_fault           /* Load the fault handler */
61         SET_FAULT_HANDLER(a6, a4)       /* And set it */
62         ENTER_USER_ACCESS(a4)
63         lr.w    a4, 0(a0)               /* Load-exclusive the data */
64         bne     a4, a1, 1f              /* If not equal then exit */
65         sc.w    a5, a3, 0(a0)           /* Store the new data */
66         beqz    a5, 2f                  /* Success */
67 1:      li      a5, 1                   /* Normalize failure result */
68 2:      EXIT_USER_ACCESS(a6)
69         SET_FAULT_HANDLER(x0, a6)       /* Reset the fault handler */
70         sw      a4, 0(a2)               /* Store the read data */
71         mv      a0, a5                  /* Success indicator */
72         ret                             /* Return */
73 END(casueword32)
74
75 /*
76  * int casueword(volatile u_long *, u_long, u_long *, u_long)
77  */
78 ENTRY(casueword)
79         li      a4, (VM_MAXUSER_ADDRESS-7)
80         bgt     a0, a4, fsu_fault_nopcb
81         la      a6, fsu_fault           /* Load the fault handler */
82         SET_FAULT_HANDLER(a6, a4)       /* And set it */
83         ENTER_USER_ACCESS(a4)
84         lr.d    a4, 0(a0)               /* Load-exclusive the data */
85         bne     a4, a1, 1f              /* If not equal then exit */
86         sc.d    a5, a3, 0(a0)           /* Store the new data */
87         beqz    a5, 2f                  /* Success */
88 1:      li      a5, 1                   /* Normalize failure result */
89 2:      EXIT_USER_ACCESS(a6)
90         SET_FAULT_HANDLER(x0, a6)       /* Reset the fault handler */
91         sd      a4, 0(a2)               /* Store the read data */
92         mv      a0, a5                  /* Success indicator */
93         ret                             /* Return */
94 END(casueword)
95
96 /*
97  * int fubyte(volatile const void *)
98  */
99 ENTRY(fubyte)
100         li      a1, VM_MAXUSER_ADDRESS
101         bgt     a0, a1, fsu_fault_nopcb
102         la      a6, fsu_fault           /* Load the fault handler */
103         SET_FAULT_HANDLER(a6, a1)       /* And set it */
104         ENTER_USER_ACCESS(a1)
105         lbu     a0, 0(a0)               /* Try loading the data */
106         EXIT_USER_ACCESS(a1)
107         SET_FAULT_HANDLER(x0, a1)       /* Reset the fault handler */
108         ret                             /* Return */
109 END(fubyte)
110
111 /*
112  * int fuword(volatile const void *)
113  */
114 ENTRY(fuword16)
115         li      a1, (VM_MAXUSER_ADDRESS-1)
116         bgt     a0, a1, fsu_fault_nopcb
117         la      a6, fsu_fault           /* Load the fault handler */
118         SET_FAULT_HANDLER(a6, a1)       /* And set it */
119         ENTER_USER_ACCESS(a1)
120         lhu     a0, 0(a0)               /* Try loading the data */
121         EXIT_USER_ACCESS(a1)
122         SET_FAULT_HANDLER(x0, a1)       /* Reset the fault handler */
123         ret                             /* Return */
124 END(fuword16)
125
126 /*
127  * int32_t fueword32(volatile const void *, int32_t *)
128  */
129 ENTRY(fueword32)
130         li      a2, (VM_MAXUSER_ADDRESS-3)
131         bgt     a0, a2, fsu_fault_nopcb
132         la      a6, fsu_fault           /* Load the fault handler */
133         SET_FAULT_HANDLER(a6, a2)       /* And set it */
134         ENTER_USER_ACCESS(a2)
135         lw      a0, 0(a0)               /* Try loading the data */
136         EXIT_USER_ACCESS(a2)
137         SET_FAULT_HANDLER(x0, a2)       /* Reset the fault handler */
138         sw      a0, 0(a1)               /* Save the data in kernel space */
139         li      a0, 0                   /* Success */
140         ret                             /* Return */
141 END(fueword32)
142
143 /*
144  * long fueword(volatile const void *, int64_t *)
145  * int64_t fueword64(volatile const void *, int64_t *)
146  */
147 ENTRY(fueword)
148 EENTRY(fueword64)
149         li      a2, (VM_MAXUSER_ADDRESS-7)
150         bgt     a0, a2, fsu_fault_nopcb
151         la      a6, fsu_fault           /* Load the fault handler */
152         SET_FAULT_HANDLER(a6, a2)       /* And set it */
153         ENTER_USER_ACCESS(a2)
154         ld      a0, 0(a0)               /* Try loading the data */
155         EXIT_USER_ACCESS(a2)
156         SET_FAULT_HANDLER(x0, a2)       /* Reset the fault handler */
157         sd      a0, 0(a1)               /* Save the data in kernel space */
158         li      a0, 0                   /* Success */
159         ret                             /* Return */
160 EEND(fueword64)
161 END(fueword)
162
163 /*
164  * int subyte(volatile void *, int)
165  */
166 ENTRY(subyte)
167         li      a2, VM_MAXUSER_ADDRESS
168         bgt     a0, a2, fsu_fault_nopcb
169         la      a6, fsu_fault           /* Load the fault handler */
170         SET_FAULT_HANDLER(a6, a2)       /* And set it */
171         ENTER_USER_ACCESS(a2)
172         sb      a1, 0(a0)               /* Try storing the data */
173         EXIT_USER_ACCESS(a2)
174         SET_FAULT_HANDLER(x0, a2)       /* Reset the fault handler */
175         li      a0, 0                   /* Success */
176         ret                             /* Return */
177 END(subyte)
178
179 /*
180  * int suword16(volatile void *, int)
181  */
182 ENTRY(suword16)
183         li      a2, (VM_MAXUSER_ADDRESS-1)
184         bgt     a0, a2, fsu_fault_nopcb
185         la      a6, fsu_fault           /* Load the fault handler */
186         SET_FAULT_HANDLER(a6, a2)       /* And set it */
187         ENTER_USER_ACCESS(a2)
188         sh      a1, 0(a0)               /* Try storing the data */
189         EXIT_USER_ACCESS(a2)
190         SET_FAULT_HANDLER(x0, a2)       /* Reset the fault handler */
191         li      a0, 0                   /* Success */
192         ret                             /* Return */
193 END(suword16)
194
195 /*
196  * int suword32(volatile void *, int)
197  */
198 ENTRY(suword32)
199         li      a2, (VM_MAXUSER_ADDRESS-3)
200         bgt     a0, a2, fsu_fault_nopcb
201         la      a6, fsu_fault           /* Load the fault handler */
202         SET_FAULT_HANDLER(a6, a2)       /* And set it */
203         ENTER_USER_ACCESS(a2)
204         sw      a1, 0(a0)               /* Try storing the data */
205         EXIT_USER_ACCESS(a2)
206         SET_FAULT_HANDLER(x0, a2)       /* Reset the fault handler */
207         li      a0, 0                   /* Success */
208         ret                             /* Return */
209 END(suword32)
210
211 /*
212  * int suword(volatile void *, long)
213  */
214 ENTRY(suword)
215 EENTRY(suword64)
216         li      a2, (VM_MAXUSER_ADDRESS-7)
217         bgt     a0, a2, fsu_fault_nopcb
218         la      a6, fsu_fault           /* Load the fault handler */
219         SET_FAULT_HANDLER(a6, a2)       /* And set it */
220         ENTER_USER_ACCESS(a2)
221         sd      a1, 0(a0)               /* Try storing the data */
222         EXIT_USER_ACCESS(a2)
223         SET_FAULT_HANDLER(x0, a2)       /* Reset the fault handler */
224         li      a0, 0                   /* Success */
225         ret                             /* Return */
226 EEND(suword64)
227 END(suword)
228
229 ENTRY(setjmp)
230         /* Store the stack pointer */
231         sd      sp, 0(a0)
232         addi    a0, a0, 8
233
234         /* Store the general purpose registers and ra */
235         sd      s0, (0 * 8)(a0)
236         sd      s1, (1 * 8)(a0)
237         sd      s2, (2 * 8)(a0)
238         sd      s3, (3 * 8)(a0)
239         sd      s4, (4 * 8)(a0)
240         sd      s5, (5 * 8)(a0)
241         sd      s6, (6 * 8)(a0)
242         sd      s7, (7 * 8)(a0)
243         sd      s8, (8 * 8)(a0)
244         sd      s9, (9 * 8)(a0)
245         sd      s10, (10 * 8)(a0)
246         sd      s11, (11 * 8)(a0)
247         sd      ra, (12 * 8)(a0)
248
249         /* Return value */
250         li      a0, 0
251         ret
252 END(setjmp)
253
254 ENTRY(longjmp)
255         /* Restore the stack pointer */
256         ld      sp, 0(a0)
257         addi    a0, a0, 8
258
259         /* Restore the general purpose registers and ra */
260         ld      s0, (0 * 8)(a0)
261         ld      s1, (1 * 8)(a0)
262         ld      s2, (2 * 8)(a0)
263         ld      s3, (3 * 8)(a0)
264         ld      s4, (4 * 8)(a0)
265         ld      s5, (5 * 8)(a0)
266         ld      s6, (6 * 8)(a0)
267         ld      s7, (7 * 8)(a0)
268         ld      s8, (8 * 8)(a0)
269         ld      s9, (9 * 8)(a0)
270         ld      s10, (10 * 8)(a0)
271         ld      s11, (11 * 8)(a0)
272         ld      ra, (12 * 8)(a0)
273
274         /* Load the return value */
275         mv      a0, a1
276         ret
277 END(longjmp)