1/*	$NetBSD: locore.s,v 1.85 2024/01/17 12:33:50 thorpej Exp $	*/
2
3/*
4 * Copyright (c) 1998 Darrin B. Jewell
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/*
42 * Copyright (c) 1994, 1995 Gordon W. Ross
43 * Copyright (c) 1988 University of Utah.
44 *
45 * This code is derived from software contributed to Berkeley by
46 * the Systems Programming Group of the University of Utah Computer
47 * Science Department.
48 *
49 * Redistribution and use in source and binary forms, with or without
50 * modification, are permitted provided that the following conditions
51 * are met:
52 * 1. Redistributions of source code must retain the above copyright
53 *    notice, this list of conditions and the following disclaimer.
54 * 2. Redistributions in binary form must reproduce the above copyright
55 *    notice, this list of conditions and the following disclaimer in the
56 *    documentation and/or other materials provided with the distribution.
57 * 3. All advertising materials mentioning features or use of this software
58 *    must display the following acknowledgement:
59 *	This product includes software developed by the University of
60 *	California, Berkeley and its contributors.
61 * 4. Neither the name of the University nor the names of its contributors
62 *    may be used to endorse or promote products derived from this software
63 *    without specific prior written permission.
64 *
65 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
66 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
67 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
68 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
69 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
70 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
71 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
72 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
73 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
74 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
75 * SUCH DAMAGE.
76 *
77 * from: Utah $Hdr: locore.s 1.66 92/12/22$
78 *
79 *	@(#)locore.s	8.6 (Berkeley) 5/27/94
80 */
81
82/* This is currently amid development by
83 * Darrin Jewell <jewell@mit.edu>  Fri Jan  2 14:36:47 1998
84 * for the next68k port
85 */
86
87#include "opt_compat_netbsd.h"
88#include "opt_compat_sunos.h"
89#include "opt_ddb.h"
90#include "opt_fpsp.h"
91#include "opt_kgdb.h"
92#include "opt_lockdebug.h"
93#include "opt_fpu_emulate.h"
94#include "opt_useleds.h"
95#include "opt_m68k_arch.h"
96
97#include "assym.h"
98#include <machine/asm.h>
99#include <machine/trap.h>
100
101#if (!defined(M68040))
102#error "M68040 is not defined! (check that the generated assym.h is not empty)"
103#endif
104
105#include "ksyms.h"
106
107/*
108 * This is for kvm_mkdb, and should be the address of the beginning
109 * of the kernel text segment (not necessarily the same as kernbase).
110 */
111	.text
112GLOBAL(kernel_text)
113
114 /*
115  * Leave page zero empty so it can be unmapped
116  */
117	.space	PAGE_SIZE
118
119/*
120 * Temporary stack for a variety of purposes.
121 */
122	.data
123GLOBAL(endstack)
124	.space	PAGE_SIZE
125GLOBAL(bgnstack)
126ASLOCAL(tmpstk)
127
128/*
129 * Macro to relocate a symbol, used before MMU is enabled.
130 * On the NeXT, memory is laid out as in the mach header
131 * so therefore we need to relocate symbols until the MMU
132 * is turned on.
133 */
134#define	_RELOC(var, ar)		\
135	lea	var,ar;		\
136	addl	%a5,ar
137
138#define	RELOC(var, ar)		_RELOC(_C_LABEL(var), ar)
139#define	ASRELOC(var, ar)	_RELOC(_ASM_LABEL(var), ar)
140
141/*
142 * Initialization info as per grossman's boot loader:
143 *
144 * We are called from the boot prom, not the boot loader. We have the
145 * prom's stack initialized for us and we were called like this:
146 * start(mg, mg->mg_console_i, mg->mg_console_o,
147 *       mg->mg_boot_dev, mg->mg_boot_arg, mg->mg_boot_info,
148 *       mg->mg_sid, mg->mg_pagesize, 4, mg->mg_region,
149 *       etheraddr, mg->mg_boot_file);
150 * so we actually only really need the first parameter from the stack.
151 * Exceptions will be handled by the prom until we feel ready to handle
152 * them ourselves.
153 * By the way, we get loaded at our final address i.e. PA==VA for the kernel.
154 */
155 /* I think the PA==VA comment to be a lie, but I have yet to verify it.
156  * Darrin B Jewell <jewell@mit.edu>  Sun Jan 11 01:05:54 1998
157 */
158BSS(lowram,4)
159BSS(esym,4)
160
161ASENTRY_NOPROFILE(start)
162	movw	#PSL_HIGHIPL,%sr	| no interrupts
163	movl	#CACHE_OFF,%d0
164	movc	%d0,%cacr		| clear and disable on-chip cache(s)
165
166	moveal	#NEXT_RAMBASE,%a5	| amount to RELOC by.
167	RELOC(lowram,%a0)		| store base of memory.
168	movl    %a5,%a0@
169
170	| Create a new stack at address tmpstk, and push
171	| The existing sp onto it as an arg for next68k_bootargs.
172	ASRELOC(tmpstk, %a0)
173	movel	%sp,%a0@-
174	moveal  %a0,%sp
175	moveal  #0,%a6
176
177	/* Read the header to get our segment list */
178	RELOC(next68k_bootargs,%a0)
179	jbsr	%a0@			| next68k_bootargs(args)
180	addqw	#4,%sp			| clear arg from stack.
181
182	/*
183	 * All data registers are now free.  All address registers
184	 * except %a5 are free.  %a5 is used by the RELOC() macro on hp300
185	 * and cannot be used until after the MMU is enabled.
186	 */
187
188/* determine our CPU/MMU combo - check for all regardless of kernel config */
189	movl	#0x200,%d0		| data freeze bit
190	movc	%d0,%cacr		|   only exists on 68030
191	movc	%cacr,%d0		| read it back
192	tstl	%d0			| zero?
193	jeq	Lnot68030		| yes, we have 68020/68040
194
195	/*
196	 * 68030 models
197	 */
198
199	RELOC(mmutype, %a0)		| no, we have 68030
200	movl	#MMU_68030,%a0@		| set to reflect 68030 PMMU
201	RELOC(cputype, %a0)
202	movl	#CPU_68030,%a0@		| and 68030 CPU
203	RELOC(machineid, %a0)
204	movl	#30,%a0@		| @@@ useless
205	jra	Lstart1
206
207	/*
208	 * End of 68030 section
209	 */
210
211Lnot68030:
212	bset	#31,%d0			| data cache enable bit
213	movc	%d0,%cacr		|   only exists on 68040
214	movc	%cacr,%d0		| read it back
215	tstl	%d0			| zero?
216	beq	Lis68020		| yes, we have 68020
217	moveq	#0,%d0			| now turn it back off
218	movec	%d0,%cacr		|   before we access any data
219
220	/*
221	 * 68040 models
222	 */
223
224	RELOC(mmutype, %a0)
225	movl	#MMU_68040,%a0@		| with a 68040 MMU
226	RELOC(cputype, %a0)
227	movl	#CPU_68040,%a0@		| and a 68040 CPU
228	RELOC(fputype, %a0)
229	movl	#FPU_68040,%a0@		| ...and FPU
230	RELOC(machineid, %a0)
231	movl	#40,%a0@		| @@@ useless
232	jra	Lstart1
233
234	/*
235	 * End of 68040 section
236	 */
237
238	/*
239	 * 68020 models
240	 * (There are no 68020 models of NeXT, but we'll pretend)
241	 */
242
243Lis68020:
244	RELOC(mmutype, %a0)
245	movl	#MMU_68851,%a0@		| no, we have PMMU
246	RELOC(fputype, %a0)		| all of the 68020 systems
247	movl	#FPU_68881,%a0@		|   have a 68881 FPU
248	RELOC(cputype, %a0)
249	movl	#CPU_68020,%a0@		| and a 68020 CPU
250	RELOC(machineid, %a0)
251	movl	#20,%a0@			| @@@ useless
252	jra	Lstart1
253
254	/*
255	 * End of 68020 section
256	 */
257
258Lstart1:
259/* initialize source/destination control registers for movs */
260	moveq	#FC_USERD,%d0		| user space
261	movc	%d0,%sfc		|   as source
262	movc	%d0,%dfc		|   and destination of transfers
263/* configure kernel and lwp0 VA space so we can get going */
264#if NKSYMS || defined(DDB) || defined(MODULAR)
265	RELOC(esym,%a0)			| end of static kernel test/data/syms
266	movl	%a0@,%d5
267	jne	Lstart3
268#endif
269	movl	#_C_LABEL(end),%d5	| end of static kernel text/data
270
271Lstart3:
272	addl	#PAGE_SIZE-1,%d5
273	andl	#PG_FRAME,%d5		| round to a page
274	movl	%d5,%a4
275	addl	%a5,%a4			| convert to PA
276	pea	%a5@			| firstpa
277	pea	%a4@			| nextpa
278	RELOC(pmap_bootstrap,%a0)
279	jbsr	%a0@			| pmap_bootstrap(firstpa,nextpa)
280	addql	#8,%sp
281
282/*
283 * Prepare to enable MMU.
284 * Since the kernel is not mapped logical == physical we must insure
285 * that when the MMU is turned on, all prefetched addresses (including
286 * the PC) are valid.  In order guarantee that, we use the transparent
287 * translation registers (which provide PA == VA mappings) and just
288 * turns on the MMU, then jump from the VA == PA address (at 0x40XXXXXX)
289 * to the actual kernel virtual address (at 0x00XXXXXX) code via a far
290 * jump instruction so that we can defeat the prefetch.
291 */
292	RELOC(Sysseg_pa, %a0)		| system segment table addr
293	movl	%a0@,%d1		| read value (a PA)
294
295	RELOC(mmutype, %a0)
296	cmpl	#MMU_68040,%a0@		| 68040?
297	jne	Lmotommu1		| no, skip
298	.long	0x4e7b1807		| movc %d1,%srp
299	jra	Lstploaddone
300Lmotommu1:
301#ifdef M68030
302	RELOC(protorp, %a0)
303	movl	%d1,%a0@(4)		| segtable address
304	pmove	%a0@,%srp		| load the supervisor root pointer
305#endif /* M68030 */
306
307Lstploaddone:
308	RELOC(mmutype, %a0)
309	cmpl	#MMU_68040,%a0@		| 68040?
310	jne	Lmotommu2		| no, skip
311
312	| This is a hack to get PA=KVA when turning on MMU as mentioned above.
313	| Currently this will only work on 68040's.  We should also provide
314	| %tt0 and %tt1 settings to boot 68030's later.
315	movel	#NEXT68K_TT40_IO,%d0	| see pmap.h
316	.long	0x4e7b0004		| movc %d0,%itt0
317	.long	0x4e7b0006		| movc %d0,%dtt0
318	movel	#NEXT68K_TT40_KERN,%d0	| see pmap.h
319	.long	0x4e7b0005		| movc %d0,%itt1
320	.long	0x4e7b0007		| movc %d0,%dtt1
321
322	.word	0xf4d8			| cinva bc
323	.word	0xf518			| pflusha
324	movl	#MMU40_TCR_BITS,%d0
325	.long	0x4e7b0003		| movc %d0,%tc
326	movl	#0x80008000,%d0
327	movc	%d0,%cacr		| turn on both caches
328
329	jmp     Lturnoffttr:l		| global jump into mapped memory.
330Lturnoffttr:
331	moveq	#0,%d0			| ensure TT regs are disabled
332	.long	0x4e7b0004		| movc %d0,%itt0
333	.long	0x4e7b0006		| movc %d0,%dtt0
334	.long	0x4e7b0005		| movc %d0,%itt1
335	.long	0x4e7b0007		| movc %d0,%dtt1
336	jmp	Lenab1
337
338Lmotommu2:
339	pflusha
340	RELOC(prototc, %a2)
341	movl	#MMU51_TCR_BITS,%a2@	| value to load TC with
342	pmove	%a2@,%tc		| load it
343	jmp	Lenab1:l		| force absolute (not pc-relative) jmp
344
345/*
346 * Should be running mapped from this point on
347 */
348Lenab1:
349	lea	_ASM_LABEL(tmpstk),%sp	| re-load temporary stack
350	jbsr	_C_LABEL(vec_init)	| initialize vector table
351/* call final pmap setup */
352	jbsr	_C_LABEL(pmap_bootstrap_finalize)
353/* set kernel stack, user SP */
354	movl	_C_LABEL(lwp0uarea),%a1	| get lwp0 uarea
355	lea	%a1@(USPACE-4),%sp	| set kernel stack to end of area
356	movl	#USRSTACK-4,%a2
357	movl	%a2,%usp		| init user SP
358
359	tstl	_C_LABEL(fputype)	| Have an FPU?
360	jeq	Lenab2			| No, skip.
361	clrl	%a1@(PCB_FPCTX)		| ensure null FP context
362	movl	%a1,%sp@-
363	jbsr	_C_LABEL(m68881_restore) | restore it (does not kill %a1)
364	addql	#4,%sp
365Lenab2:
366	cmpl	#MMU_68040,_C_LABEL(mmutype)	| 68040?
367	jeq	Ltbia040		| yes, cache already on
368	pflusha
369	movl	#CACHE_ON,%d0
370	movc	%d0,%cacr		| clear cache(s)
371	jra	Lenab3
372Ltbia040:
373	.word	0xf518			| pflusha
374Lenab3:
375
376	jbsr	_C_LABEL(next68k_init)
377
378/* Final setup for call to main(). */
379/*
380 * Create a fake exception frame so that cpu_lwp_fork() can copy it.
381 * main() nevers returns; we exit to user mode from a forked process
382 * later on.
383 */
384	clrw	%sp@-			| vector offset/frame type
385	clrl	%sp@-			| PC - filled in by "execve"
386	movw	#PSL_USER,%sp@-		| in user mode
387	clrl	%sp@-			| stack adjust count and padding
388	lea	%sp@(-64),%sp		| construct space for %D0-%D7/%A0-%A7
389	lea	_C_LABEL(lwp0),%a0	| save pointer to frame
390	movl	%sp,%a0@(L_MD_REGS)	|   in lwp0.p_md.md_regs
391
392	jra	_C_LABEL(main)		| main()
393	PANIC("main() returned")
394	/* NOTREACHED */
395
396/*
397 * Trap/interrupt vector routines
398 */
399#include <m68k/m68k/trap_subr.s>
400
401/*
402 * Use common m68k bus error and address error handlers.
403 */
404#include <m68k/m68k/busaddrerr.s>
405
406/*
407 * FP exceptions.
408 */
409ENTRY_NOPROFILE(fpfline)
410#if defined(M68040)
411	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
412	jne	Lfp_unimp		| no, skip FPSP
413	cmpw	#0x202c,%sp@(6)		| format type 2?
414	jne	_C_LABEL(illinst)	| no, not an FP emulation
415Ldofp_unimp:
416#ifdef FPSP
417	jmp	_ASM_LABEL(fpsp_unimp)	| yes, go handle it
418#endif
419Lfp_unimp:
420#endif /* M68040 */
421#ifdef FPU_EMULATE
422	clrl	%sp@-			| stack adjust count
423	moveml	#0xFFFF,%sp@-		| save registers
424	moveq	#T_FPEMULI,%d0		| denote as FP emulation trap
425	jra	_ASM_LABEL(fault)	| do it
426#else
427	jra	_C_LABEL(illinst)
428#endif
429
430ENTRY_NOPROFILE(fpunsupp)
431#if defined(M68040)
432	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
433	jne	_C_LABEL(illinst)	| no, treat as illinst
434#ifdef FPSP
435	jmp	_ASM_LABEL(fpsp_unsupp)	| yes, go handle it
436#endif
437Lfp_unsupp:
438#endif /* M68040 */
439#ifdef FPU_EMULATE
440	clrl	%sp@-			| stack adjust count
441	moveml	#0xFFFF,%sp@-		| save registers
442	moveq	#T_FPEMULD,%d0		| denote as FP emulation trap
443	jra	_ASM_LABEL(fault)	| do it
444#else
445	jra	_C_LABEL(illinst)
446#endif
447
448/*
449 * Handles all other FP coprocessor exceptions.
450 * Note that since some FP exceptions generate mid-instruction frames
451 * and may cause signal delivery, we need to test for stack adjustment
452 * after the trap call.
453 */
454ENTRY_NOPROFILE(fpfault)
455	clrl	%sp@-		| stack adjust count
456	moveml	#0xFFFF,%sp@-	| save user registers
457	movl	%usp,%a0		| and save
458	movl	%a0,%sp@(FR_SP)	|   the user stack pointer
459	clrl	%sp@-		| no VA arg
460	movl	_C_LABEL(curpcb),%a0 | current pcb
461	lea	%a0@(PCB_FPCTX),%a0 | address of FP savearea
462	fsave	%a0@		| save state
463#if defined(M68040) || defined(M68060)
464	/* always null state frame on 68040, 68060 */
465	cmpl	#FPU_68040,_C_LABEL(fputype)
466	jge	Lfptnull
467#endif
468	tstb	%a0@		| null state frame?
469	jeq	Lfptnull	| yes, safe
470	clrw	%d0		| no, need to tweak BIU
471	movb	%a0@(1),%d0	| get frame size
472	bset	#3,%a0@(0,%d0:w) | set exc_pend bit of BIU
473Lfptnull:
474	fmovem	%fpsr,%sp@-	| push %fpsr as code argument
475	frestore %a0@		| restore state
476	movl	#T_FPERR,%sp@-	| push type arg
477	jra	_ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup
478
479/*
480 * Other exceptions only cause four and six word stack frame and require
481 * no post-trap stack adjustment.
482 */
483
484ENTRY_NOPROFILE(badtrap)
485	moveml	#0xC0C0,%sp@-		| save scratch regs
486	movw	%sp@(22),%sp@-		| push exception vector info
487	clrw	%sp@-
488	movl	%sp@(22),%sp@-		| and PC
489	jbsr	_C_LABEL(straytrap)	| report
490	addql	#8,%sp			| pop args
491	moveml	%sp@+,#0x0303		| restore regs
492	jra	_ASM_LABEL(rei)		| all done
493
494ENTRY_NOPROFILE(trap0)
495	clrl	%sp@-			| stack adjust count
496	moveml	#0xFFFF,%sp@-		| save user registers
497	movl	%usp,%a0		| save the user SP
498	movl	%a0,%sp@(FR_SP)		|   in the savearea
499	movl	%d0,%sp@-		| push syscall number
500	jbsr	_C_LABEL(syscall)	| handle it
501	addql	#4,%sp			| pop syscall arg
502	tstl	_C_LABEL(astpending)
503	jne	Lrei
504	movl	%sp@(FR_SP),%a0		| grab and restore
505	movl	%a0,%usp		|   user SP
506	moveml	%sp@+,#0x7FFF		| restore most registers
507	addql	#8,%sp			| pop SP and stack adjust
508	rte
509
510/*
511 * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD)
512 *	cachectl(command, addr, length)
513 * command in %d0, addr in %a1, length in %d1
514 */
515ENTRY_NOPROFILE(trap12)
516	movl	_C_LABEL(curlwp),%a0
517	movl	%a0@(L_PROC),%sp@-	| push curproc pointer
518	movl	%d1,%sp@-		| push length
519	movl	%a1,%sp@-		| push addr
520	movl	%d0,%sp@-		| push command
521	jbsr	_C_LABEL(cachectl1)	| do it
522	lea	%sp@(16),%sp		| pop args
523	jra	_ASM_LABEL(rei)		| all done
524
525/*
526 * Trace (single-step) trap.  Kernel-mode is special.
527 * User mode traps are simply passed on to trap().
528 */
529ENTRY_NOPROFILE(trace)
530	clrl	%sp@-			| stack adjust count
531	moveml	#0xFFFF,%sp@-
532	moveq	#T_TRACE,%d0
533
534	| Check PSW and see what happen.
535	|   T=0 S=0	(should not happen)
536	|   T=1 S=0	trace trap from user mode
537	|   T=0 S=1	trace trap on a trap instruction
538	|   T=1 S=1	trace trap from system mode (kernel breakpoint)
539
540	movw	%sp@(FR_HW),%d1		| get PSW
541	notw	%d1			| XXX no support for T0 on 680[234]0
542	andw	#PSL_TS,%d1		| from system mode (T=1, S=1)?
543	jeq	Lkbrkpt			| yes, kernel breakpoint
544	jra	_ASM_LABEL(fault)	| no, user-mode fault
545
546/*
547 * Trap 15 is used for:
548 *	- GDB breakpoints (in user programs)
549 *	- KGDB breakpoints (in the kernel)
550 *	- trace traps for SUN binaries (not fully supported yet)
551 * User mode traps are simply passed to trap().
552 */
553ENTRY_NOPROFILE(trap15)
554	clrl	%sp@-			| stack adjust count
555	moveml	#0xFFFF,%sp@-
556	moveq	#T_TRAP15,%d0
557	movw	%sp@(FR_HW),%d1		| get PSW
558	andw	#PSL_S,%d1		| from system mode?
559	jne	Lkbrkpt			| yes, kernel breakpoint
560	jra	_ASM_LABEL(fault)	| no, user-mode fault
561
562Lkbrkpt: | Kernel-mode breakpoint or trace trap. (%d0=trap_type)
563	| Save the system %sp rather than the user %sp.
564	movw	#PSL_HIGHIPL,%sr	| lock out interrupts
565	lea	%sp@(FR_SIZE),%a6	| Save stack pointer
566	movl	%a6,%sp@(FR_SP)		|  from before trap
567
568	| If were are not on tmpstk switch to it.
569	| (so debugger can change the stack pointer)
570	movl	%a6,%d1
571	cmpl	#_ASM_LABEL(tmpstk),%d1
572	jls	Lbrkpt2			| already on tmpstk
573	| Copy frame to the temporary stack
574	movl	%sp,%a0			| %a0=src
575	lea	_ASM_LABEL(tmpstk)-96,%a1 | %a1=dst
576	movl	%a1,%sp			| %sp=new frame
577	moveq	#FR_SIZE,%d1
578Lbrkpt1:
579	movl	%a0@+,%a1@+
580	subql	#4,%d1
581	bgt	Lbrkpt1
582
583Lbrkpt2:
584	| Call the trap handler for the kernel debugger.
585	| Do not call trap() to do it, so that we can
586	| set breakpoints in trap() if we want.  We know
587	| the trap type is either T_TRACE or T_BREAKPOINT.
588	| If we have both DDB and KGDB, let KGDB see it first,
589	| because KGDB will just return 0 if not connected.
590	| Save args in %d2, %a2
591	movl	%d0,%d2			| trap type
592	movl	%sp,%a2			| frame ptr
593#ifdef KGDB
594	| Let KGDB handle it (if connected)
595	movl	%a2,%sp@-		| push frame ptr
596	movl	%d2,%sp@-		| push trap type
597	jbsr	_C_LABEL(kgdb_trap)	| handle the trap
598	addql	#8,%sp			| pop args
599	cmpl	#0,%d0			| did kgdb handle it?
600	jne	Lbrkpt3			| yes, done
601#endif
602#ifdef DDB
603	| Let DDB handle it
604	movl	%a2,%sp@-		| push frame ptr
605	movl	%d2,%sp@-		| push trap type
606	jbsr	_C_LABEL(kdb_trap)	| handle the trap
607	addql	#8,%sp			| pop args
608#if 0	/* not needed on hp300 */
609	cmpl	#0,%d0			| did ddb handle it?
610	jne	Lbrkpt3			| yes, done
611#endif
612#endif
613	/* Sun 3 drops into PROM here. */
614Lbrkpt3:
615	| The stack pointer may have been modified, or
616	| data below it modified (by kgdb push call),
617	| so push the hardware frame at the current %sp
618	| before restoring registers and returning.
619
620	movl	%sp@(FR_SP),%a0		| modified %sp
621	lea	%sp@(FR_SIZE),%a1	| end of our frame
622	movl	%a1@-,%a0@-		| copy 2 longs with
623	movl	%a1@-,%a0@-		| ... predecrement
624	movl	%a0,%sp@(FR_SP)		| %sp = h/w frame
625	moveml	%sp@+,#0x7FFF		| restore all but %sp
626	movl	%sp@,%sp		| ... and %sp
627	rte				| all done
628
629/*
630 * Interrupt handlers.
631 *
632 * For auto-vectored interrupts, the CPU provides the
633 * vector 0x18+level.  Note we count spurious interrupts,
634 * but don't do anything else with them.
635 *
636 * intrhand_autovec is the entry point for auto-vectored
637 * interrupts.
638 *
639 * For vectored interrupts, we pull the pc, evec, and exception frame
640 * and pass them to the vectored interrupt dispatcher.  The vectored
641 * interrupt dispatcher will deal with strays.
642 */
643
644ENTRY_NOPROFILE(lev7intr)	/* level 7: parity errors, reset key */
645	addql	#1,_C_LABEL(m68k_intr_evcnt)+NMI_INTRCNT
646	clrl	%sp@-
647	moveml	#0xFFFF,%sp@-		| save registers
648	movl	%usp,%a0		| and save
649	movl	%a0,%sp@(FR_SP)		|   the user stack pointer
650	jbsr	_C_LABEL(nmihand)	| call handler
651	movl	%sp@(FR_SP),%a0		| restore
652	movl	%a0,%usp			|   user SP
653	moveml	%sp@+,#0x7FFF		| and remaining registers
654	addql	#8,%sp			| pop SP and stack adjust
655	jra	_ASM_LABEL(rei)		| all done
656
657/*
658 * Emulation of VAX REI instruction.
659 *
660 * This code deals with checking for and servicing ASTs
661 * (profiling, scheduling) and software interrupts (network, softclock).
662 * We check for ASTs first, just like the VAX.  To avoid excess overhead
663 * the T_ASTFLT handling code will also check for software interrupts so we
664 * do not have to do it here.  After identifying that we need an AST we
665 * drop the IPL to allow device interrupts.
666 *
667 * This code is complicated by the fact that sendsig may have been called
668 * necessitating a stack cleanup.
669 */
670
671ASENTRY_NOPROFILE(rei)
672	tstl	_C_LABEL(astpending)	| AST pending?
673	jne	1f			| no, done
674	rte
6751:
676	btst	#5,%sp@			| yes, are we returning to user mode?
677	jeq	2f			| no, done
678	rte
6792:
680	movw	#PSL_LOWIPL,%sr		| lower SPL
681	clrl	%sp@-			| stack adjust
682	moveml	#0xFFFF,%sp@-		| save all registers
683	movl	%usp,%a1		| including
684	movl	%a1,%sp@(FR_SP)		|    the users SP
685Lrei:
686	clrl	%sp@-			| VA == none
687	clrl	%sp@-			| code == none
688	movl	#T_ASTFLT,%sp@-		| type == async system trap
689	pea	%sp@(12)		| fp == address of trap frame
690	jbsr	_C_LABEL(trap)		| go handle it
691	lea	%sp@(16),%sp		| pop value args
692	movl	%sp@(FR_SP),%a0		| restore user SP
693	movl	%a0,%usp		|   from save area
694	movw	%sp@(FR_ADJ),%d0	| need to adjust stack?
695	jne	Laststkadj		| yes, go to it
696	moveml	%sp@+,#0x7FFF		| no, restore most user regs
697	addql	#8,%sp			| toss SP and stack adjust
698	rte				| and do real RTE
699Laststkadj:
700	lea	%sp@(FR_HW),%a1		| pointer to HW frame
701	addql	#8,%a1			| source pointer
702	movl	%a1,%a0			| source
703	addw	%d0,%a0			|  + hole size = dest pointer
704	movl	%a1@-,%a0@-		| copy
705	movl	%a1@-,%a0@-		|  8 bytes
706	movl	%a0,%sp@(FR_SP)		| new SSP
707	moveml	%sp@+,#0x7FFF		| restore user registers
708	movl	%sp@,%sp		| and our SP
709	rte				| and do real RTE
710
711/*
712 * Primitives
713 */
714
715/*
716 * Use common m68k process/lwp switch and context save subroutines.
717 */
718#define FPCOPROC	/* XXX: Temp. Reqd. */
719#include <m68k/m68k/switch_subr.s>
720
721
722#if defined(M68040)
723ENTRY(suline)
724	movl	%sp@(4),%a0		| address to write
725	movl	_C_LABEL(curpcb),%a1	| current pcb
726	movl	#Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault
727	movl	%sp@(8),%a1		| address of line
728	movl	%a1@+,%d0		| get lword
729	movsl	%d0,%a0@+		| put lword
730	nop				| sync
731	movl	%a1@+,%d0		| get lword
732	movsl	%d0,%a0@+		| put lword
733	nop				| sync
734	movl	%a1@+,%d0		| get lword
735	movsl	%d0,%a0@+		| put lword
736	nop				| sync
737	movl	%a1@+,%d0		| get lword
738	movsl	%d0,%a0@+		| put lword
739	nop				| sync
740	moveq	#0,%d0			| indicate no fault
741	jra	Lsldone
742Lslerr:
743	moveq	#-1,%d0
744Lsldone:
745	movl	_C_LABEL(curpcb),%a1	| current pcb
746	clrl	%a1@(PCB_ONFAULT) 	| clear fault address
747	rts
748#endif
749
750/*
751 * _delay(u_int N)
752 *
753 * Delay for at least (N/256) microseconds.
754 * This routine depends on the variable:  delay_divisor
755 * which should be set based on the CPU clock rate.
756 */
757ENTRY_NOPROFILE(_delay)
758	| %d0 = arg = (usecs << 8)
759	movl	%sp@(4),%d0
760	| %d1 = delay_divisor
761	movl	_C_LABEL(delay_divisor),%d1
762	jra	L_delay			/* Jump into the loop! */
763
764	/*
765	 * Align the branch target of the loop to a half-line (8-byte)
766	 * boundary to minimize cache effects.  This guarantees both
767	 * that there will be no prefetch stalls due to cache line burst
768	 * operations and that the loop will run from a single cache
769	 * half-line.
770	 */
771	.align	8
772L_delay:
773	subl	%d1,%d0
774	jgt	L_delay
775	rts
776
777/*
778 * Handle the nitty-gritty of rebooting the machine.
779 * Basically we just turn off the MMU and jump to the appropriate ROM routine.
780 * Note that we must be running in an address range that is mapped one-to-one
781 * logical to physical so that the PC is still valid immediately after the MMU
782 * is turned off.  We have conveniently mapped the last page of physical
783 * memory this way.
784 */
785ENTRY_NOPROFILE(doboot)
786	movw	#PSL_HIGHIPL,%sr	| no interrupts
787
788	movl	#CACHE_OFF,%d0
789	movc	%d0,%cacr		| clear and disable on-chip cache(s)
790
791	| Turn on physical memory mapping.
792	| @@@ This is also 68040 specific and needs fixing.
793	movel	#0x0200c040,%d0		| intio devices are at 0x02000000
794	.long	0x4e7b0004		| movc %d0,%itt0
795	.long	0x4e7b0006		| movc %d0,%dtt0
796	movel	#0x0403c000,%d0		| kernel text and data at 0x04000000
797	.long	0x4e7b0005		| movc %d0,%itt1
798	.long	0x4e7b0007		| movc %d0,%dtt1
799
800	moveal   #NEXT_RAMBASE,%a5	| amount to RELOC by.
801
802	| Create a new stack at address tmpstk, and push
803	| The existing sp onto it for kicks.
804	ASRELOC(tmpstk, %a0)
805	movel	%sp,%a0@-
806	moveal  %a0,%sp
807	moveal  #0,%a6
808
809	ASRELOC(Ldoboot1, %a0)
810	jmp     %a0@			| jump into physical address space.
811Ldoboot1:
812	RELOC(saved_vbr, %a0)
813	movl    %a0@,%d0
814	movc    %d0,%vbr
815
816	| reset the registers as the boot rom likes them:
817	movel	#0x0200c040,%d0		|
818	.long	0x4e7b0004		| movc %d0,%itt0
819	.long	0x4e7b0006		| movc %d0,%dtt0
820	movel	#0x00ffc000,%d0		|
821	.long	0x4e7b0005		| movc %d0,%itt1
822	.long	0x4e7b0007		| movc %d0,%dtt1
823
824	RELOC(monbootflag, %a0)
825	movel %a0,%d0			| "-h" halts instead of reboot.
826	trap #13
827
828hloop:
829	bra hloop			| This shouldn't be reached.
830/*
831 * Misc. global variables.
832 */
833	.data
834GLOBAL(machineid)
835	.long	0xdeadbeef	| default to @@@
836
837GLOBAL(mmuid)
838	.long	0		| default to nothing
839
840GLOBAL(mmutype)
841	.long	0xdeadbeef	| default to 68040 mmu
842
843GLOBAL(cputype)
844	.long	0xdeadbeef	| default to 68020 CPU
845
846GLOBAL(fputype)
847	.long	0xdeadbeef	| default to 68882 FPU
848
849GLOBAL(prototc)
850	.long	0		| prototype translation control
851
852GLOBAL(intiobase)
853	.long	INTIOBASE	| KVA of base of internal IO space
854
855GLOBAL(intiolimit)
856	.long	INTIOTOP	| KVA of end of internal IO space
857
858GLOBAL(fbbase)
859	.long	0		| KVA of base of framebuffer
860
861GLOBAL(fblimit)
862	.long	0		| KVA of end of framebuffer
863
864GLOBAL(fbbasepa)
865	.long	MONOBASE	| PA of base of framebuffer
866
867GLOBAL(fblimitpa)
868	.long	MONOTOP		| PA of end of framebuffer
869
870GLOBAL(monbootflag)
871	.long 0
872
873#ifdef USELEDS
874ASLOCAL(heartbeat)
875	.long	0		| clock ticks since last pulse of heartbeat
876
877ASLOCAL(beatstatus)
878	.long	0		| for determining a fast or slow throb
879#endif
880
881#ifdef DEBUG
882ASGLOBAL(fulltflush)
883	.long	0
884
885ASGLOBAL(fullcflush)
886	.long	0
887#endif
888