xref: /openbsd/sys/arch/m88k/m88k/process.S (revision e0004d15)
1/*	$OpenBSD: process.S,v 1.15 2006/11/22 22:49:02 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
41ASLOCAL(swchanpanic)
42	string	"switch wchan %x\0"
43	align	4
44ASLOCAL(swsrunpanic)
45	string	"switch SRUN %x\0"
46
47	text
48	align	8
49ASLOCAL(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
55ASLOCAL(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
70ENTRY(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 */
111ENTRY(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
154ASLOCAL(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
168ASGLOBAL(cpu_switch_idle)
169#else
170ASLOCAL(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
196ASLOCAL(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 */
2151:	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
2192:
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))
2483:
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
264	ld	r3,  r9,  P_ADDR
265	st	r0,  r9,  P_BACK			/* p->p_back = 0 */
266	st	r3,  r11, CI_CURPCB			/* curpcb = p->p_addr */
267
268	/* pmap_activate() the process' pmap */
269	bsr.n	_C_LABEL(pmap_activate)
270	 or	r2, r0, r9
271
272	ldcr	r10,  CPU
273	ld	r10,  r10, CI_CURPCB
274
275	/* restore from the current context */
276	ld	r2,  r10, PCB_FCR62
277	ld	r3,  r10, PCB_FCR63
278	fstcr	r2,  fcr62
279	fstcr	r3,  fcr63
280	ld	r15, r10, PCB_R15
281	ld	r16, r10, PCB_R16
282	ld	r17, r10, PCB_R17
283	ld	r18, r10, PCB_R18
284	ld	r19, r10, PCB_R19
285	ld	r20, r10, PCB_R20
286	ld	r21, r10, PCB_R21
287	ld	r22, r10, PCB_R22
288	ld	r23, r10, PCB_R23
289	ld	r24, r10, PCB_R24
290	ld	r25, r10, PCB_R25
291	ld	r26, r10, PCB_R26
292	ld	r27, r10, PCB_R27
293	ld	r28, r10, PCB_R28
294	ld	r29, r10, PCB_R29
295	ld	r30, r10, PCB_R30	/* restore frame pointer & stack */
296	ld	r31, r10, PCB_SP
297#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
298	bsr.n	_C_LABEL(sched_unlock_idle)
299	 or	r14, r10, r0
300	ld	r1,  r14, PCB_PC
301	ld	r14, r14, PCB_R14
302#else
303	ld	r1,  r10, PCB_PC
304	ld	r14, r10, PCB_R14
305#endif
306
307	/*
308	 * Enable interrupts again.
309	 */
310	ldcr	r2, PSR
311	clr	r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT>
312	stcr	r2, PSR
313	FLUSH_PIPELINE
314
315	jmp	r1
316
317/*
318 * savectx(pcb)
319 * Update pcb, saving current processor state.
320 */
321ENTRY(savectx)
322	/*
323	 * Save preserved general register set.
324	 */
325	st	r1,  r2,  PCB_PC		/* save return address */
326ASLOCAL(__savectx)
327	st	r14, r2,  PCB_R14
328	st	r15, r2,  PCB_R15
329	st	r16, r2,  PCB_R16
330	st	r17, r2,  PCB_R17
331	st	r18, r2,  PCB_R18
332	st	r19, r2,  PCB_R19
333	st	r20, r2,  PCB_R20
334	st	r21, r2,  PCB_R21
335	st	r22, r2,  PCB_R22
336	st	r23, r2,  PCB_R23
337	st	r24, r2,  PCB_R24
338	st	r25, r2,  PCB_R25
339	st	r26, r2,  PCB_R26
340	st	r27, r2,  PCB_R27
341	st	r28, r2,  PCB_R28
342	st	r29, r2,  PCB_R29
343	st	r30, r2,  PCB_R30	/* save frame pointer & stack pointer */
344	st	r31, r2,  PCB_SP
345
346	/*
347	 * Save FP state.
348	 */
349	fldcr	r4,  fcr62
350	fldcr	r5,  fcr63
351	st	r4,  r2, PCB_FCR62
352	jmp.n	r1
353	 st	r5,  r2, PCB_FCR63
354