xref: /netbsd-src/sys/arch/mvme68k/mvme68k/locore.s (revision 179b12252ecaf3553d9c2b7458ce62b6a2203d0c)
1/*	$NetBSD: locore.s,v 1.106 2010/06/06 04:50:07 mrg Exp $	*/
2
3/*
4 * Copyright (c) 1980, 1990, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * the Systems Programming Group of the University of Utah Computer
9 * Science Department.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * from: Utah $Hdr: locore.s 1.66 92/12/22$
36 *
37 *	@(#)locore.s	8.6 (Berkeley) 5/27/94
38 */
39/*
40 * Copyright (c) 1988 University of Utah.
41 *
42 * This code is derived from software contributed to Berkeley by
43 * the Systems Programming Group of the University of Utah Computer
44 * Science Department.
45 *
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
48 * are met:
49 * 1. Redistributions of source code must retain the above copyright
50 *    notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright
52 *    notice, this list of conditions and the following disclaimer in the
53 *    documentation and/or other materials provided with the distribution.
54 * 3. All advertising materials mentioning features or use of this software
55 *    must display the following acknowledgement:
56 *	This product includes software developed by the University of
57 *	California, Berkeley and its contributors.
58 * 4. Neither the name of the University nor the names of its contributors
59 *    may be used to endorse or promote products derived from this software
60 *    without specific prior written permission.
61 *
62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72 * SUCH DAMAGE.
73 *
74 * from: Utah $Hdr: locore.s 1.66 92/12/22$
75 *
76 *	@(#)locore.s	8.6 (Berkeley) 5/27/94
77 */
78
79#include "opt_compat_netbsd.h"
80#include "opt_compat_svr4.h"
81#include "opt_compat_sunos.h"
82#include "opt_fpsp.h"
83#include "opt_ddb.h"
84#include "opt_kgdb.h"
85#include "opt_lockdebug.h"
86#include "opt_m68k_arch.h"
87
88#include "assym.h"
89#include <machine/asm.h>
90#include <machine/trap.h>
91
92#include "ksyms.h"
93
94/*
95 * Temporary stack for a variety of purposes.
96 * Try and make this the first thing is the data segment so it
97 * is page aligned.  Note that if we overflow here, we run into
98 * our text segment.
99 */
100	.data
101	.space	PAGE_SIZE
102ASLOCAL(tmpstk)
103
104ASLOCAL(bug_vbr)
105	.long	0
106
107#include <mvme68k/mvme68k/vectors.s>
108
109
110/*
111 * Macro to relocate a symbol, used before MMU is enabled.
112 */
113#define	_RELOC(var, ar)		\
114	lea	var,ar
115
116#define	RELOC(var, ar)		_RELOC(_C_LABEL(var), ar)
117#define	ASRELOC(var, ar)	_RELOC(_ASM_LABEL(var), ar)
118
119/*
120 * Macro to call into the Bug ROM monitor
121 */
122#define	CALLBUG(func)	\
123	trap #15; .short func
124
125/*
126 * Initialization
127 *
128 * The bootstrap loader loads us in starting at 0, and VBR is non-zero.
129 * On entry, args on stack are boot device, boot filename, console unit,
130 * boot flags (howto), boot device name, filesystem type name.
131 */
132BSS(lowram,4)
133BSS(esym,4)
134
135	.globl	_C_LABEL(edata)
136	.globl	_C_LABEL(etext),_C_LABEL(end)
137
138
139/*
140 * This is for kvm_mkdb, and should be the address of the beginning
141 * of the kernel text segment (not necessarily the same as kernbase).
142 */
143	.text
144GLOBAL(kernel_text)
145
146/*
147 * start of kernel and .text!
148 */
149ASENTRY_NOPROFILE(start)
150	movw	#PSL_HIGHIPL,%sr	| no interrupts
151	movl	#0,%a5			| RAM starts at 0 (a5)
152	movl	%sp@(4), %d7		| get boothowto
153	movl	%sp@(8), %d6		| get bootaddr
154	movl	%sp@(12),%d5		| get bootctrllun
155	movl	%sp@(16),%d4		| get bootdevlun
156	movl	%sp@(20),%d3		| get bootpart
157	movl	%sp@(24),%d2		| get esyms
158
159	RELOC(bootpart,%a0)
160	movl	%d3, %a0@		| save bootpart
161	RELOC(bootdevlun,%a0)
162	movl	%d4, %a0@		| save bootdevlun
163	RELOC(bootctrllun,%a0)
164	movl	%d5, %a0@		| save booctrllun
165	RELOC(bootaddr,%a0)
166	movl	%d6, %a0@		| save bootaddr
167	RELOC(boothowto,%a0)
168	movl	%d7, %a0@		| save boothowto
169	/* note: d3-d7 free, d2 still in use */
170
171	ASRELOC(tmpstk, %a0)
172	movl	%a0,%sp			| give ourselves a temporary stack
173
174	RELOC(edata,%a0)		| clear out BSS
175	movl	#_C_LABEL(end) - 4, %d0	| (must be <= 256 kB)
176	subl	#_C_LABEL(edata), %d0
177	lsrl	#2,%d0
1781:	clrl	%a0@+
179	dbra	%d0,1b
180
181	RELOC(esym, %a0)
182	movl	%d2,%a0@		| store end of symbol table
183	/* d2 now free */
184	RELOC(lowram, %a0)
185	movl	%a5,%a0@		| store start of physical memory
186	movl	#CACHE_OFF,%d0
187	movc	%d0,%cacr		| clear and disable on-chip cache(s)
188
189	/* ask the Bug what we are... */
190	clrl	%sp@-
191	CALLBUG(MVMEPROM_GETBRDID)
192	movl	%sp@+,%a1
193
194	/* copy to a struct mvmeprom_brdid */
195	movl	#MVMEPROM_BRDID_SIZE,%d0
196	RELOC(boardid,%a0)
1971:	movb	%a1@+,%a0@+
198	subql	#1,%d0
199	jbne	1b
200
201	/*
202	 * Grab the model number from _boardid and use the value
203	 * to setup machineid, cputype, and mmutype.
204	 */
205	clrl	%d0
206	RELOC(boardid,%a1)
207	movw	%a1@(MVMEPROM_BRDID_MODEL_OFFSET),%d0
208	RELOC(machineid,%a0)
209	movl	%d0,%a0@
210
211	ASRELOC(Lbrdid2mach,%a0)
212Lbrdmatch:
213	cmpw	%a0@+,%d0
214	jbeq	Lgotmatch
215	addw	#0x12,%a0		| Each entry is 20-2 bytes long
216	tstw	%a0@
217	jbne	Lbrdmatch
218
219	/*
220	 * If we fall to here, the board is not supported.
221	 * Print a warning, then drop out to the Bug.
222	 */
223	movl	#Lenotconf,%sp@-
224	movl	#Lnotconf,%sp@-
225	CALLBUG(MVMEPROM_OUTSTRCRLF)
226	addql	#8,%sp			| clean up stack after call
227
228	CALLBUG(MVMEPROM_EXIT)
229	/* NOTREACHED */
230
231	.data
232Lnotconf:
233	.ascii	"Sorry, the kernel isn't configured for this model."
234Lenotconf:
235	.even
236
237ASLOCAL(Lbrdid2mach)
238#ifdef MVME147
239	.word	MVME_147
240	.word		CPU_68030
241	.word		MMU_68030
242	.word		FPU_68882
243	.long		_C_LABEL(busaddrerr2030)
244	.long		_C_LABEL(busaddrerr2030)
245	.long		Linit147
246#endif
247#ifdef MVME162
248	.word	MVME_162
249	.word		CPU_68040
250	.word		MMU_68040
251	.word		FPU_68040
252	.long		_C_LABEL(buserr40)
253	.long		_C_LABEL(addrerr4060)
254	.long		Linit1x2
255#endif
256#ifdef MVME167
257	.word	MVME_167
258	.word		CPU_68040
259	.word		MMU_68040
260	.word		FPU_68040
261	.long		_C_LABEL(buserr40)
262	.long		_C_LABEL(addrerr4060)
263	.long		Linit1x7
264#endif
265#ifdef MVME172
266	.word	MVME_172
267	.word		CPU_68060
268	.word		MMU_68040
269	.word		FPU_68060
270	.long		_C_LABEL(buserr60)
271	.long		_C_LABEL(addrerr4060)
272	.long		Linit1x2
273#endif
274#ifdef MVME177
275	.word	MVME_177
276	.word		CPU_68060
277	.word		MMU_68040
278	.word		FPU_68060
279	.long		_C_LABEL(buserr60)
280	.long		_C_LABEL(addrerr4060)
281	.long		Linit1x7
282#endif
283	.word	0
284	.text
285	.even
286
287/*
288 * We have a match, so the kernel should support this board.
289 * a0 points to the matching entry in Lbrdid2mach.
290 */
291Lgotmatch:
292	movew	%a0@+,%d1		| Copy the CPU type
293	extl	%d1
294	RELOC(cputype,%a1)
295	movel	%d1,%a1@
296	movew	%a0@+,%d1		| Copy the MMU type
297	extl	%d1
298	RELOC(mmutype,%a1)
299	movel	%d1,%a1@
300	movew	%a0@+,%d1		| Copy the FPU type
301	extl	%d1
302	RELOC(fputype,%a1)
303	movel	%d1,%a1@
304	movel	%a0@+,%a2		| Fetch the bus error vector
305	RELOC(vectab,%a1)
306	movl	%a2,%a1@(8)
307	movel	%a0@+,%a2		| Fetch the address error vector
308	movl	%a2,%a1@(12)
309	movel	%a0@,%a0		| Finally, the board-specific init code
310	jmp	%a0@
311
312
313#ifdef MVME147
314Linit147:
315	/* MVME-147 - 68030 CPU/MMU, 68882 FPU */
316	/* XXXCDC SHUTUP 147 CALL */
317	movb	#0, 0xfffe1026		| serial interrupt off
318	movb	#0, 0xfffe1018		| timer 1 off
319	movb	#0, 0xfffe1028		| ethernet off
320	/* XXXCDC SHUTUP 147 CALL */
321
322	/* Save our ethernet address */
323	RELOC(mvme_ea, %a0)
324	lea	0xfffe0778,%a1		| XXXCDC -- HARDWIRED HEX
325	movb	#0x08,%a0@+
326	clrb	%a0@+
327	movb	#0x3e,%a0@+
328	movql	#0x0f,%d0
329	andb	%a1@+,%d0
330	orb	#0x20,%d0
331	movb	%d0,%a0@+
332	movb	%a1@+,%a0@+
333	movb	%a1@,%a0@
334
335	/*
336	 * Fix up the physical addresses of the MVME147's onboard
337	 * I/O registers.
338	 */
339	RELOC(intiobase_phys, %a0);
340	movl	#INTIOBASE147,%a0@
341	RELOC(intiotop_phys, %a0);
342	movl	#INTIOTOP147,%a0@
343
344	/* initialise list of physical memory segments for pmap_bootstrap */
345	RELOC(phys_seg_list, %a0)
346	movl	%a5,%a0@		| phys_seg_list[0].ps_start
347	movl	0xfffe0774,%d1		| End + 1 of onboard memory
348	movl	%d1,%a0@(4)		| phys_seg_list[0].ps_end
349	clrl	%a0@(8)			| phys_seg_list[0].ps_startpage
350
351	/* offboard RAM */
352	clrl	%a0@(0x0c)		| phys_seg_list[1].ps_start
353	movl	#PAGE_SIZE-1,%d0
354	addl	0xfffe0764,%d0		| Start of offboard segment
355	andl	#-PAGE_SIZE,%d0		| Round up to page boundary
356	jbeq	Lsavmaxmem		| Jump if none defined
357	movl	#PAGE_SIZE,%d1		| Note: implicit '+1'
358	addl	0xfffe0768,%d1		| End of offboard segment
359	andl	#-PAGE_SIZE,%d1		| Round up to page boundary
360	cmpl	%d1,%d0			| Quick and dirty validity check
361	jbcs	Loff_ok			| Yup, looks good.
362	movel	%a0@(4),%d1		| Just use onboard RAM otherwise
363	jbra	Lsavmaxmem
364Loff_ok:
365	movl	%d0,%a0@(0x0c)		| phys_seg_list[1].ps_start
366	movl	%d1,%a0@(0x10)		| phys_seg_list[1].ps_end
367	clrl	%a0@(0x14)		| phys_seg_list[1].ps_startpage
368
369	/*
370	 * Offboard RAM needs to be cleared to zero to initialise parity
371	 * on most VMEbus RAM cards. Without this, some cards will buserr
372	 * when first read.
373	 */
374	movel	%d0,%a0			| offboard start address again.
375Lclearoff:
376	clrl	%a0@+			| zap a word
377	cmpl	%a0,%d1			| reached end?
378	jbne	Lclearoff
379
380Lsavmaxmem:
381	moveq	#PGSHIFT,%d2
382	lsrl	%d2,%d1			| convert to page (click) number
383	RELOC(maxmem, %a0)
384	movl	%d1,%a0@		| save as maxmem
385	jra	Lstart1
386#endif
387
388#if defined(MVME162) || defined(MVME172)
389Linit1x2:
390	/* MVME-162 - 68040 CPU/MMU/FPU */
391	/* MVME-172 - 68060 CPU/MMU/FPU */
392
393	/*
394	 * Verify the user has removed the GPIO#0 jumper...
395	 */
396	btst	#0,0xfff4202d		| Clear == jumper installed
397	jne	1f			| Ok.
398
399	movl	#Le1x2jump,%sp@-
400	movl	#L1x2jump,%sp@-
401	CALLBUG(MVMEPROM_OUTSTRCRLF)
402	addql	#8,%sp			| clean up stack after call
403
404	CALLBUG(MVMEPROM_EXIT)
405	/* NOTREACHED */
406
4071:
408	/*
409	 * Determine if this board has a VMEchip2
410	 */
411	btst	#1,0xfff4202e		| VMEchip2 presence detect
412	jne	2f			| Jump if it doesn't exist.
413
414	/*
415	 * Disable all interrupts from VMEchip2. This is especially
416	 * useful when the kernel doesn't have the VMEchip2 driver
417	 * configured. If we didn't do this, then we're at the mercy
418	 * of whatever VMEchip2 interrupts the ROM set up. For example,
419	 * hitting the ABORT switch could kill the system...
420	 */
421	movl	0xfff40088,%d0
422	andl	#0xff7fffff,%d0		| Clear 'MIEN'
423	movl	%d0,0xfff40088
4242:
425	/*
426	 * Determine how much onboard memory is installed
427	 */
428	movql	#0x07,%d0
429	andb	0xfff42024,%d0
430	ASRELOC(Ldramsize1x2,%a0)
431	movl	%a0@(%d0:w:4),%d1	| Lookup the size
432	jeq	Lmemcquery		| Assume a MEMC chip if this is zero.
433	jra	Lis1xx_common
434
435	.data
436	.even
437	/*
438	 * Table of DRAM register size values -> actual size in bytes
439	 */
440ASLOCAL(Ldramsize1x2)
441	.long	0x00100000
442	.long	0x00200000
443	.long	0x00000000
444	.long	0x00400000
445	.long	0x00400000
446	.long	0x00800000
447	.long	0x00000000
448	.long	0x01000000
449
450L1x2jump:
451	.ascii	"You must remove the jumper from pins 15-16 of J22 (mvme162)"
452	.ascii	"or pins 1-2\015\012"
453	.ascii	"J11 (mvme162-LX) first! See NetBSD/mvme68k FAQ for details."
454Le1x2jump:
455	.even
456
457	.text
458#endif
459
460#if defined(MVME167) || defined(MVME177)
461Linit1x7:
462	/* MVME-167 - 68040 CPU/MMU/FPU */
463	/* MVME-177 - 68060 CPU/MMU/FPU */
464
465	/*
466	 * Verify the user has removed the GPIO#0 jumper...
467	 */
468	movel	#0x00000001,%d0
469	andl	0xfff40088,%d0		| Clear == jumper installed
470	jne	1f			| Ok.
471
472	movl	#Le1x7jump,%sp@-
473	movl	#L1x7jump,%sp@-
474	CALLBUG(MVMEPROM_OUTSTRCRLF)
475	addql	#8,%sp			| clean up stack after call
476
477	CALLBUG(MVMEPROM_EXIT)
478	/* NOTREACHED */
479
4801:
481	/*
482	 * Disable all interrupts from VMEchip2. This is especially
483	 * useful when the kernel doesn't have the VMEchip2 driver
484	 * configured. If we didn't do this, then we're at the mercy
485	 * of whatever VMEchip2 interrupts the ROM set up. For example,
486	 * hitting the ABORT switch could kill the system...
487	 */
488	movl	0xfff40088,%d0
489	andl	#0xff7fffff,%d0		| Clear 'MIEN'
490	movl	%d0,0xfff40088
491
492	.data
493	.even
494L1x7jump:
495	.ascii	"You must remove the jumper from pins 1-2 of J1!\015\012"
496	.ascii	"See NetBSD/mvme68k FAQ for details."
497Le1x7jump:
498	.even
499
500	.text
501#endif
502
503#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177)
504Lmemcquery:
505	/*
506	 * Figure out the size of onboard DRAM by querying
507	 * the memory controller ASIC(s)
508	 */
509	lea	0xfff43008,%a0		| MEMC040/MEMECC Controller #1
510	jbsr	memc040read
511	movl	%d0,%d1
512
513	lea	0xfff43108,%a0		| MEMC040/MEMECC Controller #2
514	jbsr	memc040read
515	addl	%d0,%d1
516
517Lis1xx_common:
518	/* Save our ethernet address */
519	RELOC(mvme_ea, %a0)
520	lea	0xfffc1f2c,%a1
521	movb	%a1@+,%a0@+
522	movb	%a1@+,%a0@+
523	movb	%a1@+,%a0@+
524	movb	%a1@+,%a0@+
525	movb	%a1@+,%a0@+
526	movb	%a1@,%a0@
527
528	/*
529	 * Fix up the physical addresses of the onboard
530	 * I/O registers.
531	 */
532	RELOC(intiobase_phys, %a0);
533	movl	#INTIOBASE1xx,%a0@
534	RELOC(intiotop_phys, %a0);
535	movl	#INTIOTOP1xx,%a0@
536
537	/*
538	 * Initialise first physical memory segment with onboard RAM details
539	 */
540	RELOC(phys_seg_list, %a0)
541	movl	%a5,%a0@		| phys_seg_list[0].ps_start
542	movl	%d1,%a0@(4)		| phys_seg_list[0].ps_end
543	clrl	%a0@(8)			| phys_seg_list[0].ps_startpage
544
545	/* offboard RAM */
546	clrl	%a0@(0x0c)		| phys_seg_list[1].ps_start
547	movl	#PAGE_SIZE-1,%d0
548	addl	0xfffc0000,%d0		| Start of offboard segment
549	andl	#-PAGE_SIZE,%d0		| Round up to page boundary
550	jbeq	Ldone1xx		| Jump if none defined
551	movl	#PAGE_SIZE,%d1		| Note: implicit '+1'
552	addl	0xfffc0004,%d1		| End of offboard segment
553	andl	#-PAGE_SIZE,%d1		| Round up to page boundary
554	cmpl	%d1,%d0			| Quick and dirty validity check
555	jbcs	Lramsave1xx		| Yup, looks good.
556	movel	%a0@(4),%d1		| Just use onboard RAM otherwise
557	jbra	Ldone1xx
558
559Lramsave1xx:
560	movl	%d0,%a0@(0x0c)		| phys_seg_list[1].ps_start
561	movl	%d1,%a0@(0x10)		| phys_seg_list[1].ps_end
562	clrl	%a0@(0x14)		| phys_seg_list[1].ps_startpage
563
564	/*
565	 * Offboard RAM needs to be cleared to zero to initialise parity
566	 * on most VMEbus RAM cards. Without this, some cards will buserr
567	 * when first read.
568	 */
569	movel	%d0,%a0			| offboard start address again.
570Lramclr1xx:
571	clrl	%a0@+			| zap a word
572	cmpl	%a0,%d1			| reached end?
573	jbne	Lramclr1xx
574
575Ldone1xx:
576	moveq	#PGSHIFT,%d2
577	lsrl	%d2,%d1			| convert to page (click) number
578	RELOC(maxmem, %a0)
579	movl	%d1,%a0@		| save as maxmem
580
581	/* FALLTHROUGH to Lstart1 */
582#endif
583
584
585Lstart1:
586/* initialize source/destination control registers for movs */
587	moveq	#FC_USERD,%d0		| user space
588	movc	%d0,%sfc		|   as source
589	movc	%d0,%dfc		|   and destination of transfers
590/*
591 * configure kernel and lwp0 VA space so we can get going
592 */
593#if NKSYMS || defined(DDB) || defined(LKM)
594	RELOC(esym,%a0)			| end of static kernel text/data syms
595	movl	%a0@,%d2
596	jne	Lstart2
597#endif
598	movl	#_C_LABEL(end),%d2	| end of static kernel text/data
599Lstart2:
600	addl	#PAGE_SIZE-1,%d2
601	andl	#PG_FRAME,%d2		| round to a page
602	movl	%d2,%a4
603	addl	%a5,%a4			| convert to PA
604	pea	%a5@			| firstpa
605	pea	%a4@			| nextpa
606	RELOC(pmap_bootstrap,%a0)
607	jbsr	%a0@			| pmap_bootstrap(firstpa, nextpa)
608	addql	#8,%sp
609
610/*
611 * Enable the MMU.
612 * Since the kernel is mapped logical == physical, we just turn it on.
613 */
614	RELOC(Sysseg_pa, %a0)		| system segment table addr
615	movl	%a0@,%d1		| read value (a PA)
616	RELOC(mmutype, %a0)
617	cmpl	#MMU_68040,%a0@		| 68040?
618	jne	Lmotommu1		| no, skip
619	.long	0x4e7b1807		| movc d1,srp
620	jra	Lstploaddone
621Lmotommu1:
622	RELOC(protorp, %a0)
623	movl	#0x80000202,%a0@	| nolimit + share global + 4 byte PTEs
624	movl	%d1,%a0@(4)		| + segtable address
625	pmove	%a0@,%srp		| load the supervisor root pointer
626	movl	#0x80000002,%a0@	| reinit upper half for CRP loads
627Lstploaddone:
628	RELOC(mmutype, %a0)
629	cmpl	#MMU_68040,%a0@		| 68040?
630	jne	Lmotommu2		| no, skip
631	moveq	#0,%d0			| ensure TT regs are disabled
632	.long	0x4e7b0004		| movc d0,itt0
633	.long	0x4e7b0005		| movc d0,itt1
634	.long	0x4e7b0006		| movc d0,dtt0
635	.long	0x4e7b0007		| movc d0,dtt1
636	.word	0xf4d8			| cinva bc
637	.word	0xf518			| pflusha
638	movl	#0x8000,%d0
639	.long	0x4e7b0003		| movc d0,tc
640#ifdef M68060
641	RELOC(cputype, %a0)
642	cmpl	#CPU_68060,%a0@		| 68060?
643	jne	Lnot060cache
644	movl	#1,%d0
645	.long	0x4e7b0808		| movcl d0,pcr
646	movl	#0xa0808000,%d0
647	movc	%d0,%cacr		| enable store buffer, both caches
648	jmp	Lenab1
649Lnot060cache:
650#endif
651	movl	#0x80008000,%d0
652	movc	%d0,%cacr		| turn on both caches
653	jmp	Lenab1
654Lmotommu2:
655	movl	#0x82c0aa00,%sp@-	| value to load TC with
656	pmove	%sp@,%tc		| load it
657
658/*
659 * Should be running mapped from this point on
660 */
661Lenab1:
662/* Point the CPU VBR at our vector table */
663	movc	%vbr,%d0		| Preserve Bug's VBR address
664	movl	%d0,_ASM_LABEL(bug_vbr)
665	movl	#_C_LABEL(vectab),%d0	| get our VBR address
666	movc	%d0,%vbr
667	lea	_ASM_LABEL(tmpstk),%sp	| temporary stack
668/* call final pmap setup */
669	jbsr	_C_LABEL(pmap_bootstrap_finalize)
670/* set kernel stack, user SP */
671	movl	_C_LABEL(lwp0uarea),%a1	| get lwp0 uarea
672	lea	%a1@(USPACE-4),%sp	| set kernel stack to end of area
673	movl	#USRSTACK-4,%a2
674	movl	%a2,%usp		| init user SP
675	tstl	_C_LABEL(fputype)	| Have an FPU?
676	jeq	Lenab2			| No, skip.
677	clrl	%a1@(PCB_FPCTX)		| ensure null FP context
678	movl	%a1,%sp@-
679	jbsr	_C_LABEL(m68881_restore) | restore it (does not kill a1)
680	addql	#4,%sp
681Lenab2:
682	cmpl	#MMU_68040,_C_LABEL(mmutype)	| 68040?
683	jeq	Ltbia040		| yes, cache already on
684	pflusha
685	movl	#CACHE_ON,%d0
686	movc	%d0,%cacr		| clear cache(s)
687	jra	Lenab3
688Ltbia040:
689	.word	0xf518
690Lenab3:
691/*
692 * final setup for C code:
693 * Create a fake exception frame so that cpu_lwp_fork() can copy it.
694 * main() nevers returns; we exit to user mode from a forked process
695 * later on.
696 */
697	jbsr	_C_LABEL(mvme68k_init)	| additional pre-main initialization
698	movw	#PSL_LOWIPL,%sr		| lower SPL
699	clrw	%sp@-			| vector offset/frame type
700	clrl	%sp@-			| PC - filled in by "execve"
701	movw	#PSL_USER,%sp@-		| in user mode
702	clrl	%sp@-			| stack adjust count and padding
703	lea	%sp@(-64),%sp		| construct space for D0-D7/A0-A7
704	lea	_C_LABEL(lwp0),%a0	| save pointer to frame
705	movl	%sp,%a0@(L_MD_REGS)	|   in lwp0.l_md.md_regs
706
707	jra	_C_LABEL(main)		| main()
708
709#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177)
710/*
711 * Probe for a memory controller ASIC (MEMC040 or MEMECC) at the
712 * address in a0. If found, return the size in bytes of any RAM
713 * controlled by the ASIC in d0. Otherwise return zero.
714 */
715ASLOCAL(memc040read)
716	moveml	%d1-%d2/%a1-%a2,%sp@-	| save scratch regs
717	movc	%vbr,%d2		| Save vbr
718	RELOC(vectab,%a2)		| Install our own vectab, temporarily
719	movc	%a2,%vbr
720	ASRELOC(Lmemc040berr,%a1)	| get address of bus error handler
721	movl	%a2@(8),%sp@-		| Save current bus error handler addr
722	movl	%a1,%a2@(8)		| Install our own handler
723	movl	%sp,%d0			| Save current stack pointer value
724	movql	#0x07,%d1
725	andb	%a0@,%d1		| Access MEMC040/MEMECC
726	movl	#0x400000,%d0
727	lsll	%d1,%d0			| Convert to memory size, in bytes
728Lmemc040ret:
729	movc	%d2,%vbr		| Restore original vbr
730	movl	%sp@+,%a2@(8)		| Restore original bus error handler
731	moveml  %sp@+,%d1-%d2/%a1-%a2
732	rts
733/*
734 * If the memory controller doesn't exist, we get a bus error trying
735 * to access a0@ above. Control passes here, where we flag 'no bytes',
736 * ditch the exception frame and return as normal.
737 */
738Lmemc040berr:
739	movl	%d0,%sp			| Get rid of the exception frame
740	movql	#0,%d0			| No ASIC at this location, then!
741	jbra	Lmemc040ret		| Done
742#endif
743
744/*
745 * Trap/interrupt vector routines
746 */
747#include <m68k/m68k/trap_subr.s>
748
749#if defined(M68040) || defined(M68060)
750ENTRY_NOPROFILE(addrerr4060)
751	clrl	%sp@-			| stack adjust count
752	moveml	#0xFFFF,%sp@-		| save user registers
753	movl	%usp,%a0		| save the user SP
754	movl	%a0,%sp@(FR_SP)		|   in the savearea
755	movl	%sp@(FR_HW+8),%sp@-
756	clrl	%sp@-			| dummy code
757	movl	#T_ADDRERR,%sp@-	| mark address error
758	jra	_ASM_LABEL(faultstkadj)	| and deal with it
759#endif
760
761#if defined(M68060)
762ENTRY_NOPROFILE(buserr60)
763	clrl	%sp@-			| stack adjust count
764	moveml	#0xFFFF,%sp@-		| save user registers
765	movl	%usp,%a0		| save the user SP
766	movl	%a0,%sp@(FR_SP)		|   in the savearea
767	movel	%sp@(FR_HW+12),%d0	| FSLW
768	btst	#2,%d0			| branch prediction error?
769	jeq	Lnobpe
770	movc	%cacr,%d2
771	orl	#IC60_CABC,%d2		| clear all branch cache entries
772	movc	%d2,%cacr
773	movl	%d0,%d1
774	andl	#0x7ffd,%d1
775	jeq	_ASM_LABEL(faultstkadjnotrap2)
776Lnobpe:
777| we need to adjust for misaligned addresses
778	movl	%sp@(FR_HW+8),%d1	| grab VA
779	btst	#27,%d0			| check for mis-aligned access
780	jeq	Lberr3			| no, skip
781	addl	#28,%d1			| yes, get into next page
782					| operand case: 3,
783					| instruction case: 4+12+12
784	andl	#PG_FRAME,%d1		| and truncate
785Lberr3:
786	movl	%d1,%sp@-
787	movl	%d0,%sp@-		| code is FSLW now.
788	andw	#0x1f80,%d0
789	jeq	Lberr60			| it is a bus error
790	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
791	jra	_ASM_LABEL(faultstkadj)	| and deal with it
792Lberr60:
793	tstl	_C_LABEL(nofault)	| catch bus error?
794	jeq	Lisberr			| no, handle as usual
795	movl	_C_LABEL(nofault),%sp@-	| yes,
796	jbsr	_C_LABEL(longjmp)	|  longjmp(nofault)
797	/* NOTREACHED */
798#endif
799#if defined(M68040)
800ENTRY_NOPROFILE(buserr40)
801	clrl	%sp@-			| stack adjust count
802	moveml	#0xFFFF,%sp@-		| save user registers
803	movl	%usp,%a0		| save the user SP
804	movl	%a0,%sp@(FR_SP)		|   in the savearea
805	movl	%sp@(FR_HW+20),%d1	| get fault address
806	moveq	#0,%d0
807	movw	%sp@(FR_HW+12),%d0	| get SSW
808	btst	#11,%d0			| check for mis-aligned
809	jeq	Lbe1stpg		| no skip
810	addl	#3,%d1			| get into next page
811	andl	#PG_FRAME,%d1		| and truncate
812Lbe1stpg:
813	movl	%d1,%sp@-		| pass fault address.
814	movl	%d0,%sp@-		| pass SSW as code
815	btst	#10,%d0			| test ATC
816	jeq	Lberr40			| it is a bus error
817	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
818	jra	_ASM_LABEL(faultstkadj)	| and deal with it
819Lberr40:
820	tstl	_C_LABEL(nofault)	| catch bus error?
821	jeq	Lisberr			| no, handle as usual
822	movl	_C_LABEL(nofault),%sp@-	| yes,
823	jbsr	_C_LABEL(longjmp)	|  longjmp(nofault)
824	/* NOTREACHED */
825#endif
826
827#if defined(M68020) || defined(M68030)
828ENTRY_NOPROFILE(busaddrerr2030)
829	clrl	%sp@-			| stack adjust count
830	moveml	#0xFFFF,%sp@-		| save user registers
831	movl	%usp,%a0		| save the user SP
832	movl	%a0,%sp@(FR_SP)		|   in the savearea
833	moveq	#0,%d0
834	movw	%sp@(FR_HW+10),%d0	| grab SSW for fault processing
835	btst	#12,%d0			| RB set?
836	jeq	LbeX0			| no, test RC
837	bset	#14,%d0			| yes, must set FB
838	movw	%d0,%sp@(FR_HW+10)	| for hardware too
839LbeX0:
840	btst	#13,%d0			| RC set?
841	jeq	LbeX1			| no, skip
842	bset	#15,%d0			| yes, must set FC
843	movw	%d0,%sp@(FR_HW+10)	| for hardware too
844LbeX1:
845	btst	#8,%d0			| data fault?
846	jeq	Lbe0			| no, check for hard cases
847	movl	%sp@(FR_HW+16),%d1	| fault address is as given in frame
848	jra	Lbe10			| thats it
849Lbe0:
850	btst	#4,%sp@(FR_HW+6)	| long (type B) stack frame?
851	jne	Lbe4			| yes, go handle
852	movl	%sp@(FR_HW+2),%d1	| no, can use save PC
853	btst	#14,%d0			| FB set?
854	jeq	Lbe3			| no, try FC
855	addql	#4,%d1			| yes, adjust address
856	jra	Lbe10			| done
857Lbe3:
858	btst	#15,%d0			| FC set?
859	jeq	Lbe10			| no, done
860	addql	#2,%d1			| yes, adjust address
861	jra	Lbe10			| done
862Lbe4:
863	movl	%sp@(FR_HW+36),%d1	| long format, use stage B address
864	btst	#15,%d0			| FC set?
865	jeq	Lbe10			| no, all done
866	subql	#2,%d1			| yes, adjust address
867Lbe10:
868	movl	%d1,%sp@-		| push fault VA
869	movl	%d0,%sp@-		| and padded SSW
870	movw	%sp@(FR_HW+8+6),%d0	| get frame format/vector offset
871	andw	#0x0FFF,%d0		| clear out frame format
872	cmpw	#12,%d0			| address error vector?
873	jeq	Lisaerr			| yes, go to it
874	movl	%d1,%a0			| fault address
875	movl	%sp@,%d0		| function code from ssw
876	btst	#8,%d0			| data fault?
877	jne	Lbe10a
878	movql	#1,%d0			| user program access FC
879					| (we dont separate data/program)
880	btst	#5,%sp@(FR_HW+8)	| supervisor mode?
881	jeq	Lbe10a			| if no, done
882	movql	#5,%d0			| else supervisor program access
883Lbe10a:
884	ptestr	%d0,%a0@,#7		| do a table search
885	pmove	%psr,%sp@		| save result
886	movb	%sp@,%d1
887	btst	#2,%d1			| invalid (incl. limit viol. and berr)?
888	jeq	Lmightnotbemerr		| no -> wp check
889	btst	#7,%d1			| is it MMU table berr?
890	jne	Lisberr1		| yes, needs not be fast.
891Lismerr:
892	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
893	jra	_ASM_LABEL(faultstkadj)	| and deal with it
894Lmightnotbemerr:
895	btst	#3,%d1			| write protect bit set?
896	jeq	Lisberr1		| no: must be bus error
897	movl	%sp@,%d0		| ssw into low word of d0
898	andw	#0xc0,%d0		| Write protect is set on page:
899	cmpw	#0x40,%d0		| was it read cycle?
900	jne	Lismerr			| no, was not WPE, must be MMU fault
901	jra	Lisberr1		| real bus err needs not be fast.
902Lisaerr:
903	movl	#T_ADDRERR,%sp@-	| mark address error
904	jra	_ASM_LABEL(faultstkadj)	| and deal with it
905Lisberr1:
906	clrw	%sp@			| re-clear pad word
907	tstl	_C_LABEL(nofault)	| catch bus error?
908	jeq	Lisberr			| no, handle as usual
909	movl	_C_LABEL(nofault),%sp@-	| yes,
910	jbsr	_C_LABEL(longjmp)	|  longjmp(nofault)
911	/* NOTREACHED */
912#endif /* M68020 || M68030 */
913
914Lisberr:				| also used by M68040/60
915	movl	#T_BUSERR,%sp@-		| mark bus error
916	jra	_ASM_LABEL(faultstkadj)	| and deal with it
917
918/*
919 * FP exceptions.
920 */
921ENTRY_NOPROFILE(fpfline)
922#if defined(M68040)
923	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
924	jne	Lfp_unimp		| no, skip FPSP
925	cmpw	#0x202c,%sp@(6)		| format type 2?
926	jne	_C_LABEL(illinst)	| no, not an FP emulation
927#ifdef FPSP
928	jmp	_ASM_LABEL(fpsp_unimp)	| yes, go handle it
929#else
930	clrl	%sp@-			| stack adjust count
931	moveml	#0xFFFF,%sp@-		| save registers
932	moveq	#T_FPEMULD,%d0		| denote as FP emulation trap
933	jra	_ASM_LABEL(fault)	| do it
934#endif
935Lfp_unimp:
936#endif /* M68040 */
937	jra	_C_LABEL(illinst)
938
939ENTRY_NOPROFILE(fpunsupp)
940#if defined(M68040)
941	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
942	jne	Lfp_unsupp		| No, skip FPSP
943#ifdef FPSP
944	jmp	_ASM_LABEL(fpsp_unsupp)	| yes, go handle it
945#else
946	clrl	%sp@-			| stack adjust count
947	moveml	#0xFFFF,%sp@-		| save registers
948	moveq	#T_FPEMULD,%d0		| denote as FP emulation trap
949	jra	_ASM_LABEL(fault)	| do it
950#endif
951Lfp_unsupp:
952#endif /* M68040 */
953	jra	_C_LABEL(illinst)
954
955/*
956 * Handles all other FP coprocessor exceptions.
957 * Note that since some FP exceptions generate mid-instruction frames
958 * and may cause signal delivery, we need to test for stack adjustment
959 * after the trap call.
960 */
961ENTRY_NOPROFILE(fpfault)
962	clrl	%sp@-		| stack adjust count
963	moveml	#0xFFFF,%sp@-	| save user registers
964	movl	%usp,%a0	| and save
965	movl	%a0,%sp@(FR_SP)	|   the user stack pointer
966	clrl	%sp@-		| no VA arg
967	movl	_C_LABEL(curpcb),%a0 | current pcb
968	lea	%a0@(PCB_FPCTX),%a0 | address of FP savearea
969	fsave	%a0@		| save state
970#if defined(M68040) || defined(M68060)
971	/* always null state frame on 68040, 68060 */
972	cmpl	#FPU_68040,_C_LABEL(fputype)
973	jge	Lfptnull
974#endif
975	tstb	%a0@		| null state frame?
976	jeq	Lfptnull	| yes, safe
977	clrw	%d0		| no, need to tweak BIU
978	movb	%a0@(1),%d0	| get frame size
979	bset	#3,%a0@(0,%d0:w) | set exc_pend bit of BIU
980Lfptnull:
981	fmovem	%fpsr,%sp@-	| push fpsr as code argument
982	frestore %a0@		| restore state
983	movl	#T_FPERR,%sp@-	| push type arg
984	jra	_ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup
985
986
987/*
988 * Other exceptions only cause four and six word stack frame and require
989 * no post-trap stack adjustment.
990 */
991
992ENTRY_NOPROFILE(badtrap)
993	moveml	#0xC0C0,%sp@-		| save scratch regs
994	movw	%sp@(22),%sp@-		| push exception vector info
995	clrw	%sp@-
996	movl	%sp@(22),%sp@-		| and PC
997	jbsr	_C_LABEL(straytrap)	| report
998	addql	#8,%sp			| pop args
999	moveml	%sp@+,#0x0303		| restore regs
1000	jra	_ASM_LABEL(rei)		| all done
1001
1002ENTRY_NOPROFILE(trap0)
1003	clrl	%sp@-			| stack adjust count
1004	moveml	#0xFFFF,%sp@-		| save user registers
1005	movl	%usp,%a0		| save the user SP
1006	movl	%a0,%sp@(FR_SP)		|   in the savearea
1007	movl	%d0,%sp@-		| push syscall number
1008	jbsr	_C_LABEL(syscall)	| handle it
1009	addql	#4,%sp			| pop syscall arg
1010	tstl	_C_LABEL(astpending)	| AST pending?
1011	jne	Lrei1			| Yup, go deal with it.
1012	movl	%sp@(FR_SP),%a0		| grab and restore
1013	movl	%a0,%usp		|   user SP
1014	moveml	%sp@+,#0x7FFF		| restore most registers
1015	addql	#8,%sp			| pop SP and stack adjust
1016	rte
1017
1018/*
1019 * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD)
1020 *	cachectl(command, addr, length)
1021 * command in d0, addr in a1, length in d1
1022 */
1023ENTRY_NOPROFILE(trap12)
1024	movl	_C_LABEL(curlwp),%a0
1025	movl	%a0@(L_PROC),%sp@-	| push current proc pointer
1026	movl	%d1,%sp@-		| push length
1027	movl	%a1,%sp@-		| push addr
1028	movl	%d0,%sp@-		| push command
1029	jbsr	_C_LABEL(cachectl1)	| do it
1030	lea	%sp@(16),%sp		| pop args
1031	jra	_ASM_LABEL(rei)		| all done
1032
1033/*
1034 * Trace (single-step) trap.  Kernel-mode is special.
1035 * User mode traps are simply passed on to trap().
1036 */
1037ENTRY_NOPROFILE(trace)
1038	clrl	%sp@-			| stack adjust count
1039	moveml	#0xFFFF,%sp@-
1040	moveq	#T_TRACE,%d0
1041
1042	| Check PSW and see what happen.
1043	|   T=0 S=0	(should not happen)
1044	|   T=1 S=0	trace trap from user mode
1045	|   T=0 S=1	trace trap on a trap instruction
1046	|   T=1 S=1	trace trap from system mode (kernel breakpoint)
1047
1048	movw	%sp@(FR_HW),%d1		| get PSW
1049	notw	%d1			| XXX no support for T0 on 680[234]0
1050	andw	#PSL_TS,%d1		| from system mode (T=1, S=1)?
1051	jeq	Lkbrkpt			| yes, kernel breakpoint
1052	jra	_ASM_LABEL(fault)	| no, user-mode fault
1053
1054/*
1055 * Trap 15 is used for:
1056 *	- GDB breakpoints (in user programs)
1057 *	- KGDB breakpoints (in the kernel)
1058 *	- trace traps for SUN binaries (not fully supported yet)
1059 * User mode traps are simply passed to trap().
1060 */
1061ENTRY_NOPROFILE(trap15)
1062	clrl	%sp@-			| stack adjust count
1063	moveml	#0xFFFF,%sp@-
1064	moveq	#T_TRAP15,%d0
1065	movw	%sp@(FR_HW),%d1		| get PSW
1066	andw	#PSL_S,%d1		| from system mode?
1067	jne	Lkbrkpt			| yes, kernel breakpoint
1068	jra	_ASM_LABEL(fault)	| no, user-mode fault
1069
1070Lkbrkpt: | Kernel-mode breakpoint or trace trap. (d0=trap_type)
1071	| Save the system sp rather than the user sp.
1072	movw	#PSL_HIGHIPL,%sr	| lock out interrupts
1073	lea	%sp@(FR_SIZE),%a6	| Save stack pointer
1074	movl	%a6,%sp@(FR_SP)		|  from before trap
1075
1076	| If were are not on tmpstk switch to it.
1077	| (so debugger can change the stack pointer)
1078	movl	%a6,%d1
1079	cmpl	#_ASM_LABEL(tmpstk),%d1
1080	jls	Lbrkpt2			| already on tmpstk
1081	| Copy frame to the temporary stack
1082	movl	%sp,%a0			| a0=src
1083	lea	_ASM_LABEL(tmpstk)-96,%a1 | a1=dst
1084	movl	%a1,%sp			| sp=new frame
1085	movql	#FR_SIZE,%d1
1086Lbrkpt1:
1087	movl	%a0@+,%a1@+
1088	subql	#4,%d1
1089	jbgt	Lbrkpt1
1090
1091Lbrkpt2:
1092	| Call the trap handler for the kernel debugger.
1093	| Do not call trap() to do it, so that we can
1094	| set breakpoints in trap() if we want.  We know
1095	| the trap type is either T_TRACE or T_BREAKPOINT.
1096	| If we have both DDB and KGDB, let KGDB see it first,
1097	| because KGDB will just return 0 if not connected.
1098	| Save args in d2, a2
1099	movl	%d0,%d2			| trap type
1100	movl	%sp,%a2			| frame ptr
1101#ifdef KGDB
1102	| Let KGDB handle it (if connected)
1103	movl	%a2,%sp@-		| push frame ptr
1104	movl	%d2,%sp@-		| push trap type
1105	jbsr	_C_LABEL(kgdb_trap)	| handle the trap
1106	addql	#8,%sp			| pop args
1107	cmpl	#0,%d0			| did kgdb handle it?
1108	jne	Lbrkpt3			| yes, done
1109#endif
1110#ifdef DDB
1111	| Let DDB handle it
1112	movl	%a2,%sp@-		| push frame ptr
1113	movl	%d2,%sp@-		| push trap type
1114	jbsr	_C_LABEL(kdb_trap)	| handle the trap
1115	addql	#8,%sp			| pop args
1116#endif
1117	/* Sun 3 drops into PROM here. */
1118Lbrkpt3:
1119	| The stack pointer may have been modified, or
1120	| data below it modified (by kgdb push call),
1121	| so push the hardware frame at the current sp
1122	| before restoring registers and returning.
1123
1124	movl	%sp@(FR_SP),%a0		| modified sp
1125	lea	%sp@(FR_SIZE),%a1	| end of our frame
1126	movl	%a1@-,%a0@-		| copy 2 longs with
1127	movl	%a1@-,%a0@-		| ... predecrement
1128	movl	%a0,%sp@(FR_SP)		| sp = h/w frame
1129	moveml	%sp@+,#0x7FFF		| restore all but sp
1130	movl	%sp@,%sp		| ... and sp
1131	rte				| all done
1132
1133/*
1134 * Use common m68k sigreturn routine.
1135 */
1136#include <m68k/m68k/sigreturn.s>
1137
1138/*
1139 * Interrupt handlers.
1140 *
1141 * For auto-vectored interrupts, the CPU provides the
1142 * vector 0x18+level.
1143 *
1144 * intrhand_autovec is the entry point for auto-vectored
1145 * interrupts.
1146 *
1147 * For vectored interrupts, we pull the pc, evec, and exception frame
1148 * and pass them to the vectored interrupt dispatcher.  The vectored
1149 * interrupt dispatcher will deal with strays.
1150 *
1151 * intrhand_vectored is the entry point for vectored interrupts.
1152 */
1153
1154#define INTERRUPT_SAVEREG	moveml  #0xC0C0,%sp@-
1155#define INTERRUPT_RESTOREREG	moveml  %sp@+,#0x0303
1156
1157ENTRY_NOPROFILE(intrhand_autovec)
1158	addql	#1,_C_LABEL(interrupt_depth)
1159	INTERRUPT_SAVEREG
1160	lea	%sp@(16),%a1		| get pointer to frame
1161	movl	%a1,%sp@-
1162	jbsr	_C_LABEL(isrdispatch_autovec)  | call dispatcher
1163	addql	#4,%sp
1164	jbra	Lintrhand_exit
1165
1166ENTRY_NOPROFILE(intrhand_vectored)
1167	addql	#1,_C_LABEL(interrupt_depth)
1168	INTERRUPT_SAVEREG
1169	lea	%sp@(16),%a1		| get pointer to frame
1170	movl	%a1,%sp@-
1171	movw	%sr,%d0
1172	bfextu	%d0,21,3,%d0		| Get current ipl
1173	movl	%d0,%sp@-		| Push it
1174	jbsr	_C_LABEL(isrdispatch_vectored) | call dispatcher
1175	addql	#8,%sp
1176Lintrhand_exit:
1177	INTERRUPT_RESTOREREG
1178	subql	#1,_C_LABEL(interrupt_depth)
1179
1180	/* FALLTHROUGH to rei */
1181
1182#undef INTERRUPT_SAVEREG
1183#undef INTERRUPT_RESTOREREG
1184
1185/*
1186 * Emulation of VAX REI instruction.
1187 *
1188 * This code deals with checking for and servicing ASTs
1189 * (profiling, scheduling).
1190 * After identifing that we need an AST we drop the IPL to allow device
1191 * interrupts.
1192 *
1193 * This code is complicated by the fact that sendsig may have been called
1194 * necessitating a stack cleanup.
1195 */
1196ASENTRY_NOPROFILE(rei)
1197	tstl	_C_LABEL(astpending)	| AST pending?
1198	jeq	Ldorte			| Nope. Just return.
1199	btst	#5,%sp@			| Returning to kernel mode?
1200	jne	Ldorte			| Yup. Can't do ASTs
1201	movw	#PSL_LOWIPL,%sr		| lower SPL
1202	clrl	%sp@-			| stack adjust
1203	moveml	#0xFFFF,%sp@-		| save all registers
1204	movl	%usp,%a1		| including
1205	movl	%a1,%sp@(FR_SP)		|    the users SP
1206Lrei1:	clrl	%sp@-			| VA == none
1207	clrl	%sp@-			| code == none
1208	movl	#T_ASTFLT,%sp@-		| type == async system trap
1209	pea	%sp@(12)		| fp == address of trap frame
1210	jbsr	_C_LABEL(trap)		| go handle it
1211	lea	%sp@(16),%sp		| pop value args
1212	movl	%sp@(FR_SP),%a0		| restore user SP
1213	movl	%a0,%usp		|   from save area
1214	movw	%sp@(FR_ADJ),%d0	| need to adjust stack?
1215	jne	Laststkadj		| yes, go to it
1216	moveml	%sp@+,#0x7FFF		| no, restore most user regs
1217	addql	#8,%sp			| toss SP and stack adjust
1218Ldorte:	rte				| and do real RTE
1219
1220Laststkadj:
1221	lea	%sp@(FR_HW),%a1		| pointer to HW frame
1222	addql	#8,%a1			| source pointer
1223	movl	%a1,%a0			| source
1224	addw	%d0,%a0			|  + hole size = dest pointer
1225	movl	%a1@-,%a0@-		| copy
1226	movl	%a1@-,%a0@-		|  8 bytes
1227	movl	%a0,%sp@(FR_SP)		| new SSP
1228	moveml	%sp@+,#0x7FFF		| restore user registers
1229	movl	%sp@,%sp		| and our SP
1230	rte				| and do real RTE
1231
1232/*
1233 * Use common m68k sigcode.
1234 */
1235#include <m68k/m68k/sigcode.s>
1236#ifdef COMPAT_SUNOS
1237#include <m68k/m68k/sunos_sigcode.s>
1238#endif
1239#ifdef COMPAT_SVR4
1240#include <m68k/m68k/svr4_sigcode.s>
1241#endif
1242
1243/*
1244 * Primitives
1245 */
1246
1247/*
1248 * Use common m68k support routines.
1249 */
1250#include <m68k/m68k/support.s>
1251
1252/*
1253 * Use common m68k process/lwp switch and context save subroutines.
1254 */
1255#define	FPCOPROC	/* XXX: Temp. Reqd. */
1256#include <m68k/m68k/switch_subr.s>
1257
1258
1259#if defined(M68040) || defined(M68060)
1260ENTRY(suline)
1261	movl	%sp@(4),%a0		| address to write
1262	movl	_C_LABEL(curpcb),%a1	| current pcb
1263	movl	#Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault
1264	movl	%sp@(8),%a1		| address of line
1265	movl	%a1@+,%d0		| get lword
1266	movsl	%d0,%a0@+		| put lword
1267	nop				| sync
1268	movl	%a1@+,%d0		| get lword
1269	movsl	%d0,%a0@+		| put lword
1270	nop				| sync
1271	movl	%a1@+,%d0		| get lword
1272	movsl	%d0,%a0@+		| put lword
1273	nop				| sync
1274	movl	%a1@+,%d0		| get lword
1275	movsl	%d0,%a0@+		| put lword
1276	nop				| sync
1277	moveq	#0,%d0			| indicate no fault
1278	jra	Lsldone
1279Lslerr:
1280	moveq	#-1,%d0
1281Lsldone:
1282	movl	_C_LABEL(curpcb),%a1	| current pcb
1283	clrl	%a1@(PCB_ONFAULT)	| clear fault address
1284	rts
1285#endif
1286
1287
1288ENTRY(ecacheon)
1289	rts
1290
1291ENTRY(ecacheoff)
1292	rts
1293
1294/*
1295 * Get callers current SP value.
1296 * Note that simply taking the address of a local variable in a C function
1297 * doesn't work because callee saved registers may be outside the stack frame
1298 * defined by A6 (e.g. GCC generated code).
1299 */
1300ENTRY_NOPROFILE(getsp)
1301	movl	%sp,%d0			| get current SP
1302	addql	#4,%d0			| compensate for return address
1303	movl	%d0,%a0
1304	rts
1305
1306ENTRY_NOPROFILE(getsfc)
1307	movc	%sfc,%d0
1308	movl	%d0,%a0
1309	rts
1310
1311ENTRY_NOPROFILE(getdfc)
1312	movc	%dfc,%d0
1313	movl	%d0,%a0
1314	rts
1315
1316/*
1317 * Load a new user segment table pointer.
1318 */
1319ENTRY(loadustp)
1320	movl	%sp@(4),%d0		| new USTP
1321	moveq	#PGSHIFT, %d1
1322	lsll	%d1,%d0			| convert to addr
1323#if defined(M68040) || defined(M68060)
1324	cmpl    #MMU_68040,_C_LABEL(mmutype) | 68040?
1325	jne     LmotommuC               | no, skip
1326	.word	0xf518			| pflusha
1327	.long   0x4e7b0806              | movc d0,urp
1328#ifdef M68060
1329	cmpl	#CPU_68060,_C_LABEL(cputype)
1330	jne	Lldno60
1331	movc	%cacr,%d0
1332	orl	#IC60_CUBC,%d0		| clear user branch cache entries
1333	movc	%d0,%cacr
1334Lldno60:
1335#endif
1336	rts
1337LmotommuC:
1338#endif
1339	pflusha				| flush entire TLB
1340	lea	_C_LABEL(protorp),%a0	| CRP prototype
1341	movl	%d0,%a0@(4)		| stash USTP
1342	pmove	%a0@,%crp		| load root pointer
1343	movl	#CACHE_CLR,%d0
1344	movc	%d0,%cacr		| invalidate cache(s)
1345	rts
1346
1347ENTRY(ploadw)
1348#ifdef M68030
1349#if defined(M68040) || defined(M68060)
1350	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
1351	jeq	Lploadwskp		| yes, skip
1352#endif
1353	movl	%sp@(4),%a0		| address to load
1354	ploadw	#1,%a0@			| pre-load translation
1355Lploadwskp:
1356#endif
1357	rts
1358
1359ENTRY(getsr)
1360	moveq	#0,%d0
1361	movw	%sr,%d0
1362	rts
1363
1364/*
1365 * _delay(unsigned N)
1366 *
1367 * Delay for at least (N/1024) microseconds.
1368 * This routine depends on the variable:  delay_divisor
1369 * which should be set based on the CPU clock rate.
1370 */
1371ENTRY_NOPROFILE(_delay)
1372	| d0 = arg = (usecs << 10)
1373	movl	%sp@(4),%d0
1374	| d1 = delay_divisor
1375	movl	_C_LABEL(delay_divisor),%d1
1376	jra	L_delay			/* Jump into the loop! */
1377
1378	/*
1379	 * Align the branch target of the loop to a half-line (8-byte)
1380	 * boundary to minimize cache effects.  This guarantees both
1381	 * that there will be no prefetch stalls due to cache line burst
1382	 * operations and that the loop will run from a single cache
1383	 * half-line.
1384	 */
1385#ifdef __ELF__
1386	.align	8
1387#else
1388	.align	3
1389#endif
1390L_delay:
1391	subl	%d1,%d0
1392	jgt	L_delay
1393	rts
1394
1395/*
1396 * Save and restore 68881 state.
1397 */
1398ENTRY(m68881_save)
1399	movl	%sp@(4),%a0		| save area pointer
1400	fsave	%a0@			| save state
1401#if defined(M68020) || defined(M68030) || defined(M68040)
1402#if defined(M68060)
1403	cmpl	#FPU_68060,_C_LABEL(fputype)
1404	jeq	Lm68060fpsave
1405#endif
1406Lm68881fpsave:
1407	tstb	%a0@			| null state frame?
1408	jeq	Lm68881sdone		| yes, all done
1409	fmovem	%fp0-%fp7,%a0@(FPF_REGS)	| save FP general registers
1410	fmovem	%fpcr/%fpsr/%fpi,%a0@(FPF_FPCR) | save FP control registers
1411Lm68881sdone:
1412	rts
1413#endif
1414#if defined(M68060)
1415Lm68060fpsave:
1416	tstb	%a0@(2)			| null state frame?
1417	jeq	Lm68060sdone		| yes, all done
1418	fmovem	%fp0-%fp7,%a0@(FPF_REGS)	| save FP general registers
1419	fmovem	%fpcr,%a0@(FPF_FPCR)	| save FP control registers
1420	fmovem	%fpsr,%a0@(FPF_FPSR)
1421	fmovem	%fpi,%a0@(FPF_FPI)
1422Lm68060sdone:
1423        rts
1424#endif
1425
1426ENTRY(m68881_restore)
1427	movl	%sp@(4),%a0		| save area pointer
1428#if defined(M68020) || defined(M68030) || defined(M68040)
1429#if defined(M68060)
1430	cmpl	#FPU_68060,_C_LABEL(fputype)
1431	jeq	Lm68060fprestore
1432#endif
1433Lm68881fprestore:
1434	tstb	%a0@			| null state frame?
1435	jeq	Lm68881rdone		| yes, easy
1436	fmovem	%a0@(FPF_FPCR),%fpcr/%fpsr/%fpi | restore FP control registers
1437	fmovem	%a0@(FPF_REGS),%fp0-%fp7	| restore FP general registers
1438Lm68881rdone:
1439	frestore %a0@			| restore state
1440	rts
1441#endif
1442#if defined(M68060)
1443Lm68060fprestore:
1444	tstb	%a0@(2)			| null state frame?
1445	jeq	Lm68060fprdone		| yes, easy
1446	fmovem	%a0@(FPF_FPCR),%fpcr	| restore FP control registers
1447	fmovem	%a0@(FPF_FPSR),%fpsr
1448	fmovem	%a0@(FPF_FPI),%fpi
1449	fmovem	%a0@(FPF_REGS),%fp0-%fp7 | restore FP general registers
1450Lm68060fprdone:
1451	frestore %a0@			| restore state
1452	rts
1453#endif
1454
1455/*
1456 * Handle the nitty-gritty of rebooting the machine.
1457 * Basically we just turn off the MMU, restore the Bug's initial VBR
1458 * and either return to Bug or jump through the ROM reset vector
1459 * depending on how the system was halted.
1460 */
1461ENTRY_NOPROFILE(doboot)
1462	movw	#PSL_HIGHIPL,%sr
1463	movl	_C_LABEL(boothowto),%d1	| load howto
1464	movl	%sp@(4),%d2		| arg
1465	movl	_ASM_LABEL(bug_vbr),%d3	| Fetch Bug's original VBR value
1466	movl	_C_LABEL(machineid),%d4	| What type of board is this?
1467	movl	#CACHE_OFF,%d0
1468#if defined(M68040) || defined(M68060)
1469	cmpl	#MMU_68040,_C_LABEL(mmutype)	| 68040/68060?
1470	jne	Lnocache0		| no, skip
1471	.word	0xf4f8			| cpusha bc - push and invalidate caches
1472	nop
1473	movl	#CACHE40_OFF,%d0
1474#endif
1475Lnocache0:
1476	movc	%d0,%cacr		| disable on-chip cache(s)
1477
1478#if defined(M68040) || defined(M68060)
1479	cmpl	#MMU_68040,_C_LABEL(mmutype)
1480	jne	LmotommuF
1481	movql	#0,%d0
1482	movc	%d0,%cacr
1483	.long	0x4e7b0003              | movc d0,tc
1484	jra	Lbootcommon
1485LmotommuF:
1486#endif
1487	clrl	%sp@-			| value for pmove to TC (turn off MMU)
1488	pmove	%sp@,%tc		| disable MMU
1489	addql	#4,%sp
1490
1491Lbootcommon:
1492	/*
1493	 * MMU Switched off by now, so relocate all absolute references
1494	 */
1495	ASRELOC(tmpstk, %sp)		| physical SP in case of NMI
1496	movc	%d3,%vbr		| Restore Bug's VBR
1497	andl	#RB_SBOOT, %d1		| mask off
1498	jbne	Lsboot			| sboot?
1499	/* NOT sboot */
1500	tstl	%d2			| autoboot?
1501	jbeq	Ldoreset		| yes!
1502	CALLBUG(MVMEPROM_EXIT)		| return to bug
1503	/* NOTREACHED */
1504
1505Ldoreset:
1506	movl	#0xff800000,%a0		| Bug's reset vector address
1507	movl	%a0@+, %a7		| get SP
1508	movl	%a0@, %a0		| get PC
1509	jmp	%a0@			| go!
1510
1511Lsboot: /* sboot */
1512	tstl	%d2			| autoboot?
1513	jbeq	1f			| yes!
1514	jmp 	0x4000			| back to sboot
15151:	jmp	0x400a			| tell sboot to reboot us
1516
1517
1518/*
1519 * Misc. global variables.
1520 */
1521	.data
1522
1523GLOBAL(machineid)
1524	.long	MVME_147	| default to MVME_147
1525
1526GLOBAL(mmutype)
1527	.long	MMU_68030	| default to MMU_68030
1528
1529GLOBAL(cputype)
1530	.long	CPU_68030	| default to CPU_68030
1531
1532GLOBAL(fputype)
1533	.long	FPU_68882	| default to FPU_68882
1534
1535GLOBAL(protorp)
1536	.long	0,0		| prototype root pointer
1537
1538/*
1539 * Information from first stage boot program
1540 */
1541GLOBAL(bootpart)
1542	.long	0
1543GLOBAL(bootdevlun)
1544	.long	0
1545GLOBAL(bootctrllun)
1546	.long	0
1547GLOBAL(bootaddr)
1548	.long	0
1549
1550GLOBAL(intiobase)
1551	.long	0		| KVA of base of internal IO space
1552
1553GLOBAL(intiolimit)
1554	.long	0		| KVA of end of internal IO space
1555
1556GLOBAL(intiobase_phys)
1557	.long	0		| PA of board's I/O registers
1558
1559GLOBAL(intiotop_phys)
1560	.long	0		| PA of top of board's I/O registers
1561
1562/*
1563 * interrupt counters.
1564 * XXXSCW: Will go away soon; kept here to keep vmstat happy
1565 */
1566GLOBAL(intrnames)
1567	.asciz	"spur"
1568	.asciz	"lev1"
1569	.asciz	"lev2"
1570	.asciz	"lev3"
1571	.asciz	"lev4"
1572	.asciz	"clock"
1573	.asciz	"lev6"
1574	.asciz	"nmi"
1575	.asciz	"statclock"
1576GLOBAL(eintrnames)
1577	.even
1578
1579GLOBAL(intrcnt)
1580	.long	0,0,0,0,0,0,0,0,0,0
1581GLOBAL(eintrcnt)
1582