4xx_locore.S revision 1.1.6.2 1 /* $NetBSD: 4xx_locore.S,v 1.1.6.2 2002/09/06 08:39:01 jdolecek Exp $ */
2
3 /*
4 * Copyright 2001 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Eduardo Horvath and Simon Burge for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 /*
39 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
40 * Copyright (C) 1995, 1996 TooLs GmbH.
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by TooLs GmbH.
54 * 4. The name of TooLs GmbH may not be used to endorse or promote products
55 * derived from this software without specific prior written permission.
56 *
57 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
58 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
59 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
60 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
61 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
62 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
63 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
64 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
65 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
66 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67 */
68
69 /*
70 * This is not a standalone file. To use it, #inlcude it at
71 * the end of your port's locore.S
72 */
73
74 /*
75 * Taken straight from Walnut's locore.S, with the following attribution:
76 * $OpenBSD: locore.S,v 1.4 1997/01/26 09:06:38 rahnds Exp $
77 */
78
79 /*
80 * No processes are runnable, so loop waiting for one.
81 * Separate label here for accounting purposes.
82 * When we get here, interrupts are off (MSR[EE]=0) and sched_lock is held.
83 */
84 ASENTRY(Idle)
85 lis 8,_C_LABEL(sched_whichqs)@ha
86 lwz 9,_C_LABEL(sched_whichqs)@l(8)
87
88 or. 9,9,9
89 bne- .Lsw1 /* at least one queue non-empty */
90
91 wrteei 1 /* reenable ints again */
92
93 /* May do some power saving here? */
94 /* Check if we can use power saving mode */
95 lis 8,_C_LABEL(powersave)@ha
96 lwz 9,_C_LABEL(powersave)@l(8)
97
98 or. 9,9,9
99 beq 1f
100
101 /* TODO: Enter power saving mode here */
102 1:
103
104 wrteei 0 /* disable interrupts while manipulating runque */
105
106 b _ASM_LABEL(Idle)
107
108 /*
109 * switchexit gets called from cpu_exit to complete the exit procedure.
110 */
111 ENTRY(switchexit)
112 /* First switch to the idle pcb/kernel stack */
113 lis 6,idle_u@ha
114 lwz 6,idle_u@l(6)
115 lis 7,_C_LABEL(curpcb)@ha
116 stw 6,_C_LABEL(curpcb)@l(7)
117 addi 1,6,USPACE-16 /* 16 bytes are reserved at stack top */
118 /*
119 * Schedule the vmspace and stack to be freed (the proc arg is
120 * already in r3).
121 */
122 bl _C_LABEL(exit2)
123
124 /* Fall through to cpu_switch to actually select another proc */
125 li 3,0 /* indicate exited process */
126
127 /*
128 * void cpu_switch(struct proc *p)
129 * Find a runnable process and switch to it.
130 */
131 /* XXX noprofile? --thorpej (at) netbsd.org */
132 ENTRY(cpu_switch)
133 mflr 0 /* save lr */
134 stw 0,4(1)
135 stwu 1,-16(1)
136 stw 31,12(1)
137 stw 30,8(1)
138
139 mr 30,3
140 lis 3,_C_LABEL(curproc)@ha
141 xor 31,31,31
142 stw 31,_C_LABEL(curproc)@l(3) /* Zero to not accumulate cpu time */
143 lis 3,_C_LABEL(curpcb)@ha
144 lwz 31,_C_LABEL(curpcb)@l(3)
145
146 xor 3,3,3
147 bl _C_LABEL(lcsplx)
148 stw 3,PCB_SPL(31) /* save spl */
149
150 wrteei 0 /* disable interrupts while manipulating runque */
151
152 /* Find a new process */
153 lis 8,_C_LABEL(sched_whichqs)@ha
154 lwz 9,_C_LABEL(sched_whichqs)@l(8)
155
156 or. 9,9,9
157 beq- _ASM_LABEL(Idle) /* all queues empty */
158 .Lsw1:
159 cntlzw 10,9
160 lis 4,_C_LABEL(sched_qs)@ha
161 addi 4,4,_C_LABEL(sched_qs)@l
162 slwi 3,10,3
163 add 3,3,4 /* select queue */
164
165 lwz 31,P_FORW(3) /* unlink first proc from queue */
166 lwz 4,P_FORW(31)
167 stw 4,P_FORW(3)
168 stw 3,P_BACK(4)
169
170 cmpl 0,3,4 /* queue empty? */
171 bne 1f
172
173 lis 3,0x80000000@h
174 srw 3,3,10
175 andc 9,9,3
176 stw 9,_C_LABEL(sched_whichqs)@l(8) /* mark it empty */
177
178 1:
179 /* just did this resched thing */
180 xor 3,3,3
181 lis 4,_C_LABEL(want_resched)@ha
182 stw 3,_C_LABEL(want_resched)@l(4)
183
184 stw 3,P_BACK(31) /* probably superfluous */
185
186 /* Process now running on a processor. */
187 li 3,SONPROC /* p->p_stat = SONPROC */
188 stb 3,P_STAT(31)
189
190 /* record new process */
191 lis 4,_C_LABEL(curproc)@ha
192 stw 31,_C_LABEL(curproc)@l(4)
193
194 wrteei 1 /* Now we can interrupt again */
195
196 cmpl 0,31,30 /* is it the same process? */
197 beq switch_return
198
199 or. 30,30,30 /* old process was exiting? */
200 beq switch_exited
201
202 #ifndef PPC_IBM4XX
203 mfsr 10,USER_SR /* save USER_SR for copyin/copyout */
204 #else
205 li 10,0 /* no SR for 4xx CPUs */
206 #endif
207 mfcr 11 /* save cr */
208 mr 12,2 /* save r2 */
209 stwu 1,-SFRAMELEN(1) /* still running on old stack */
210 stmw 10,8(1)
211 lwz 3,P_ADDR(30)
212 stw 1,PCB_SP(3) /* save SP */
213
214 switch_exited:
215 wrteei 0 /* disable interrupts while actually switching */
216
217 /* indicate new pcb */
218 lwz 4,P_ADDR(31)
219 lis 5,_C_LABEL(curpcb)@ha
220 stw 4,_C_LABEL(curpcb)@l(5)
221
222 /* save real pmap pointer for spill fill */
223 lwz 5,PCB_PMR(4)
224 lis 6,_C_LABEL(curpm)@ha
225 stwu 5,_C_LABEL(curpm)@l(6)
226 stwcx. 5,0,6 /* clear possible reservation */
227
228 /* Switch to the new virtual space */
229 /* Do not have to do anything here. TLB PID gets updated on return from trap. */
230
231 lwz 1,PCB_SP(4) /* get new procs SP */
232
233 wrteei 1 /* interrupts are okay again */
234
235 lmw 10,8(1) /* get other regs */
236 lwz 1,0(1) /* get saved SP */
237 mr 2,12 /* get saved r2 */
238 mtcr 11 /* get saved cr */
239 isync
240
241 switch_return:
242 mr 30,7 /* save proc pointer */
243
244 lwz 3,PCB_SPL(4)
245 bl _C_LABEL(lcsplx)
246
247 0:
248 lis 3,_C_LABEL(curpm)@ha
249 addi 3,3,_C_LABEL(curpm)@l /* Do we need a context? */
250 lwz 4,PM_CTX(3)
251 cmpwi 4,0
252 # mtspr SPR_SPR0,4 /* Always keep the current ctx here */
253 mr 3,30
254 bne 1f
255 bl _C_LABEL(ctx_alloc)
256 mr 3,30 /* get curproc for special fork
257 returns */
258 b 0b /* Reload */
259 1:
260 lwz 31,12(1)
261 lwz 30,8(1)
262 addi 1,1,16
263 lwz 0,4(1)
264 mtlr 0
265 blr
266
267 /*
268 * Child comes here at the end of a fork.
269 * Return to userspace via the trap return path.
270 */
271 .globl _C_LABEL(fork_trampoline)
272 _C_LABEL(fork_trampoline):
273 xor 3,3,3
274 bl _C_LABEL(lcsplx)
275 mtlr 31
276 mr 3,30
277 blrl /* jump indirect to r31 */
278 b trapexit
279
280 /*
281 * Pull in common trap vector code.
282 */
283 #include <powerpc/ibm4xx/trap_subr.S>
284 #include <powerpc/ibm4xx/4xx_trap_subr.S>
285
286 /*
287 * int setfault()
288 *
289 * Similar to setjmp to setup for handling faults on accesses to user memory.
290 * Any routine using this may only call bcopy, either the form below,
291 * or the (currently used) C code optimized, so it doesn't use any non-volatile
292 * registers.
293 */
294 .globl _C_LABEL(setfault)
295 _C_LABEL(setfault):
296 mflr 0
297 mfcr 12
298 lis 4,_C_LABEL(curpcb)@ha
299 lwz 4,_C_LABEL(curpcb)@l(4)
300 stw 3,PCB_FAULT(4)
301 stw 0,0(3)
302 stw 1,4(3)
303 stw 2,8(3)
304 stmw 12,12(3)
305 xor 3,3,3
306 blr
307
308 .globl _C_LABEL(ppc4xx_reset)
309 _C_LABEL(ppc4xx_reset):
310 mfspr 3,SPR_DBCR0
311 oris 3,r13,DBCR0_RST_SYSTEM@h
312 mtspr SPR_DBCR0,3
313 ba 0
314
315 #if 0
316 /*
317 * XXXX the following doesn't quite work right yet.
318 */
319 /*
320 * void bcopy(const void *src, void *dst, size_t len);
321 *
322 * swap r3 and r4 and fall through to memcopy.
323 */
324 .globl _C_LABEL(bcopy)
325 _C_LABEL(bcopy):
326 mr r0,r3
327 mr r3,r4
328 mr r4,r0
329 /* FALLTHROUGH */
330
331 /*
332 * void * memcpy(void *dst (r3), const void *src (r4), size_t len (r5));
333 *
334 * Copy memory (obviously)
335 *
336 * We will try to do data cache block aligned stores so we
337 * can use block allocate and not have to read from the
338 * destination.
339 *
340 * Register use:
341 *
342 * r1 stack (of course)
343 * r3 dst
344 * r4 src
345 * r5 len
346 * r6 tmp
347 * r7 holds 32
348 * r8 holds dst
349 * r24-r31 block move regs
350 *
351 */
352
353 ENTRY(memcpy)
354 stwu r1,-(10*4)(r1) /* Allocate some RAM to save 8 regs to. */
355 cmpwi r5, 32 /* Less than 32 bytes ? */
356 stmw r24,8(r1) /* Save ALL regs (could be optimized) */
357
358 mr r8,r3 /* save dst */
359 li r7,32
360
361 dcbt 0,r4 /* Start bringing in cache line. */
362 blt 1f /* Finish up */
363
364 neg r6,r3 /* Find how far unaligned we are... */
365 andi. r6,r6,31 /* Cache-align dest. */
366 mtxer r6
367 sub r5,r5,r6 /* subtract count */
368 lswx r24,0,r4 /* Load some. */
369 add r4,r4,r6
370 dcbt 0,r4 /* Fetch next line */
371 stswx r24,0,r3 /* Store some */
372 add r3,r3,r6
373 addic. r6,r5,-32 /* Pre-decrement next line */
374 ble 1f /* Less than 32-bytes? finishup */
375
376 /* Dest should not be cache line aligned. */
377 /* XXX need gas 2.11 to grok dcba insn */
378 #ifdef GAS_2_11
379 dcba 0,r3 /* Allocate a line */
380 #else
381 .long 0x7c001dec /* dcba 0,r3 */
382 #endif
383 0:
384 dcbt r7,r4 /* Bring in the next line, too */
385
386 lswi r24,r4,32
387 addi r4,r4,32 /* Inc src */
388 mr r5,r6
389
390 addic. r6,r5,-32
391 stswi r24,r3,32
392 addi r3,r3,32 /* Inc dst */
393 #ifdef GAS_2_11
394 dcba 0,r3 /* Allocate another line */
395 #else
396 .long 0x7c071dec /* dcba r7,r3 */
397 #endif
398 bgt 0b
399 1:
400 mtxer r5 /* Store byte count */
401 lswx r24,0,r4 /* Load up to 32 bytes */
402 stswx r24,0,r3 /* Store up to 32 bytes */
403
404 mr r3,r8 /* Return dst */
405
406 lmw r24,8(r1)
407 addi r1,r1,(10*4)
408 blr
409 #endif
410