Home | History | Annotate | Line # | Download | only in sun3x
      1  1.78   thorpej /*	$NetBSD: locore.s,v 1.78 2024/01/17 12:33:51 thorpej Exp $	*/
      2   1.1       gwr 
      3   1.1       gwr /*
      4  1.62     rmind  * Copyright (c) 1988 University of Utah.
      5   1.1       gwr  * Copyright (c) 1980, 1990, 1993
      6   1.1       gwr  *	The Regents of the University of California.  All rights reserved.
      7  1.52       agc  *
      8  1.52       agc  * This code is derived from software contributed to Berkeley by
      9  1.52       agc  * the Systems Programming Group of the University of Utah Computer
     10  1.52       agc  * Science Department.
     11  1.52       agc  *
     12  1.52       agc  * Redistribution and use in source and binary forms, with or without
     13  1.52       agc  * modification, are permitted provided that the following conditions
     14  1.52       agc  * are met:
     15  1.52       agc  * 1. Redistributions of source code must retain the above copyright
     16  1.52       agc  *    notice, this list of conditions and the following disclaimer.
     17  1.52       agc  * 2. Redistributions in binary form must reproduce the above copyright
     18  1.52       agc  *    notice, this list of conditions and the following disclaimer in the
     19  1.52       agc  *    documentation and/or other materials provided with the distribution.
     20  1.52       agc  * 3. Neither the name of the University nor the names of its contributors
     21  1.52       agc  *    may be used to endorse or promote products derived from this software
     22  1.52       agc  *    without specific prior written permission.
     23  1.52       agc  *
     24  1.52       agc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  1.52       agc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  1.52       agc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  1.52       agc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  1.52       agc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  1.52       agc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  1.52       agc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  1.52       agc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  1.52       agc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  1.52       agc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  1.52       agc  * SUCH DAMAGE.
     35  1.52       agc  *
     36  1.52       agc  *	from: Utah $Hdr: locore.s 1.66 92/12/22$
     37  1.52       agc  *	@(#)locore.s	8.6 (Berkeley) 5/27/94
     38  1.52       agc  */
     39   1.1       gwr 
     40  1.29   thorpej #include "opt_compat_netbsd.h"
     41  1.35  christos #include "opt_compat_sunos.h"
     42  1.47     lukem #include "opt_kgdb.h"
     43  1.42   thorpej #include "opt_lockdebug.h"
     44  1.27       gwr 
     45   1.1       gwr #include "assym.h"
     46  1.17   thorpej #include <machine/asm.h>
     47   1.1       gwr #include <machine/trap.h>
     48   1.1       gwr 
     49   1.1       gwr | Remember this is a fun project!
     50   1.1       gwr 
     51   1.1       gwr 	.data
     52  1.19    jeremy GLOBAL(mon_crp)
     53   1.1       gwr 	.long	0,0
     54   1.1       gwr 
     55   1.1       gwr | This is for kvm_mkdb, and should be the address of the beginning
     56   1.1       gwr | of the kernel text segment (not necessarily the same as kernbase).
     57   1.1       gwr 	.text
     58  1.19    jeremy GLOBAL(kernel_text)
     59   1.1       gwr 
     60   1.1       gwr | This is the entry point, as well as the end of the temporary stack
     61   1.1       gwr | used during process switch (one 8K page ending at start)
     62  1.19    jeremy ASGLOBAL(tmpstk)
     63  1.20       gwr ASGLOBAL(start)
     64  1.19    jeremy 
     65   1.1       gwr | The first step, after disabling interrupts, is to map enough of the kernel
     66   1.1       gwr | into high virtual address space so that we can use position dependent code.
     67   1.1       gwr | This is a tricky task on the sun3x because the MMU is already enabled and
     68   1.1       gwr | the ROM monitor provides no indication of where the root MMU table is mapped.
     69   1.1       gwr | Therefore we must use one of the 68030's 'transparent translation' registers
     70   1.1       gwr | to define a range in the address space where the MMU translation is
     71   1.1       gwr | turned off.  Once this is complete we can modify the MMU table directly
     72   1.1       gwr | without the need for it to be mapped into virtual memory.
     73   1.1       gwr | All code must be position independent until otherwise noted, as the
     74   1.1       gwr | boot loader has loaded us into low memory but all the symbols in this
     75   1.1       gwr | code have been linked high.
     76  1.45       chs 	movw	#PSL_HIGHIPL,%sr	| no interrupts
     77  1.61   tsutsui 	movl	#KERNBASE3X,%a5		| for vtop conversion
     78  1.45       chs 	lea	_C_LABEL(mon_crp),%a0	| where to store the CRP
     79  1.45       chs 	subl	%a5,%a0
     80   1.1       gwr 	| Note: borrowing mon_crp for tt0 setup...
     81  1.45       chs 	movl	#0x3F8107,%a0@		| map the low 1GB v=p with the
     82  1.14    jeremy 	.long	0xf0100800		| transparent translation reg0
     83  1.14    jeremy 					| [ pmove a0@, tt0 ]
     84   1.1       gwr | In order to map the kernel into high memory we will copy the root table
     85   1.1       gwr | entry which maps the 16 megabytes of memory starting at 0x0 into the
     86   1.1       gwr | entry which maps the 16 megabytes starting at KERNBASE.
     87  1.45       chs 	pmove	%crp,%a0@		| Get monitor CPU root pointer
     88  1.45       chs 	movl	%a0@(4),%a1		| 2nd word is PA of level A table
     89   1.1       gwr 
     90  1.45       chs 	movl	%a1,%a0			| compute the descriptor address
     91  1.45       chs 	addl	#0x3e0,%a1		| for VA starting at KERNBASE
     92  1.45       chs 	movl	%a0@,%a1@		| copy descriptor type
     93  1.45       chs 	movl	%a0@(4),%a1@(4)		| copy physical address
     94   1.1       gwr 
     95   1.1       gwr | Kernel is now double mapped at zero and KERNBASE.
     96   1.1       gwr | Force a long jump to the relocated code (high VA).
     97  1.45       chs 	movl	#IC_CLEAR,%d0		| Flush the I-cache
     98  1.45       chs 	movc	%d0,%cacr
     99   1.1       gwr 	jmp L_high_code:l		| long jump
    100   1.1       gwr 
    101   1.1       gwr L_high_code:
    102   1.1       gwr | We are now running in the correctly relocated kernel, so
    103   1.1       gwr | we are no longer restricted to position-independent code.
    104   1.1       gwr | It is handy to leave transparent translation enabled while
    105  1.20       gwr | for the low 1GB while _bootstrap() is doing its thing.
    106   1.1       gwr 
    107   1.1       gwr | Do bootstrap stuff needed before main() gets called.
    108   1.1       gwr | Our boot loader leaves a copy of the kernel's exec header
    109   1.1       gwr | just before the start of the kernel text segment, so the
    110   1.1       gwr | kernel can sanity-check the DDB symbols at [end...esym].
    111  1.20       gwr | Pass the struct exec at tmpstk-32 to _bootstrap().
    112   1.7       gwr | Also, make sure the initial frame pointer is zero so that
    113   1.7       gwr | the backtrace algorithm used by KGDB terminates nicely.
    114  1.45       chs 	lea	_ASM_LABEL(tmpstk)-32,%sp
    115  1.45       chs 	movl	#0,%a6
    116  1.26       gwr 	jsr	_C_LABEL(_bootstrap)	| See locore2.c
    117   1.1       gwr 
    118   1.1       gwr | Now turn off the transparent translation of the low 1GB.
    119   1.1       gwr | (this also flushes the ATC)
    120  1.45       chs 	clrl	%sp@-
    121  1.14    jeremy 	.long	0xf0170800		| pmove	sp@,tt0
    122  1.45       chs 	addql	#4,%sp
    123   1.1       gwr 
    124  1.20       gwr | Now that _bootstrap() is done using the PROM functions,
    125   1.1       gwr | we can safely set the sfc/dfc to something != FC_CONTROL
    126  1.45       chs 	moveq	#FC_USERD,%d0		| make movs access "user data"
    127  1.45       chs 	movc	%d0,%sfc		| space for copyin/copyout
    128  1.45       chs 	movc	%d0,%dfc
    129   1.1       gwr 
    130   1.1       gwr | Setup process zero user/kernel stacks.
    131  1.58      matt 	lea	_C_LABEL(lwp0),%a0	| get lwp0
    132  1.59     rmind 	movl	%a0@(L_PCB),%a1		| XXXuvm_lwp_getuarea
    133  1.45       chs 	lea	%a1@(USPACE-4),%sp	| set SSP to last word
    134  1.61   tsutsui 	movl	#USRSTACK3X-4,%a2
    135  1.45       chs 	movl	%a2,%usp		| init user SP
    136   1.1       gwr 
    137  1.20       gwr | Note curpcb was already set in _bootstrap().
    138   1.1       gwr | Will do fpu initialization during autoconfig (see fpu.c)
    139   1.1       gwr | The interrupt vector table and stack are now ready.
    140   1.1       gwr | Interrupts will be enabled later, AFTER  autoconfiguration
    141   1.1       gwr | is finished, to avoid spurrious interrupts.
    142   1.1       gwr 
    143   1.1       gwr /*
    144  1.60     skrll  * Create a fake exception frame so that cpu_lwp_fork() can copy it.
    145  1.49       chs  * main() nevers returns; we exit to user mode from a forked process
    146  1.49       chs  * later on.
    147   1.1       gwr  */
    148  1.45       chs 	clrw	%sp@-			| tf_format,tf_vector
    149  1.45       chs 	clrl	%sp@-			| tf_pc (filled in later)
    150  1.45       chs 	movw	#PSL_USER,%sp@-		| tf_sr for user mode
    151  1.45       chs 	clrl	%sp@-			| tf_stackadj
    152  1.45       chs 	lea	%sp@(-64),%sp		| tf_regs[16]
    153  1.58      matt 	movl	%a1,%a0@(L_MD_REGS)	| lwp0.l_md.md_regs = trapframe
    154  1.19    jeremy 	jbsr	_C_LABEL(main)		| main(&trapframe)
    155  1.49       chs 	PANIC("main() returned")
    156   1.1       gwr 
    157   1.1       gwr | That is all the assembly startup code we need on the sun3x!
    158   1.1       gwr | The rest of this is like the hp300/locore.s where possible.
    159   1.1       gwr 
    160   1.1       gwr /*
    161   1.1       gwr  * Trap/interrupt vector routines
    162   1.1       gwr  */
    163  1.17   thorpej #include <m68k/m68k/trap_subr.s>
    164   1.1       gwr 
    165  1.19    jeremy GLOBAL(buserr)
    166  1.19    jeremy 	tstl	_C_LABEL(nofault)	| device probe?
    167  1.19    jeremy 	jeq	_C_LABEL(addrerr)	| no, handle as usual
    168  1.45       chs 	movl	_C_LABEL(nofault),%sp@-	| yes,
    169  1.19    jeremy 	jbsr	_C_LABEL(longjmp)	|  longjmp(nofault)
    170  1.19    jeremy GLOBAL(addrerr)
    171  1.45       chs 	clrl	%sp@-			| stack adjust count
    172  1.45       chs 	moveml	#0xFFFF,%sp@-		| save user registers
    173  1.45       chs 	movl	%usp,%a0		| save the user SP
    174  1.45       chs 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    175  1.45       chs 	lea	%sp@(FR_HW),%a1		| grab base of HW berr frame
    176  1.45       chs 	moveq	#0,%d0
    177  1.45       chs 	movw	%a1@(10),%d0		| grab SSW for fault processing
    178  1.45       chs 	btst	#12,%d0			| RB set?
    179   1.1       gwr 	jeq	LbeX0			| no, test RC
    180  1.45       chs 	bset	#14,%d0			| yes, must set FB
    181  1.45       chs 	movw	%d0,%a1@(10)		| for hardware too
    182   1.1       gwr LbeX0:
    183  1.45       chs 	btst	#13,%d0			| RC set?
    184   1.1       gwr 	jeq	LbeX1			| no, skip
    185  1.45       chs 	bset	#15,%d0			| yes, must set FC
    186  1.45       chs 	movw	%d0,%a1@(10)		| for hardware too
    187   1.1       gwr LbeX1:
    188  1.45       chs 	btst	#8,%d0			| data fault?
    189   1.1       gwr 	jeq	Lbe0			| no, check for hard cases
    190  1.45       chs 	movl	%a1@(16),%d1		| fault address is as given in frame
    191   1.1       gwr 	jra	Lbe10			| thats it
    192   1.1       gwr Lbe0:
    193  1.45       chs 	btst	#4,%a1@(6)		| long (type B) stack frame?
    194   1.1       gwr 	jne	Lbe4			| yes, go handle
    195  1.45       chs 	movl	%a1@(2),%d1		| no, can use save PC
    196  1.45       chs 	btst	#14,%d0			| FB set?
    197   1.1       gwr 	jeq	Lbe3			| no, try FC
    198  1.45       chs 	addql	#4,%d1			| yes, adjust address
    199   1.1       gwr 	jra	Lbe10			| done
    200   1.1       gwr Lbe3:
    201  1.45       chs 	btst	#15,%d0			| FC set?
    202   1.1       gwr 	jeq	Lbe10			| no, done
    203  1.45       chs 	addql	#2,%d1			| yes, adjust address
    204   1.1       gwr 	jra	Lbe10			| done
    205   1.1       gwr Lbe4:
    206  1.45       chs 	movl	%a1@(36),%d1		| long format, use stage B address
    207  1.45       chs 	btst	#15,%d0			| FC set?
    208   1.1       gwr 	jeq	Lbe10			| no, all done
    209  1.45       chs 	subql	#2,%d1			| yes, adjust address
    210   1.1       gwr Lbe10:
    211  1.45       chs 	movl	%d1,%sp@-		| push fault VA
    212  1.45       chs 	movl	%d0,%sp@-		| and padded SSW
    213  1.45       chs 	movw	%a1@(6),%d0		| get frame format/vector offset
    214  1.45       chs 	andw	#0x0FFF,%d0		| clear out frame format
    215  1.45       chs 	cmpw	#12,%d0			| address error vector?
    216   1.1       gwr 	jeq	Lisaerr			| yes, go to it
    217   1.1       gwr 
    218   1.1       gwr /* MMU-specific code to determine reason for bus error. */
    219  1.45       chs 	movl	%d1,%a0			| fault address
    220  1.45       chs 	movl	%sp@,%d0		| function code from ssw
    221  1.45       chs 	btst	#8,%d0			| data fault?
    222   1.1       gwr 	jne	Lbe10a
    223  1.45       chs 	movql	#1,%d0			| user program access FC
    224   1.1       gwr 					| (we dont separate data/program)
    225  1.45       chs 	btst	#5,%a1@			| supervisor mode?
    226   1.1       gwr 	jeq	Lbe10a			| if no, done
    227  1.45       chs 	movql	#5,%d0			| else supervisor program access
    228   1.1       gwr Lbe10a:
    229  1.45       chs 	ptestr	%d0,%a0@,#7		| do a table search
    230  1.45       chs 	pmove	%psr,%sp@		| save result
    231  1.45       chs 	movb	%sp@,%d1
    232  1.45       chs 	btst	#2,%d1			| invalid? (incl. limit viol and berr)
    233   1.1       gwr 	jeq	Lmightnotbemerr		| no -> wp check
    234  1.45       chs 	btst	#7,%d1			| is it MMU table berr?
    235   1.1       gwr 	jeq	Lismerr			| no, must be fast
    236   1.1       gwr 	jra	Lisberr1		| real bus err needs not be fast
    237   1.1       gwr Lmightnotbemerr:
    238  1.45       chs 	btst	#3,%d1			| write protect bit set?
    239   1.1       gwr 	jeq	Lisberr1		| no, must be bus error
    240  1.45       chs 	movl	%sp@,%d0		| ssw into low word of d0
    241  1.45       chs 	andw	#0xc0,%d0		| write protect is set on page:
    242  1.45       chs 	cmpw	#0x40,%d0		| was it read cycle?
    243   1.1       gwr 	jeq	Lisberr1		| yes, was not WPE, must be bus err
    244   1.1       gwr /* End of MMU-specific bus error code. */
    245   1.1       gwr 
    246   1.1       gwr Lismerr:
    247  1.45       chs 	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
    248  1.17   thorpej 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    249   1.1       gwr Lisaerr:
    250  1.45       chs 	movl	#T_ADDRERR,%sp@-	| mark address error
    251  1.17   thorpej 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    252   1.1       gwr Lisberr1:
    253  1.45       chs 	clrw	%sp@			| re-clear pad word
    254   1.1       gwr Lisberr:
    255  1.45       chs 	movl	#T_BUSERR,%sp@-		| mark bus error
    256  1.17   thorpej 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    257   1.1       gwr 
    258   1.1       gwr /*
    259   1.1       gwr  * FP exceptions.
    260   1.1       gwr  */
    261  1.19    jeremy GLOBAL(fpfline)
    262  1.45       chs 	clrl	%sp@-			| stack adjust count
    263  1.45       chs 	moveml	#0xFFFF,%sp@-		| save registers
    264  1.45       chs 	moveq	#T_FPEMULI,%d0		| denote as FP emulation trap
    265  1.19    jeremy 	jra	_ASM_LABEL(fault)	| do it
    266   1.1       gwr 
    267  1.19    jeremy GLOBAL(fpunsupp)
    268  1.45       chs 	clrl	%sp@-			| stack adjust count
    269  1.45       chs 	moveml	#0xFFFF,%sp@-		| save registers
    270  1.45       chs 	moveq	#T_FPEMULD,%d0		| denote as FP emulation trap
    271  1.19    jeremy 	jra	_ASM_LABEL(fault)	| do it
    272   1.1       gwr 
    273   1.1       gwr /*
    274   1.1       gwr  * Handles all other FP coprocessor exceptions.
    275   1.1       gwr  * Note that since some FP exceptions generate mid-instruction frames
    276   1.1       gwr  * and may cause signal delivery, we need to test for stack adjustment
    277   1.1       gwr  * after the trap call.
    278   1.1       gwr  */
    279  1.19    jeremy GLOBAL(fpfault)
    280  1.45       chs 	clrl	%sp@-		| stack adjust count
    281  1.45       chs 	moveml	#0xFFFF,%sp@-	| save user registers
    282  1.45       chs 	movl	%usp,%a0	| and save
    283  1.45       chs 	movl	%a0,%sp@(FR_SP)	|   the user stack pointer
    284  1.45       chs 	clrl	%sp@-		| no VA arg
    285  1.45       chs 	movl	_C_LABEL(curpcb),%a0	| current pcb
    286  1.45       chs 	lea	%a0@(PCB_FPCTX),%a0 | address of FP savearea
    287  1.45       chs 	fsave	%a0@		| save state
    288  1.45       chs 	tstb	%a0@		| null state frame?
    289   1.1       gwr 	jeq	Lfptnull	| yes, safe
    290  1.45       chs 	clrw	%d0		| no, need to tweak BIU
    291  1.45       chs 	movb	%a0@(1),%d0	| get frame size
    292  1.45       chs 	bset	#3,%a0@(0,%d0:w) | set exc_pend bit of BIU
    293   1.1       gwr Lfptnull:
    294  1.45       chs 	fmovem	%fpsr,%sp@-	| push fpsr as code argument
    295  1.45       chs 	frestore %a0@		| restore state
    296  1.45       chs 	movl	#T_FPERR,%sp@-	| push type arg
    297  1.17   thorpej 	jra	_ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup
    298   1.1       gwr 
    299   1.1       gwr /*
    300   1.1       gwr  * Other exceptions only cause four and six word stack frame and require
    301   1.1       gwr  * no post-trap stack adjustment.
    302   1.1       gwr  */
    303  1.19    jeremy GLOBAL(badtrap)
    304  1.45       chs 	clrl	%sp@-			| stack adjust count
    305  1.45       chs 	moveml	#0xFFFF,%sp@-		| save std frame regs
    306  1.19    jeremy 	jbsr	_C_LABEL(straytrap)	| report
    307  1.45       chs 	moveml	%sp@+,#0xFFFF		| restore regs
    308  1.45       chs 	addql	#4,%sp			| stack adjust count
    309  1.19    jeremy 	jra	_ASM_LABEL(rei)		| all done
    310   1.1       gwr 
    311   1.1       gwr /*
    312   1.1       gwr  * Trap 0 is for system calls
    313   1.1       gwr  */
    314  1.19    jeremy GLOBAL(trap0)
    315  1.45       chs 	clrl	%sp@-			| stack adjust count
    316  1.45       chs 	moveml	#0xFFFF,%sp@-		| save user registers
    317  1.45       chs 	movl	%usp,%a0		| save the user SP
    318  1.45       chs 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    319  1.45       chs 	movl	%d0,%sp@-		| push syscall number
    320  1.19    jeremy 	jbsr	_C_LABEL(syscall)	| handle it
    321  1.45       chs 	addql	#4,%sp			| pop syscall arg
    322  1.45       chs 	movl	%sp@(FR_SP),%a0		| grab and restore
    323  1.45       chs 	movl	%a0,%usp		|   user SP
    324  1.45       chs 	moveml	%sp@+,#0x7FFF		| restore most registers
    325  1.45       chs 	addql	#8,%sp			| pop SP and stack adjust
    326  1.19    jeremy 	jra	_ASM_LABEL(rei)		| all done
    327  1.11       gwr 
    328  1.11       gwr /*
    329  1.11       gwr  * Trap 12 is the entry point for the cachectl "syscall"
    330  1.11       gwr  *	cachectl(command, addr, length)
    331  1.11       gwr  * command in d0, addr in a1, length in d1
    332  1.11       gwr  */
    333  1.19    jeremy GLOBAL(trap12)
    334  1.51   thorpej 	movl	_C_LABEL(curlwp),%a0
    335  1.51   thorpej 	movl	%a0@(L_PROC),%sp@-	| push curproc pointer
    336  1.45       chs 	movl	%d1,%sp@-		| push length
    337  1.45       chs 	movl	%a1,%sp@-		| push addr
    338  1.45       chs 	movl	%d0,%sp@-		| push command
    339  1.32        is 	jbsr	_C_LABEL(cachectl1)	| do it
    340  1.45       chs 	lea	%sp@(16),%sp		| pop args
    341  1.19    jeremy 	jra	_ASM_LABEL(rei)		| all done
    342   1.1       gwr 
    343   1.1       gwr /*
    344   1.1       gwr  * Trace (single-step) trap.  Kernel-mode is special.
    345   1.1       gwr  * User mode traps are simply passed on to trap().
    346   1.1       gwr  */
    347  1.19    jeremy GLOBAL(trace)
    348  1.45       chs 	clrl	%sp@-			| stack adjust count
    349  1.45       chs 	moveml	#0xFFFF,%sp@-
    350  1.45       chs 	moveq	#T_TRACE,%d0
    351  1.37     itohy 
    352  1.37     itohy 	| Check PSW and see what happen.
    353  1.37     itohy 	|   T=0 S=0	(should not happen)
    354  1.37     itohy 	|   T=1 S=0	trace trap from user mode
    355  1.37     itohy 	|   T=0 S=1	trace trap on a trap instruction
    356  1.37     itohy 	|   T=1 S=1	trace trap from system mode (kernel breakpoint)
    357  1.37     itohy 
    358  1.45       chs 	movw	%sp@(FR_HW),%d1		| get PSW
    359  1.45       chs 	notw	%d1			| XXX no support for T0 on 680[234]0
    360  1.45       chs 	andw	#PSL_TS,%d1		| from system mode (T=1, S=1)?
    361  1.37     itohy 	jeq	_ASM_LABEL(kbrkpt)	|  yes, kernel brkpt
    362  1.19    jeremy 	jra	_ASM_LABEL(fault)	| no, user-mode fault
    363   1.1       gwr 
    364   1.1       gwr /*
    365   1.1       gwr  * Trap 15 is used for:
    366   1.1       gwr  *	- GDB breakpoints (in user programs)
    367   1.1       gwr  *	- KGDB breakpoints (in the kernel)
    368   1.1       gwr  *	- trace traps for SUN binaries (not fully supported yet)
    369  1.11       gwr  * User mode traps are simply passed to trap().
    370   1.1       gwr  */
    371  1.19    jeremy GLOBAL(trap15)
    372  1.45       chs 	clrl	%sp@-			| stack adjust count
    373  1.45       chs 	moveml	#0xFFFF,%sp@-
    374  1.45       chs 	moveq	#T_TRAP15,%d0
    375  1.45       chs 	btst	#5,%sp@(FR_HW)		| was supervisor mode?
    376  1.19    jeremy 	jne	_ASM_LABEL(kbrkpt)	|  yes, kernel brkpt
    377  1.19    jeremy 	jra	_ASM_LABEL(fault)	| no, user-mode fault
    378   1.1       gwr 
    379  1.19    jeremy ASLOCAL(kbrkpt)
    380  1.45       chs 	| Kernel-mode breakpoint or trace trap. (%d0=trap_type)
    381   1.1       gwr 	| Save the system sp rather than the user sp.
    382  1.45       chs 	movw	#PSL_HIGHIPL,%sr	| lock out interrupts
    383  1.45       chs 	lea	%sp@(FR_SIZE),%a6	| Save stack pointer
    384  1.45       chs 	movl	%a6,%sp@(FR_SP)		|  from before trap
    385   1.1       gwr 
    386   1.1       gwr 	| If we are not on tmpstk switch to it.
    387   1.1       gwr 	| (so debugger can change the stack pointer)
    388  1.45       chs 	movl	%a6,%d1
    389  1.45       chs 	cmpl	#_ASM_LABEL(tmpstk),%d1
    390   1.1       gwr 	jls	Lbrkpt2 		| already on tmpstk
    391   1.1       gwr 	| Copy frame to the temporary stack
    392  1.45       chs 	movl	%sp,%a0			| %a0=src
    393  1.45       chs 	lea	_ASM_LABEL(tmpstk)-96,%a1 | %a1=dst
    394  1.45       chs 	movl	%a1,%sp			| sp=new frame
    395  1.45       chs 	moveq	#FR_SIZE,%d1
    396   1.1       gwr Lbrkpt1:
    397  1.45       chs 	movl	%a0@+,%a1@+
    398  1.45       chs 	subql	#4,%d1
    399   1.1       gwr 	bgt	Lbrkpt1
    400   1.1       gwr 
    401   1.1       gwr Lbrkpt2:
    402  1.11       gwr 	| Call the trap handler for the kernel debugger.
    403   1.6       gwr 	| Do not call trap() to handle it, so that we can
    404   1.1       gwr 	| set breakpoints in trap() if we want.  We know
    405   1.1       gwr 	| the trap type is either T_TRACE or T_BREAKPOINT.
    406  1.45       chs 	movl	%d0,%sp@-		| push trap type
    407  1.19    jeremy 	jbsr	_C_LABEL(trap_kdebug)
    408  1.45       chs 	addql	#4,%sp			| pop args
    409   1.6       gwr 
    410   1.1       gwr 	| The stack pointer may have been modified, or
    411   1.1       gwr 	| data below it modified (by kgdb push call),
    412   1.1       gwr 	| so push the hardware frame at the current sp
    413   1.1       gwr 	| before restoring registers and returning.
    414  1.45       chs 	movl	%sp@(FR_SP),%a0		| modified sp
    415  1.45       chs 	lea	%sp@(FR_SIZE),%a1	| end of our frame
    416  1.45       chs 	movl	%a1@-,%a0@-		| copy 2 longs with
    417  1.45       chs 	movl	%a1@-,%a0@-		| ... predecrement
    418  1.45       chs 	movl	%a0,%sp@(FR_SP)		| sp = h/w frame
    419  1.45       chs 	moveml	%sp@+,#0x7FFF		| restore all but sp
    420  1.45       chs 	movl	%sp@,%sp		| ... and sp
    421   1.1       gwr 	rte				| all done
    422   1.1       gwr 
    423   1.1       gwr /*
    424   1.1       gwr  * Interrupt handlers.  Most are auto-vectored,
    425   1.1       gwr  * and hard-wired the same way on all sun3 models.
    426   1.1       gwr  * Format in the stack is:
    427  1.45       chs  *   %d0,%d1,%a0,%a1, sr, pc, vo
    428   1.1       gwr  */
    429   1.1       gwr 
    430   1.1       gwr /* clock: see clock.c */
    431  1.46    kleink #ifdef __ELF__
    432  1.46    kleink 	.align	4
    433  1.46    kleink #else
    434   1.1       gwr 	.align	2
    435  1.46    kleink #endif
    436  1.19    jeremy GLOBAL(_isr_clock)
    437   1.1       gwr 	INTERRUPT_SAVEREG
    438  1.19    jeremy 	jbsr	_C_LABEL(clock_intr)
    439  1.65  christos 	INTERRUPT_RESTOREREG
    440  1.19    jeremy 	jra	_ASM_LABEL(rei)
    441   1.1       gwr 
    442   1.1       gwr /*
    443   1.1       gwr  * Emulation of VAX REI instruction.
    444   1.1       gwr  *
    445   1.1       gwr  * This code is (mostly) un-altered from the hp300 code,
    446   1.1       gwr  * except that sun machines do not need a simulated SIR
    447   1.1       gwr  * because they have a real software interrupt register.
    448   1.1       gwr  *
    449   1.1       gwr  * This code deals with checking for and servicing ASTs
    450   1.1       gwr  * (profiling, scheduling) and software interrupts (network, softclock).
    451   1.1       gwr  * We check for ASTs first, just like the VAX.  To avoid excess overhead
    452   1.1       gwr  * the T_ASTFLT handling code will also check for software interrupts so we
    453   1.1       gwr  * do not have to do it here.  After identifying that we need an AST we
    454   1.1       gwr  * drop the IPL to allow device interrupts.
    455   1.1       gwr  *
    456   1.1       gwr  * This code is complicated by the fact that sendsig may have been called
    457   1.1       gwr  * necessitating a stack cleanup.
    458   1.1       gwr  */
    459   1.1       gwr 
    460  1.19    jeremy ASGLOBAL(rei)
    461   1.1       gwr #ifdef	DIAGNOSTIC
    462  1.69    andvar 	tstl	_C_LABEL(panicstr)	| have we panicked?
    463   1.1       gwr 	jne	Ldorte			| yes, do not make matters worse
    464   1.1       gwr #endif
    465  1.19    jeremy 	tstl	_C_LABEL(astpending)	| AST pending?
    466   1.1       gwr 	jeq	Ldorte			| no, done
    467   1.1       gwr Lrei1:
    468  1.45       chs 	btst	#5,%sp@			| yes, are we returning to user mode?
    469   1.1       gwr 	jne	Ldorte			| no, done
    470  1.45       chs 	movw	#PSL_LOWIPL,%sr		| lower SPL
    471  1.45       chs 	clrl	%sp@-			| stack adjust
    472  1.45       chs 	moveml	#0xFFFF,%sp@-		| save all registers
    473  1.45       chs 	movl	%usp,%a1		| including
    474  1.45       chs 	movl	%a1,%sp@(FR_SP)		|    the users SP
    475  1.45       chs 	clrl	%sp@-			| VA == none
    476  1.45       chs 	clrl	%sp@-			| code == none
    477  1.45       chs 	movl	#T_ASTFLT,%sp@-		| type == async system trap
    478  1.56   tsutsui 	pea	%sp@(12)		| fp == address of trap frame
    479  1.19    jeremy 	jbsr	_C_LABEL(trap)		| go handle it
    480  1.56   tsutsui 	lea	%sp@(16),%sp		| pop value args
    481  1.45       chs 	movl	%sp@(FR_SP),%a0		| restore user SP
    482  1.45       chs 	movl	%a0,%usp		|   from save area
    483  1.45       chs 	movw	%sp@(FR_ADJ),%d0	| need to adjust stack?
    484   1.1       gwr 	jne	Laststkadj		| yes, go to it
    485  1.45       chs 	moveml	%sp@+,#0x7FFF		| no, restore most user regs
    486  1.45       chs 	addql	#8,%sp			| toss SP and stack adjust
    487   1.1       gwr 	rte				| and do real RTE
    488   1.1       gwr Laststkadj:
    489  1.45       chs 	lea	%sp@(FR_HW),%a1		| pointer to HW frame
    490  1.45       chs 	addql	#8,%a1			| source pointer
    491  1.45       chs 	movl	%a1,%a0			| source
    492  1.45       chs 	addw	%d0,%a0			|  + hole size = dest pointer
    493  1.45       chs 	movl	%a1@-,%a0@-		| copy
    494  1.45       chs 	movl	%a1@-,%a0@-		|  8 bytes
    495  1.45       chs 	movl	%a0,%sp@(FR_SP)		| new SSP
    496  1.45       chs 	moveml	%sp@+,#0x7FFF		| restore user registers
    497  1.45       chs 	movl	%sp@,%sp		| and our SP
    498   1.1       gwr Ldorte:
    499   1.1       gwr 	rte				| real return
    500   1.1       gwr 
    501   1.1       gwr /*
    502   1.1       gwr  * Initialization is at the beginning of this file, because the
    503   1.1       gwr  * kernel entry point needs to be at zero for compatibility with
    504   1.1       gwr  * the Sun boot loader.  This works on Sun machines because the
    505   1.1       gwr  * interrupt vector table for reset is NOT at address zero.
    506   1.1       gwr  * (The MMU has a "boot" bit that forces access to the PROM)
    507   1.1       gwr  */
    508   1.1       gwr 
    509   1.1       gwr /*
    510   1.1       gwr  * Primitives
    511   1.1       gwr  */
    512   1.1       gwr 
    513   1.1       gwr /*
    514  1.51   thorpej  * Use common m68k process/lwp switch and context save subroutines.
    515   1.1       gwr  */
    516  1.51   thorpej #define FPCOPROC	/* XXX: Temp. Reqd. */
    517  1.51   thorpej #include <m68k/m68k/switch_subr.s>
    518   1.1       gwr 
    519   1.1       gwr 
    520  1.20       gwr /* suline() */
    521   1.1       gwr 
    522   1.1       gwr #ifdef DEBUG
    523   1.1       gwr 	.data
    524  1.19    jeremy ASGLOBAL(fulltflush)
    525   1.1       gwr 	.long	0
    526  1.19    jeremy ASGLOBAL(fullcflush)
    527   1.1       gwr 	.long	0
    528   1.1       gwr 	.text
    529   1.1       gwr #endif
    530   1.1       gwr 
    531   1.1       gwr ENTRY(ecacheon)
    532   1.1       gwr 	rts
    533   1.1       gwr 
    534   1.1       gwr ENTRY(ecacheoff)
    535   1.1       gwr 	rts
    536   1.1       gwr 
    537   1.1       gwr /*
    538   1.1       gwr  * Load a new CPU Root Pointer (CRP) into the MMU.
    539   1.2       gwr  *	void	loadcrp(struct mmu_rootptr *);
    540   1.1       gwr  */
    541   1.1       gwr ENTRY(loadcrp)
    542  1.45       chs 	movl	%sp@(4),%a0		| arg1: &CRP
    543  1.45       chs 	movl	#CACHE_CLR,%d0
    544  1.45       chs 	movc	%d0,%cacr		| invalidate cache(s)
    545   1.1       gwr 	pflusha				| flush entire TLB
    546  1.45       chs 	pmove	%a0@,%crp		| load new user root pointer
    547  1.45       chs 	rts
    548  1.45       chs 
    549  1.45       chs ENTRY(getcrp)
    550  1.45       chs 	movl	%sp@(4),%a0		| arg1: &crp
    551  1.45       chs 	pmove	%crp,%a0@		| *crpp = %crp
    552  1.10       gwr 	rts
    553  1.10       gwr 
    554  1.10       gwr /*
    555  1.10       gwr  * Get the physical address of the PTE for a given VA.
    556  1.10       gwr  */
    557  1.10       gwr ENTRY(ptest_addr)
    558  1.45       chs 	movl	%sp@(4),%a1		| VA
    559  1.45       chs 	ptestr	#5,%a1@,#7,%a0		| %a0 = addr of PTE
    560  1.48       scw 	movl	%a0,%d0			| Result in %d0 (not a pointer return)
    561   1.1       gwr 	rts
    562   1.1       gwr 
    563   1.1       gwr /*
    564   1.1       gwr  * _delay(unsigned N)
    565   1.1       gwr  * Delay for at least (N/256) microseconds.
    566   1.1       gwr  * This routine depends on the variable:  delay_divisor
    567   1.1       gwr  * which should be set based on the CPU clock rate.
    568  1.26       gwr  * XXX: Currently this is set based on the CPU model,
    569  1.26       gwr  * XXX: but this should be determined at run time...
    570   1.1       gwr  */
    571  1.19    jeremy GLOBAL(_delay)
    572  1.45       chs 	| %d0 = arg = (usecs << 8)
    573  1.45       chs 	movl	%sp@(4),%d0
    574  1.45       chs 	| %d1 = delay_divisor;
    575  1.45       chs 	movl	_C_LABEL(delay_divisor),%d1
    576  1.36   thorpej 	jra	L_delay			/* Jump into the loop! */
    577  1.36   thorpej 
    578  1.36   thorpej 	/*
    579  1.36   thorpej 	 * Align the branch target of the loop to a half-line (8-byte)
    580  1.36   thorpej 	 * boundary to minimize cache effects.  This guarantees both
    581  1.36   thorpej 	 * that there will be no prefetch stalls due to cache line burst
    582  1.36   thorpej 	 * operations and that the loop will run from a single cache
    583  1.36   thorpej 	 * half-line.
    584  1.36   thorpej 	 */
    585  1.46    kleink #ifdef __ELF__
    586  1.36   thorpej 	.align	8
    587  1.46    kleink #else
    588  1.46    kleink 	.align	3
    589  1.46    kleink #endif
    590   1.1       gwr L_delay:
    591  1.45       chs 	subl	%d1,%d0
    592   1.1       gwr 	jgt	L_delay
    593   1.1       gwr 	rts
    594   1.1       gwr 
    595   1.1       gwr | Define some addresses, mostly so DDB can print useful info.
    596  1.24       gwr | Not using _C_LABEL() here because these symbols are never
    597  1.24       gwr | referenced by any C code, and if the leading underscore
    598  1.24       gwr | ever goes away, these lines turn into syntax errors...
    599  1.61   tsutsui 	.set	_KERNBASE3X,KERNBASE3X
    600  1.26       gwr 	.set	_MONSTART,SUN3X_MONSTART
    601  1.26       gwr 	.set	_PROM_BASE,SUN3X_PROM_BASE
    602  1.26       gwr 	.set	_MONEND,SUN3X_MONEND
    603   1.1       gwr 
    604   1.1       gwr |The end!
    605