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