1 /*-
2 * Copyright (c) 2015-2016 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.s"
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
43 __FBSDID("$FreeBSD: releng/11.2/sys/riscv/riscv/swtch.S 298580 2016-04-25 14:47:51Z br $");
44
45 /*
46 * void cpu_throw(struct thread *old, struct thread *new)
47 */
48 ENTRY(cpu_throw)
49 /* Store the new curthread */
50 sd a1, PC_CURTHREAD(gp)
51 /* And the new pcb */
52 ld x13, TD_PCB(a1)
53 sd x13, PC_CURPCB(gp)
54
55 sfence.vm
56
57 /* Switch to the new pmap */
58 ld t0, PCB_L1ADDR(x13)
59 csrw sptbr, t0
60
61 /* TODO: Invalidate the TLB */
62
63 sfence.vm
64
65 /* Load registers */
66 ld ra, (PCB_RA)(x13)
67 ld sp, (PCB_SP)(x13)
68
69 /* s[0-11] */
70 ld s0, (PCB_S + 0 * 8)(x13)
71 ld s1, (PCB_S + 1 * 8)(x13)
72 ld s2, (PCB_S + 2 * 8)(x13)
73 ld s3, (PCB_S + 3 * 8)(x13)
74 ld s4, (PCB_S + 4 * 8)(x13)
75 ld s5, (PCB_S + 5 * 8)(x13)
76 ld s6, (PCB_S + 6 * 8)(x13)
77 ld s7, (PCB_S + 7 * 8)(x13)
78 ld s8, (PCB_S + 8 * 8)(x13)
79 ld s9, (PCB_S + 9 * 8)(x13)
80 ld s10, (PCB_S + 10 * 8)(x13)
81 ld s11, (PCB_S + 11 * 8)(x13)
82 ret
83
84 .Lcpu_throw_panic_str:
85 .asciz "cpu_throw: %p\0"
86 END(cpu_throw)
87
88 /*
89 * void cpu_switch(struct thread *old, struct thread *new, struct mtx *mtx)
90 *
91 * a0 = old
92 * a1 = new
93 * a2 = mtx
94 * x3 to x7, x16 and x17 are caller saved
95 */
96 ENTRY(cpu_switch)
97 /* Store the new curthread */
98 sd a1, PC_CURTHREAD(gp)
99 /* And the new pcb */
100 ld x13, TD_PCB(a1)
101 sd x13, PC_CURPCB(gp)
102
103 /* Save the old context. */
104 ld x13, TD_PCB(a0)
105
106 /* Store ra, sp and the callee-saved registers */
107 sd ra, (PCB_RA)(x13)
108 sd sp, (PCB_SP)(x13)
109
110 /* s[0-11] */
111 sd s0, (PCB_S + 0 * 8)(x13)
112 sd s1, (PCB_S + 1 * 8)(x13)
113 sd s2, (PCB_S + 2 * 8)(x13)
114 sd s3, (PCB_S + 3 * 8)(x13)
115 sd s4, (PCB_S + 4 * 8)(x13)
116 sd s5, (PCB_S + 5 * 8)(x13)
117 sd s6, (PCB_S + 6 * 8)(x13)
118 sd s7, (PCB_S + 7 * 8)(x13)
119 sd s8, (PCB_S + 8 * 8)(x13)
120 sd s9, (PCB_S + 9 * 8)(x13)
121 sd s10, (PCB_S + 10 * 8)(x13)
122 sd s11, (PCB_S + 11 * 8)(x13)
123
124 /*
125 * Restore the saved context.
126 */
127 ld x13, TD_PCB(a1)
128
129 /*
130 * TODO: We may need to flush the cache here if switching
131 * to a user process.
132 */
133
134 sfence.vm
135
136 /* Switch to the new pmap */
137 ld t0, PCB_L1ADDR(x13)
138 csrw sptbr, t0
139
140 /* TODO: Invalidate the TLB */
141
142 sfence.vm
143
144 /* Release the old thread */
145 sd a2, TD_LOCK(a0)
146 #if defined(SCHED_ULE) && defined(SMP)
147 /* Spin if TD_LOCK points to a blocked_lock */
148 la a2, _C_LABEL(blocked_lock)
149 1:
150 ld t0, TD_LOCK(a1)
151 beq t0, a2, 1b
152 #endif
153
154 /* Restore the registers */
155 ld ra, (PCB_RA)(x13)
156 ld sp, (PCB_SP)(x13)
157
158 /* s[0-11] */
159 ld s0, (PCB_S + 0 * 8)(x13)
160 ld s1, (PCB_S + 1 * 8)(x13)
161 ld s2, (PCB_S + 2 * 8)(x13)
162 ld s3, (PCB_S + 3 * 8)(x13)
163 ld s4, (PCB_S + 4 * 8)(x13)
164 ld s5, (PCB_S + 5 * 8)(x13)
165 ld s6, (PCB_S + 6 * 8)(x13)
166 ld s7, (PCB_S + 7 * 8)(x13)
167 ld s8, (PCB_S + 8 * 8)(x13)
168 ld s9, (PCB_S + 9 * 8)(x13)
169 ld s10, (PCB_S + 10 * 8)(x13)
170 ld s11, (PCB_S + 11 * 8)(x13)
171 ret
172 .Lcpu_switch_panic_str:
173 .asciz "cpu_switch: %p\0"
174 END(cpu_switch)
175
176 /*
177 * fork_exit(void (*callout)(void *, struct trapframe *), void *arg,
178 * struct trapframe *frame)
179 */
180
181 ENTRY(fork_trampoline)
182 mv a0, s0
183 mv a1, s1
184 mv a2, sp
185 call _C_LABEL(fork_exit)
186
187 /* Restore sstatus */
188 ld t0, (TF_SSTATUS)(sp)
189 /* Ensure interrupts disabled */
190 li t1, ~SSTATUS_IE
191 and t0, t0, t1
192 csrw sstatus, t0
193
194 /* Restore exception program counter */
195 ld t0, (TF_SEPC)(sp)
196 csrw sepc, t0
197
198 /* Restore the registers */
199 ld t0, (TF_T + 0 * 8)(sp)
200 ld t1, (TF_T + 1 * 8)(sp)
201 ld t2, (TF_T + 2 * 8)(sp)
202 ld t3, (TF_T + 3 * 8)(sp)
203 ld t4, (TF_T + 4 * 8)(sp)
204 ld t5, (TF_T + 5 * 8)(sp)
205 ld t6, (TF_T + 6 * 8)(sp)
206
207 ld s0, (TF_S + 0 * 8)(sp)
208 ld s1, (TF_S + 1 * 8)(sp)
209 ld s2, (TF_S + 2 * 8)(sp)
210 ld s3, (TF_S + 3 * 8)(sp)
211 ld s4, (TF_S + 4 * 8)(sp)
212 ld s5, (TF_S + 5 * 8)(sp)
213 ld s6, (TF_S + 6 * 8)(sp)
214 ld s7, (TF_S + 7 * 8)(sp)
215 ld s8, (TF_S + 8 * 8)(sp)
216 ld s9, (TF_S + 9 * 8)(sp)
217 ld s10, (TF_S + 10 * 8)(sp)
218 ld s11, (TF_S + 11 * 8)(sp)
219
220 ld a0, (TF_A + 0 * 8)(sp)
221 ld a1, (TF_A + 1 * 8)(sp)
222 ld a2, (TF_A + 2 * 8)(sp)
223 ld a3, (TF_A + 3 * 8)(sp)
224 ld a4, (TF_A + 4 * 8)(sp)
225 ld a5, (TF_A + 5 * 8)(sp)
226 ld a6, (TF_A + 6 * 8)(sp)
227 ld a7, (TF_A + 7 * 8)(sp)
228
229 /* Load user ra and sp */
230 ld tp, (TF_TP)(sp)
231 ld ra, (TF_RA)(sp)
232
233 /*
234 * Store our pcpup on stack, we will load it back
235 * on kernel mode trap.
236 */
237 sd gp, (TF_SIZE)(sp)
238 ld gp, (TF_GP)(sp)
239
240 /* Save kernel stack so we can use it doing a user trap */
241 addi sp, sp, TF_SIZE
242 csrw sscratch, sp
243
244 /* Load user stack */
245 ld sp, (TF_SP - TF_SIZE)(sp)
246
247 eret
248 END(fork_trampoline)
249
250 ENTRY(savectx)
251 /* Store ra, sp and the callee-saved registers */
252 sd ra, (PCB_RA)(a0)
253 sd sp, (PCB_SP)(a0)
254
255 /* s[0-11] */
256 sd s0, (PCB_S + 0 * 8)(a0)
257 sd s1, (PCB_S + 1 * 8)(a0)
258 sd s2, (PCB_S + 2 * 8)(a0)
259 sd s3, (PCB_S + 3 * 8)(a0)
260 sd s4, (PCB_S + 4 * 8)(a0)
261 sd s5, (PCB_S + 5 * 8)(a0)
262 sd s6, (PCB_S + 6 * 8)(a0)
263 sd s7, (PCB_S + 7 * 8)(a0)
264 sd s8, (PCB_S + 8 * 8)(a0)
265 sd s9, (PCB_S + 9 * 8)(a0)
266 sd s10, (PCB_S + 10 * 8)(a0)
267 sd s11, (PCB_S + 11 * 8)(a0)
268
269 /* Store the VFP registers */
270 #ifdef VFP
271 /* TODO */
272 #endif
273 ret
274 END(savectx)
Cache object: 257359dc8a9e9cef06418de2b35e110d
|