Annotation of sys/arch/m88k/m88k/process.S, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: process.S,v 1.16 2007/05/12 19:59:52 miod Exp $ */
2: /*
3: * Copyright (c) 1996 Nivas Madhur
4: * All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: * 3. All advertising materials mentioning features or use of this software
15: * must display the following acknowledgement:
16: * This product includes software developed by Nivas Madhur.
17: * 4. The name of the author may not be used to endorse or promote products
18: * derived from this software without specific prior written permission
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30: *
31: */
32:
33: #include "assym.h"
34: #include <machine/asm.h>
35: #include <machine/psl.h>
36: #include <machine/intr.h>
37:
38: #ifdef DIAGNOSTIC
39: data
40: align 4
41: ASLOCAL(swchanpanic)
42: string "switch wchan %x\0"
43: align 4
44: ASLOCAL(swsrunpanic)
45: string "switch SRUN %x\0"
46:
47: text
48: align 8
49: ASLOCAL(Lswchanpanic)
50: or.u r2, r0, hi16(_ASM_LABEL(swchanpanic))
51: or r2, r2, lo16(_ASM_LABEL(swchanpanic))
52: bsr.n _C_LABEL(panic)
53: or r3, r0, r9
54:
55: ASLOCAL(Lswsrunpanic)
56: or.u r2, r0, hi16(_ASM_LABEL(swsrunpanic))
57: or r2, r2, lo16(_ASM_LABEL(swsrunpanic))
58: bsr.n _C_LABEL(panic)
59: or r3, r0, r9
60: #endif
61:
62: /*
63: * void switch_exit(struct proc *p)
64: *
65: * Do the final work to exit from a process. After switching to the
66: * idle stack and pcb, invoke exit2() on behalf of the exiting process,
67: * then continue into cpu_switch() to select another process to run.
68: */
69:
70: ENTRY(switch_exit)
71: /*
72: * Disable interrupts since we are about to change the kernel
73: * stack.
74: */
75: ldcr r3, PSR
76: set r3, r3, 1<PSR_INTERRUPT_DISABLE_BIT>
77: stcr r3, PSR
78: FLUSH_PIPELINE
79:
80: /*
81: * Change pcb to idle u. area, i.e., set r31 to top of stack
82: * and set curpcb to point to the cpu's idle stack.
83: * r2 contains proc *p.
84: */
85: ldcr r10, CPU
86: ld r30, r10, CI_IDLE_PCB
87: addu r31, r30, USIZE /* now on idle stack */
88: st r30, r10, CI_CURPCB /* curpcb = idle_pcb */
89:
90: /* Schedule the vmspace and stack to be freed. */
91: bsr.n _C_LABEL(exit2)
92: st r0, r10, CI_CURPROC /* curproc = NULL */
93:
94: /*
95: * exit2() has acquired the scheduler lock for us. Jump into
96: * cpu_switch(), after the context save since we do not need
97: * to save anything.
98: */
99: br _ASM_LABEL(cpu_switch_search)
100:
101: /*
102: * void cpu_switch(struct proc *p)
103: *
104: * Find a runnable process and switch to it. On entry, the scheduler lock is
105: * held; it has to be released before returning to the process.
106: *
107: * Note that this code ignores its proc parameter and assumes it has the
108: * same value as curproc. This may change in mi_switch() in the future,
109: * be careful.
110: */
111: ENTRY(cpu_switch)
112: /*
113: * Disable interrupts, we do not want to be disturbed while
114: * saving context.
115: */
116: ldcr r2, PSR
117: set r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT>
118: stcr r2, PSR
119: FLUSH_PIPELINE
120:
121: /*
122: * Save state of previous process in its pcb, and pmap_deactivate()
123: * the process.
124: */
125: ldcr r2, CPU
126: ld r2, r2, CI_CURPCB
127: st r1, r2, PCB_PC /* save return address */
128: bsr _ASM_LABEL(__savectx)
129: /* note that we don't need to recover r1 at this point */
130:
131: ldcr r11, CPU
132: ld r2, r11, CI_CURPROC
133:
134: /*
135: * Note that we can still use curpcb as our stack after
136: * pmap_deactivate() has been called, as it does not affect the u
137: * area mappings.
138: */
139: bsr.n _C_LABEL(pmap_deactivate)
140: st r0, r11, CI_CURPROC /* curproc = NULL */
141:
142: #ifdef MULTIPROCESSOR
143: /*
144: * We need to switch to the processor's idle stack now (in case the
145: * process we are using the stack of gets scheduled on another
146: * processor).
147: */
148: ldcr r10, CPU
149: ld r30, r10, CI_IDLE_PCB
150: addu r31, r30, USIZE /* now on idle stack */
151: st r30, r10, CI_CURPCB /* curpcb = idle_pcb */
152: #endif
153:
154: ASLOCAL(cpu_switch_search)
155: /*
156: * This is the start of the idle loop. Find the highest-priority
157: * queue that isn't empty, then take the first proc from that queue.
158: */
159: or.u r7, r0, hi16(_C_LABEL(whichqs))
160: ld r7, r7, lo16(_C_LABEL(whichqs))
161: bcnd ne0, r7, _ASM_LABEL(cpu_switch_found)
162:
163: #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
164: bsr _C_LABEL(sched_unlock_idle)
165: #endif
166:
167: #ifdef MULTIPROCESSOR
168: ASGLOBAL(cpu_switch_idle)
169: #else
170: ASLOCAL(cpu_switch_idle)
171: #endif
172: /*
173: * There were no runnable processes. Enable all interrupts and
174: * busy-wait for this to change.
175: * Note that, besides doing setipl(IPL_NONE), this will actually enable
176: * interrupts in the psr. Bootstrap of secondary processors
177: * relies upon this.
178: */
179: ldcr r2, PSR
180: clr r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT>
181: stcr r2, PSR
182: FLUSH_PIPELINE
183:
184: bsr.n _C_LABEL(setipl)
185: or r2, r0, IPL_NONE
186:
187: or.u r7, r0, hi16(_C_LABEL(whichqs))
188: ld r7, r7, lo16(_C_LABEL(whichqs))
189: bcnd eq0, r7, _ASM_LABEL(cpu_switch_idle)
190: /* XXX run fancy things here, such as page zeroing... */
191:
192: #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
193: bsr _C_LABEL(sched_lock_idle)
194: #endif
195:
196: ASLOCAL(cpu_switch_found)
197: /*
198: * Disable interrupts.
199: */
200: ldcr r2, PSR
201: set r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT>
202: stcr r2, PSR
203: FLUSH_PIPELINE
204:
205: /*
206: * An interrupt could have occured between the last whichqs check
207: * and the call to setipl(). Check again that whichqs is nonzero.
208: */
209: or.u r7, r0, hi16(_C_LABEL(whichqs)) /* reload whichqs */
210: ld r7, r7, lo16(_C_LABEL(whichqs))
211: bcnd eq0, r7, _ASM_LABEL(cpu_switch_search)
212:
213: /* XXX use ff1, like powerpc... needs *runqueue() adjustments */
214: xor r6, r6, r6 /* set r6 to 0 */
215: 1: bb1 0, r7, 2f /* if rightmost bit set, done */
216: extu r7, r7, 0<1> /* else, right shift whichqs, */
217: br.n 1b /* increment r6, and repeat */
218: addu r6, r6, 1
219: 2:
220: or.u r7, r0, hi16(_C_LABEL(qs))
221: or r7, r7, lo16(_C_LABEL(qs))
222:
223: /*
224: * Need to make
225: * p->p_forw->p_back = p->p_back and
226: * p->p_back->p_forw = p->p_forw where
227: * p is q->p_forw.
228: * Remember that q->p_forw == p and p->p_back == q.
229: */
230:
231: lda.d r8, r7[r6] /* r8 = &qs[ff1(whichqs)] */
232: ld r9, r8, P_FORW /* r8 is q, r9 is p */
233:
234: ld r12, r9, P_FORW /* r12 = p->p_forw */
235: st r8, r12, P_BACK /* p->p_forw->p_back = q (p->p_back) */
236: st r12, r8, P_FORW /* q->p_forw = p->p_forw */
237: lda.d r8, r7[r6] /* reload r8 with qs[ff1(whichqs)] */
238: ld r12, r8, P_FORW /* q->p_forw */
239: cmp r12, r12, r8 /* q == q->p_forw; anyone left on queue? */
240: bb1 ne, r12, 3f /* yes, skip clearing bit in whichqs */
241:
242: or r12, r0, 1
243: mak r12, r12, r6
244: or.u r7, r0, hi16(_C_LABEL(whichqs))
245: ld r8, r7, lo16(_C_LABEL(whichqs))
246: and.c r8, r8, r12 /* whichqs &= ~the bit */
247: st r8, r7, lo16(_C_LABEL(whichqs))
248: 3:
249: #ifdef DIAGNOSTIC
250: ld r2, r9, P_WCHAN
251: bcnd ne0, r2, _ASM_LABEL(Lswchanpanic)
252: ld.b r2, r9, P_STAT
253: cmp r2, r2, SRUN
254: bb1 ne, r2, _ASM_LABEL(Lswsrunpanic)
255: #endif
256:
257: ldcr r11, CPU
258: st r0, r11, CI_WANT_RESCHED /* clear want_resched */
259:
260: st r9, r11, CI_CURPROC /* curproc = p */
261: or r2, r0, SONPROC
262: st.b r2, r9, P_STAT
263: #ifdef MULTIPROCESSOR
264: st r11, r9, P_CPU /* p->p_cpu = curcpu */
265: #endif
266:
267: ld r3, r9, P_ADDR
268: st r0, r9, P_BACK /* p->p_back = 0 */
269: st r3, r11, CI_CURPCB /* curpcb = p->p_addr */
270:
271: /* pmap_activate() the process' pmap */
272: bsr.n _C_LABEL(pmap_activate)
273: or r2, r0, r9
274:
275: ldcr r10, CPU
276: ld r10, r10, CI_CURPCB
277:
278: /* restore from the current context */
279: ld r2, r10, PCB_FCR62
280: ld r3, r10, PCB_FCR63
281: fstcr r2, fcr62
282: fstcr r3, fcr63
283: ld r15, r10, PCB_R15
284: ld r16, r10, PCB_R16
285: ld r17, r10, PCB_R17
286: ld r18, r10, PCB_R18
287: ld r19, r10, PCB_R19
288: ld r20, r10, PCB_R20
289: ld r21, r10, PCB_R21
290: ld r22, r10, PCB_R22
291: ld r23, r10, PCB_R23
292: ld r24, r10, PCB_R24
293: ld r25, r10, PCB_R25
294: ld r26, r10, PCB_R26
295: ld r27, r10, PCB_R27
296: ld r28, r10, PCB_R28
297: ld r29, r10, PCB_R29
298: ld r30, r10, PCB_R30 /* restore frame pointer & stack */
299: ld r31, r10, PCB_SP
300: #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
301: bsr.n _C_LABEL(sched_unlock_idle)
302: or r14, r10, r0
303: ld r1, r14, PCB_PC
304: ld r14, r14, PCB_R14
305: #else
306: ld r1, r10, PCB_PC
307: ld r14, r10, PCB_R14
308: #endif
309:
310: /*
311: * Enable interrupts again.
312: */
313: ldcr r2, PSR
314: clr r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT>
315: stcr r2, PSR
316: FLUSH_PIPELINE
317:
318: jmp r1
319:
320: /*
321: * savectx(pcb)
322: * Update pcb, saving current processor state.
323: */
324: ENTRY(savectx)
325: /*
326: * Save preserved general register set.
327: */
328: st r1, r2, PCB_PC /* save return address */
329: ASLOCAL(__savectx)
330: st r14, r2, PCB_R14
331: st r15, r2, PCB_R15
332: st r16, r2, PCB_R16
333: st r17, r2, PCB_R17
334: st r18, r2, PCB_R18
335: st r19, r2, PCB_R19
336: st r20, r2, PCB_R20
337: st r21, r2, PCB_R21
338: st r22, r2, PCB_R22
339: st r23, r2, PCB_R23
340: st r24, r2, PCB_R24
341: st r25, r2, PCB_R25
342: st r26, r2, PCB_R26
343: st r27, r2, PCB_R27
344: st r28, r2, PCB_R28
345: st r29, r2, PCB_R29
346: st r30, r2, PCB_R30 /* save frame pointer & stack pointer */
347: st r31, r2, PCB_SP
348:
349: /*
350: * Save FP state.
351: */
352: fldcr r4, fcr62
353: fldcr r5, fcr63
354: st r4, r2, PCB_FCR62
355: jmp.n r1
356: st r5, r2, PCB_FCR63
CVSweb