xref: /openbsd/sys/arch/m88k/m88k/process.S (revision 7625720e)
1/*	$OpenBSD: process.S,v 1.13 2005/12/11 21:45:30 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	 * Change pcb to idle u. area, i.e., set r31 to top of stack
73	 * and set curpcb to point to the cpu's idle stack.
74	 * r2 contains proc *p.
75	 */
76	ldcr	r10, CPU
77	ld	r30, r10, CI_IDLE_PCB
78	addu	r31, r30, USIZE				/* now on idle stack */
79	st	r30, r10, CI_CURPCB			/* curpcb = idle_pcb */
80
81	/* Schedule the vmspace and stack to be freed. */
82	bsr.n	_C_LABEL(exit2)
83	 st	r0, r10, CI_CURPROC			/* curproc = NULL */
84
85	/*
86	 * exit2() has acquired the scheduler lock for us. Jump into
87	 * cpu_switch(), after the context save since we do not need
88	 * to save anything.
89	 */
90	bsr	_ASM_LABEL(cpu_switch_search)
91
92/*
93 * void cpu_switch(struct proc *p)
94 *
95 * Find a runnable process and switch to it. On entry, the scheduler lock is
96 * held; it has to be released before returning to the process.
97 *
98 * Note that this code ignores its proc parameter and assumes it has the
99 * same value as curproc. This may change in mi_switch() in the future,
100 * be careful.
101 */
102ENTRY(cpu_switch)
103	/*
104	 * Save state of previous process in its pcb, and pmap_deactivate()
105	 * the process.
106	 */
107	ldcr	r2,  CPU
108	ld	r2,  r2,  CI_CURPCB
109	st	r1,  r2,  PCB_PC		/* save return address */
110	bsr	_ASM_LABEL(__savectx)
111	/* note that we don't need to recover r1 at this point */
112
113	ldcr	r11, CPU
114	ld	r2,  r11, CI_CURPROC
115
116	/*
117	 * Note that we can still use curpcb as our stack after
118	 * pmap_deactivate() has been called, as it does not affect the u
119	 * area mappings.
120	 */
121	bsr.n	_C_LABEL(pmap_deactivate)
122	 st	r0,  r11, CI_CURPROC		/* curproc = NULL */
123
124ASLOCAL(cpu_switch_search)
125	/*
126	 * This is the start of the idle loop. Find the highest-priority
127	 * queue that isn't empty, then take the first proc from that queue.
128	 */
129	or.u	r7, r0, hi16(_C_LABEL(whichqs))
130	ld	r7, r7, lo16(_C_LABEL(whichqs))
131	bcnd	ne0, r7, _ASM_LABEL(cpu_switch_found)
132
133#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
134	bsr	_C_LABEL(sched_unlock_idle)
135#endif
136
137#ifdef MULTIPROCESSOR
138ASGLOBAL(cpu_switch_idle)
139#endif
140	/*
141	 * There were no runnable processes. Enable all interrupts and
142	 * busy-wait for this to change.
143	 * Note that, besides doing setipl(IPL_NONE), this will actually enable
144	 * interrupts in the psr. Bootstrap of secondary processors
145	 * relies upon this.
146	 */
147	ldcr	r2, PSR
148	bb0	PSR_INTERRUPT_DISABLE_BIT, r2, 2f
149	clr	r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT>
150	stcr	r2, PSR
151	FLUSH_PIPELINE
1522:
153	bsr.n	_C_LABEL(setipl)
154	 or	r2, r0, IPL_NONE
155
156	or.u	r7, r0, hi16(_C_LABEL(whichqs))
157	ld	r7, r7, lo16(_C_LABEL(whichqs))
158	bcnd	eq0, r7, 2b
159	/* XXX run fancy things here, such as page zeroing... */
160
161#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
162	bsr	_C_LABEL(sched_lock_idle)
163#endif
164
165ASLOCAL(cpu_switch_found)
166	bsr.n	_C_LABEL(setipl)		/* disable interrupts */
167	 or	r2, r0, IPL_HIGH
168
169	/*
170	 * An interrupt could have occured between the last whichqs check
171	 * and the call to setipl(). Check again that whichqs is nonzero.
172	 */
173	or.u	r7, r0, hi16(_C_LABEL(whichqs))	/* reload whichqs */
174	ld	r7, r7, lo16(_C_LABEL(whichqs))
175	bcnd	eq0, r7, _ASM_LABEL(cpu_switch_search)
176
177	/* XXX use ff1, like powerpc... needs *runqueue() adjustments */
178	xor	r6, r6, r6		/* set r6 to 0 */
1791:	bb1	0,  r7, 2f		/* if rightmost bit set, done */
180	extu	r7, r7, 0<1>		/* else, right shift whichqs, */
181	br.n	1b			/* increment r6, and repeat */
182	 addu	r6, r6, 1
1832:
184	or.u	r7, r0, hi16(_C_LABEL(qs))
185	or	r7, r7, lo16(_C_LABEL(qs))
186
187	/*
188	 * Need to make
189	 *	p->p_forw->p_back = p->p_back and
190	 *	p->p_back->p_forw = p->p_forw where
191	 *	p is q->p_forw.
192	 * Remember that q->p_forw == p and p->p_back == q.
193	 */
194
195	lda.d	r8,  r7[r6]	/* r8 = &qs[ff1(whichqs)] */
196	ld	r9,  r8, P_FORW	/* r8 is q, r9 is p */
197
198	ld	r12, r9, P_FORW	/* r12 = p->p_forw */
199	st	r8, r12, P_BACK	/* p->p_forw->p_back = q (p->p_back) */
200	st	r12, r8, P_FORW	/* q->p_forw = p->p_forw */
201	lda.d	r8,  r7[r6]	/* reload r8 with qs[ff1(whichqs)] */
202	ld	r12, r8, P_FORW	/* q->p_forw */
203	cmp	r12, r12, r8	/* q == q->p_forw; anyone left on queue? */
204	bb1	ne,  r12, 3f	/* yes, skip clearing bit in whichqs  */
205
206	or	r12, r0, 1
207	mak	r12, r12, r6
208	or.u	r7,  r0, hi16(_C_LABEL(whichqs))
209	ld	r8,  r7, lo16(_C_LABEL(whichqs))
210	and.c	r8,  r8, r12	/* whichqs &= ~the bit */
211	st	r8,  r7, lo16(_C_LABEL(whichqs))
2123:
213#ifdef DIAGNOSTIC
214	ld	r2, r9, P_WCHAN
215	bcnd	ne0, r2, _ASM_LABEL(Lswchanpanic)
216	ld.b	r2, r9, P_STAT
217	cmp	r2, r2, SRUN
218	bb1	ne, r2, _ASM_LABEL(Lswsrunpanic)
219#endif
220
221	ldcr	r11, CPU
222	st	r0,  r11, CI_WANT_RESCHED		/* clear want_resched */
223
224	st	r9,  r11, CI_CURPROC			/* curproc = p */
225	or	r2,  r0,  SONPROC
226	st.b	r2,  r9,  P_STAT
227
228	ld	r3,  r9,  P_ADDR
229	st	r0,  r9,  P_BACK			/* p->p_back = 0 */
230	st	r3,  r11, CI_CURPCB			/* curpcb = p->p_addr */
231
232	/* pmap_activate() the process' pmap */
233	bsr.n	_C_LABEL(pmap_activate)
234	 or	r2, r0, r9
235
236	ldcr	r10,  CPU
237	ld	r10,  r10, CI_CURPCB
238
239	/* restore from the current context */
240	ld	r2,  r10, PCB_FCR62
241	ld	r3,  r10, PCB_FCR63
242	fstcr	r2,  fcr62
243	fstcr	r3,  fcr63
244	ld	r15, r10, PCB_R15
245	ld	r16, r10, PCB_R16
246	ld	r17, r10, PCB_R17
247	ld	r18, r10, PCB_R18
248	ld	r19, r10, PCB_R19
249	ld	r20, r10, PCB_R20
250	ld	r21, r10, PCB_R21
251	ld	r22, r10, PCB_R22
252	ld	r23, r10, PCB_R23
253	ld	r24, r10, PCB_R24
254	ld	r25, r10, PCB_R25
255	ld	r26, r10, PCB_R26
256	ld	r27, r10, PCB_R27
257	ld	r28, r10, PCB_R28
258	ld	r29, r10, PCB_R29
259	or	r14, r10, r0		/* preserve curpcb in a register... */
260	bsr.n	_C_LABEL(setipl)
261	 ld	r2,  r10, PCB_IPL	/* restore interrupt mask */
262	ld	r1,  r14, PCB_PC
263	ld	r30, r14, PCB_R30	/* restore frame pointer & stack */
264	ld	r31, r14, PCB_SP
265#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
266	br.n	_C_LABEL(sched_unlock_idle)
267#else
268	jmp.n	r1
269#endif
270	 ld	r14, r14, PCB_R14
271
272/*
273 * savectx(pcb)
274 * Update pcb, saving current processor state.
275 */
276ENTRY(savectx)
277	/*
278	 * Save preserved general register set.
279	 */
280	st	r1,  r2,  PCB_PC		/* save return address */
281ASLOCAL(__savectx)
282	st	r14, r2,  PCB_R14
283	st	r15, r2,  PCB_R15
284	st	r16, r2,  PCB_R16
285	st	r17, r2,  PCB_R17
286	st	r18, r2,  PCB_R18
287	st	r19, r2,  PCB_R19
288	st	r20, r2,  PCB_R20
289	st	r21, r2,  PCB_R21
290	st	r22, r2,  PCB_R22
291	st	r23, r2,  PCB_R23
292	st	r24, r2,  PCB_R24
293	st	r25, r2,  PCB_R25
294	st	r26, r2,  PCB_R26
295	st	r27, r2,  PCB_R27
296	st	r28, r2,  PCB_R28
297	st	r29, r2,  PCB_R29
298	st	r30, r2,  PCB_R30	/* save frame pointer & stack pointer */
299	st	r31, r2,  PCB_SP
300
301	/*
302	 * Get the current spl.
303	 * We need to save r1 on the stack because we don't know if we were
304	 * called as savectx or __savectx.
305	 */
306	subu	r31, r31, 16		/* allocate stack for r1 and args */
307	st	r1,  r31, 0
308	bsr.n	_C_LABEL(getipl)	/* get the current interrupt mask */
309	 or	r14, r0,  r2
310	st	r2,  r14, PCB_IPL	/* save interrupt mask */
311	ld	r1,  r31, 0		/* recover return address */
312	addu	r31, r31, 16		/* put stack pointer back */
313
314	/*
315	 * Save FP state.
316	 */
317	fldcr	r2,  fcr62
318	fldcr	r3,  fcr63
319	st	r2,  r14, PCB_FCR62
320	st	r3,  r14, PCB_FCR63
321	jmp.n	r1
322	 ld	r14, r14, PCB_R14	/* preserve r14 */
323