cpuswitch.S revision 1.55.6.2 1 1.55.6.1 mjf /* $NetBSD: cpuswitch.S,v 1.55.6.2 2008/06/02 13:21:52 mjf Exp $ */
2 1.1 chris
3 1.1 chris /*
4 1.30 scw * Copyright 2003 Wasabi Systems, Inc.
5 1.30 scw * All rights reserved.
6 1.30 scw *
7 1.30 scw * Written by Steve C. Woodford for Wasabi Systems, Inc.
8 1.30 scw *
9 1.30 scw * Redistribution and use in source and binary forms, with or without
10 1.30 scw * modification, are permitted provided that the following conditions
11 1.30 scw * are met:
12 1.30 scw * 1. Redistributions of source code must retain the above copyright
13 1.30 scw * notice, this list of conditions and the following disclaimer.
14 1.30 scw * 2. Redistributions in binary form must reproduce the above copyright
15 1.30 scw * notice, this list of conditions and the following disclaimer in the
16 1.30 scw * documentation and/or other materials provided with the distribution.
17 1.30 scw * 3. All advertising materials mentioning features or use of this software
18 1.30 scw * must display the following acknowledgement:
19 1.30 scw * This product includes software developed for the NetBSD Project by
20 1.30 scw * Wasabi Systems, Inc.
21 1.30 scw * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 1.30 scw * or promote products derived from this software without specific prior
23 1.30 scw * written permission.
24 1.30 scw *
25 1.30 scw * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 1.30 scw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 1.30 scw * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 1.30 scw * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 1.30 scw * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 1.30 scw * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 1.30 scw * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 1.30 scw * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 1.30 scw * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 1.30 scw * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 1.30 scw * POSSIBILITY OF SUCH DAMAGE.
36 1.30 scw */
37 1.30 scw /*
38 1.1 chris * Copyright (c) 1994-1998 Mark Brinicombe.
39 1.1 chris * Copyright (c) 1994 Brini.
40 1.1 chris * All rights reserved.
41 1.1 chris *
42 1.1 chris * This code is derived from software written for Brini by Mark Brinicombe
43 1.1 chris *
44 1.1 chris * Redistribution and use in source and binary forms, with or without
45 1.1 chris * modification, are permitted provided that the following conditions
46 1.1 chris * are met:
47 1.1 chris * 1. Redistributions of source code must retain the above copyright
48 1.1 chris * notice, this list of conditions and the following disclaimer.
49 1.1 chris * 2. Redistributions in binary form must reproduce the above copyright
50 1.1 chris * notice, this list of conditions and the following disclaimer in the
51 1.1 chris * documentation and/or other materials provided with the distribution.
52 1.1 chris * 3. All advertising materials mentioning features or use of this software
53 1.1 chris * must display the following acknowledgement:
54 1.1 chris * This product includes software developed by Brini.
55 1.1 chris * 4. The name of the company nor the name of the author may be used to
56 1.1 chris * endorse or promote products derived from this software without specific
57 1.1 chris * prior written permission.
58 1.1 chris *
59 1.1 chris * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
60 1.1 chris * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
61 1.1 chris * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
62 1.1 chris * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
63 1.1 chris * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
64 1.1 chris * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
65 1.1 chris * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 1.1 chris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 1.1 chris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 1.1 chris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 1.1 chris * SUCH DAMAGE.
70 1.1 chris *
71 1.1 chris * RiscBSD kernel project
72 1.1 chris *
73 1.1 chris * cpuswitch.S
74 1.1 chris *
75 1.1 chris * cpu switching functions
76 1.1 chris *
77 1.1 chris * Created : 15/10/94
78 1.1 chris */
79 1.1 chris
80 1.1 chris #include "opt_armfpe.h"
81 1.30 scw #include "opt_arm32_pmap.h"
82 1.19 bjh21 #include "opt_multiprocessor.h"
83 1.55.6.2 mjf #include "opt_cpuoptions.h"
84 1.36 martin #include "opt_lockdebug.h"
85 1.1 chris
86 1.1 chris #include "assym.h"
87 1.46 briggs #include <arm/arm32/pte.h>
88 1.1 chris #include <machine/param.h>
89 1.1 chris #include <machine/frame.h>
90 1.1 chris #include <machine/asm.h>
91 1.55.6.2 mjf #include <machine/cpu.h>
92 1.55.6.2 mjf
93 1.55.6.2 mjf RCSID("$NetBSD: cpuswitch.S,v 1.55.6.2 2008/06/02 13:21:52 mjf Exp $")
94 1.1 chris
95 1.34 kristerw /* LINTSTUB: include <sys/param.h> */
96 1.34 kristerw
97 1.1 chris #undef IRQdisable
98 1.1 chris #undef IRQenable
99 1.1 chris
100 1.1 chris /*
101 1.1 chris * New experimental definitions of IRQdisable and IRQenable
102 1.1 chris * These keep FIQ's enabled since FIQ's are special.
103 1.1 chris */
104 1.1 chris
105 1.55.6.2 mjf #ifdef _ARM_ARCH_6
106 1.55.6.2 mjf #define IRQdisable cpsid i
107 1.55.6.2 mjf #define IRQenable cpsie i
108 1.55.6.2 mjf #else
109 1.1 chris #define IRQdisable \
110 1.13 thorpej mrs r14, cpsr ; \
111 1.1 chris orr r14, r14, #(I32_bit) ; \
112 1.55.6.2 mjf msr cpsr_c, r14
113 1.1 chris
114 1.1 chris #define IRQenable \
115 1.13 thorpej mrs r14, cpsr ; \
116 1.1 chris bic r14, r14, #(I32_bit) ; \
117 1.55.6.2 mjf msr cpsr_c, r14
118 1.1 chris
119 1.22 bjh21 #endif
120 1.1 chris
121 1.1 chris .text
122 1.55.6.2 mjf .Lpmap_previous_active_lwp:
123 1.55.6.2 mjf .word _C_LABEL(pmap_previous_active_lwp)
124 1.30 scw
125 1.1 chris /*
126 1.47 yamt * struct lwp *
127 1.47 yamt * cpu_switchto(struct lwp *current, struct lwp *next)
128 1.48 skrll *
129 1.47 yamt * Switch to the specified next LWP
130 1.47 yamt * Arguments:
131 1.16 thorpej *
132 1.55.6.2 mjf * r0 'struct lwp *' of the current LWP (or NULL if exiting)
133 1.47 yamt * r1 'struct lwp *' of the LWP to switch to
134 1.55.6.2 mjf * r2 returning
135 1.1 chris */
136 1.47 yamt ENTRY(cpu_switchto)
137 1.51 skrll mov ip, sp
138 1.51 skrll stmfd sp!, {r4-r7, ip, lr}
139 1.1 chris
140 1.55.6.2 mjf /* move lwps into caller saved registers */
141 1.55 chris mov r6, r1
142 1.55 chris mov r4, r0
143 1.55.6.2 mjf
144 1.55.6.2 mjf #ifdef PROCESS_ID_CURCPU
145 1.55.6.2 mjf GET_CURCPU(r7)
146 1.55.6.2 mjf #elif defined(PROCESS_ID_IS_CURLWP)
147 1.55.6.2 mjf mcr p15, 0, r0, c13, c0, 4 /* get old lwp (r4 maybe 0) */
148 1.55.6.2 mjf ldr r7, [r0, #(L_CPU)] /* get cpu from old lwp */
149 1.55.6.2 mjf #elif !defined(MULTIPROCESSOR)
150 1.55.6.2 mjf ldr r7, [r6, #L_CPU] /* get cpu from new lwp */
151 1.55.6.2 mjf #else
152 1.55.6.2 mjf #error curcpu() method not defined
153 1.55.6.2 mjf #endif
154 1.7 chris
155 1.55 chris /* rem: r4 = old lwp */
156 1.55 chris /* rem: r6 = new lwp */
157 1.55.6.2 mjf /* rem: r7 = curcpu() */
158 1.55 chris
159 1.1 chris IRQdisable
160 1.7 chris
161 1.19 bjh21 #ifdef MULTIPROCESSOR
162 1.55.6.2 mjf str r7, [r6, #(L_CPU)]
163 1.19 bjh21 #else
164 1.29 thorpej /* l->l_cpu initialized in fork1() for single-processor */
165 1.19 bjh21 #endif
166 1.1 chris
167 1.55.6.2 mjf #if defined(PROCESS_ID_IS_CURLWP)
168 1.55.6.2 mjf mcr p15, 0, r6, c13, c0, 4 /* set current lwp */
169 1.55.6.2 mjf #endif
170 1.55.6.2 mjf #if !defined(PROCESS_ID_IS_CURLWP) || defined(MULTIPROCESSOR)
171 1.55.6.2 mjf /* We have a new curlwp now so make a note it */
172 1.55.6.2 mjf str r6, [r7, #(CI_CURLWP)]
173 1.55.6.2 mjf #endif
174 1.55 chris
175 1.55.6.2 mjf /* Hook in a new pcb */
176 1.55.6.2 mjf ldr r0, [r6, #(L_ADDR)]
177 1.55.6.2 mjf str r0, [r7, #(CI_CURPCB)]
178 1.55.6.2 mjf mov r7, r0
179 1.1 chris
180 1.1 chris /* At this point we can allow IRQ's again. */
181 1.1 chris IRQenable
182 1.1 chris
183 1.47 yamt /* rem: r4 = old lwp */
184 1.43 skrll /* rem: r6 = new lwp */
185 1.55 chris /* rem: r7 = new pcb */
186 1.4 chris /* rem: interrupts are enabled */
187 1.1 chris
188 1.1 chris /*
189 1.47 yamt * If the old lwp on entry to cpu_switchto was zero then the
190 1.1 chris * process that called it was exiting. This means that we do
191 1.1 chris * not need to save the current context. Instead we can jump
192 1.1 chris * straight to restoring the context for the new process.
193 1.1 chris */
194 1.55.6.2 mjf teq r4, #0
195 1.49 scw beq .Ldo_switch
196 1.1 chris
197 1.47 yamt /* rem: r4 = old lwp */
198 1.43 skrll /* rem: r6 = new lwp */
199 1.55 chris /* rem: r7 = new pcb */
200 1.4 chris /* rem: interrupts are enabled */
201 1.1 chris
202 1.48 skrll /* Save old context */
203 1.1 chris
204 1.29 thorpej /* Get the user structure for the old lwp. */
205 1.55 chris ldr r5, [r4, #(L_ADDR)]
206 1.1 chris
207 1.29 thorpej /* Save all the registers in the old lwp's pcb */
208 1.55.6.2 mjf #if defined(__XSCALE__) || defined(_ARM_ARCH_6)
209 1.55 chris strd r8, [r5, #(PCB_R8)]
210 1.55 chris strd r10, [r5, #(PCB_R10)]
211 1.55 chris strd r12, [r5, #(PCB_R12)]
212 1.55.6.2 mjf #else
213 1.55.6.2 mjf add r0, r5, #(PCB_R8)
214 1.55.6.2 mjf stmia r0, {r8-r13}
215 1.37 scw #endif
216 1.1 chris
217 1.55.6.2 mjf #ifdef _ARM_ARCH_6
218 1.55.6.2 mjf /*
219 1.55.6.2 mjf * Save user read/write thread/process id register
220 1.55.6.2 mjf */
221 1.55.6.2 mjf mrc p15, 0, r0, c13, c0, 2
222 1.55.6.2 mjf str r0, [r5, #(PCB_USER_PID_RW)]
223 1.55.6.2 mjf #endif
224 1.1 chris /*
225 1.29 thorpej * NOTE: We can now use r8-r13 until it is time to restore
226 1.29 thorpej * them for the new process.
227 1.29 thorpej */
228 1.29 thorpej
229 1.47 yamt /* rem: r4 = old lwp */
230 1.55 chris /* rem: r5 = old pcb */
231 1.47 yamt /* rem: r6 = new lwp */
232 1.55 chris /* rem: r7 = new pcb */
233 1.47 yamt /* rem: interrupts are enabled */
234 1.47 yamt
235 1.55.6.1 mjf #ifdef FPU_VFP
236 1.55.6.1 mjf /*
237 1.55.6.1 mjf * Now's a good time to 'save' the VFP context. Note that we
238 1.55.6.1 mjf * don't really force a save here, which can save time if we
239 1.55.6.1 mjf * end up restarting the same context.
240 1.55.6.1 mjf */
241 1.55.6.1 mjf bl _C_LABEL(vfp_savecontext)
242 1.55.6.1 mjf #endif
243 1.1 chris
244 1.48 skrll /* Restore saved context */
245 1.1 chris
246 1.49 scw .Ldo_switch:
247 1.47 yamt /* rem: r4 = old lwp */
248 1.29 thorpej /* rem: r6 = new lwp */
249 1.55 chris /* rem: r7 = new pcb */
250 1.53 chris /* rem: interrupts are enabled */
251 1.29 thorpej
252 1.55.6.2 mjf #ifdef _ARM_ARCH_6
253 1.55.6.2 mjf /*
254 1.55.6.2 mjf * Restore user thread/process id registers
255 1.55.6.2 mjf */
256 1.55.6.2 mjf ldr r0, [r7, #(PCB_USER_PID_RW)]
257 1.55.6.2 mjf mcr p15, 0, r0, c13, c0, 2
258 1.55.6.2 mjf ldr r0, [r7, #(PCB_USER_PID_RO)]
259 1.55.6.2 mjf mcr p15, 0, r0, c13, c0, 3
260 1.55.6.2 mjf #endif
261 1.55.6.2 mjf
262 1.55 chris ldr r5, [r6, #(L_PROC)] /* fetch the proc for below */
263 1.55 chris
264 1.52 skrll /* Restore all the saved registers */
265 1.55.6.2 mjf #ifdef __XSCALE__
266 1.37 scw ldr r8, [r7, #(PCB_R8)]
267 1.37 scw ldr r9, [r7, #(PCB_R9)]
268 1.37 scw ldr r10, [r7, #(PCB_R10)]
269 1.37 scw ldr r11, [r7, #(PCB_R11)]
270 1.37 scw ldr r12, [r7, #(PCB_R12)]
271 1.37 scw ldr r13, [r7, #(PCB_SP)]
272 1.55.6.2 mjf #elif defined(_ARM_ARCH_6)
273 1.55.6.2 mjf ldrd r8, [r7, #(PCB_R8)]
274 1.55.6.2 mjf ldrd r10, [r7, #(PCB_R10)]
275 1.55.6.2 mjf ldrd r12, [r7, #(PCB_R12)]
276 1.55.6.2 mjf #else
277 1.55.6.2 mjf add r0, r7, #PCB_R8
278 1.55.6.2 mjf ldmia r0, {r8-r13}
279 1.37 scw #endif
280 1.29 thorpej
281 1.55.6.2 mjf /* Record the old lwp for pmap_activate()'s benefit */
282 1.55.6.2 mjf ldr r1, .Lpmap_previous_active_lwp
283 1.55.6.2 mjf str r4, [r1]
284 1.55.6.2 mjf
285 1.47 yamt /* rem: r4 = old lwp */
286 1.29 thorpej /* rem: r5 = new lwp's proc */
287 1.29 thorpej /* rem: r6 = new lwp */
288 1.29 thorpej /* rem: r7 = new pcb */
289 1.18 thorpej
290 1.55.6.1 mjf #ifdef FPU_VFP
291 1.55.6.1 mjf mov r0, r6
292 1.55.6.1 mjf bl _C_LABEL(vfp_loadcontext)
293 1.55.6.1 mjf #endif
294 1.1 chris #ifdef ARMFPE
295 1.29 thorpej add r0, r7, #(USER_SIZE) & 0x00ff
296 1.1 chris add r0, r0, #(USER_SIZE) & 0xff00
297 1.1 chris bl _C_LABEL(arm_fpe_core_changecontext)
298 1.1 chris #endif
299 1.1 chris
300 1.47 yamt /* rem: r4 = old lwp */
301 1.29 thorpej /* rem: r5 = new lwp's proc */
302 1.29 thorpej /* rem: r6 = new lwp */
303 1.18 thorpej /* rem: r7 = new PCB */
304 1.18 thorpej
305 1.18 thorpej /*
306 1.18 thorpej * Check for restartable atomic sequences (RAS).
307 1.18 thorpej */
308 1.18 thorpej
309 1.39 dsl ldr r2, [r5, #(P_RASLIST)]
310 1.38 scw ldr r1, [r7, #(PCB_TF)] /* r1 = trapframe (used below) */
311 1.18 thorpej teq r2, #0 /* p->p_nras == 0? */
312 1.18 thorpej bne .Lswitch_do_ras /* no, check for one */
313 1.18 thorpej
314 1.14 briggs .Lswitch_return:
315 1.47 yamt /* cpu_switchto returns the old lwp */
316 1.29 thorpej mov r0, r4
317 1.47 yamt /* lwp_trampoline expects new lwp as it's second argument */
318 1.47 yamt mov r1, r6
319 1.1 chris
320 1.1 chris /*
321 1.51 skrll * Pull the registers that got pushed when cpu_switchto() was called,
322 1.51 skrll * and return.
323 1.1 chris */
324 1.51 skrll ldmfd sp, {r4-r7, sp, pc}
325 1.18 thorpej
326 1.18 thorpej .Lswitch_do_ras:
327 1.38 scw ldr r1, [r1, #(TF_PC)] /* second ras_lookup() arg */
328 1.29 thorpej mov r0, r5 /* first ras_lookup() arg */
329 1.18 thorpej bl _C_LABEL(ras_lookup)
330 1.18 thorpej cmn r0, #1 /* -1 means "not in a RAS" */
331 1.38 scw ldrne r1, [r7, #(PCB_TF)]
332 1.38 scw strne r0, [r1, #(TF_PC)]
333 1.18 thorpej b .Lswitch_return
334 1.1 chris
335 1.47 yamt ENTRY(lwp_trampoline)
336 1.52 skrll /*
337 1.52 skrll * cpu_switchto gives us:
338 1.52 skrll *
339 1.52 skrll * arg0(r0) = old lwp
340 1.52 skrll * arg1(r1) = new lwp
341 1.52 skrll */
342 1.47 yamt bl _C_LABEL(lwp_startup)
343 1.38 scw
344 1.1 chris mov r0, r5
345 1.1 chris mov r1, sp
346 1.24 bjh21 mov lr, pc
347 1.1 chris mov pc, r4
348 1.1 chris
349 1.1 chris /* Kill irq's */
350 1.13 thorpej mrs r0, cpsr
351 1.1 chris orr r0, r0, #(I32_bit)
352 1.13 thorpej msr cpsr_c, r0
353 1.1 chris
354 1.1 chris PULLFRAME
355 1.1 chris
356 1.1 chris movs pc, lr /* Exit */
357 1.55.6.2 mjf
358 1.55.6.2 mjf #ifdef __HAVE_FAST_SOFTINTS
359 1.55.6.2 mjf /*
360 1.55.6.2 mjf * Called at IPL_HIGH
361 1.55.6.2 mjf * r0 = new lwp
362 1.55.6.2 mjf * r1 = ipl for softint_dispatch
363 1.55.6.2 mjf */
364 1.55.6.2 mjf ENTRY_NP(softint_switch)
365 1.55.6.2 mjf stmfd sp!, {r4, r6, r7, lr}
366 1.55.6.2 mjf
367 1.55.6.2 mjf ldr r7, [r0, #L_CPU] /* get curcpu */
368 1.55.6.2 mjf #if defined(PROCESS_ID_IS_CURLWP)
369 1.55.6.2 mjf mrc p15, 0, r4, c13, c0, 4 /* get old lwp */
370 1.55.6.2 mjf #else
371 1.55.6.2 mjf ldr r4, [r7, #(CI_CURLWP)] /* get old lwp */
372 1.55.6.2 mjf #endif
373 1.55.6.2 mjf mrs r6, cpsr /* we need to save this */
374 1.55.6.2 mjf
375 1.55.6.2 mjf /*
376 1.55.6.2 mjf * If the soft lwp blocks, it needs to return to softint_tramp
377 1.55.6.2 mjf */
378 1.55.6.2 mjf mov r2, sp /* think ip */
379 1.55.6.2 mjf adr r3, softint_tramp /* think lr */
380 1.55.6.2 mjf stmfd sp!, {r2-r3}
381 1.55.6.2 mjf stmfd sp!, {r4-r7}
382 1.55.6.2 mjf
383 1.55.6.2 mjf mov r5, r0 /* save new lwp */
384 1.55.6.2 mjf
385 1.55.6.2 mjf ldr r2, [r4, #(L_ADDR)] /* get old lwp's pcb */
386 1.55.6.2 mjf
387 1.55.6.2 mjf /* Save all the registers into the old lwp's pcb */
388 1.55.6.2 mjf #if defined(__XSCALE__) || defined(_ARM_ARCH_6)
389 1.55.6.2 mjf strd r8, [r2, #(PCB_R8)]
390 1.55.6.2 mjf strd r10, [r2, #(PCB_R10)]
391 1.55.6.2 mjf strd r12, [r2, #(PCB_R12)]
392 1.55.6.2 mjf #else
393 1.55.6.2 mjf add r3, r2, #(PCB_R8)
394 1.55.6.2 mjf stmia r3, {r8-r13}
395 1.55.6.2 mjf #endif
396 1.55.6.2 mjf
397 1.55.6.2 mjf /* this is an invariant so load before disabling intrs */
398 1.55.6.2 mjf ldr r2, [r5, #(L_ADDR)] /* get new lwp's pcb */
399 1.55.6.2 mjf
400 1.55.6.2 mjf IRQdisable
401 1.55.6.2 mjf /*
402 1.55.6.2 mjf * We're switching to a bound LWP so its l_cpu is already correct.
403 1.55.6.2 mjf */
404 1.55.6.2 mjf #if defined(PROCESS_ID_IS_CURLWP)
405 1.55.6.2 mjf mcr p15, 0, r5, c13, c0, 4 /* save new lwp */
406 1.55.6.2 mjf #endif
407 1.55.6.2 mjf #if !defined(PROCESS_ID_IS_CURLWP) || defined(MULTIPROCESSOR)
408 1.55.6.2 mjf str r5, [r7, #(CI_CURLWP)] /* save new lwp */
409 1.55.6.2 mjf #endif
410 1.55.6.2 mjf
411 1.55.6.2 mjf /* Hook in a new pcb */
412 1.55.6.2 mjf str r2, [r7, #(CI_CURPCB)]
413 1.55.6.2 mjf
414 1.55.6.2 mjf /*
415 1.55.6.2 mjf * Normally, we'd get {r8-r13} but since this is a softint lwp
416 1.55.6.2 mjf * it's existing state doesn't matter. We start the stack just
417 1.55.6.2 mjf * below the trapframe.
418 1.55.6.2 mjf */
419 1.55.6.2 mjf ldr sp, [r2, #(PCB_TF)] /* get new lwp's stack ptr */
420 1.55.6.2 mjf
421 1.55.6.2 mjf /* At this point we can allow IRQ's again. */
422 1.55.6.2 mjf IRQenable
423 1.55.6.2 mjf
424 1.55.6.2 mjf /* r1 still has ipl */
425 1.55.6.2 mjf mov r0, r4 /* r0 has pinned (old) lwp */
426 1.55.6.2 mjf bl _C_LABEL(softint_dispatch)
427 1.55.6.2 mjf /*
428 1.55.6.2 mjf * If we've returned, we need to change everything back and return.
429 1.55.6.2 mjf */
430 1.55.6.2 mjf ldr r2, [r4, #(L_ADDR)] /* get pinned lwp's pcb */
431 1.55.6.2 mjf
432 1.55.6.2 mjf IRQdisable
433 1.55.6.2 mjf /*
434 1.55.6.2 mjf * We don't need to restore all the registers since another lwp was
435 1.55.6.2 mjf * never executed. But we do need the SP from the formerly pinned lwp.
436 1.55.6.2 mjf */
437 1.55.6.2 mjf
438 1.55.6.2 mjf #if defined(PROCESS_ID_IS_CURLWP)
439 1.55.6.2 mjf mcr p15, 0, r4, c13, c0, 4 /* restore pinned lwp */
440 1.55.6.2 mjf #endif
441 1.55.6.2 mjf #if !defined(PROCESS_ID_IS_CURLWP) || defined(MULTIPROCESSOR)
442 1.55.6.2 mjf str r4, [r7, #(CI_CURLWP)] /* restore pinned lwp */
443 1.55.6.2 mjf #endif
444 1.55.6.2 mjf str r2, [r7, #(CI_CURPCB)] /* restore the curpcb */
445 1.55.6.2 mjf ldr sp, [r2, #(PCB_SP)] /* now running on the old stack. */
446 1.55.6.2 mjf
447 1.55.6.2 mjf /* At this point we can allow IRQ's again. */
448 1.55.6.2 mjf msr cpsr_c, r6
449 1.55.6.2 mjf
450 1.55.6.2 mjf /*
451 1.55.6.2 mjf * Grab the registers that got pushed at the start and return.
452 1.55.6.2 mjf */
453 1.55.6.2 mjf ldmfd sp!, {r4-r7, ip, lr} /* eat switch frame */
454 1.55.6.2 mjf ldmfd sp!, {r4, r6, r7, pc} /* pop stack and return */
455 1.55.6.2 mjf
456 1.55.6.2 mjf END(softint_switch)
457 1.55.6.2 mjf
458 1.55.6.2 mjf /*
459 1.55.6.2 mjf * r0 = previous LWP (the soft lwp)
460 1.55.6.2 mjf * r4 = original LWP (the current lwp)
461 1.55.6.2 mjf * r6 = original CPSR
462 1.55.6.2 mjf * r7 = curcpu()
463 1.55.6.2 mjf */
464 1.55.6.2 mjf ENTRY_NP(softint_tramp)
465 1.55.6.2 mjf ldr r3, [r7, #(CI_MTX_COUNT)] /* readust after mi_switch */
466 1.55.6.2 mjf add r3, r3, #1
467 1.55.6.2 mjf str r3, [r7, #(CI_MTX_COUNT)]
468 1.55.6.2 mjf
469 1.55.6.2 mjf mov r3, #0 /* tell softint_dispatch */
470 1.55.6.2 mjf str r3, [r0, #(L_CTXSWTCH)] /* the soft lwp blocked */
471 1.55.6.2 mjf
472 1.55.6.2 mjf msr cpsr_c, r6 /* restore interrupts */
473 1.55.6.2 mjf ldmfd sp!, {r4, r6, r7, pc} /* pop stack and return */
474 1.55.6.2 mjf END(softint_tramp)
475 1.55.6.2 mjf #endif /* __HAVE_FAST_SOFTINTS */
476