xref: /openbsd/sys/arch/m88k/m88k/process.S (revision 5b4ba075)
1/*	$OpenBSD: process.S,v 1.7 2004/08/09 20:52:11 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	data
39	align	4
40ASLOCAL(swchanpanic)
41	string	"switch wchan %x\0"
42	align	4
43ASLOCAL(swsrunpanic)
44	string	"switch SRUN %x\0"
45#ifdef DEBUG
46	align	4
47ASLOCAL(boguspsr)
48	string	"Invalid PSR in idle loop 0x%x\n\0"
49#endif
50
51	text
52	align	8
53ASLOCAL(Lswchanpanic)
54	or.u	r2, r0, hi16(_ASM_LABEL(swchanpanic))
55	or	r2, r2, lo16(_ASM_LABEL(swchanpanic))
56	bsr.n	_C_LABEL(panic)
57	 or	r3, r0, r9
58
59ASLOCAL(Lswsrunpanic)
60	or.u	r2, r0, hi16(_ASM_LABEL(swsrunpanic))
61	or	r2, r2, lo16(_ASM_LABEL(swsrunpanic))
62	bsr.n	_C_LABEL(panic)
63	 or	r3, r0, r9
64
65/*
66 * At exit of a process, do a cpu_switch for the last time.
67 * The mapping of the pcb at p->p_addr has already been deleted,
68 * and the memory for the pcb+stack has been freed.
69 * The ipl is high enough to prevent the memory from being reallocated.
70 * switch_exit(proc * p)
71 */
72
73ENTRY(switch_exit)
74	/*
75	 * Change pcb to idle u. area, i.e., set r31 to top of stack
76	 * and set curpcb to point to _idle_u.  r2 contains proc *p.
77	 */
78	or.u	r30, r0, hi16(_C_LABEL(idle_u))
79	or	r30, r30,lo16(_C_LABEL(idle_u))
80	addu	r31, r30, USIZE			/* now on idle_u stack */
81	or.u	r10, r0, hi16(_C_LABEL(curpcb))
82	st	r30, r10,lo16(_C_LABEL(curpcb))		/* curpcb = &idle_u */
83
84	/* Schedule the vmspace and stack to be freed. */
85	or.u	r10, r0, hi16(_C_LABEL(curproc))
86	bsr.n	_C_LABEL(exit2)
87	 st	r0, r10, lo16(_C_LABEL(curproc))	/* curproc = NULL */
88	bsr	_C_LABEL(cpu_switch)	/* goto final switch */
89
90/*
91 * cpu_switch()
92 * XXX - Arg 1 is a proc pointer (curproc) but this doesn't use it.
93 * XXX - how about using stack for saving spl and last proc?
94 * XXX rewrite this whole mess in C nivas
95 */
96ENTRY(cpu_switch)
97
98	/*
99	 * Save state of previous process in its pcb.
100	 */
101	or.u	r2, r0, hi16(_C_LABEL(curpcb))
102	ld	r2, r2, lo16(_C_LABEL(curpcb))
103	st	r1, r2, PCB_PC		/* save return address */
104	bsr	_ASM_LABEL(__savectx)
105	/* note that we don't need to recover r1 at this point */
106
107	or.u	r11, r0, hi16(_C_LABEL(curproc))
108	ld	r2, r11, lo16(_C_LABEL(curproc))
109	bcnd	eq0, r2, 1f
110
111	bsr	_C_LABEL(pmap_deactivate)
112	or.u	r11, r0, hi16(_C_LABEL(curproc))
113
1141:
115	st	r0, r11, lo16(_C_LABEL(curproc))	/* curproc = NULL */
116
117ASLOCAL(Lidleloop)
118
119	/*
120	 * Find the highest-priority queue that isn't empty,
121	 * then take the first proc from that queue.
122	 */
123
124	or.u	r7, r0, hi16(_C_LABEL(whichqs))
125	ld	r7, r7, lo16(_C_LABEL(whichqs))
126
127	bcnd	ne0, r7, _ASM_LABEL(Ldoneloop)
128
129ASLOCAL(Lloopchk)			/* if whichqs is zero, keep checking */
130	bsr.n	_C_LABEL(setipl)	/* unmask all ints... */
131	 or	r2, r0, IPL_NONE
132
133	ldcr	r2, PSR
134	bb0	PSR_INTERRUPT_DISABLE_BIT, r2, 1f
135#ifdef DEBUG
136	or	r3, r2, r0
137	or.u	r2, r0, hi16(_ASM_LABEL(boguspsr))
138	bsr.n	_C_LABEL(printf)
139	 or	r2, r2, lo16(_ASM_LABEL(boguspsr))
140	ldcr	r2, PSR
141#endif
142	clr	r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT>	/* ...and enable them */
143	stcr	r2, PSR
144	FLUSH_PIPELINE
1451:
146	br	_ASM_LABEL(Lidleloop)
147
148ASLOCAL(Ldoneloop)
149
150	bsr.n	_C_LABEL(setipl)	/* disable ints */
151	 or	r2, r0, IPL_HIGH
152
153	or.u	r7, r0, hi16(_C_LABEL(whichqs))	/* reload whichqs */
154	ld	r7, r7, lo16(_C_LABEL(whichqs))
155
156	bcnd	eq0, r7, _ASM_LABEL(Lloopchk)	/* keep spinning for whichqs to be != 0 */
157
158	xor	r6, r6, r6		/* set r6 to 0 */
1591:	bb1	0,  r7, 2f		/* if rightmost bit set, done */
160	extu	r7, r7, 0<1>		/* else, right shift whichqs, */
161	br.n	1b			/* increment r6, and repeat */
162	 addu	r6, r6, 1
1632:
164	or.u	r7, r0, hi16(_qs)
165	or	r7, r7, lo16(_qs)
166
167	/*
168	 * Need to make
169	 *	p->p_forw->p_back = p->p_back and
170	 *	p->p_back->p_forw = p->p_forw where
171	 *	p is q->p_forw.
172	 * Remember that q->p_forw == p and p->p_back == q.
173	 */
174
175	lda.d	r8,  r7[r6]	/* r8 = &qs[ff1(whichqs)] */
176	ld	r9,  r8, P_FORW	/* r8 is q, r9 is p */
177
178	ld	r12, r9, P_FORW	/* r12 = p->p_forw */
179	st	r8, r12, P_BACK	/* p->p_forw->p_back = q (p->p_back) */
180	st	r12, r8, P_FORW	/* q->p_forw = p->p_forw */
181	lda.d	r8,  r7[r6]	/* reload r8 with qs[ff1(whichqs)] */
182	ld	r12, r8, P_FORW	/* q->p_forw */
183	cmp	r12, r12, r8	/* q == q->p_forw; anyone left on queue? */
184	bb1	ne,  r12, 3f	/* yes, skip clearing bit in whichqs  */
185
186	or	r12, r0, 1	/* r12 is 1 now */
1871:	bcnd	eq0, r6, 2f
188	mak	r12, r12, 0<1>	/* shift left by 1 */
189	br.n	1b
190	 subu	r6,  r6, 1	/* keep doing this while r6 != 0 */
1912:
192	/*
193	 * NOTE: we could have just used "mak r12, r12, r6" instead of the
194	 * loop above. But that will break if NQS is made > 32. I can use
195	 * preprocessor to do the right thing, but that means I have to
196	 * include sys/proc.h in this file. XXX nivas
197	 */
198	or.u	r7,  r0, hi16(_C_LABEL(whichqs))
199	ld	r8,  r7, lo16(_C_LABEL(whichqs))
200	and.c	r8,  r8, r12	/* whichqs &= ~the bit */
201	st	r8,  r7, lo16(_C_LABEL(whichqs))
2023:
203	ld	r2, r9, P_WCHAN
204	bcnd	ne0, r2, _ASM_LABEL(Lswchanpanic)
205	ld.b	r2, r9, P_STAT
206	cmp	r2, r2, SRUN
207	bb1	ne, r2, _ASM_LABEL(Lswsrunpanic)
208
209	or.u	r11, r0, hi16(_C_LABEL(want_resched))
210	st	r0, r11, lo16(_C_LABEL(want_resched))	/* clear want_resched */
211
212	or.u	r11, r0, hi16(_C_LABEL(curproc))
213	st	r9,  r11,lo16(_C_LABEL(curproc))	/* curproc = p */
214	or	r2, r0, SONPROC
215	st.b	r2, r9, P_STAT
216
217	/*  r9 is curproc */
218	st	r0, r9, P_BACK			/* p->p_back = 0 */
219	ld	r3, r9, P_ADDR
220	or.u	r10, r0, hi16(_C_LABEL(curpcb))
221	st	r3, r10, lo16(_C_LABEL(curpcb))		/* curpcb = p->p_addr */
222
223	/* pmap_activate() the process' pmap */
224	or	r14, r0, r9		/* save p in r14 */
225	bsr.n	_C_LABEL(pmap_activate)
226	 or	r2, r0, r9
227	or	r9, r0, r14		/* restore p saved in r14 */
228
229	or.u	r31, r0, hi16(_ASM_LABEL(intstack_end))
230	or	r31,r31, lo16(_ASM_LABEL(intstack_end))
231	bsr.n    _C_LABEL(load_u_area)
232	 or	r2, r0, r9
233
234	or.u	r10, r0,  hi16(_C_LABEL(curpcb))
235	ld	r10, r10,  lo16(_C_LABEL(curpcb))
236	/* XXX Is this correct/necessary? */
237	st	r10, r14, P_ADDR	/* p->p_addr = curpcb; restore p_addr */
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	ld	r14,r14, PCB_R14
266	jmp.n	r1
267	 or	r2, r0, 1		/* return 1 (for alternate returns) */
268
269/*
270 * savectx(pcb)
271 * Update pcb, saving current processor state.
272 */
273ENTRY(savectx)
274	/*
275	 * Save preserved general register set.
276	 */
277	st	r1,  r2,  PCB_PC		/* save return address */
278ASLOCAL(__savectx)
279	st	r14, r2,  PCB_R14
280	st	r15, r2,  PCB_R15
281	st	r16, r2,  PCB_R16
282	st	r17, r2,  PCB_R17
283	st	r18, r2,  PCB_R18
284	st	r19, r2,  PCB_R19
285	st	r20, r2,  PCB_R20
286	st	r21, r2,  PCB_R21
287	st	r22, r2,  PCB_R22
288	st	r23, r2,  PCB_R23
289	st	r24, r2,  PCB_R24
290	st	r25, r2,  PCB_R25
291	st	r26, r2,  PCB_R26
292	st	r27, r2,  PCB_R27
293	st	r28, r2,  PCB_R28
294	st	r29, r2,  PCB_R29
295	st	r30, r2,  PCB_R30	/* save frame pointer & stack pointer */
296	st	r31, r2,  PCB_SP
297
298	/*
299	 * Get the current spl.
300	 * We need to save r1 on the stack because we don't know if we were
301	 * called as savectx or __savectx.
302	 */
303	subu	r31, r31, 16		/* allocate stack for r1 and args */
304	st	r1,  r31, 0
305	bsr.n	_C_LABEL(getipl)	/* get the current interrupt mask */
306	 or	r14, r0,  r2
307	st	r2,  r14, PCB_IPL	/* save interrupt mask */
308	ld	r1,  r31, 0		/* recover return address */
309	addu	r31, r31, 16		/* put stack pointer back */
310
311	/*
312	 * Save FP state.
313	 */
314	fldcr	r2,  fcr62
315	fldcr	r3,  fcr63
316	st	r2,  r14, PCB_FCR62
317	st	r3,  r14, PCB_FCR63
318	jmp.n	r1
319	 ld	r14, r14, PCB_R14	/* preserve r14 */
320