cpuswitch.S revision 1.41.16.6 1 1.41.16.6 yamt /* $NetBSD: cpuswitch.S,v 1.41.16.6 2008/03/17 09:14:15 yamt 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.36 martin #include "opt_lockdebug.h"
84 1.1 chris
85 1.1 chris #include "assym.h"
86 1.41.16.2 yamt #include <arm/arm32/pte.h>
87 1.1 chris #include <machine/param.h>
88 1.1 chris #include <machine/cpu.h>
89 1.1 chris #include <machine/frame.h>
90 1.1 chris #include <machine/asm.h>
91 1.1 chris
92 1.34 kristerw /* LINTSTUB: include <sys/param.h> */
93 1.34 kristerw
94 1.1 chris #undef IRQdisable
95 1.1 chris #undef IRQenable
96 1.1 chris
97 1.1 chris /*
98 1.1 chris * New experimental definitions of IRQdisable and IRQenable
99 1.1 chris * These keep FIQ's enabled since FIQ's are special.
100 1.1 chris */
101 1.1 chris
102 1.1 chris #define IRQdisable \
103 1.13 thorpej mrs r14, cpsr ; \
104 1.1 chris orr r14, r14, #(I32_bit) ; \
105 1.13 thorpej msr cpsr_c, r14 ; \
106 1.1 chris
107 1.1 chris #define IRQenable \
108 1.13 thorpej mrs r14, cpsr ; \
109 1.1 chris bic r14, r14, #(I32_bit) ; \
110 1.13 thorpej msr cpsr_c, r14 ; \
111 1.1 chris
112 1.1 chris .text
113 1.1 chris
114 1.19 bjh21 #ifdef MULTIPROCESSOR
115 1.19 bjh21 .Lcpu_info_store:
116 1.19 bjh21 .word _C_LABEL(cpu_info_store)
117 1.29 thorpej .Lcurlwp:
118 1.19 bjh21 /* FIXME: This is bogus in the general case. */
119 1.29 thorpej .word _C_LABEL(cpu_info_store) + CI_CURLWP
120 1.22 bjh21
121 1.22 bjh21 .Lcurpcb:
122 1.22 bjh21 .word _C_LABEL(cpu_info_store) + CI_CURPCB
123 1.19 bjh21 #else
124 1.29 thorpej .Lcurlwp:
125 1.29 thorpej .word _C_LABEL(curlwp)
126 1.1 chris
127 1.17 thorpej .Lcurpcb:
128 1.1 chris .word _C_LABEL(curpcb)
129 1.22 bjh21 #endif
130 1.1 chris
131 1.22 bjh21 #ifndef MULTIPROCESSOR
132 1.1 chris .data
133 1.1 chris .global _C_LABEL(curpcb)
134 1.1 chris _C_LABEL(curpcb):
135 1.1 chris .word 0x00000000
136 1.1 chris .text
137 1.22 bjh21 #endif
138 1.1 chris
139 1.17 thorpej .Lblock_userspace_access:
140 1.1 chris .word _C_LABEL(block_userspace_access)
141 1.1 chris
142 1.30 scw
143 1.1 chris /*
144 1.41.16.3 yamt * struct lwp *
145 1.41.16.3 yamt * cpu_switchto(struct lwp *current, struct lwp *next)
146 1.29 thorpej *
147 1.41.16.3 yamt * Switch to the specified next LWP
148 1.29 thorpej * Arguments:
149 1.41.16.3 yamt *
150 1.29 thorpej * r0 'struct lwp *' of the current LWP
151 1.41.16.3 yamt * r1 'struct lwp *' of the LWP to switch to
152 1.1 chris */
153 1.41.16.3 yamt ENTRY(cpu_switchto)
154 1.41.16.5 yamt mov ip, sp
155 1.41.16.5 yamt stmfd sp!, {r4-r7, ip, lr}
156 1.1 chris
157 1.41.16.5 yamt /* move lwps and new pcb into caller saved registers */
158 1.41.16.5 yamt mov r6, r1
159 1.41.16.5 yamt mov r4, r0
160 1.41.16.5 yamt ldr r7, [r6, #(L_ADDR)]
161 1.7 chris
162 1.41.16.5 yamt /* rem: r4 = old lwp */
163 1.41.16.5 yamt /* rem: r6 = new lwp */
164 1.41.16.5 yamt /* rem: r7 = new pcb */
165 1.41.16.5 yamt
166 1.1 chris IRQdisable
167 1.7 chris
168 1.19 bjh21 #ifdef MULTIPROCESSOR
169 1.19 bjh21 /* XXX use curcpu() */
170 1.19 bjh21 ldr r0, .Lcpu_info_store
171 1.29 thorpej str r0, [r6, #(L_CPU)]
172 1.19 bjh21 #else
173 1.29 thorpej /* l->l_cpu initialized in fork1() for single-processor */
174 1.19 bjh21 #endif
175 1.1 chris
176 1.41.16.5 yamt /* We have a new curlwp and pcb so make a note of them */
177 1.41.16.5 yamt ldr r0, .Lcurlwp
178 1.41.16.5 yamt ldr r1, .Lcurpcb
179 1.41.16.5 yamt
180 1.41.16.5 yamt str r6, [r0]
181 1.41.16.5 yamt str r7, [r1]
182 1.1 chris
183 1.1 chris /* At this point we can allow IRQ's again. */
184 1.1 chris IRQenable
185 1.1 chris
186 1.41.16.3 yamt /* rem: r4 = old lwp */
187 1.41.16.1 yamt /* rem: r6 = new lwp */
188 1.41.16.5 yamt /* rem: r7 = new pcb */
189 1.4 chris /* rem: interrupts are enabled */
190 1.1 chris
191 1.1 chris /*
192 1.41.16.3 yamt * If the old lwp on entry to cpu_switchto was zero then the
193 1.1 chris * process that called it was exiting. This means that we do
194 1.1 chris * not need to save the current context. Instead we can jump
195 1.1 chris * straight to restoring the context for the new process.
196 1.1 chris */
197 1.41.16.3 yamt teq r4, #0x00000000
198 1.41.16.4 yamt beq .Ldo_switch
199 1.1 chris
200 1.41.16.3 yamt /* rem: r4 = old lwp */
201 1.41.16.1 yamt /* rem: r6 = new lwp */
202 1.41.16.5 yamt /* rem: r7 = new pcb */
203 1.4 chris /* rem: interrupts are enabled */
204 1.1 chris
205 1.41.16.3 yamt /* Save old context */
206 1.1 chris
207 1.29 thorpej /* Get the user structure for the old lwp. */
208 1.41.16.5 yamt ldr r5, [r4, #(L_ADDR)]
209 1.1 chris
210 1.29 thorpej /* Save all the registers in the old lwp's pcb */
211 1.37 scw #ifndef __XSCALE__
212 1.41.16.5 yamt add r0, r5, #(PCB_R8)
213 1.41.16.5 yamt stmia r0, {r8-r13}
214 1.37 scw #else
215 1.41.16.5 yamt strd r8, [r5, #(PCB_R8)]
216 1.41.16.5 yamt strd r10, [r5, #(PCB_R10)]
217 1.41.16.5 yamt strd r12, [r5, #(PCB_R12)]
218 1.37 scw #endif
219 1.1 chris
220 1.1 chris /*
221 1.29 thorpej * NOTE: We can now use r8-r13 until it is time to restore
222 1.29 thorpej * them for the new process.
223 1.29 thorpej */
224 1.29 thorpej
225 1.41.16.3 yamt /* rem: r4 = old lwp */
226 1.41.16.5 yamt /* rem: r5 = old pcb */
227 1.41.16.3 yamt /* rem: r6 = new lwp */
228 1.41.16.5 yamt /* rem: r7 = new pcb */
229 1.41.16.3 yamt /* rem: interrupts are enabled */
230 1.41.16.3 yamt
231 1.41.16.3 yamt /* What else needs to be saved? Only FPA stuff when that is supported */
232 1.41.16.6 yamt #ifdef FPU_VFP
233 1.41.16.6 yamt /*
234 1.41.16.6 yamt * Now's a good time to 'save' the VFP context. Note that we
235 1.41.16.6 yamt * don't really force a save here, which can save time if we
236 1.41.16.6 yamt * end up restarting the same context.
237 1.41.16.6 yamt */
238 1.41.16.6 yamt bl _C_LABEL(vfp_savecontext)
239 1.41.16.6 yamt #endif
240 1.1 chris
241 1.41.16.3 yamt /* Restore saved context */
242 1.1 chris
243 1.41.16.4 yamt .Ldo_switch:
244 1.41.16.4 yamt mov r0, r4
245 1.41.16.4 yamt mov r1, r6
246 1.41.16.4 yamt bl _C_LABEL(pmap_switch)
247 1.30 scw
248 1.41.16.3 yamt /* rem: r4 = old lwp */
249 1.29 thorpej /* rem: r6 = new lwp */
250 1.41.16.5 yamt /* rem: r7 = new pcb */
251 1.41.16.5 yamt /* rem: interrupts are enabled */
252 1.1 chris
253 1.41.16.5 yamt ldr r5, [r6, #(L_PROC)] /* fetch the proc for below */
254 1.1 chris
255 1.41.16.5 yamt /* Restore all the saved registers */
256 1.37 scw #ifndef __XSCALE__
257 1.41.16.5 yamt add r0, r7, #PCB_R8
258 1.41.16.5 yamt ldmia r0, {r8-r13}
259 1.37 scw #else
260 1.37 scw ldr r8, [r7, #(PCB_R8)]
261 1.37 scw ldr r9, [r7, #(PCB_R9)]
262 1.37 scw ldr r10, [r7, #(PCB_R10)]
263 1.37 scw ldr r11, [r7, #(PCB_R11)]
264 1.37 scw ldr r12, [r7, #(PCB_R12)]
265 1.37 scw ldr r13, [r7, #(PCB_SP)]
266 1.37 scw #endif
267 1.29 thorpej
268 1.41.16.3 yamt /* rem: r4 = old lwp */
269 1.29 thorpej /* rem: r5 = new lwp's proc */
270 1.29 thorpej /* rem: r6 = new lwp */
271 1.29 thorpej /* rem: r7 = new pcb */
272 1.18 thorpej
273 1.41.16.6 yamt #ifdef FPU_VFP
274 1.41.16.6 yamt mov r0, r6
275 1.41.16.6 yamt bl _C_LABEL(vfp_loadcontext)
276 1.41.16.6 yamt #endif
277 1.1 chris #ifdef ARMFPE
278 1.29 thorpej add r0, r7, #(USER_SIZE) & 0x00ff
279 1.1 chris add r0, r0, #(USER_SIZE) & 0xff00
280 1.1 chris bl _C_LABEL(arm_fpe_core_changecontext)
281 1.1 chris #endif
282 1.1 chris
283 1.41.16.3 yamt /* rem: r4 = old lwp */
284 1.29 thorpej /* rem: r5 = new lwp's proc */
285 1.29 thorpej /* rem: r6 = new lwp */
286 1.18 thorpej /* rem: r7 = new PCB */
287 1.18 thorpej
288 1.18 thorpej /*
289 1.18 thorpej * Check for restartable atomic sequences (RAS).
290 1.18 thorpej */
291 1.18 thorpej
292 1.39 dsl ldr r2, [r5, #(P_RASLIST)]
293 1.38 scw ldr r1, [r7, #(PCB_TF)] /* r1 = trapframe (used below) */
294 1.18 thorpej teq r2, #0 /* p->p_nras == 0? */
295 1.18 thorpej bne .Lswitch_do_ras /* no, check for one */
296 1.18 thorpej
297 1.14 briggs .Lswitch_return:
298 1.41.16.3 yamt /* cpu_switchto returns the old lwp */
299 1.29 thorpej mov r0, r4
300 1.41.16.3 yamt /* lwp_trampoline expects new lwp as it's second argument */
301 1.41.16.3 yamt mov r1, r6
302 1.1 chris
303 1.1 chris /*
304 1.41.16.5 yamt * Pull the registers that got pushed when cpu_switchto() was called,
305 1.41.16.5 yamt * and return.
306 1.1 chris */
307 1.41.16.5 yamt ldmfd sp, {r4-r7, sp, pc}
308 1.18 thorpej
309 1.18 thorpej .Lswitch_do_ras:
310 1.38 scw ldr r1, [r1, #(TF_PC)] /* second ras_lookup() arg */
311 1.29 thorpej mov r0, r5 /* first ras_lookup() arg */
312 1.18 thorpej bl _C_LABEL(ras_lookup)
313 1.18 thorpej cmn r0, #1 /* -1 means "not in a RAS" */
314 1.38 scw ldrne r1, [r7, #(PCB_TF)]
315 1.38 scw strne r0, [r1, #(TF_PC)]
316 1.18 thorpej b .Lswitch_return
317 1.1 chris
318 1.41.16.5 yamt ENTRY(lwp_trampoline)
319 1.1 chris /*
320 1.41.16.5 yamt * cpu_switchto gives us:
321 1.41.16.5 yamt *
322 1.41.16.5 yamt * arg0(r0) = old lwp
323 1.41.16.5 yamt * arg1(r1) = new lwp
324 1.1 chris */
325 1.41.16.3 yamt bl _C_LABEL(lwp_startup)
326 1.38 scw
327 1.1 chris mov r0, r5
328 1.1 chris mov r1, sp
329 1.24 bjh21 mov lr, pc
330 1.1 chris mov pc, r4
331 1.1 chris
332 1.1 chris /* Kill irq's */
333 1.13 thorpej mrs r0, cpsr
334 1.1 chris orr r0, r0, #(I32_bit)
335 1.13 thorpej msr cpsr_c, r0
336 1.1 chris
337 1.1 chris PULLFRAME
338 1.1 chris
339 1.1 chris movs pc, lr /* Exit */
340