Home | History | Annotate | Line # | Download | only in amiga
      1 /*	$NetBSD: locore.s,v 1.172 2024/01/19 18:18:53 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1988 University of Utah.
      5  * Copyright (c) 1980, 1990 The Regents of the University of California.
      6  * 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.58 91/04/22$
     37  *
     38  *	@(#)locore.s	7.11 (Berkeley) 5/9/91
     39  *
     40  * Original (hp300) Author: unknown, maybe Mike Hibler?
     41  * Amiga author: Markus Wild
     42  * Other contributors: Bryan Ford (kernel reload stuff)
     43  */
     44 
     45 #include "opt_fpu_emulate.h"
     46 #include "opt_bb060stupidrom.h"
     47 #include "opt_p5ppc68kboard.h"
     48 #include "opt_compat_netbsd.h"
     49 #include "opt_compat_sunos.h"
     50 #include "opt_fpsp.h"
     51 #include "opt_kgdb.h"
     52 #include "opt_lockdebug.h"
     53 #include "opt_lev6_defer.h"
     54 #include "opt_m68k_arch.h"
     55 
     56 #include "assym.h"
     57 #include <machine/asm.h>
     58 #include <machine/trap.h>
     59 
     60 	.text
     61 GLOBAL(kernel_text)
     62 L_base:
     63 	.long	0x4ef80400+PAGE_SIZE	/* jmp jmp0.w */
     64 	.fill	PAGE_SIZE/4-1,4,0/*xdeadbeef*/
     65 
     66 #include <amiga/amiga/vectors.s>
     67 #include <amiga/amiga/custom.h>
     68 
     69 #ifdef DRACO
     70 #include <amiga/amiga/drcustom.h>
     71 #endif
     72 
     73 #define CIAAADDR(ar)	movl	_C_LABEL(CIAAbase),ar
     74 #define CIABADDR(ar)	movl	_C_LABEL(CIABbase),ar
     75 #define CUSTOMADDR(ar)	movl	_C_LABEL(CUSTOMbase),ar
     76 #define INTREQRADDR(ar)	movl	_C_LABEL(INTREQRaddr),ar
     77 #define INTREQWADDR(ar)	movl	_C_LABEL(INTREQWaddr),ar
     78 #define INTENAWADDR(ar) movl	_C_LABEL(amiga_intena_write),ar
     79 #define	INTENARADDR(ar)	movl	_C_LABEL(amiga_intena_read),ar
     80 
     81 	.text
     82 /*
     83  * This is where we wind up if the kernel jumps to location 0.
     84  * (i.e. a bogus PC)  This is known to immediately follow the vector
     85  * table and is hence at 0x400 (see reset vector in vectors.s).
     86  */
     87 	pea	Ljmp0panic
     88 	jbsr	_C_LABEL(panic)
     89 	/* NOTREACHED */
     90 Ljmp0panic:
     91 	.asciz	"kernel jump to zero"
     92 	.even
     93 
     94 /*
     95  * Do a dump.
     96  * Called by auto-restart.
     97  */
     98 ENTRY_NOPROFILE(doadump)
     99 	jbsr	_C_LABEL(dumpsys)
    100 	jbsr	_C_LABEL(doboot)
    101 	/*NOTREACHED*/
    102 
    103 /*
    104  * Trap/interrupt vector routines
    105  */
    106 #include <m68k/m68k/trap_subr.s>
    107 
    108 #if defined(M68040) || defined(M68060)
    109 ENTRY_NOPROFILE(addrerr4060)
    110 	clrl	%sp@-			| stack adjust count
    111 	moveml	%d0-%d7/%a0-%a7,%sp@-	| save user registers
    112 	movl	%usp,%a0		| save the user SP
    113 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    114 	movl	%sp@(FR_HW+8),%sp@-
    115 	clrl	%sp@-			| dummy code
    116 	movl	#T_ADDRERR,%sp@-	| mark address error
    117 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    118 #endif
    119 
    120 #if defined(M68060)
    121 ENTRY_NOPROFILE(buserr60)
    122 	clrl	%sp@-			| stack adjust count
    123 	moveml	%d0-%d7/%a0-%a7,%sp@-	| save user registers
    124 	movl	%usp,%a0		| save the user SP
    125 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    126 	movel	%sp@(FR_HW+12),%d0	| FSLW
    127 	btst	#2,%d0			| branch prediction error?
    128 	jeq	Lnobpe
    129 	movc	%cacr,%d2
    130 	orl	#IC60_CABC,%d2		| clear all branch cache entries
    131 	movc	%d2,%cacr
    132 	movl	%d0,%d1
    133 	addql	#1,L60bpe
    134 	andl	#0x7ffd,%d1
    135 	jeq	_ASM_LABEL(faultstkadjnotrap2)
    136 Lnobpe:
    137 | we need to adjust for misaligned addresses
    138 	movl	%sp@(FR_HW+8),%d1	| grab VA
    139 	btst	#27,%d0			| check for mis-aligned access
    140 	jeq	Lberr3			| no, skip
    141 	addl	#28,%d1			| yes, get into next page
    142 					| operand case: 3,
    143 					| instruction case: 4+12+12
    144 	andl	#PG_FRAME,%d1           | and truncate
    145 Lberr3:
    146 	movl	%d1,%sp@-
    147 	movl	%d0,%sp@-		| code is FSLW now.
    148 	andw	#0x1f80,%d0
    149 	jeq	Lisberr
    150 	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
    151 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    152 #endif
    153 #if defined(M68040)
    154 ENTRY_NOPROFILE(buserr40)
    155 	clrl	%sp@-			| stack adjust count
    156 	moveml	%d0-%d7/%a0-%a7,%sp@-	| save user registers
    157 	movl	%usp,%a0		| save the user SP
    158 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    159 	movl	%sp@(FR_HW+20),%d1	| get fault address
    160 	moveq	#0,%d0
    161 	movw	%sp@(FR_HW+12),%d0	| get SSW
    162 	btst	#11,%d0			| check for mis-aligned
    163 	jeq	Lbe1stpg		| no skip
    164 	addl	#3,%d1			| get into next page
    165 	andl	#PG_FRAME,%d1		| and truncate
    166 Lbe1stpg:
    167 	movl	%d1,%sp@-		| pass fault address.
    168 	movl	%d0,%sp@-		| pass SSW as code
    169 	btst	#10,%d0			| test ATC
    170 	jeq	Lisberr			| it is a bus error
    171 	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
    172 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    173 #endif
    174 
    175 ENTRY_NOPROFILE(buserr)
    176 ENTRY_NOPROFILE(addrerr)
    177 #if !(defined(M68020) || defined(M68030))
    178 	jra	_C_LABEL(badtrap)
    179 #else
    180 	clrl	%sp@-			| stack adjust count
    181 	moveml	%d0-%d7/%a0-%a7,%sp@-	| save user registers
    182 	movl	%usp,%a0		| save the user SP
    183 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    184 	moveq	#0,%d0
    185 	movw	%sp@(FR_HW+10),%d0	| grab SSW for fault processing
    186 	btst	#12,%d0			| RB set?
    187 	jeq	LbeX0			| no, test RC
    188 	bset	#14,%d0			| yes, must set FB
    189 	movw	%d0,%sp@(FR_HW+10)	| for hardware too
    190 LbeX0:
    191 	btst	#13,%d0			| RC set?
    192 	jeq	LbeX1			| no, skip
    193 	bset	#15,%d0			| yes, must set FC
    194 	movw	%d0,%sp@(FR_HW+10)	| for hardware too
    195 LbeX1:
    196 	btst	#8,%d0			| data fault?
    197 	jeq	Lbe0			| no, check for hard cases
    198 	movl	%sp@(FR_HW+16),%d1	| fault address is as given in frame
    199 	jra	Lbe10			| thats it
    200 Lbe0:
    201 	btst	#4,%sp@(FR_HW+6)	| long (type B) stack frame?
    202 	jne	Lbe4			| yes, go handle
    203 	movl	%sp@(FR_HW+2),%d1	| no, can use save PC
    204 	btst	#14,%d0			| FB set?
    205 	jeq	Lbe3			| no, try FC
    206 	addql	#4,%d1			| yes, adjust address
    207 	jra	Lbe10			| done
    208 Lbe3:
    209 	btst	#15,%d0			| FC set?
    210 	jeq	Lbe10			| no, done
    211 	addql	#2,%d1			| yes, adjust address
    212 	jra	Lbe10			| done
    213 Lbe4:
    214 	movl	%sp@(FR_HW+36),%d1	| long format, use stage B address
    215 	btst	#15,%d0			| FC set?
    216 	jeq	Lbe10			| no, all done
    217 	subql	#2,%d1			| yes, adjust address
    218 Lbe10:
    219 	movl	%d1,%sp@-		| push fault VA
    220 	movl	%d0,%sp@-		| and padded SSW
    221 	movw	%sp@(FR_HW+8+6),%d0	| get frame format/vector offset
    222 	andw	#0x0FFF,%d0		| clear out frame format
    223 	cmpw	#12,%d0			| address error vector?
    224 	jeq	Lisaerr			| yes, go to it
    225 	movl	%d1,%a0			| fault address
    226 	movl	%sp@,%d0		| function code from ssw
    227 	btst	#8,%d0			| data fault?
    228 	jne	Lbe10a
    229 	movql	#1,%d0			| user program access FC
    230 					| (we dont separate data/program)
    231 	btst	#5,%sp@(FR_HW+8)	| supervisor mode?
    232 	jeq	Lbe10a			| if no, done
    233 	movql	#5,%d0			| else supervisor program access
    234 Lbe10a:
    235 	ptestr	%d0,%a0@,#7		| do a table search
    236 	pmove	%psr,%sp@		| save result
    237 	movb	%sp@,%d1
    238 	btst	#2,%d1			| invalid (incl. limit viol. and berr)?
    239 	jeq	Lmightnotbemerr		| no -> wp check
    240 	btst	#7,%d1			| is it MMU table berr?
    241 	jeq	Lismerr			| no, must be fast
    242 	jra	Lisberr1		| real bus err needs not be fast.
    243 Lmightnotbemerr:
    244 	btst	#3,%d1			| write protect bit set?
    245 	jeq	Lisberr1		| no: must be bus error
    246 	movl	%sp@,%d0		| ssw into low word of d0
    247 	andw	#0xc0,%d0		| Write protect is set on page:
    248 	cmpw	#0x40,%d0		| was it read cycle?
    249 	jeq	Lisberr1		| yes, was not WPE, must be bus err
    250 Lismerr:
    251 	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
    252 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    253 Lisaerr:
    254 	movl	#T_ADDRERR,%sp@-	| mark address error
    255 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    256 Lisberr1:
    257 	clrw	%sp@			| re-clear pad word
    258 #endif
    259 Lisberr:				| also used by M68040/60
    260 	tstl	_C_LABEL(nofault)	| device probe?
    261 	jeq	LberrIsProbe		| no, handle as usual
    262 	movl	_C_LABEL(nofault),%sp@-	| yes,
    263 	jbsr	_C_LABEL(longjmp)	|  longjmp(nofault)
    264 	/* NOTREACHED */
    265 LberrIsProbe:
    266 	movl	#T_BUSERR,%sp@-		| mark bus error
    267 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    268 
    269 /*
    270  * FP exceptions.
    271  */
    272 ENTRY_NOPROFILE(fpfline)
    273 #if defined(M68040)
    274 	cmpw	#0x202c,%sp@(6)		| format type 2?
    275 	jne	_C_LABEL(illinst)	| no, not an FP emulation
    276 #ifdef FPSP
    277 	jmp	_ASM_LABEL(fpsp_unimp)	| yes, go handle it
    278 #endif
    279 #endif
    280 
    281 #ifdef FPU_EMULATE
    282 ENTRY_NOPROFILE(fpemuli)
    283 	addql	#1,Lfpecnt
    284 	clrl	%sp@-			| stack adjust count
    285 	moveml	%d0-%d7/%a0-%a7,%sp@-	| save registers
    286 	movql	#T_FPEMULI,%d0		| denote as FP emulation trap
    287 	jra	_ASM_LABEL(fault)	| do it
    288 #endif
    289 
    290 ENTRY_NOPROFILE(fpunsupp)
    291 #if defined(M68040)
    292 	cmpl	#MMU_68040,_C_LABEL(mmutype)	| 68040?
    293 	jne	_C_LABEL(illinst)	| no, treat as illinst
    294 #ifdef FPSP
    295 	jmp	_ASM_LABEL(fpsp_unsupp)	| yes, go handle it
    296 #else
    297 	clrl	%sp@-			| stack adjust count
    298 	moveml	%d0-%d7/%a0-%a7,%sp@-	| save registers
    299 	movql	#T_FPEMULD,%d0		| denote as FP emulation trap
    300 	jra	_ASM_LABEL(fault)	| do it
    301 #endif
    302 #else
    303 	jra	_C_LABEL(illinst)
    304 #endif
    305 /*
    306  * Handles all other FP coprocessor exceptions.
    307  * Note that since some FP exceptions generate mid-instruction frames
    308  * and may cause signal delivery, we need to test for stack adjustment
    309  * after the trap call.
    310  */
    311 ENTRY_NOPROFILE(fpfault)
    312 #ifdef FPCOPROC
    313 	clrl	%sp@-			| stack adjust count
    314 	moveml	%d0-%d7/%a0-%a7,%sp@-	| save user registers
    315 	movl	%usp,%a0		| and save
    316 	movl	%a0,%sp@(FR_SP)		|   the user stack pointer
    317 	clrl	%sp@-			| no VA arg
    318 	movl	_C_LABEL(curpcb),%a0	| current pcb
    319 	lea	%a0@(PCB_FPCTX),%a0	| address of FP savearea
    320 	fsave	%a0@			| save state
    321 #if defined(M68020) || defined(M68030)
    322 #if defined(M68060) || defined(M68040)
    323 	movb	_C_LABEL(machineid)+3,%d0
    324 	andb	#0x90,%d0		| AMIGA_68060 | AMIGA_68040
    325 	jne	Lfptnull		| XXX
    326 #endif
    327 	tstb	%a0@			| null state frame?
    328 	jeq	Lfptnull		| yes, safe
    329 	clrw	%d0			| no, need to tweak BIU
    330 	movb	%a0@(1),%d0		| get frame size
    331 	bset	#3,%a0@(0,%d0:w)	| set exc_pend bit of BIU
    332 Lfptnull:
    333 #endif
    334 	fmovem	%fpsr,%sp@-		| push fpsr as code argument
    335 	frestore %a0@			| restore state
    336 	movl	#T_FPERR,%sp@-		| push type arg
    337 	jra	_ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup
    338 #else
    339 	jra	_C_LABEL(badtrap)	| treat as an unexpected trap
    340 #endif
    341 
    342 /*
    343  * Other exceptions only cause four and six word stack frame and require
    344  * no post-trap stack adjustment.
    345  */
    346 
    347 ENTRY_NOPROFILE(badtrap)
    348 	INTERRUPT_SAVEREG
    349 	movw	%sp@(22),%sp@-		| push exception vector info
    350 	clrw	%sp@-
    351 	movl	%sp@(22),%sp@-		| and PC
    352 	jbsr	_C_LABEL(straytrap)	| report
    353 	addql	#8,%sp			| pop args
    354 	INTERRUPT_RESTOREREG		| restore regs
    355 	jra	_ASM_LABEL(rei)		| all done
    356 
    357 ENTRY_NOPROFILE(trap0)
    358 	clrl	%sp@-			| stack adjust count
    359 	moveml	%d0-%d7/%a0-%a7,%sp@-	| save user registers
    360 	movl	%usp,%a0		| save the user SP
    361 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    362 	movl	%d0,%sp@-		| push syscall number
    363 	jbsr	_C_LABEL(syscall)	| handle it
    364 	addql	#4,%sp			| pop syscall arg
    365 	movl	%sp@(FR_SP),%a0		| grab and restore
    366 	movl	%a0,%usp		|   user SP
    367 	moveml	%sp@+,%d0-%d7/%a0-%a6	| restore most registers
    368 	addql	#8,%sp			| pop SP and stack adjust
    369 	jra	_ASM_LABEL(rei)		| all done
    370 
    371 /*
    372  * Trap 12 is the entry point for the cachectl "syscall"
    373  *	cachectl(command, addr, length)
    374  * command in d0, addr in a1, length in d1
    375  */
    376 ENTRY_NOPROFILE(trap12)
    377 	movl	_C_LABEL(curlwp),%a0
    378 	movl	%a0@(L_PROC),%sp@-	| push current proc pointer
    379 	movl	%d1,%sp@-		| push length
    380 	movl	%a1,%sp@-		| push addr
    381 	movl	%d0,%sp@-		| push command
    382 	jbsr	_C_LABEL(cachectl1)	| do it
    383 	lea	%sp@(16),%sp		| pop args
    384 	jra	_ASM_LABEL(rei)		| all done
    385 
    386 /*
    387  * Trap 15 is used for:
    388  *	- KGDB traps
    389  *	- trace traps for SUN binaries (not fully supported yet)
    390  * We just pass it on and let trap() sort it all out
    391  */
    392 ENTRY_NOPROFILE(trap15)
    393 	clrl	%sp@-
    394 	moveml	%d0-%d7/%a0-%a7,%sp@-
    395 #ifdef KGDB
    396 	moveq	#T_TRAP15,%d0
    397 	movw	%sp@(FR_HW),%d1		| get PSW
    398 	andw	#PSL_S,%d1		| from user mode?
    399 	jeq	_ASM_LABEL(fault)	| yes, just a regular fault
    400 	movl	%d0,%sp@-
    401 	jbsr	_C_LABEL(kgdb_trap_glue) | returns if no debugger
    402 	addl	#4,%sp
    403 #endif
    404 	moveq	#T_TRAP15,%d0
    405 	jra	_ASM_LABEL(fault)
    406 
    407 /*
    408  * Hit a breakpoint (trap 1 or 2) instruction.
    409  * Push the code and treat as a normal fault.
    410  */
    411 ENTRY_NOPROFILE(trace)
    412 	clrl	%sp@-
    413 	moveml	%d0-%d7/%a0-%a7,%sp@-
    414 #ifdef KGDB
    415 	moveq	#T_TRACE,%d0
    416 	movw	%sp@(FR_HW),%d1		| get SSW
    417 	andw	#PSL_S,%d1		| from user mode?
    418 	jeq	_ASM_LABEL(fault)	| no, regular fault
    419 	movl	%d0,%sp@-
    420 	jbsr	_C_LABEL(kgdb_trap_glue) | returns if no debugger
    421 	addl	#4,%sp
    422 #endif
    423 	moveq	#T_TRACE,%d0
    424 	jra	_ASM_LABEL(fault)
    425 
    426 /*
    427  * Interrupt handlers.
    428  *
    429  *	Level 0:	Spurious: ignored.
    430  *	Level 1:	builtin-RS232 TBE, softint (not used yet)
    431  *	Level 2:	keyboard (CIA-A) + DMA + SCSI
    432  *	Level 3:	VBL
    433  *	Level 4:	not used
    434  *	Level 5:	builtin-RS232 RBF
    435  *	Level 6:	Clock (CIA-B-Timers), Floppy index pulse
    436  *	Level 7:	Non-maskable: shouldn't be possible. ignore.
    437  */
    438 
    439 /* Provide a generic interrupt dispatcher, only handle hardclock (int6)
    440  * and serial RBF (int5) specially, to improve performance
    441  */
    442 ENTRY_NOPROFILE(spurintr)
    443 	addql	#1,_C_LABEL(intr_depth)
    444 	addql	#1,_C_LABEL(intrcnt)+0
    445 	INTERRUPT_SAVEREG
    446 	CPUINFO_INCREMENT(CI_NINTR)
    447 	INTERRUPT_RESTOREREG
    448 	subql	#1,_C_LABEL(intr_depth)
    449 	jra	_ASM_LABEL(rei)
    450 
    451 ENTRY_NOPROFILE(lev5intr)
    452 	addql	#1,_C_LABEL(intr_depth)
    453 	INTERRUPT_SAVEREG
    454 #include "ser.h"
    455 #if NSER > 0
    456 	jsr	_C_LABEL(ser_fastint)
    457 #else
    458 	INTREQWADDR(%a0)
    459 	movew	#INTF_RBF,%a0@		| clear RBF interrupt in intreq
    460 #endif
    461 	CPUINFO_INCREMENT(CI_NINTR)
    462 	INTERRUPT_RESTOREREG
    463 	addql	#1,_C_LABEL(intrcnt)+20
    464 	subql	#1,_C_LABEL(intr_depth)
    465 	jra	_ASM_LABEL(rei)
    466 
    467 #ifdef DRACO
    468 ENTRY_NOPROFILE(DraCoLev2intr)
    469 	addql	#1,_C_LABEL(intr_depth)
    470 	INTERRUPT_SAVEREG
    471 
    472 	CIAAADDR(%a0)
    473 	movb	%a0@(CIAICR),%d0	| read irc register (clears ints!)
    474 	jge     Ldrintrcommon		| CIAA IR not set, go through isr chain
    475 	movel	_C_LABEL(draco_intpen),%a0
    476 |	andib	#4,%a0@
    477 |XXX this would better be
    478 	bclr	#2,%a0@
    479 	btst	#0,%d0			| timerA interrupt?
    480 	jeq	Ldraciaend
    481 
    482 	movl	%sp,%sp@-		| push pointer to clockframe
    483 	movw	#PSL_HIGHIPL,%sr	| hardclock at high IPL
    484 	jbsr	_C_LABEL(hardclock)	| call generic clock int routine
    485 	addql	#4,%sp			| pop params
    486 	addql	#1,_C_LABEL(intrcnt)+32	| add another system clock interrupt
    487 
    488 Ldraciaend:
    489 	CPUINFO_INCREMENT(CI_NINTR)
    490 	INTERRUPT_RESTOREREG
    491 	subql	#1,_C_LABEL(intr_depth)
    492 	jra	_ASM_LABEL(rei)
    493 
    494 /* XXX on the DraCo rev. 4 or later, lev 1 is vectored here. */
    495 ENTRY_NOPROFILE(DraCoLev1intr)
    496 	addql	#1,_C_LABEL(intr_depth)
    497 	INTERRUPT_SAVEREG
    498 	movl	_C_LABEL(draco_ioct),%a0
    499 	btst	#5,%a0@(7)
    500 	jeq	Ldrintrcommon
    501 	btst	#4,%a0@(7)	| this only happens during autoconfiguration,
    502 	jeq	Ldrintrcommon	| so test last.
    503 	movw	#PSL_HIGHIPL,%sr	| run clock at high ipl
    504 Ldrclockretry:
    505 	movl	%sp,%sp@-		| push pointer to clockframe
    506 	jbsr	_C_LABEL(hardclock)
    507 	addql	#4,%sp			| pop params
    508 	addql	#1,_C_LABEL(intrcnt)+32	| add another system clock interrupt
    509 
    510 	movl	_C_LABEL(draco_ioct),%a0
    511 	tstb	%a0@(9)		| latch timer value
    512 	movw	%a0@(11),%d0	| can't use movpw here, might be 68060
    513 	movb	%a0@(13),%d0
    514 	addw	_C_LABEL(amiga_clk_interval)+2,%d0
    515 	movb	%d0,%a0@(13)	| low byte: latch write value
    516 	movw	%d0,%a0@(11)	| ...and write it into timer
    517 	tstw	%d0		| already positive?
    518 	jcs	Ldrclockretry	| we lost more than one tick, call us again.
    519 
    520 	clrb	%a0@(9)		| reset timer irq
    521 
    522 	CPUINFO_INCREMENT(CI_NINTR)
    523 	INTERRUPT_RESTOREREG
    524 	subql	#1,_C_LABEL(intr_depth)
    525 	jra	_ASM_LABEL(rei)	| XXXX: shouldn't we call the normal lev1?
    526 
    527 /* XXX on the DraCo, lev 1, 3, 4, 5 and 6 are vectored here by initcpu() */
    528 ENTRY_NOPROFILE(DraCoIntr)
    529 	addql	#1,_C_LABEL(intr_depth)
    530 	INTERRUPT_SAVEREG
    531 Ldrintrcommon:
    532 	lea	_ASM_LABEL(Drintrcnt)-4,%a0
    533 	movw	%sp@(22),%d0		| use vector offset
    534 	andw	#0xfff,%d0		|   sans frame type
    535 	addql	#1,%a0@(-0x60,%d0:w)	|     to increment apropos counter
    536 	movw	%sr,%sp@-		| push current SR value
    537 	clrw	%sp@-			|    padded to longword
    538 	jbsr	_C_LABEL(intrhand)	| handle interrupt
    539 	addql	#4,%sp			| pop SR
    540 	CPUINFO_INCREMENT(CI_NINTR)
    541 	INTERRUPT_RESTOREREG
    542 	subql	#1,_C_LABEL(intr_depth)
    543 	jra	_ASM_LABEL(rei)
    544 #endif
    545 
    546 
    547 ENTRY_NOPROFILE(lev1intr)
    548 ENTRY_NOPROFILE(lev2intr)
    549 ENTRY_NOPROFILE(lev3intr)
    550 #ifndef LEV6_DEFER
    551 ENTRY_NOPROFILE(lev4intr)
    552 #endif
    553 	addql	#1,_C_LABEL(intr_depth)
    554 	INTERRUPT_SAVEREG
    555 Lintrcommon:
    556 	lea	_C_LABEL(intrcnt),%a0
    557 	movw	%sp@(22),%d0		| use vector offset
    558 	andw	#0xfff,%d0		|   sans frame type
    559 	addql	#1,%a0@(-0x60,%d0:w)	|     to increment apropos counter
    560 	movw	%sr,%sp@-		| push current SR value
    561 	clrw	%sp@-			|    padded to longword
    562 	jbsr	_C_LABEL(intrhand)	| handle interrupt
    563 	addql	#4,%sp			| pop SR
    564 	CPUINFO_INCREMENT(CI_NINTR)
    565 	INTERRUPT_RESTOREREG
    566 	subql	#1,_C_LABEL(intr_depth)
    567 	jra	_ASM_LABEL(rei)
    568 
    569 /* XXX used to be ifndef DRACO; vector will be overwritten by initcpu() */
    570 
    571 ENTRY_NOPROFILE(lev6intr)
    572 #ifdef LEV6_DEFER
    573 	/*
    574 	 * cause a level 4 interrupt (AUD3) to occur as soon
    575 	 * as we return. Block generation of level 6 ints until
    576 	 * we have dealt with this one.
    577 	 */
    578 	addql	#1,_C_LABEL(intr_depth)
    579 	moveml	%d0/%a0,%sp@-
    580 	INTREQRADDR(%a0)
    581 	movew	%a0@,%d0
    582 	btst	#INTB_EXTER,%d0
    583 	jeq	Llev6spur
    584 	INTREQWADDR(%a0)
    585 	movew	#INTF_SETCLR+INTF_AUD3,%a0@
    586 	INTENAWADDR(%a0)
    587 	movew	#INTF_EXTER,%a0@
    588 	movew	#INTF_SETCLR+INTF_AUD3,%a0@	| make sure THIS one is ok...
    589 	moveml	%sp@+,%d0/%a0
    590 	subql	#1,_C_LABEL(intr_depth)
    591 	rte
    592 Llev6spur:
    593 	addql	#1,_C_LABEL(intrcnt)+36	| count spurious level 6 interrupts
    594 	moveml	%sp@+,%d0/%a0
    595 	subql	#1,_C_LABEL(intr_depth)
    596 	rte
    597 
    598 ENTRY_NOPROFILE(lev4intr)
    599 ENTRY_NOPROFILE(fake_lev6intr)
    600 #endif
    601 	addql	#1,_C_LABEL(intr_depth)
    602 	INTERRUPT_SAVEREG
    603 #ifdef LEV6_DEFER
    604 	/*
    605 	 * check for fake level 6
    606 	 */
    607 	INTREQRADDR(%a0)
    608 	movew	%a0@,%d0
    609 	btst	#INTB_EXTER,%d0
    610 	jeq	Lintrcommon		| if EXTER not pending, handle normally
    611 #endif
    612 
    613 	CIABADDR(%a0)
    614 	movb	%a0@(CIAICR),%d0	| read irc register (clears ints!)
    615 	jge	Lchkexter		| CIAB IR not set, go through isr chain
    616 	INTREQWADDR(%a0)
    617 #ifndef LEV6_DEFER
    618 	movew	#INTF_EXTER,%a0@	| clear EXTER interrupt in intreq
    619 #else
    620 	movew	#INTF_EXTER+INTF_AUD3,%a0@ | clear EXTER & AUD3 in intreq
    621 	INTENAWADDR(%a0)
    622 	movew	#INTF_SETCLR+INTF_EXTER,%a0@ | reenable EXTER interrupts
    623 #endif
    624 	btst	#0,%d0			| timerA interrupt?
    625 	jeq     Ltstciab4		| no
    626 	movl	%d0,%sp@-		| push CIAB interrupt flags
    627 	lea	%sp@(4),%a1		| get pointer to clockframe
    628 	movl	%a1,%sp@-		| push pointer to clockframe
    629 	jbsr	_C_LABEL(hardclock)	| call generic clock int routine
    630 	addql	#4,%sp			| pop params
    631 	addql	#1,_C_LABEL(intrcnt)+32	| add another system clock interrupt
    632 	movl	%sp@+,%d0		| pop interrupt flags
    633 Ltstciab4:
    634 #include "fd.h"
    635 #if NFD > 0
    636 	btst	#4,%d0			| FLG (dskindex) interrupt?
    637 	jeq	Lskipciab		| no
    638 	jbsr	_C_LABEL(fdidxintr)	| tell floppy driver we got it
    639 Lskipciab:
    640 #endif
    641 | other ciab interrupts?
    642 Llev6done:
    643 	CPUINFO_INCREMENT(CI_NINTR)
    644 	INTERRUPT_RESTOREREG
    645 	subql	#1,_C_LABEL(intr_depth)
    646 	jra	_ASM_LABEL(rei)		| all done [can we do rte here?]
    647 Lchkexter:
    648 | check to see if EXTER request is really set?
    649 	movl	_C_LABEL(isr_exter),%a0	| get head of EXTER isr chain
    650 Lnxtexter:
    651 	movl	%a0,%d0			| test if any more entries
    652 	jeq	Lexterdone		| (spurious interrupt?)
    653 	movl	%a0,%sp@-		| save isr pointer
    654 	movl	%a0@(ISR_ARG),%sp@-
    655 	movl	%a0@(ISR_INTR),%a0
    656 	jsr	%a0@			| call isr handler
    657 	addql	#4,%sp
    658 	movl	%sp@+,%a0		| restore isr pointer
    659 	movl	%a0@(ISR_FORW),%a0	| get next pointer
    660 	tstl	%d0			| did handler process the int?
    661 	jeq	Lnxtexter		| no, try next
    662 Lexterdone:
    663 	INTREQWADDR(%a0)
    664 #ifndef LEV6_DEFER
    665 	movew	#INTF_EXTER,%a0@	| clear EXTER interrupt
    666 #else
    667 	movew	#INTF_EXTER+INTF_AUD3,%a0@ | clear EXTER & AUD3 interrupt
    668 	INTENAWADDR(%a0)
    669 	movew	#INTF_SETCLR+INTF_EXTER,%a0@ | reenable EXTER interrupts
    670 #endif
    671 	addql	#1,_C_LABEL(intrcnt)+24	| count EXTER interrupts
    672 	jra	Llev6done
    673 /* XXX endifndef DRACO used to be here */
    674 
    675 ENTRY_NOPROFILE(lev7intr)
    676 	addql	#1,_C_LABEL(intrcnt)+28
    677 	/*
    678 	 * some amiga zorro2 boards seem to generate spurious NMIs. Best
    679 	 * thing to do is to return as quick as possible. That's the
    680 	 * reason why I do RTE here instead of jra rei.
    681 	 */
    682 	rte				| all done
    683 
    684 
    685 /*
    686  * Emulation of VAX REI instruction.
    687  *
    688  * This code deals with checking for and servicing ASTs
    689  * (profiling, scheduling) and software interrupts (network, softclock).
    690  * We check for ASTs first, just like the VAX.  To avoid excess overhead
    691  * the T_ASTFLT handling code will also check for software interrupts so we
    692  * do not have to do it here.  After identifying that we need an AST we
    693  * drop the IPL to allow device interrupts.
    694  *
    695  * This code is complicated by the fact that sendsig may have been called
    696  * necessitating a stack cleanup.  A cleanup should only be needed at this
    697  * point for coprocessor mid-instruction frames (type 9), but we also test
    698  * for bus error frames (type 10 and 11).
    699  */
    700 ASENTRY_NOPROFILE(rei)
    701 #ifdef DEBUG
    702 	tstl	_C_LABEL(panicstr)	| have we panicked?
    703 	jne	Ldorte			| yes, do not make matters worse
    704 #endif
    705 	tstl	_C_LABEL(astpending)	| AST pending?
    706 	jeq	Ldorte			| no, done
    707 Lrei1:
    708 	btst	#5,%sp@			| yes, are we returning to user mode?
    709 	jne	Ldorte			| no, done
    710 	movw	#PSL_LOWIPL,%sr		| lower SPL
    711 	clrl	%sp@-			| stack adjust
    712 	moveml	%d0-%d7/%a0-%a7,%sp@-	| save all registers
    713 	movl	%usp,%a1		| including
    714 	movl	%a1,%sp@(FR_SP)		|    the users SP
    715 	clrl	%sp@-			| VA == none
    716 	clrl	%sp@-			| code == none
    717 	movl	#T_ASTFLT,%sp@-		| type == async system trap
    718 	pea	%sp@(12)		| fp == address of trap frame
    719 	jbsr	_C_LABEL(trap)		| go handle it
    720 	lea	%sp@(16),%sp		| pop value args
    721 	movl	%sp@(FR_SP),%a0		| restore user SP
    722 	movl	%a0,%usp		|   from save area
    723 	movw	%sp@(FR_ADJ),%d0	| need to adjust stack?
    724 	jne	Laststkadj		| yes, go to it
    725 	moveml	%sp@+,%d0-%d7/%a0-%a6	| no, restore most user regs
    726 	addql	#8,%sp			| toss SP and stack adjust
    727 	rte				| and do real RTE
    728 Laststkadj:
    729 	lea	%sp@(FR_HW),%a1		| pointer to HW frame
    730 	addql	#8,%a1			| source pointer
    731 	movl	%a1,%a0			| source
    732 	addw	%d0,%a0			|  + hole size = dest pointer
    733 	movl	%a1@-,%a0@-		| copy
    734 	movl	%a1@-,%a0@-		|  8 bytes
    735 	movl	%a0,%sp@(FR_SP)		| new SSP
    736 	moveml	%sp@+,%d0-%d7/%a0-%a6	| restore user registers
    737 	movl	%sp@,%sp		| and our SP
    738 Ldorte:
    739 	rte				| real return
    740 
    741 /*
    742  * Kernel access to the current processes kernel stack is via a fixed
    743  * virtual address.  It is at the same address as in the users VA space.
    744  */
    745 BSS(esym,4)
    746 
    747 
    748 /*
    749  * Initialization
    750  *
    751  * A5 contains physical load point from boot
    752  * exceptions vector thru our table, that's bad.. just hope nothing exceptional
    753  * happens till we had time to initialize ourselves..
    754  */
    755 BSS(lowram,4)
    756 
    757 #define	RELOC(var, ar)			\
    758 	lea	_C_LABEL(var),ar;	\
    759 	addl	%a5,ar
    760 
    761 #define	ASRELOC(var, ar)		\
    762 	lea	_ASM_LABEL(var),ar;	\
    763 	addl	%a5,ar
    764 
    765 	.text
    766 
    767 	| XXX should be a symbol?
    768 	| 2: needs a4 = esym
    769 	| 3: no chipmem requirement
    770 	|    bootinfo data structure
    771 
    772 	.word	0
    773 	.word	0x0003			| loadbsd version required
    774 ASENTRY_NOPROFILE(start)
    775 	lea	%pc@(L_base),%a5	| initialize relocation register
    776 
    777 	movw	#PSL_HIGHIPL,%sr	| no interrupts
    778 	ASRELOC(tmpstk,%a6)
    779 	movl	%a6,%sp			| give ourselves a temporary stack
    780 
    781 	| save the passed parameters. "prepass" them on the stack for
    782 	| later catch by start_c()
    783 	movl	%a5,%sp@-		| pass loadbase
    784 	movl	%d6,%sp@-		| pass boot partition offset
    785 	movl	%a2,%sp@-		| pass sync inhibit flags
    786 	movl	%d3,%sp@-		| pass AGA mode
    787 	movl	%a4,%sp@-		| pass address of _esym
    788 	movl	%d1,%sp@-		| pass chipmem-size
    789 	movl	%d0,%sp@-		| pass fastmem-size
    790 	movl	%a0,%sp@-		| pass fastmem_start
    791 	movl	%d5,%sp@-		| pass machine id
    792 
    793 	/*
    794 	 * initialize some hw addresses to their physical address
    795 	 * for early running
    796 	 */
    797 #ifdef DRACO
    798 	/*
    799 	 * this is already dynamically done on DraCo
    800 	 */
    801 	cmpb	#0x7D,%sp@
    802 	jne	LisAmiga1
    803 | debug code:
    804 | we should need about 1 uSec for the loop.
    805 | we dont need the AGA mode register.
    806 	movel	#100000,%d3
    807 LisDraco0:
    808 #ifdef DEBUG_KERNEL_START
    809 	movb	#0,0x200003c8
    810 	movb	#00,0x200003c9
    811 	movb	#40,0x200003c9
    812 	movb	#00,0x200003c9
    813 |XXX:
    814 	movb	#0,0x200003c8
    815 	movb	#40,0x200003c9
    816 	movb	#00,0x200003c9
    817 	movb	#00,0x200003c9
    818 	subql	#1,%d3
    819 	jcc	LisDraco0
    820 #endif
    821 
    822 	RELOC(chipmem_start, %a0)
    823 	movl	#0,%a0@
    824 
    825 	RELOC(CIAAbase, %a0)
    826 	movl	#0x2801001, %a0@
    827 	RELOC(CIABbase, %a0)
    828 	movl	#0x2800000, %a0@
    829 
    830 	/* XXXX more to come here; as we need it */
    831 
    832 	jra	LisDraco1
    833 LisAmiga1:
    834 #endif
    835 	RELOC(chipmem_start, %a0)
    836 	movl	#0x400,%a0@
    837 	RELOC(CIAAbase, %a0)
    838 	movl	#0xbfe001,%a0@
    839 	RELOC(CIABbase, %a0)
    840 	movl	#0xbfd000,%a0@
    841 	RELOC(CUSTOMbase, %a0)
    842 	movl	#0xdff000,%a0@
    843 
    844 #ifdef DRACO
    845 LisDraco1:
    846 #endif
    847 	/*
    848 	 * initialize the timer frequency
    849 	 */
    850 	RELOC(eclockfreq, %a0)
    851 	movl	%d4,%a0@
    852 
    853 	movl	#AMIGA_68030,%d1	| 68030 Attn flag from exec
    854 	andl	%d5,%d1
    855 	jeq	Ltestfor020
    856 	RELOC(mmutype, %a0)
    857 	movl	#MMU_68030,%a0@		| assume 020 means 851
    858 	RELOC(cputype, %a0)
    859 	movl	#CPU_68030,%a0@
    860 	jra	Lsetcpu040		| skip to init.
    861 Ltestfor020:
    862 	movl	#AMIGA_68020,%d1	| 68020 Attn flag from exec
    863 	andl	%d5,%d1
    864 	jeq	Lsetcpu040
    865 	RELOC(mmutype, %a0)
    866 	movl	#MMU_68851,%a0@
    867 	RELOC(cputype, %a0)
    868 	movl	#CPU_68020,%a0@
    869 Lsetcpu040:
    870 	movl	#CACHE_OFF,%d0		| 68020/030 cache
    871 	movl	#AMIGA_68040,%d1
    872 	andl	%d1,%d5
    873 	jeq	Lstartnot040		| it is not 68040
    874 	RELOC(mmutype, %a0)
    875 	movl	#MMU_68040,%a0@		| same as hp300 for compat
    876 	RELOC(cputype, %a0)
    877 	movl	#CPU_68040,%a0@
    878 	.word	0xf4f8			| cpusha bc - push and invalidate caches
    879 	movl	#CACHE40_OFF,%d0	| 68040 cache disable
    880 #ifndef BB060STUPIDROM
    881 	btst	#7,%sp@(3)
    882 	jeq	Lstartnot040
    883 	movl	#CPU_68060,%a0@		| and in the cputype
    884 	orl	#IC60_CABC,%d0		| XXX and clear all 060 branch cache
    885 #else
    886 	movc	%d0,%cacr
    887 	bset	#30,%d0			| not allocate data cache bit
    888 	movc	%d0,%cacr		| does it stick?
    889 	movc	%cacr,%d0
    890 	tstl	%d0
    891 	jeq	Lstartnot040
    892 	bset	#7,%sp@(3)		| note it is '60 family in machineid
    893 	movl	#CPU_68060,%a0@		| and in the cputype
    894 	orl	#IC60_CABC,%d0		| XXX and clear all 060 branch cache
    895 	.word	0x4e7a,0x1808		| movc	pcr,d1
    896 	swap	%d1
    897 	cmpw	#0x430,%d1
    898 	jne	Lstartnot040		| but no FPU
    899 	bset	#6,%sp@(3)		| yes, we have FPU, note that
    900 	swap	%d1
    901 	bclr	#1,%d1			| ... and switch it on.
    902 	.word	0x4e7b,0x1808		| movc	d1,pcr
    903 #endif
    904 Lstartnot040:
    905 	movc	%d0,%cacr		| clear and disable on-chip cache(s)
    906 	movl	#_C_LABEL(vectab),%a0
    907 	movc	%a0,%vbr
    908 
    909 /* initialize source/destination control registers for movs */
    910 	moveq	#FC_USERD,%d0		| user space
    911 	movc	%d0,%sfc		|   as source
    912 	movc	%d0,%dfc		|   and destination of transfers
    913 
    914 /* let the C function initialize everything */
    915 	RELOC(start_c, %a0)
    916 	jbsr	%a0@
    917 	lea	%sp@(4*9),%sp
    918 
    919 #ifdef DRACO
    920 	RELOC(machineid,%a0)
    921 	cmpb	#0x7d,%a0@
    922 	jne	LAmiga_enable_MMU
    923 
    924 	lea	%pc@(0),%a0
    925 	movl	%a0,%d0
    926 	andl	#0xff000000,%d0
    927 	orl	#0x0000c044,%d0		| 16 MB, ro, cache inhibited
    928 	.word	0x4e7b,0x0004		| movc %d0,%itt0
    929 	.word	0xf518			| pflusha
    930 	movl	#MMU40_TCR_BITS,%d0	| enable MMU
    931 	.word	0x4e7b,0x0003		| movc %d0,%tc
    932 	jmp	Lcleanitt0:l
    933 Lcleanitt0:
    934 	movq	#0,%d0
    935 	.word	0x4e7b,0x0004		| movc %d0,%itt0
    936 	bra	LMMUenable_end
    937 
    938 LAmiga_enable_MMU:
    939 #endif /* DRACO */
    940 
    941 /* Copy just the code to enable the MMU into chip memory */
    942 	lea	LMMUenable_start,%a0
    943 	movl	#LMMUenable_start:l,%a1
    944 	lea	LMMUenable_end,%a2
    945 Lcopy_MMU_enabler:
    946 	movl	%a0@+,%a1@+
    947 	cmpl	%a0,%a2
    948 	jgt	Lcopy_MMU_enabler
    949 
    950 	jmp	LMMUenable_start:l
    951 
    952 LMMUenable_start:
    953 
    954 /* enable the MMU */
    955 #if defined(M68040) || defined(M68060)
    956 	RELOC(mmutype, %a0)
    957 	cmpl	#MMU_68040,%a0@
    958 	jne	Lenable030
    959 	.word	0xf518			| pflusha
    960 	movl	#MMU40_TCR_BITS,%d0	| enable MMU
    961 	.word	0x4e7b,0x0003		| movc	%d0,%tc
    962 	jmp	LMMUenable_end:l
    963 #endif /* M68040 || M68060 */
    964 Lenable030:
    965 	pflusha
    966 	lea	Ltc,%a0
    967 	pmove	%a0@,%tc
    968 	jmp	LMMUenable_end:l
    969 
    970 Ltc:	.long	MMU51_TCR_BITS		| see pmap.h
    971 
    972 LMMUenable_end:
    973 
    974 	lea	_ASM_LABEL(tmpstk),%sp	| give ourselves a temporary stack
    975 	jbsr	_C_LABEL(start_c_finish)
    976 
    977 /* set kernel stack, user SP */
    978 	movl	_C_LABEL(lwp0uarea),%a1	| grab lwp0 uarea
    979 	lea	%a1@(USPACE-4),%sp	| set kernel stack to end of area
    980 	movl	#USRSTACK-4,%a2
    981 	movl	%a2,%usp		| init user SP
    982 	movl	%a2,%a1@(PCB_USP)	| and save it
    983 	clrw	%a1@(PCB_FLAGS)		| clear flags
    984 #ifdef FPCOPROC
    985 	clrl	%a1@(PCB_FPCTX)		| ensure null FP context
    986 |WRONG!	movl	%a1,%sp@-
    987 |	pea	%a1@(PCB_FPCTX)
    988 |	jbsr	_C_LABEL(m68881_restore)	| restore it (does not kill a1)
    989 |	addql	#4,%sp
    990 #endif
    991 /* flush TLB and turn on caches */
    992 
    993 	jbsr	_C_LABEL(_TBIA)		| invalidate TLB
    994 	movl	#CACHE_ON,%d0
    995 	tstl	%d5
    996 	jeq	Lcacheon
    997 | is this needed? MLH
    998 	.word	0xf4f8			| cpusha bc - push & invalidate caches
    999 	movl	#CACHE40_ON,%d0
   1000 #ifdef M68060
   1001 	cmpl	#CPU_68060,_C_LABEL(cputype)
   1002 	jne	Lcacheon
   1003 	movl	#CACHE60_ON,%d0
   1004 #endif
   1005 Lcacheon:
   1006 	movc	%d0,%cacr		| clear cache(s)
   1007 /* final setup for C code */
   1008 
   1009 	movw	#PSL_LOWIPL,%sr		| lower SPL
   1010 
   1011 	movl	%d7,_C_LABEL(boothowto)	| save reboot flags
   1012 /*
   1013  * Create a fake exception frame that returns to user mode,
   1014  * make space for the rest of a fake saved register set, and
   1015  * pass the first available RAM and a pointer to the register
   1016  * set to "main()".  "main()" will do an "execve()" using that
   1017  * stack frame.
   1018  * When "main()" returns, we're running in process 1 and have
   1019  * successfully executed the "execve()".  We load up the registers from
   1020  * that set; the "rte" loads the PC and PSR, which jumps to "init".
   1021  */
   1022   	clrw	%sp@-			| vector offset/frame type
   1023 	clrl	%sp@-			| PC - filled in by "execve"
   1024   	movw	#PSL_USER,%sp@-		| in user mode
   1025 	clrl	%sp@-			| stack adjust count
   1026 	lea	%sp@(-64),%sp		| construct space for D0-D7/A0-A7
   1027 	lea	_C_LABEL(lwp0),%a0		| lwp0 in a0
   1028 	movl	%sp,%a0@(L_MD_REGS)	| save frame for lwp0
   1029 	movl	%usp,%a1
   1030 	movl	%a1,%sp@(FR_SP)		| save user stack pointer in frame
   1031 	pea	%sp@			| addr of space for D0
   1032 
   1033 	jbsr	_C_LABEL(main)		| main(firstaddr, r0)
   1034 	addql	#4,%sp			| pop args
   1035 
   1036 	cmpl	#MMU_68040,_C_LABEL(mmutype)	| 68040?
   1037 	jne	Lnoflush		| no, skip
   1038 	.word	0xf478			| cpusha dc
   1039 	.word	0xf498			| cinva ic, also clears the 060 btc
   1040 Lnoflush:
   1041 	movl	%sp@(FR_SP),%a0		| grab and load
   1042 	movl	%a0,%usp		|   user SP
   1043 	moveml	%sp@+,%d0-%d7/%a0-%a6	| load most registers (all but SSP)
   1044 	addql	#8,%sp			| pop SSP and stack adjust count
   1045   	rte
   1046 
   1047 /*
   1048  * Primitives
   1049  */
   1050 
   1051 /*
   1052  * non-local gotos
   1053  */
   1054 ENTRY(qsetjmp)
   1055 	movl	%sp@(4),%a0	| savearea pointer
   1056 	lea	%a0@(40),%a0	| skip regs we do not save
   1057 	movl	%a6,%a0@+	| save FP
   1058 	movl	%sp,%a0@+	| save SP
   1059 	movl	%sp@,%a0@	| and return address
   1060 	moveq	#0,%d0		| return 0
   1061 	rts
   1062 
   1063 /*
   1064  * Use common m68k process/lwp switch and context save subroutines.
   1065  */
   1066 #include <m68k/m68k/switch_subr.s>
   1067 
   1068 ENTRY(ecacheon)
   1069 	rts
   1070 
   1071 ENTRY(ecacheoff)
   1072 	rts
   1073 
   1074 /*
   1075  * Check out a virtual address to see if it's okay to write to.
   1076  *
   1077  * probeva(va, fc)
   1078  *
   1079  */
   1080 ENTRY(probeva)
   1081 	movl	%sp@(8),%d0
   1082 	movec	%d0,%dfc
   1083 	movl	%sp@(4),%a0
   1084 	.word	0xf548				| ptestw (a0)
   1085 	moveq	#FC_USERD,%d0			| restore DFC to user space
   1086 	movc	%d0,%dfc
   1087 	.word	0x4e7a,0x0805			| movec  MMUSR,d0
   1088 	rts
   1089 
   1090 /*
   1091  * Handle the nitty-gritty of rebooting the machine.
   1092  *
   1093  */
   1094 #if defined(P5PPC68KBOARD)
   1095 	.data
   1096 GLOBAL(p5ppc)
   1097 	.long	0
   1098 	.text
   1099 #endif
   1100 
   1101 ENTRY_NOPROFILE(doboot)
   1102 	movl	#CACHE_OFF,%d0
   1103 	cmpl	#MMU_68040,_C_LABEL(mmutype)	| is it 68040
   1104 	jne	Ldoboot0
   1105 	.word	0xf4f8			| cpusha bc - push and invalidate caches
   1106 	nop
   1107 	movl	#CACHE40_OFF,%d0
   1108 Ldoboot0:
   1109 	movc	%d0,%cacr			| disable on-chip cache(s)
   1110 
   1111 	movw	#0x2700,%sr			| cut off any interrupts
   1112 
   1113 #if defined(P5PPC68KBOARD)
   1114 	tstl	_C_LABEL(p5ppc)
   1115 	jne	Lp5ppcboot
   1116 #endif
   1117 #if defined(DRACO)
   1118 	cmpb	#0x7d,_C_LABEL(machineid)
   1119 	jeq	LdbOnDraCo
   1120 #endif
   1121 
   1122 	| clear first 4k of CHIPMEM
   1123 	movl	_C_LABEL(CHIPMEMADDR),%a0
   1124 	movl	%a0,%a1
   1125 	movl	#1024,%d0
   1126 Ldb1:
   1127 	clrl	%a0@+
   1128 	dbra	%d0,Ldb1
   1129 
   1130 	| now, copy the following code over
   1131 |	lea	%a1@(Ldoreboot),%a0	| KVA starts at 0, CHIPMEM is phys 0
   1132 |	lea	%a1@(Ldorebootend),%a1
   1133 |	lea	%pc@(Ldoreboot-.+2),%a0
   1134 |	addl	%a1,%a0
   1135 |	lea	%a0@(128),%a1
   1136 |	lea	%pc@(Ldoreboot-.+2),%a2
   1137 	lea	Ldoreboot,%a2
   1138 	lea	Ldorebootend,%a0
   1139 	addl	%a1,%a0
   1140 	addl	%a2,%a1
   1141 	exg	%a0,%a1
   1142 Ldb2:
   1143 	movel	%a2@+,%a0@+
   1144 	cmpl	%a1,%a0
   1145 	jle	Ldb2
   1146 
   1147 	| ok, turn off MMU..
   1148 Ldoreboot:
   1149 	cmpl	#MMU_68040,_C_LABEL(mmutype)	| is it 68040
   1150  	jeq	Lmmuoff040
   1151 	lea	_ASM_LABEL(zero),%a0
   1152 	pmove	%a0@,%tc		| Turn off MMU
   1153 	lea	_ASM_LABEL(nullrp),%a0
   1154 	pmove	%a0@,%crp		| Turn off MMU some more
   1155 	pmove	%a0@,%srp		| Really, really, turn off MMU
   1156 	jra	Ldoboot1
   1157 Lmmuoff040:
   1158 	movl	#0,%d0
   1159 	.word	0x4e7b,0x0003		| movc d0,TC
   1160 	.word	0x4e7b,0x0806		| movc d0,URP
   1161 	.word	0x4e7b,0x0807		| movc d0,SRP
   1162 Ldoboot1:
   1163 
   1164 	| this weird code is the OFFICIAL way to reboot an Amiga ! ..
   1165 	lea	0x1000000,%a0
   1166 	subl	%a0@(-0x14),%a0
   1167 	movl	%a0@(4),%a0
   1168 	subl	#2,%a0
   1169 	cmpw	#0x4e70,%a0@		| 68040 kludge: if ROM entry is not
   1170 	jne	Ldoreset		| a reset, do the reset here
   1171 	jmp	%a0@			| otherwise, jump to the ROM to reset
   1172 	| reset needs to be on longword boundary
   1173 	nop
   1174 #ifdef __ELF__
   1175 	.align	4
   1176 #else
   1177 	.align	2
   1178 #endif
   1179 Ldoreset:
   1180 	| reset unconfigures all memory!
   1181 	reset
   1182 	| now rely on prefetch for next jmp
   1183 	jmp	%a0@
   1184 	| NOT REACHED
   1185 
   1186 #if defined(P5PPC68KBOARD)
   1187 Lp5ppcboot:
   1188 | The Linux-Apus boot code does it in a similar way
   1189 | For 040 on uncached pages, eieio can be replaced by nothing.
   1190 	movl	_C_LABEL(ZTWOROMADDR),%a0
   1191 	lea	%a0@(0xf60000-0xd80000),%a0
   1192 	movb	#0x60,%a0@(0x20)
   1193 	movb	#0x50,%a0@(0x20)
   1194 	movb	#0x30,%a0@(0x20)
   1195 	movb	#0x40,%a0@(0x18)
   1196 	movb	#0x04,%a0@
   1197 Lwaithere:
   1198 	jra	Lwaithere
   1199 #endif
   1200 
   1201 #ifdef DRACO
   1202 LdbOnDraCo:
   1203 | we use a TTR. We want to boot even if half of us is already dead.
   1204 
   1205 	movl	_C_LABEL(boot_fphystart), %d0
   1206 	lea	LdoDraCoBoot, %a0
   1207 	lea	%a0@(%d0),%a0
   1208 	andl	#0xFF000000,%d0
   1209 	orl	#0x0000C044,%d0	| enable, supervisor, CI, RO
   1210 	.word	0x4e7b,0x0004	| movc d0,ITT0
   1211 	jmp	%a0@
   1212 
   1213 #ifdef __ELF__
   1214 	.align	4
   1215 #else
   1216 	.align	2
   1217 #endif
   1218 LdoDraCoBoot:
   1219 | turn off MMU now ... were more ore less guaranteed to run on 040/060:
   1220 	movl	#0,%d0
   1221 	.word	0x4e7b,0x0003	| movc d0,TC
   1222 	.word	0x4e7b,0x0806	| movc d0,URP
   1223 	.word	0x4e7b,0x0807	| movc d0,SRP
   1224 	.word	0x4e7b,0x0004	| movc d0,ITT0
   1225 	nop
   1226 | map in boot ROM @0:
   1227 	reset
   1228 | and simulate what a reset exception would have done.
   1229 	movl	4,%a0
   1230 	movl	0,%a7
   1231 	jmp	%a0@
   1232 	| NOT REACHED
   1233 #endif
   1234 /*
   1235  * Reboot directly into a new kernel image.
   1236  * kernel_reload(image, image_size, entry,
   1237  *		 fastram_start, fastram_size, chipram_start, esym, eclockfreq)
   1238  */
   1239 ENTRY_NOPROFILE(kernel_reload)
   1240 	lea	Lreload_copy,%a0	| cursory validity check of new kernel
   1241 	movl	%a0@,%d0		|  to see if the kernel reload code
   1242 	addl	%sp@(4),%a0		|  in new image matches running kernel
   1243 	cmpl	%a0@,%d0
   1244 	jeq	Lreload_ok
   1245 	rts				| It doesn't match - can't reload
   1246 Lreload_ok:
   1247 	jsr	_C_LABEL(bootsync)
   1248 	CUSTOMADDR(%a5)
   1249 
   1250 	movew	#(1<<9),%a5@(0x096)	| disable DMA (before clobbering chipmem)
   1251 
   1252 	movl	#CACHE_OFF,%d0
   1253 	cmpl	#MMU_68040,_C_LABEL(mmutype)
   1254 	jne	Lreload1
   1255 	.word	0xf4f8		| cpusha bc - push and invalidate caches
   1256 	nop
   1257 	movl	#CACHE40_OFF,%d0
   1258 Lreload1:
   1259 	movc	%d0,%cacr		| disable on-chip cache(s)
   1260 
   1261 	movw	#0x2700,%sr		| cut off any interrupts
   1262 	movel	_C_LABEL(boothowto),%d7	| save boothowto
   1263 	movel	_C_LABEL(machineid),%d5	| (and machineid)
   1264 
   1265 	movel	%sp@(16),%a0		| load memory parameters
   1266 	movel	%sp@(20),%d0
   1267 	movel	%sp@(24),%d1
   1268 	movel	%sp@(28),%a4		| esym
   1269 	movel	%sp@(32),%d4		| eclockfreq
   1270 	movel	%sp@(36),%d3		| AGA mode
   1271 	movel	%sp@(40),%a2		| sync inhibit flags
   1272 	movel	%sp@(44),%d6		| boot partition offset
   1273 
   1274 	movel	%sp@(12),%a6		| find entrypoint (a6)
   1275 
   1276 	movel	%sp@(4),%a1		| copy kernel to low chip memory
   1277 	movel	%sp@(8),%d2
   1278 	movl	_C_LABEL(CHIPMEMADDR),%a3
   1279 Lreload_copy:
   1280 	movel	%a1@+,%a3@+
   1281 	subl	#4,%d2
   1282 	jcc	Lreload_copy
   1283 
   1284 	| ok, turn off MMU..
   1285 	cmpl	#MMU_68040,_C_LABEL(mmutype)
   1286 	jeq	Lreload040
   1287 	lea	_ASM_LABEL(zero),%a3
   1288 	pmove	%a3@,%tc		| Turn off MMU
   1289 	lea	_ASM_LABEL(nullrp),%a3
   1290 	pmove	%a3@,%crp		| Turn off MMU some more
   1291 	pmove	%a3@,%srp		| Really, really, turn off MMU
   1292 	jra	Lreload2
   1293 Lreload040:
   1294 	movl	#0,%d2
   1295 	.word	0x4e7b,0x2003	| movc d2,TC
   1296 	.word	0x4e7b,0x2806	| movc d2,URP
   1297 	.word	0x4e7b,0x2807	| movc d2,SRP
   1298 Lreload2:
   1299 
   1300 	moveq	#0,%d2			| clear unused registers
   1301 	subl	%a1,%a1
   1302 	subl	%a3,%a3
   1303 	subl	%a5,%a5
   1304 	jmp	%a6@			| start new kernel
   1305 
   1306 
   1307 | A do-nothing MMU root pointer (includes the following long as well)
   1308 
   1309 ASLOCAL(nullrp)
   1310 	.long	0x7fff0001
   1311 ASLOCAL(zero)
   1312 	.long	0
   1313 Ldorebootend:
   1314 
   1315 #ifdef __ELF__
   1316 	.align 4
   1317 #else
   1318 	.align 2
   1319 #endif
   1320 	nop
   1321 ENTRY_NOPROFILE(delay)
   1322 ENTRY_NOPROFILE(DELAY)
   1323 	movql #10,%d1		| 2 +2
   1324 	movl %sp@(4),%d0	| 4 +4
   1325 	lsll %d1,%d0		| 8 +2
   1326 	movl _C_LABEL(delaydivisor),%d1	| A +6
   1327 Ldelay:				| longword aligned again.
   1328 	subl %d1,%d0
   1329 	jcc Ldelay
   1330 	rts
   1331 
   1332 #ifdef M68060
   1333 ENTRY_NOPROFILE(intemu60)
   1334 	addql	#1,L60iem
   1335 	jra	_C_LABEL(I_CALL_TOP)+128+0x00
   1336 ENTRY_NOPROFILE(fpiemu60)
   1337 	addql	#1,L60fpiem
   1338 	jra	_C_LABEL(FP_CALL_TOP)+128+0x30
   1339 ENTRY_NOPROFILE(fpdemu60)
   1340 	addql	#1,L60fpdem
   1341 	jra	_C_LABEL(FP_CALL_TOP)+128+0x38
   1342 ENTRY_NOPROFILE(fpeaemu60)
   1343 	addql	#1,L60fpeaem
   1344 	jra	_C_LABEL(FP_CALL_TOP)+128+0x40
   1345 #endif
   1346 
   1347 	.data
   1348 	.space	PAGE_SIZE
   1349 	.align	4
   1350 ASLOCAL(tmpstk)
   1351 
   1352 GLOBAL(mmutype)
   1353 	.long	MMU_68851
   1354 GLOBAL(cputype)
   1355 	.long	CPU_68020
   1356 GLOBAL(ectype)
   1357 	.long	EC_NONE
   1358 GLOBAL(fputype)
   1359 	.long	FPU_NONE
   1360 GLOBAL(delaydivisor)
   1361 	.long	12		| should be enough for 80 MHz 68060
   1362 				| will be adapted to other CPUs in
   1363 				| start_c_cleanup and calibrated
   1364 				| at clock attach time.
   1365 #ifdef DEBUG
   1366 ASGLOBAL(fulltflush)
   1367 	.long	0
   1368 ASGLOBAL(fullcflush)
   1369 	.long	0
   1370 ASGLOBAL(timebomb)
   1371 	.long	0
   1372 #endif
   1373 /* interrupt counters */
   1374 GLOBAL(intrnames)
   1375 	.asciz	"spur"		| spurious interrupt
   1376 	.asciz	"tbe/soft"	| serial TBE & software
   1377 	.asciz	"kbd/ports"	| keyboard & PORTS
   1378 	.asciz	"vbl"		| vertical blank
   1379 	.asciz	"audio"		| audio channels
   1380 	.asciz	"rbf"		| serial receive
   1381 	.asciz	"exter"		| EXTERN
   1382 	.asciz	"nmi"		| non-maskable
   1383 	.asciz	"clock"		| clock interrupts
   1384 	.asciz	"spur6"		| spurious level 6
   1385 #ifdef DRACO
   1386 	.asciz	"kbd/soft"	| 1: native keyboard, soft ints
   1387 	.asciz	"cia/zbus"	| 2: cia, PORTS
   1388 	.asciz	"lclbus"	| 3: local bus, e.g. Altais vbl
   1389 	.asciz	"drscsi"	| 4: mainboard scsi
   1390 	.asciz	"superio"	| 5: superio chip
   1391 	.asciz	"lcl/zbus"	| 6: lcl/zorro lev6
   1392 	.asciz	"buserr"	| 7: nmi: bus timeout
   1393 #endif
   1394 #ifdef M68060
   1395 	.asciz	"60intemu"
   1396 	.asciz	"60fpiemu"
   1397 	.asciz	"60fpdemu"
   1398 	.asciz	"60fpeaemu"
   1399 	.asciz	"60bpe"
   1400 #endif
   1401 #ifdef FPU_EMULATE
   1402 	.asciz	"fpe"
   1403 #endif
   1404 GLOBAL(eintrnames)
   1405 #ifdef __ELF__
   1406 	.align	4
   1407 #else
   1408 	.align	2
   1409 #endif
   1410 GLOBAL(intrcnt)
   1411 	.long	0,0,0,0,0,0,0,0,0,0
   1412 #ifdef DRACO
   1413 ASLOCAL(Drintrcnt)
   1414 	.long	0,0,0,0,0,0,0
   1415 #endif
   1416 #ifdef M68060
   1417 L60iem:		.long	0
   1418 L60fpiem:	.long	0
   1419 L60fpdem:	.long	0
   1420 L60fpeaem:	.long	0
   1421 L60bpe:		.long	0
   1422 #endif
   1423 #ifdef FPU_EMULATE
   1424 Lfpecnt:	.long	0
   1425 #endif
   1426 GLOBAL(eintrcnt)
   1427