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