]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/riscv/riscv/swtch.S
intrng: Remove irq_root_ipicount and corresponding intr_pic_claim_root arg
[FreeBSD/FreeBSD.git] / sys / riscv / riscv / swtch.S
1 /*-
2  * Copyright (c) 2015-2017 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 "assym.inc"
36 #include "opt_sched.h"
37
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
43         /*
44          * Enable FPE usage in supervisor mode,
45          * so we can access registers.
46          */
47         li      t0, SSTATUS_FS_INITIAL
48         csrs    sstatus, t0
49
50         /* Store registers */
51         frcsr   t0
52         sd      t0, (PCB_FCSR)(\p)
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)
85
86         /* Disable FPE usage in supervisor mode. */
87         li      t0, SSTATUS_FS_MASK
88         csrc    sstatus, t0
89 .endm
90
91 .macro __fpe_state_load p
92         /*
93          * Enable FPE usage in supervisor mode,
94          * so we can access registers.
95          */
96         li      t0, SSTATUS_FS_INITIAL
97         csrs    sstatus, t0
98
99         /* Restore registers */
100         ld      t0, (PCB_FCSR)(\p)
101         fscsr   t0
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)
134
135         /* Disable FPE usage in supervisor mode. */
136         li      t0, SSTATUS_FS_MASK
137         csrc    sstatus, t0
138 .endm
139
140 /*
141  * void
142  * fpe_state_save(struct thread *td)
143  */
144 ENTRY(fpe_state_save)
145         /* Get pointer to PCB */
146         ld      a0, TD_PCB(a0)
147         __fpe_state_save a0
148         ret
149 END(fpe_state_save)
150
151 /*
152  * void
153  * fpe_state_clear(void)
154  */
155 ENTRY(fpe_state_clear)
156         /*
157          * Enable FPE usage in supervisor mode,
158          * so we can access registers.
159          */
160         li      t0, SSTATUS_FS_INITIAL
161         csrs    sstatus, t0
162
163         fscsr   zero
164         fcvt.d.l f0, zero
165         fcvt.d.l f1, zero
166         fcvt.d.l f2, zero
167         fcvt.d.l f3, zero
168         fcvt.d.l f4, zero
169         fcvt.d.l f5, zero
170         fcvt.d.l f6, zero
171         fcvt.d.l f7, zero
172         fcvt.d.l f8, zero
173         fcvt.d.l f9, zero
174         fcvt.d.l f10, zero
175         fcvt.d.l f11, zero
176         fcvt.d.l f12, zero
177         fcvt.d.l f13, zero
178         fcvt.d.l f14, zero
179         fcvt.d.l f15, zero
180         fcvt.d.l f16, zero
181         fcvt.d.l f17, zero
182         fcvt.d.l f18, zero
183         fcvt.d.l f19, zero
184         fcvt.d.l f20, zero
185         fcvt.d.l f21, zero
186         fcvt.d.l f22, zero
187         fcvt.d.l f23, zero
188         fcvt.d.l f24, zero
189         fcvt.d.l f25, zero
190         fcvt.d.l f26, zero
191         fcvt.d.l f27, zero
192         fcvt.d.l f28, zero
193         fcvt.d.l f29, zero
194         fcvt.d.l f30, zero
195         fcvt.d.l f31, zero
196
197         /* Disable FPE usage in supervisor mode. */
198         li      t0, SSTATUS_FS_MASK
199         csrc    sstatus, t0
200
201         ret
202 END(fpe_state_clear)
203
204 /*
205  * void cpu_throw(struct thread *old __unused, struct thread *new)
206  */
207 ENTRY(cpu_throw)
208         /* Activate the new thread's pmap. */
209         mv      s0, a1
210         mv      a0, a1
211         call    _C_LABEL(pmap_activate_sw)
212         mv      a0, s0
213
214         /* Store the new curthread */
215         sd      a0, PC_CURTHREAD(tp)
216         /* And the new pcb */
217         ld      x13, TD_PCB(a0)
218         sd      x13, PC_CURPCB(tp)
219
220         /* Load registers */
221         ld      ra, (PCB_RA)(x13)
222         ld      sp, (PCB_SP)(x13)
223
224         /* s[0-11] */
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)
237
238         /* Is FPE enabled for new thread? */
239         ld      t0, TD_FRAME(a0)
240         ld      t1, (TF_SSTATUS)(t0)
241         li      t2, SSTATUS_FS_MASK
242         and     t3, t1, t2
243         beqz    t3, 1f          /* No, skip. */
244
245         /* Restore registers. */
246         __fpe_state_load x13
247 1:
248         ret
249 END(cpu_throw)
250
251 /*
252  * void cpu_switch(struct thread *old, struct thread *new, struct mtx *mtx)
253  *
254  * a0 = old
255  * a1 = new
256  * a2 = mtx
257  * x3 to x7, x16 and x17 are caller saved
258  */
259 ENTRY(cpu_switch)
260         /* Store the new curthread */
261         sd      a1, PC_CURTHREAD(tp)
262         /* And the new pcb */
263         ld      x13, TD_PCB(a1)
264         sd      x13, PC_CURPCB(tp)
265
266         /* Save the old context. */
267         ld      x13, TD_PCB(a0)
268
269         /* Store ra, sp and the callee-saved registers */
270         sd      ra, (PCB_RA)(x13)
271         sd      sp, (PCB_SP)(x13)
272
273         /* s[0-11] */
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)
286
287         /*
288          * Is FPE enabled and is it in dirty state
289          * for the old thread?
290          */
291         ld      t0, TD_FRAME(a0)
292         ld      t1, (TF_SSTATUS)(t0)
293         li      t2, SSTATUS_FS_MASK
294         and     t3, t1, t2
295         li      t2, SSTATUS_FS_DIRTY
296         bne     t3, t2, 1f              /* No, skip. */
297
298         /* Yes, mark FPE state clean and save registers. */
299         li      t2, ~SSTATUS_FS_MASK
300         and     t3, t1, t2
301         li      t2, SSTATUS_FS_CLEAN
302         or      t3, t3, t2
303         sd      t3, (TF_SSTATUS)(t0)
304
305         __fpe_state_save x13
306 1:
307
308         /* Activate the new thread's pmap */
309         mv      s0, a0
310         mv      s1, a1
311         mv      s2, a2
312         mv      a0, a1
313         call    _C_LABEL(pmap_activate_sw)
314         mv      a1, s1
315
316         /* Release the old thread */
317         sd      s2, TD_LOCK(s0)
318 #if defined(SCHED_ULE) && defined(SMP)
319         /* Spin if TD_LOCK points to a blocked_lock */
320         la      s2, _C_LABEL(blocked_lock)
321 1:
322         ld      t0, TD_LOCK(a1)
323         beq     t0, s2, 1b
324 #endif
325         /*
326          * Restore the saved context.
327          */
328         ld      x13, TD_PCB(a1)
329
330         /* Restore the registers */
331         ld      ra, (PCB_RA)(x13)
332         ld      sp, (PCB_SP)(x13)
333
334         /* s[0-11] */
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)
347
348         /* Is FPE enabled for new thread? */
349         ld      t0, TD_FRAME(a1)
350         ld      t1, (TF_SSTATUS)(t0)
351         li      t2, SSTATUS_FS_MASK
352         and     t3, t1, t2
353         beqz    t3, 1f          /* No, skip. */
354
355         /* Restore registers. */
356         __fpe_state_load x13
357 1:
358         ret
359 END(cpu_switch)
360
361 /*
362  * fork_exit(void (*callout)(void *, struct trapframe *), void *arg,
363  *  struct trapframe *frame)
364  */
365
366 ENTRY(fork_trampoline)
367         mv      a0, s0
368         mv      a1, s1
369         mv      a2, sp
370         call    _C_LABEL(fork_exit)
371
372         /* Restore sstatus */
373         ld      t0, (TF_SSTATUS)(sp)
374         /* Ensure interrupts disabled */
375         li      t1, ~SSTATUS_SIE
376         and     t0, t0, t1
377         csrw    sstatus, t0
378
379         /* Restore exception program counter */
380         ld      t0, (TF_SEPC)(sp)
381         csrw    sepc, t0
382
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)
391
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)
404
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)
413
414         /* Load user ra and gp */
415         ld      ra, (TF_RA)(sp)
416         ld      gp, (TF_GP)(sp)
417
418         /*
419          * Store our pcpup on stack, we will load it back
420          * on kernel mode trap.
421          */
422         sd      tp, (TF_SIZE)(sp)
423         ld      tp, (TF_TP)(sp)
424
425         /* Save kernel stack so we can use it doing a user trap */
426         addi    sp, sp, TF_SIZE
427         csrw    sscratch, sp
428
429         /* Load user stack */
430         ld      sp, (TF_SP - TF_SIZE)(sp)
431
432         sret
433 END(fork_trampoline)
434
435 ENTRY(savectx)
436         /* Store ra, sp and the callee-saved registers */
437         sd      ra, (PCB_RA)(a0)
438         sd      sp, (PCB_SP)(a0)
439         sd      tp, (PCB_TP)(a0)
440         sd      gp, (PCB_GP)(a0)
441
442         /* s[0-11] */
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)
455
456         __fpe_state_save a0
457         ret
458 END(savectx)