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>
43 __FBSDID("$FreeBSD$");
45 .macro __fpe_state_save p
47 * Enable FPE usage in supervisor mode,
48 * so we can access registers.
50 li t0, SSTATUS_FS_INITIAL
56 fsd f0, (PCB_X + 0 * 16)(\p)
57 fsd f1, (PCB_X + 1 * 16)(\p)
58 fsd f2, (PCB_X + 2 * 16)(\p)
59 fsd f3, (PCB_X + 3 * 16)(\p)
60 fsd f4, (PCB_X + 4 * 16)(\p)
61 fsd f5, (PCB_X + 5 * 16)(\p)
62 fsd f6, (PCB_X + 6 * 16)(\p)
63 fsd f7, (PCB_X + 7 * 16)(\p)
64 fsd f8, (PCB_X + 8 * 16)(\p)
65 fsd f9, (PCB_X + 9 * 16)(\p)
66 fsd f10, (PCB_X + 10 * 16)(\p)
67 fsd f11, (PCB_X + 11 * 16)(\p)
68 fsd f12, (PCB_X + 12 * 16)(\p)
69 fsd f13, (PCB_X + 13 * 16)(\p)
70 fsd f14, (PCB_X + 14 * 16)(\p)
71 fsd f15, (PCB_X + 15 * 16)(\p)
72 fsd f16, (PCB_X + 16 * 16)(\p)
73 fsd f17, (PCB_X + 17 * 16)(\p)
74 fsd f18, (PCB_X + 18 * 16)(\p)
75 fsd f19, (PCB_X + 19 * 16)(\p)
76 fsd f20, (PCB_X + 20 * 16)(\p)
77 fsd f21, (PCB_X + 21 * 16)(\p)
78 fsd f22, (PCB_X + 22 * 16)(\p)
79 fsd f23, (PCB_X + 23 * 16)(\p)
80 fsd f24, (PCB_X + 24 * 16)(\p)
81 fsd f25, (PCB_X + 25 * 16)(\p)
82 fsd f26, (PCB_X + 26 * 16)(\p)
83 fsd f27, (PCB_X + 27 * 16)(\p)
84 fsd f28, (PCB_X + 28 * 16)(\p)
85 fsd f29, (PCB_X + 29 * 16)(\p)
86 fsd f30, (PCB_X + 30 * 16)(\p)
87 fsd f31, (PCB_X + 31 * 16)(\p)
89 /* Disable FPE usage in supervisor mode. */
90 li t0, SSTATUS_FS_MASK
94 .macro __fpe_state_load p
96 * Enable FPE usage in supervisor mode,
97 * so we can access registers.
99 li t0, SSTATUS_FS_INITIAL
102 /* Restore registers */
103 ld t0, (PCB_FCSR)(\p)
105 fld f0, (PCB_X + 0 * 16)(\p)
106 fld f1, (PCB_X + 1 * 16)(\p)
107 fld f2, (PCB_X + 2 * 16)(\p)
108 fld f3, (PCB_X + 3 * 16)(\p)
109 fld f4, (PCB_X + 4 * 16)(\p)
110 fld f5, (PCB_X + 5 * 16)(\p)
111 fld f6, (PCB_X + 6 * 16)(\p)
112 fld f7, (PCB_X + 7 * 16)(\p)
113 fld f8, (PCB_X + 8 * 16)(\p)
114 fld f9, (PCB_X + 9 * 16)(\p)
115 fld f10, (PCB_X + 10 * 16)(\p)
116 fld f11, (PCB_X + 11 * 16)(\p)
117 fld f12, (PCB_X + 12 * 16)(\p)
118 fld f13, (PCB_X + 13 * 16)(\p)
119 fld f14, (PCB_X + 14 * 16)(\p)
120 fld f15, (PCB_X + 15 * 16)(\p)
121 fld f16, (PCB_X + 16 * 16)(\p)
122 fld f17, (PCB_X + 17 * 16)(\p)
123 fld f18, (PCB_X + 18 * 16)(\p)
124 fld f19, (PCB_X + 19 * 16)(\p)
125 fld f20, (PCB_X + 20 * 16)(\p)
126 fld f21, (PCB_X + 21 * 16)(\p)
127 fld f22, (PCB_X + 22 * 16)(\p)
128 fld f23, (PCB_X + 23 * 16)(\p)
129 fld f24, (PCB_X + 24 * 16)(\p)
130 fld f25, (PCB_X + 25 * 16)(\p)
131 fld f26, (PCB_X + 26 * 16)(\p)
132 fld f27, (PCB_X + 27 * 16)(\p)
133 fld f28, (PCB_X + 28 * 16)(\p)
134 fld f29, (PCB_X + 29 * 16)(\p)
135 fld f30, (PCB_X + 30 * 16)(\p)
136 fld f31, (PCB_X + 31 * 16)(\p)
138 /* Disable FPE usage in supervisor mode. */
139 li t0, SSTATUS_FS_MASK
145 * fpe_state_save(struct thread *td)
147 ENTRY(fpe_state_save)
148 /* Get pointer to PCB */
156 * fpe_state_clear(void)
158 ENTRY(fpe_state_clear)
160 * Enable FPE usage in supervisor mode,
161 * so we can access registers.
163 li t0, SSTATUS_FS_INITIAL
200 /* Disable FPE usage in supervisor mode. */
201 li t0, SSTATUS_FS_MASK
208 * void cpu_throw(struct thread *old __unused, struct thread *new)
211 /* Activate the new thread's pmap. */
214 call _C_LABEL(pmap_activate_sw)
217 /* Store the new curthread */
218 sd a0, PC_CURTHREAD(tp)
219 /* And the new pcb */
221 sd x13, PC_CURPCB(tp)
228 ld s0, (PCB_S + 0 * 8)(x13)
229 ld s1, (PCB_S + 1 * 8)(x13)
230 ld s2, (PCB_S + 2 * 8)(x13)
231 ld s3, (PCB_S + 3 * 8)(x13)
232 ld s4, (PCB_S + 4 * 8)(x13)
233 ld s5, (PCB_S + 5 * 8)(x13)
234 ld s6, (PCB_S + 6 * 8)(x13)
235 ld s7, (PCB_S + 7 * 8)(x13)
236 ld s8, (PCB_S + 8 * 8)(x13)
237 ld s9, (PCB_S + 9 * 8)(x13)
238 ld s10, (PCB_S + 10 * 8)(x13)
239 ld s11, (PCB_S + 11 * 8)(x13)
241 /* Is FPE enabled for new thread? */
243 ld t1, (TF_SSTATUS)(t0)
244 li t2, SSTATUS_FS_MASK
246 beqz t3, 1f /* No, skip. */
248 /* Restore registers. */
255 * void cpu_switch(struct thread *old, struct thread *new, struct mtx *mtx)
260 * x3 to x7, x16 and x17 are caller saved
263 /* Store the new curthread */
264 sd a1, PC_CURTHREAD(tp)
265 /* And the new pcb */
267 sd x13, PC_CURPCB(tp)
269 /* Save the old context. */
272 /* Store ra, sp and the callee-saved registers */
277 sd s0, (PCB_S + 0 * 8)(x13)
278 sd s1, (PCB_S + 1 * 8)(x13)
279 sd s2, (PCB_S + 2 * 8)(x13)
280 sd s3, (PCB_S + 3 * 8)(x13)
281 sd s4, (PCB_S + 4 * 8)(x13)
282 sd s5, (PCB_S + 5 * 8)(x13)
283 sd s6, (PCB_S + 6 * 8)(x13)
284 sd s7, (PCB_S + 7 * 8)(x13)
285 sd s8, (PCB_S + 8 * 8)(x13)
286 sd s9, (PCB_S + 9 * 8)(x13)
287 sd s10, (PCB_S + 10 * 8)(x13)
288 sd s11, (PCB_S + 11 * 8)(x13)
291 * Is FPE enabled and is it in dirty state
292 * for the old thread?
295 ld t1, (TF_SSTATUS)(t0)
296 li t2, SSTATUS_FS_MASK
298 li t2, SSTATUS_FS_DIRTY
299 bne t3, t2, 1f /* No, skip. */
301 /* Yes, mark FPE state clean and save registers. */
302 li t2, ~SSTATUS_FS_MASK
304 li t2, SSTATUS_FS_CLEAN
306 sd t3, (TF_SSTATUS)(t0)
311 /* Activate the new thread's pmap */
316 call _C_LABEL(pmap_activate_sw)
319 /* Release the old thread */
321 #if defined(SCHED_ULE) && defined(SMP)
322 /* Spin if TD_LOCK points to a blocked_lock */
323 la s2, _C_LABEL(blocked_lock)
329 * Restore the saved context.
333 /* Restore the registers */
338 ld s0, (PCB_S + 0 * 8)(x13)
339 ld s1, (PCB_S + 1 * 8)(x13)
340 ld s2, (PCB_S + 2 * 8)(x13)
341 ld s3, (PCB_S + 3 * 8)(x13)
342 ld s4, (PCB_S + 4 * 8)(x13)
343 ld s5, (PCB_S + 5 * 8)(x13)
344 ld s6, (PCB_S + 6 * 8)(x13)
345 ld s7, (PCB_S + 7 * 8)(x13)
346 ld s8, (PCB_S + 8 * 8)(x13)
347 ld s9, (PCB_S + 9 * 8)(x13)
348 ld s10, (PCB_S + 10 * 8)(x13)
349 ld s11, (PCB_S + 11 * 8)(x13)
351 /* Is FPE enabled for new thread? */
353 ld t1, (TF_SSTATUS)(t0)
354 li t2, SSTATUS_FS_MASK
356 beqz t3, 1f /* No, skip. */
358 /* Restore registers. */
365 * fork_exit(void (*callout)(void *, struct trapframe *), void *arg,
366 * struct trapframe *frame)
369 ENTRY(fork_trampoline)
373 call _C_LABEL(fork_exit)
375 /* Restore sstatus */
376 ld t0, (TF_SSTATUS)(sp)
377 /* Ensure interrupts disabled */
382 /* Restore exception program counter */
386 /* Restore the registers */
387 ld t0, (TF_T + 0 * 8)(sp)
388 ld t1, (TF_T + 1 * 8)(sp)
389 ld t2, (TF_T + 2 * 8)(sp)
390 ld t3, (TF_T + 3 * 8)(sp)
391 ld t4, (TF_T + 4 * 8)(sp)
392 ld t5, (TF_T + 5 * 8)(sp)
393 ld t6, (TF_T + 6 * 8)(sp)
395 ld s0, (TF_S + 0 * 8)(sp)
396 ld s1, (TF_S + 1 * 8)(sp)
397 ld s2, (TF_S + 2 * 8)(sp)
398 ld s3, (TF_S + 3 * 8)(sp)
399 ld s4, (TF_S + 4 * 8)(sp)
400 ld s5, (TF_S + 5 * 8)(sp)
401 ld s6, (TF_S + 6 * 8)(sp)
402 ld s7, (TF_S + 7 * 8)(sp)
403 ld s8, (TF_S + 8 * 8)(sp)
404 ld s9, (TF_S + 9 * 8)(sp)
405 ld s10, (TF_S + 10 * 8)(sp)
406 ld s11, (TF_S + 11 * 8)(sp)
408 ld a0, (TF_A + 0 * 8)(sp)
409 ld a1, (TF_A + 1 * 8)(sp)
410 ld a2, (TF_A + 2 * 8)(sp)
411 ld a3, (TF_A + 3 * 8)(sp)
412 ld a4, (TF_A + 4 * 8)(sp)
413 ld a5, (TF_A + 5 * 8)(sp)
414 ld a6, (TF_A + 6 * 8)(sp)
415 ld a7, (TF_A + 7 * 8)(sp)
417 /* Load user ra and gp */
422 * Store our pcpup on stack, we will load it back
423 * on kernel mode trap.
428 /* Save kernel stack so we can use it doing a user trap */
432 /* Load user stack */
433 ld sp, (TF_SP - TF_SIZE)(sp)
439 /* Store ra, sp and the callee-saved registers */
446 sd s0, (PCB_S + 0 * 8)(a0)
447 sd s1, (PCB_S + 1 * 8)(a0)
448 sd s2, (PCB_S + 2 * 8)(a0)
449 sd s3, (PCB_S + 3 * 8)(a0)
450 sd s4, (PCB_S + 4 * 8)(a0)
451 sd s5, (PCB_S + 5 * 8)(a0)
452 sd s6, (PCB_S + 6 * 8)(a0)
453 sd s7, (PCB_S + 7 * 8)(a0)
454 sd s8, (PCB_S + 8 * 8)(a0)
455 sd s9, (PCB_S + 9 * 8)(a0)
456 sd s10, (PCB_S + 10 * 8)(a0)
457 sd s11, (PCB_S + 11 * 8)(a0)