2 * Copyright (c) 2015-2017 Ruslan Bukin <br@bsdpad.com>
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.
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).
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
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.
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
36 #include "opt_sched.h"
38 #include <machine/param.h>
39 #include <machine/asm.h>
40 #include <machine/riscvreg.h>
41 #include <machine/pte.h>
42 .macro __fpe_state_save p
44 * Enable FPE usage in supervisor mode,
45 * so we can access registers.
47 li t0, SSTATUS_FS_INITIAL
53 fsd f0, (PCB_X + 0 * 16)(\p)
54 fsd f1, (PCB_X + 1 * 16)(\p)
55 fsd f2, (PCB_X + 2 * 16)(\p)
56 fsd f3, (PCB_X + 3 * 16)(\p)
57 fsd f4, (PCB_X + 4 * 16)(\p)
58 fsd f5, (PCB_X + 5 * 16)(\p)
59 fsd f6, (PCB_X + 6 * 16)(\p)
60 fsd f7, (PCB_X + 7 * 16)(\p)
61 fsd f8, (PCB_X + 8 * 16)(\p)
62 fsd f9, (PCB_X + 9 * 16)(\p)
63 fsd f10, (PCB_X + 10 * 16)(\p)
64 fsd f11, (PCB_X + 11 * 16)(\p)
65 fsd f12, (PCB_X + 12 * 16)(\p)
66 fsd f13, (PCB_X + 13 * 16)(\p)
67 fsd f14, (PCB_X + 14 * 16)(\p)
68 fsd f15, (PCB_X + 15 * 16)(\p)
69 fsd f16, (PCB_X + 16 * 16)(\p)
70 fsd f17, (PCB_X + 17 * 16)(\p)
71 fsd f18, (PCB_X + 18 * 16)(\p)
72 fsd f19, (PCB_X + 19 * 16)(\p)
73 fsd f20, (PCB_X + 20 * 16)(\p)
74 fsd f21, (PCB_X + 21 * 16)(\p)
75 fsd f22, (PCB_X + 22 * 16)(\p)
76 fsd f23, (PCB_X + 23 * 16)(\p)
77 fsd f24, (PCB_X + 24 * 16)(\p)
78 fsd f25, (PCB_X + 25 * 16)(\p)
79 fsd f26, (PCB_X + 26 * 16)(\p)
80 fsd f27, (PCB_X + 27 * 16)(\p)
81 fsd f28, (PCB_X + 28 * 16)(\p)
82 fsd f29, (PCB_X + 29 * 16)(\p)
83 fsd f30, (PCB_X + 30 * 16)(\p)
84 fsd f31, (PCB_X + 31 * 16)(\p)
86 /* Disable FPE usage in supervisor mode. */
87 li t0, SSTATUS_FS_MASK
91 .macro __fpe_state_load p
93 * Enable FPE usage in supervisor mode,
94 * so we can access registers.
96 li t0, SSTATUS_FS_INITIAL
99 /* Restore registers */
100 ld t0, (PCB_FCSR)(\p)
102 fld f0, (PCB_X + 0 * 16)(\p)
103 fld f1, (PCB_X + 1 * 16)(\p)
104 fld f2, (PCB_X + 2 * 16)(\p)
105 fld f3, (PCB_X + 3 * 16)(\p)
106 fld f4, (PCB_X + 4 * 16)(\p)
107 fld f5, (PCB_X + 5 * 16)(\p)
108 fld f6, (PCB_X + 6 * 16)(\p)
109 fld f7, (PCB_X + 7 * 16)(\p)
110 fld f8, (PCB_X + 8 * 16)(\p)
111 fld f9, (PCB_X + 9 * 16)(\p)
112 fld f10, (PCB_X + 10 * 16)(\p)
113 fld f11, (PCB_X + 11 * 16)(\p)
114 fld f12, (PCB_X + 12 * 16)(\p)
115 fld f13, (PCB_X + 13 * 16)(\p)
116 fld f14, (PCB_X + 14 * 16)(\p)
117 fld f15, (PCB_X + 15 * 16)(\p)
118 fld f16, (PCB_X + 16 * 16)(\p)
119 fld f17, (PCB_X + 17 * 16)(\p)
120 fld f18, (PCB_X + 18 * 16)(\p)
121 fld f19, (PCB_X + 19 * 16)(\p)
122 fld f20, (PCB_X + 20 * 16)(\p)
123 fld f21, (PCB_X + 21 * 16)(\p)
124 fld f22, (PCB_X + 22 * 16)(\p)
125 fld f23, (PCB_X + 23 * 16)(\p)
126 fld f24, (PCB_X + 24 * 16)(\p)
127 fld f25, (PCB_X + 25 * 16)(\p)
128 fld f26, (PCB_X + 26 * 16)(\p)
129 fld f27, (PCB_X + 27 * 16)(\p)
130 fld f28, (PCB_X + 28 * 16)(\p)
131 fld f29, (PCB_X + 29 * 16)(\p)
132 fld f30, (PCB_X + 30 * 16)(\p)
133 fld f31, (PCB_X + 31 * 16)(\p)
135 /* Disable FPE usage in supervisor mode. */
136 li t0, SSTATUS_FS_MASK
142 * fpe_state_save(struct thread *td)
144 ENTRY(fpe_state_save)
145 /* Get pointer to PCB */
153 * fpe_state_clear(void)
155 ENTRY(fpe_state_clear)
157 * Enable FPE usage in supervisor mode,
158 * so we can access registers.
160 li t0, SSTATUS_FS_INITIAL
197 /* Disable FPE usage in supervisor mode. */
198 li t0, SSTATUS_FS_MASK
205 * void cpu_throw(struct thread *old __unused, struct thread *new)
208 /* Activate the new thread's pmap. */
211 call _C_LABEL(pmap_activate_sw)
214 /* Store the new curthread */
215 sd a0, PC_CURTHREAD(tp)
216 /* And the new pcb */
218 sd x13, PC_CURPCB(tp)
225 ld s0, (PCB_S + 0 * 8)(x13)
226 ld s1, (PCB_S + 1 * 8)(x13)
227 ld s2, (PCB_S + 2 * 8)(x13)
228 ld s3, (PCB_S + 3 * 8)(x13)
229 ld s4, (PCB_S + 4 * 8)(x13)
230 ld s5, (PCB_S + 5 * 8)(x13)
231 ld s6, (PCB_S + 6 * 8)(x13)
232 ld s7, (PCB_S + 7 * 8)(x13)
233 ld s8, (PCB_S + 8 * 8)(x13)
234 ld s9, (PCB_S + 9 * 8)(x13)
235 ld s10, (PCB_S + 10 * 8)(x13)
236 ld s11, (PCB_S + 11 * 8)(x13)
238 /* Is FPE enabled for new thread? */
240 ld t1, (TF_SSTATUS)(t0)
241 li t2, SSTATUS_FS_MASK
243 beqz t3, 1f /* No, skip. */
245 /* Restore registers. */
252 * void cpu_switch(struct thread *old, struct thread *new, struct mtx *mtx)
257 * x3 to x7, x16 and x17 are caller saved
260 /* Store the new curthread */
261 sd a1, PC_CURTHREAD(tp)
262 /* And the new pcb */
264 sd x13, PC_CURPCB(tp)
266 /* Save the old context. */
269 /* Store ra, sp and the callee-saved registers */
274 sd s0, (PCB_S + 0 * 8)(x13)
275 sd s1, (PCB_S + 1 * 8)(x13)
276 sd s2, (PCB_S + 2 * 8)(x13)
277 sd s3, (PCB_S + 3 * 8)(x13)
278 sd s4, (PCB_S + 4 * 8)(x13)
279 sd s5, (PCB_S + 5 * 8)(x13)
280 sd s6, (PCB_S + 6 * 8)(x13)
281 sd s7, (PCB_S + 7 * 8)(x13)
282 sd s8, (PCB_S + 8 * 8)(x13)
283 sd s9, (PCB_S + 9 * 8)(x13)
284 sd s10, (PCB_S + 10 * 8)(x13)
285 sd s11, (PCB_S + 11 * 8)(x13)
288 * Is FPE enabled and is it in dirty state
289 * for the old thread?
292 ld t1, (TF_SSTATUS)(t0)
293 li t2, SSTATUS_FS_MASK
295 li t2, SSTATUS_FS_DIRTY
296 bne t3, t2, 1f /* No, skip. */
298 /* Yes, mark FPE state clean and save registers. */
299 li t2, ~SSTATUS_FS_MASK
301 li t2, SSTATUS_FS_CLEAN
303 sd t3, (TF_SSTATUS)(t0)
308 /* Activate the new thread's pmap */
313 call _C_LABEL(pmap_activate_sw)
316 /* Release the old thread */
318 #if defined(SCHED_ULE) && defined(SMP)
319 /* Spin if TD_LOCK points to a blocked_lock */
320 la s2, _C_LABEL(blocked_lock)
326 * Restore the saved context.
330 /* Restore the registers */
335 ld s0, (PCB_S + 0 * 8)(x13)
336 ld s1, (PCB_S + 1 * 8)(x13)
337 ld s2, (PCB_S + 2 * 8)(x13)
338 ld s3, (PCB_S + 3 * 8)(x13)
339 ld s4, (PCB_S + 4 * 8)(x13)
340 ld s5, (PCB_S + 5 * 8)(x13)
341 ld s6, (PCB_S + 6 * 8)(x13)
342 ld s7, (PCB_S + 7 * 8)(x13)
343 ld s8, (PCB_S + 8 * 8)(x13)
344 ld s9, (PCB_S + 9 * 8)(x13)
345 ld s10, (PCB_S + 10 * 8)(x13)
346 ld s11, (PCB_S + 11 * 8)(x13)
348 /* Is FPE enabled for new thread? */
350 ld t1, (TF_SSTATUS)(t0)
351 li t2, SSTATUS_FS_MASK
353 beqz t3, 1f /* No, skip. */
355 /* Restore registers. */
362 * fork_exit(void (*callout)(void *, struct trapframe *), void *arg,
363 * struct trapframe *frame)
366 ENTRY(fork_trampoline)
370 call _C_LABEL(fork_exit)
372 /* Restore sstatus */
373 ld t0, (TF_SSTATUS)(sp)
374 /* Ensure interrupts disabled */
379 /* Restore exception program counter */
383 /* Restore the registers */
384 ld t0, (TF_T + 0 * 8)(sp)
385 ld t1, (TF_T + 1 * 8)(sp)
386 ld t2, (TF_T + 2 * 8)(sp)
387 ld t3, (TF_T + 3 * 8)(sp)
388 ld t4, (TF_T + 4 * 8)(sp)
389 ld t5, (TF_T + 5 * 8)(sp)
390 ld t6, (TF_T + 6 * 8)(sp)
392 ld s0, (TF_S + 0 * 8)(sp)
393 ld s1, (TF_S + 1 * 8)(sp)
394 ld s2, (TF_S + 2 * 8)(sp)
395 ld s3, (TF_S + 3 * 8)(sp)
396 ld s4, (TF_S + 4 * 8)(sp)
397 ld s5, (TF_S + 5 * 8)(sp)
398 ld s6, (TF_S + 6 * 8)(sp)
399 ld s7, (TF_S + 7 * 8)(sp)
400 ld s8, (TF_S + 8 * 8)(sp)
401 ld s9, (TF_S + 9 * 8)(sp)
402 ld s10, (TF_S + 10 * 8)(sp)
403 ld s11, (TF_S + 11 * 8)(sp)
405 ld a0, (TF_A + 0 * 8)(sp)
406 ld a1, (TF_A + 1 * 8)(sp)
407 ld a2, (TF_A + 2 * 8)(sp)
408 ld a3, (TF_A + 3 * 8)(sp)
409 ld a4, (TF_A + 4 * 8)(sp)
410 ld a5, (TF_A + 5 * 8)(sp)
411 ld a6, (TF_A + 6 * 8)(sp)
412 ld a7, (TF_A + 7 * 8)(sp)
414 /* Load user ra and gp */
419 * Store our pcpup on stack, we will load it back
420 * on kernel mode trap.
425 /* Save kernel stack so we can use it doing a user trap */
429 /* Load user stack */
430 ld sp, (TF_SP - TF_SIZE)(sp)
436 /* Store ra, sp and the callee-saved registers */
443 sd s0, (PCB_S + 0 * 8)(a0)
444 sd s1, (PCB_S + 1 * 8)(a0)
445 sd s2, (PCB_S + 2 * 8)(a0)
446 sd s3, (PCB_S + 3 * 8)(a0)
447 sd s4, (PCB_S + 4 * 8)(a0)
448 sd s5, (PCB_S + 5 * 8)(a0)
449 sd s6, (PCB_S + 6 * 8)(a0)
450 sd s7, (PCB_S + 7 * 8)(a0)
451 sd s8, (PCB_S + 8 * 8)(a0)
452 sd s9, (PCB_S + 9 * 8)(a0)
453 sd s10, (PCB_S + 10 * 8)(a0)
454 sd s11, (PCB_S + 11 * 8)(a0)