Home | History | Annotate | Line # | Download | only in mips
      1 /*	$NetBSD: mipsX_subr.S,v 1.116 2025/04/24 01:40:27 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2002 Wasabi Systems, Inc.
      5  * All rights reserved.
      6  *
      7  * Written by Simon Burge for Wasabi Systems, Inc.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *	This product includes software developed for the NetBSD Project by
     20  *	Wasabi Systems, Inc.
     21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22  *    or promote products derived from this software without specific prior
     23  *    written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  * POSSIBILITY OF SUCH DAMAGE.
     36  */
     37 
     38 /*
     39  * Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author)
     40  * All rights reserved.
     41  *
     42  * Redistribution and use in source and binary forms, with or without
     43  * modification, are permitted provided that the following conditions
     44  * are met:
     45  * 1. Redistributions of source code must retain the above copyright
     46  *    notice, this list of conditions and the following disclaimer.
     47  * 2. Redistributions in binary form must reproduce the above copyright
     48  *    notice, this list of conditions and the following disclaimer in the
     49  *    documentation and/or other materials provided with the distribution.
     50  * 3. All advertising materials mentioning features or use of this software
     51  *    must display the following acknowledgement:
     52  *      This product includes software developed by Jonathan R. Stone for
     53  *      the NetBSD Project.
     54  * 4. The name of the author may not be used to endorse or promote products
     55  *    derived from this software without specific prior written permission.
     56  *
     57  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
     58  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     59  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     60  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
     61  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     62  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     63  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     64  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     65  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     66  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     67  * SUCH DAMAGE.
     68  */
     69 
     70 /*
     71  * Copyright (c) 1992, 1993
     72  *	The Regents of the University of California.  All rights reserved.
     73  *
     74  * This code is derived from software contributed to Berkeley by
     75  * Digital Equipment Corporation and Ralph Campbell.
     76  *
     77  * Redistribution and use in source and binary forms, with or without
     78  * modification, are permitted provided that the following conditions
     79  * are met:
     80  * 1. Redistributions of source code must retain the above copyright
     81  *    notice, this list of conditions and the following disclaimer.
     82  * 2. Redistributions in binary form must reproduce the above copyright
     83  *    notice, this list of conditions and the following disclaimer in the
     84  *    documentation and/or other materials provided with the distribution.
     85  * 3. Neither the name of the University nor the names of its contributors
     86  *    may be used to endorse or promote products derived from this software
     87  *    without specific prior written permission.
     88  *
     89  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     90  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     91  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     92  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     93  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     94  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     95  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     96  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     97  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     98  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     99  * SUCH DAMAGE.
    100  *
    101  * Copyright (C) 1989 Digital Equipment Corporation.
    102  * Permission to use, copy, modify, and distribute this software and
    103  * its documentation for any purpose and without fee is hereby granted,
    104  * provided that the above copyright notice appears in all copies.
    105  * Digital Equipment Corporation makes no representations about the
    106  * suitability of this software for any purpose.  It is provided "as is"
    107  * without express or implied warranty.
    108  *
    109  * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
    110  *	v 1.1 89/07/11 17:55:04 nelson Exp  SPRITE (DECWRL)
    111  * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
    112  *	v 9.2 90/01/29 18:00:39 shirriff Exp  SPRITE (DECWRL)
    113  * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
    114  *	v 1.1 89/07/10 14:27:41 nelson Exp  SPRITE (DECWRL)
    115  *
    116  *	@(#)locore.s	8.5 (Berkeley) 1/4/94
    117  */
    118 
    119 #include <mips/asm.h>
    120 RCSID("$NetBSD: mipsX_subr.S,v 1.116 2025/04/24 01:40:27 riastradh Exp $")
    121 
    122 #include "opt_cputype.h"
    123 #include "opt_ddb.h"
    124 #include "opt_kgdb.h"
    125 #include "opt_mips3_wired.h"
    126 #include "opt_multiprocessor.h"
    127 #include "opt_vmswap.h"
    128 
    129 #include <sys/cdefs.h>
    130 #include <sys/endian.h>
    131 
    132 #include <mips/cpuregs.h>
    133 #if defined(MIPS3)
    134 #include <mips/cache_r4k.h>
    135 #endif
    136 #include <mips/trap.h>
    137 
    138 #include "assym.h"
    139 
    140 #if defined(MIPS64_OCTEON)
    141 #include "cpunode.h"			/* for NWDOG */
    142 #else
    143 #define NWDOG 0
    144 #endif
    145 
    146 #if defined(MIPS1) || defined(MIPS2)
    147 #error use locore_mips1.S
    148 #endif
    149 
    150 #if defined(__mips_o32)
    151 #define	RESET_EXCEPTION_LEVEL_DISABLE_INTERRUPTS(reg) \
    152 	mtc0 zero, MIPS_COP_0_STATUS
    153 #define	SET_EXCEPTION_LEVEL(reg) \
    154 	li reg, MIPS_SR_EXL; mtc0 reg, MIPS_COP_0_STATUS
    155 #else
    156 #define	RESET_EXCEPTION_LEVEL_DISABLE_INTERRUPTS(reg) \
    157 	li reg, MIPS_SR_KX; mtc0 reg, MIPS_COP_0_STATUS
    158 #define	SET_EXCEPTION_LEVEL(reg) \
    159 	li reg, MIPS_SR_EXL | MIPS_SR_KX; mtc0 reg, MIPS_COP_0_STATUS
    160 #endif
    161 
    162 #ifdef MIPS3_LOONGSON2
    163 #define KERN_ENTRY_ERRATA \
    164 	li k0, MIPS_DIAG_BTB_CLEAR|MIPS_DIAG_RAS_DISABLE; mtc0 k0, MIPS_COP_0_DIAG
    165 #else
    166 #define KERN_ENTRY_ERRATA /* nothing */
    167 #endif
    168 
    169 #if MIPS1
    170 #error This file can not be compiled with MIPS1 defined
    171 #endif
    172 
    173 #if (MIPS3 + MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) != 1
    174 # error  Only one of MIPS{3,32,32R2,64,64R2} can be defined
    175 #endif
    176 
    177 #if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
    178 #define MIPSNN
    179 #if (MIPS32R2 + MIPS64R2) > 0
    180 #define MIPSNNR2
    181 #endif
    182 #endif
    183 
    184 /*
    185  * Use 64bit cp0 instructions?
    186  */
    187 #if (MIPS3 + MIPS64 + MIPS64R2) > 0
    188 #define	USE_64BIT_INSTRUCTIONS
    189 #define	USE_64BIT_CP0_FUNCTIONS
    190 #elif (MIPS32 + MIPS32R2) > 0
    191 #ifdef _LP64
    192 #error	MIPS32 and MIPS32R2 can't run 64-bit kernels.
    193 #endif
    194 #undef	USE_64BIT_INSTRUCTIONS
    195 #undef	USE_64BIT_CP0_FUNCTIONS
    196 #else
    197 #error	One of MIPS{3,32,32R2,64,64R2} must be defined
    198 #endif
    199 
    200 #ifdef _LP64
    201 #define	_SLLV		dsllv
    202 #else
    203 #define	_SLLV		sllv
    204 #endif
    205 
    206 #if defined(USE_64BIT_CP0_FUNCTIONS)
    207 #define	_SLL		dsll
    208 #define	_SRL		dsrl
    209 #define	_SRA		dsra
    210 #define	_EXT		dext
    211 #define	_INS		dins
    212 #define	WIRED_SHIFT	34
    213 #define WIRED_POS	30
    214 #define	PG_V_LSHIFT	(63 - V_MIPS3_PG_V)
    215 #define	PG_V_RSHIFT	63
    216 #else
    217 #define	_SLL		sll
    218 #define	_SRL		srl
    219 #define	_SRA		sra
    220 #define	_EXT		ext
    221 #define	_INS		ins
    222 #define	WIRED_SHIFT	2
    223 #define WIRED_POS	30
    224 #define	PG_V_LSHIFT	(31 - V_MIPS3_PG_V)
    225 #define	PG_V_RSHIFT	31
    226 #endif
    227 
    228 /*
    229  * Use correct-sized m?c0/dm?c0 opcodes.
    230  */
    231 #if defined(USE_64BIT_CP0_FUNCTIONS)
    232 #define	_MFC0	dmfc0
    233 #define	_MTC0	dmtc0
    234 #else
    235 #define	_MFC0	mfc0
    236 #define	_MTC0	mtc0
    237 #endif
    238 
    239 
    240 /*
    241  * Set ISA level for the assembler.
    242  */
    243 #if defined(MIPS3)
    244 	.set	mips3
    245 #endif
    246 
    247 #if defined(MIPS32)
    248 	.set	mips32
    249 #endif
    250 
    251 #if defined(MIPS32R2)
    252 	.set	mips32r2
    253 #endif
    254 
    255 #if defined(MIPS64)
    256 	.set	mips64
    257 #endif
    258 
    259 #if defined(MIPS64R2)
    260 	.set	mips64r2
    261 #endif
    262 
    263 
    264 /*
    265  * CPP function renaming macros.
    266  */
    267 
    268 #if defined(MIPS3_LOONGSON2)
    269 #define	MIPSX(name)	__CONCAT(loongson2_,name)
    270 #elif defined(MIPS3)
    271 #define	MIPSX(name)	__CONCAT(mips3_,name)
    272 #endif
    273 
    274 #if defined(MIPS32)
    275 #define	MIPSX(name)	__CONCAT(mips32_,name)
    276 #endif
    277 
    278 #if defined(MIPS32R2)
    279 #define	MIPSX(name)	__CONCAT(mips32r2_,name)
    280 #endif
    281 
    282 #if defined(MIPS64)
    283 #define	MIPSX(name)	__CONCAT(mips64_,name)
    284 #endif
    285 
    286 #if defined(MIPS64R2)
    287 #define	MIPSX(name)	__CONCAT(mips64r2_,name)
    288 #endif
    289 
    290 #define	_VECTOR_END(name)	VECTOR_END(name)
    291 
    292 /*
    293  * XXX We need a cleaner way of handling the instruction hazards of
    294  * the various processors.  Here are the relevant rules for the QED 52XX:
    295  *	tlbw[ri]	-- two integer ops beforehand
    296  *	tlbr		-- two integer ops beforehand
    297  *	tlbp		-- two integer ops beforehand
    298  *	mtc0	[PageMask,EntryHi,Cp0] -- two integer ops afterwards
    299  *	changing JTLB	-- two integer ops afterwards
    300  *	mtc0	[EPC,ErrorEPC,Status] -- two int ops afterwards before eret
    301  *	config.k0	-- five int ops before kseg0, ckseg0 memref
    302  *
    303  * For the IDT R4000, some hazards are:
    304  *	mtc0/mfc0	one integer op before and after
    305  *	tlbp		-- one integer op afterwards
    306  * Obvious solution is to take least common denominator.
    307  *
    308  * For the Toshiba R5900, TX79:
    309  *	mtc0		following sync.p
    310  *	tlbw[ri], tlbp	following sync.p or eret
    311  * for those CPU, define COP0_SYNC as sync.p
    312  */
    313 
    314 
    315 /*
    316  *============================================================================
    317  *
    318  *  MIPS III ISA support, part 1: locore exception vectors.
    319  *  The following code is copied to the vector locations to which
    320  *  the CPU jumps in response to an exception or a TLB miss.
    321  *
    322  *============================================================================
    323  */
    324 	.set	noreorder
    325 
    326 /*
    327  * TLB handling data.   'CPUVAR(PMAP_SEG0TAB)' points to the base of the segment
    328  * table.   this is read and written by C code in mips_machdep.c.
    329  *
    330  * XXX: use linear mapped PTs at fixed VA in kseg2 in the future?
    331  */
    332 	.text
    333 
    334 
    335 /*
    336  * some useful labels for debugging
    337  */
    338 .global	mips_kseg0
    339 .equiv	mips_kseg0,		MIPS_KSEG0_START
    340 .global	mips_kseg1
    341 .equiv	mips_kseg1,		MIPS_KSEG1_START
    342 .global	mips_kseg2
    343 .equiv	mips_kseg2,		MIPS_KSEG2_START
    344 .global	mips_xkphys
    345 .equiv	mips_xkphys,		MIPS_XKPHYS_START
    346 .global	mips_xkphys_u
    347 .equiv	mips_xkphys_u,		MIPS_XKPHYS_UNCACHED
    348 .global	mips_xkphys_cca3
    349 .equiv	mips_xkphys_cca3,	MIPS_XKPHYS_CCA3
    350 .global	mips_xkphys_cca4
    351 .equiv	mips_xkphys_cca4,	MIPS_XKPHYS_CCA4
    352 .global	mips_xkseg
    353 .equiv	mips_xkseg,		MIPS_XKSEG_START
    354 
    355 
    356 /*
    357  *----------------------------------------------------------------------------
    358  *
    359  * mipsN_tlb_miss --
    360  *
    361  *	Vector code for the TLB-miss exception vector 0x80000000
    362  *	on an r4000.
    363  *
    364  * This code is copied to the TLB exception vector address to
    365  * handle TLB translation misses.
    366  * NOTE: This code should be relocatable and max 32 instructions!!!
    367  *
    368  * Don't check for invalid pte's here. We load them as well and
    369  * let the processor trap to load the correct value after service.
    370  *
    371  * Loongson2 processors don't have separate tlbmiss and xtlbmiss handlers;
    372  * so we have to check for useg addresses in tlb_miss. The good news is that
    373  * we can use 64 instructions from tlbmiss instead of 32.
    374  *
    375  *----------------------------------------------------------------------------
    376  */
    377 #ifdef MIPS3_LOONGSON2
    378 /* this loongson2-specific part is almost a copy of xtlb_miss */
    379 VECTOR(MIPSX(tlb_miss), unknown)
    380 	.set	noat
    381 	dmfc0	k0, MIPS_COP_0_BAD_VADDR	#00: k0=bad address
    382 #ifdef _LP64
    383 	nop					#01: nop
    384 	PTR_SRL k1, k0, 31			#02: clear useg bits
    385 	beqz	k1, 2f				#03: k1==0 -> useg address
    386 	 PTR_SLL k1, k0, 2			#0x: clear top bits
    387 	PTR_SRL k1, XSEGSHIFT+XSEGLENGTH+2	#04: clear valid bits
    388 	bnez	k1, MIPSX(nopagetable)		#05: not legal address
    389 	 PTR_SRA k0, XSEGSHIFT - PTR_SCALESHIFT #06: k0=seg offset (almost)
    390 	bgez	k0, 1f				#07: k0<0 -> kernel fault
    391 	 lui	k1, %hi(CPUVAR(PMAP_SEGTAB))	#08: k1=hi of segtab
    392 	PTR_ADDI k1,  1 << PTR_SCALESHIFT	#09: kernel segtab entry
    393 1:
    394 	andi	k0, (NSEGPG-1)<<PTR_SCALESHIFT	#0a: k0=seg offset (mask 0x3)
    395 	PTR_L	k1, %lo(CPUVAR(PMAP_SEGTAB))(k1)#0b: k1=segment tab
    396 	PTR_ADDU k1, k0				#0c: k1=seg entry address
    397 	dmfc0	k0, MIPS_COP_0_BAD_VADDR	#0d: k0=bad address (again)
    398 	PTR_L	k1, 0(k1)			#0e: k1=seg entry
    399 	b	MIPSX(tlb_miss_common)		#0f
    400 	 PTR_SRL k0, SEGSHIFT - PTR_SCALESHIFT	#10: k0=seg offset (almost)
    401 #endif /* LP64 */
    402 2: /* handle useg addresses */
    403 	lui	k1, %hi(CPUVAR(PMAP_SEG0TAB))	#11: k1=hi of seg0tab
    404 	dsrl	k0, 31				#12: clear low 31 bits
    405 	bnez	k0, MIPSX(nopagetable)		#13: not legal address
    406 	 PTR_L	k1, %lo(CPUVAR(PMAP_SEG0TAB))(k1)#14: k1=segment tab base
    407 	dmfc0	k0, MIPS_COP_0_BAD_VADDR	#15: k0=bad address (again)
    408 	nop					#16
    409 	b	MIPSX(tlb_miss_common)		#17
    410 	 PTR_SRL k0, 1*(PGSHIFT-PTR_SCALESHIFT)+(PGSHIFT-2) #18: k0=seg offset (almost)
    411 _VECTOR_END(MIPSX(tlb_miss))
    412 /* dummy xtlb_miss (also a placeholder for tlb_miss_common) */
    413 VECTOR(MIPSX(xtlb_miss), unknown)
    414 	lui	k0, %hi(_C_LABEL(panic))	#00
    415 	addiu	k0, %lo(_C_LABEL(panic))	#01
    416 	lui	a0, %hi(loongson2_xtlb_miss_str) #02
    417 	jr	k0				#03
    418 	 addiu	a0, %lo(loongson2_xtlb_miss_str) #04
    419 #else /* !MIPS3_LOONGSON2 */
    420 VECTOR(MIPSX(tlb_miss), unknown)
    421 	.set	noat
    422 	_MFC0	k0, MIPS_COP_0_BAD_VADDR	#00: k0=bad address
    423 	lui	k1, %hi(CPUVAR(PMAP_SEG0TAB))	#01: k1=hi of seg0tab
    424 #ifdef _LP64
    425 	bltz	k0, MIPSX(nopagetable)		#02: k0<0 -> kernel access
    426 #ifdef MIPSNNR2
    427 	 _EXT	k0, k0, SEGSHIFT, SEGLENGTH	#03: k0=seg index
    428 #else
    429 	 PTR_SRA k0, SEGSHIFT - PTR_SCALESHIFT	#03: k0=seg offset (almost)
    430 #endif
    431 #else
    432 	bgez	k0, 1f				#02: k0<0 -> kernel access
    433 #ifdef MIPSNNR2
    434 	 _EXT	k0, k0, SEGSHIFT, SEGLENGTH	#03: k0=seg index
    435 #else
    436 	 PTR_SRA k0, SEGSHIFT - PTR_SCALESHIFT	#03: k0=seg offset (almost)
    437 #endif
    438 	PTR_ADDU k1, 1 << PTR_SCALESHIFT	#04: fetch kernel segtab
    439 1:
    440 #endif
    441 	PTR_L	k1, %lo(CPUVAR(PMAP_SEG0TAB))(k1)#05: k1=seg0tab
    442 #endif /* !MIPS3_LOONGSON2 */
    443 MIPSX(tlb_miss_common):
    444 #ifdef _LP64
    445 	beqz	k1, MIPSX(nopagetable)		#06: is there a pagetable?
    446 #endif
    447 	/* the next instruction might be in a delay slot */
    448 #ifdef MIPSNNR2
    449 	_INS	k1, k0, PTR_SCALESHIFT, SEGLENGTH #07: k1=seg entry address
    450 #else
    451 	andi	k0, (NSEGPG-1)<<PTR_SCALESHIFT	#07: k0=seg offset (mask 0x3)
    452 	PTR_ADDU k1, k0				#08: k1=seg entry address
    453 #endif
    454 	PTR_L	k1, 0(k1)			#09: k1=seg entry
    455 	_MFC0	k0, MIPS_COP_0_BAD_VADDR	#0a: k0=bad address (again)
    456 	beqz	k1, MIPSX(nopagetable)		#0b: ==0 -- no page table
    457 	 # delay slot varies
    458 #if (PGSHIFT & 1)
    459 #ifdef MIPSNNR2
    460 	 _EXT	k0, k0, PGSHIFT, PTPLENGTH	#0c: delay slot: page index
    461 	_INS	k1, k0, PTPSHIFT, PTPLENGTH	#0d: k1=pte address
    462 #else
    463 	 PTR_SRL k0, PGSHIFT - PTPSHIFT		#0c: k0=VPN (aka va>>10)
    464 	andi	k0, (NPTEPG-1) << PTPSHIFT	#0d: k0=page table offset
    465 	PTR_ADDU k1, k0				#0e: k1=pte address
    466 #endif
    467 	INT_L	k0, 0(k1)			#0f: k0=lo0 pte
    468 #ifdef MIPSNNR2
    469 	_EXT	k0, k0, 0, WIRED_POS		#10: chop top 2 bits
    470 #else
    471 	_SLL	k0, WIRED_SHIFT			#10: chop top 2 bits (part 1a)
    472 	_SRL	k0, WIRED_SHIFT			#11: chop top 2 bits (part 1b)
    473 #endif
    474 	INT_ADDU k1, k0, MIPS3_PG_NEXT		#12: k1=lo1 pte
    475 #else /* (PGSHIFT & 1) == 0 */
    476 	 PTR_SRL k0, PGSHIFT - PTPSHIFT		#0c: k0=VPN (aka va>>10) --ds--
    477 	andi	k0, (NPTEPG/2-1) << (PTPSHIFT+1)#0d: k0=page table offset
    478 	PTR_ADDU k1, k0				#0e: k1=pte address
    479 #ifdef USE_64BIT_CP0_FUNCTIONS
    480 	ld	k0, 0(k1)			#0f: load both ptes
    481 #ifdef MIPSNNR2
    482 	_EXT	k1, k0, 32*_QUAD_HIGHWORD, WIRED_POS	#10: get lo1 pte
    483 	_EXT	k0, k0, 32*_QUAD_LOWWORD, WIRED_POS	#11: get lo0 pte
    484 #else
    485 	_SLL	k1, k0, WIRED_SHIFT - 32*_QUAD_HIGHWORD	#10: get lo1 pte (1a)
    486 	_SLL	k0, k0, WIRED_SHIFT - 32*_QUAD_LOWWORD	#11: get lo0 pte (2a)
    487 	_SRL	k0, WIRED_SHIFT			#12: chopped top 2 bits (1b)
    488 	_SRL	k1, WIRED_SHIFT			#13: chopped top 2 bits (2b)
    489 #endif
    490 #else
    491 	INT_L	k0, 0(k1)			#0f: k0=lo0 pte
    492 	INT_L	k1, 4(k1)			#10: k1=lo1 pte
    493 	_SLL	k0, WIRED_SHIFT			#11: chop top 2 bits (part 1a)
    494 	_SLL	k1, WIRED_SHIFT			#12: chop top 2 bits (part 2a)
    495 	_SRL	k0, WIRED_SHIFT			#13: chop top 2 bits (part 1b)
    496 	_SRL	k1, WIRED_SHIFT			#14: chop top 2 bits (part 2b)
    497 #endif
    498 #endif /* PGSHIFT & 1 */
    499 	_MTC0	k0, MIPS_COP_0_TLB_LO0		#15: lo0 is loaded
    500 	_MTC0	k1, MIPS_COP_0_TLB_LO1		#16: lo1 is loaded
    501 	sll	$0, $0, 3			#17: standard nop (ehb)
    502 #ifdef MIPS3
    503 	nop					#18: extra nop for QED5230
    504 #endif
    505 	tlbwr					#19: write to tlb
    506 	sll	$0, $0, 3			#1a: standard nop (ehb)
    507 #if (MIPS3 + MIPS64 + MIPS64R2) > 0
    508 	lui	k1, %hi(CPUVAR(EV_TLBMISSES))	#1b: k1=hi of tlbmisses
    509 	REG_L	k0, %lo(CPUVAR(EV_TLBMISSES))(k1) #1c
    510 	REG_ADDU k0, 1				#1d
    511 	REG_S	k0, %lo(CPUVAR(EV_TLBMISSES))(k1) #1e
    512 #endif
    513 	eret					#1f: return from exception
    514 	.set	at
    515 #ifdef MIPS3_LOONGSON2
    516 _VECTOR_END(MIPSX(xtlb_miss))
    517 #else
    518 _VECTOR_END(MIPSX(tlb_miss))
    519 #endif
    520 
    521 #ifndef MIPS3_LOONGSON2
    522 #if defined(USE_64BIT_CP0_FUNCTIONS)
    523 /*
    524  * mipsN_xtlb_miss routine
    525  *
    526  *	Vector code for the XTLB-miss exception vector 0x80000080 on an r4000.
    527  *
    528  * This code is copied to the XTLB exception vector address to
    529  * handle TLB translation misses while in 64-bit mode.
    530  * NOTE: This code should be relocatable and max 32 instructions!!!
    531  *
    532  * Note that we do not support the full size of the PTEs, relying
    533  * on appropriate truncation/sign extension.
    534  *
    535  * Don't check for invalid pte's here. We load them as well and
    536  * let the processor trap to load the correct value after service.
    537  *
    538  * Loongson2 CPUs don't have separate tlbmiss and xtlbmiss, so we have
    539  * to check the address size here and branch to tlb_miss if needed.
    540  */
    541 VECTOR(MIPSX(xtlb_miss), unknown)
    542 	.set	noat
    543 	dmfc0	k0, MIPS_COP_0_BAD_VADDR	#00: k0=bad address
    544 #ifdef _LP64
    545 	MFC0_HAZARD				#01: nop
    546 	PTR_SLL	k1, k0, 2			#02: clear top bits
    547 	PTR_SRL k1, XSEGSHIFT+XSEGLENGTH+2	#03: clear valid bits
    548 	bnez	k1, MIPSX(nopagetable)		#04: not legal address
    549 	 PTR_SRA k0, XSEGSHIFT - PTR_SCALESHIFT	#05: k0=seg offset (almost)
    550 	bgez	k0, 1f				#06: k0<0 -> kernel fault
    551 	 lui	k1, %hi(CPUVAR(PMAP_SEGTAB))	#07: k1=hi of segtab
    552 	PTR_ADDU k1, 1 << PTR_SCALESHIFT	#08: advance to kernel segtab
    553 1:
    554 	PTR_L	k1, %lo(CPUVAR(PMAP_SEGTAB))(k1)#09: k1=segment tab
    555 	andi	k0, (NSEGPG-1)<<PTR_SCALESHIFT	#0a: k0=seg offset (mask 0x3)
    556 	PTR_ADDU k1, k0				#0b: k1=seg entry address
    557 	dmfc0	k0, MIPS_COP_0_BAD_VADDR	#0c: k0=bad address (again)
    558 	PTR_L	k1, 0(k1)			#0d: k1=seg entry address
    559 #else
    560 	lui	k1, %hi(CPUVAR(PMAP_SEG0TAB))	#02: k1=hi of seg0tab
    561 	bgez	k0, 1f				#03: k0<0 -> kernel access
    562 	 dsra	k0, 31				#04: clear low 31 bits
    563 	PTR_ADDU k1, 1 << PTR_SCALESHIFT	#05
    564 1:
    565 	PTR_ADDU k0, 1				#06
    566 	sltiu	k0, k0, 2			#07
    567 	beqz	k0, MIPSX(nopagetable)		#08: not legal address
    568 	 nop					#09
    569 	dmfc0	k0, MIPS_COP_0_BAD_VADDR	#0a: k0=bad address (again)
    570 	PTR_L	k1, %lo(CPUVAR(PMAP_SEG0TAB))(k1)#0b: k1=segment tab base
    571 #endif /* _LP64 */
    572 	b	MIPSX(tlb_miss_common)		#0e/0c
    573 #ifdef MIPSNNR2
    574 	 _EXT	k0, k0, SEGSHIFT, SEGLENGTH	#0f/0d: k0=seg index
    575 #else
    576 	 PTR_SRL k0, SEGSHIFT - PTR_SCALESHIFT	#0f/0d: k0=seg offset (almost)
    577 #endif
    578 	.set	at
    579 _VECTOR_END(MIPSX(xtlb_miss))
    580 #else
    581 	.space	128
    582 #endif /* USE_64BIT_CP0_FUNCTIONS */
    583 #endif /* !MIPS3_LOONGSON2 */
    584 
    585 /*
    586  * Vector to real handler in KSEG1.
    587  */
    588 VECTOR(MIPSX(cache), unknown)
    589 	PTR_LA	k0, _C_LABEL(MIPSX(cache_exception))	#00
    590 	li	k1, MIPS_PHYS_MASK			#01
    591 	and	k0, k1					#02
    592 	li	k1, MIPS_KSEG1_START			#03
    593 	or	k0, k1					#04
    594 	lui	k1, %hi(CPUVAR(CURLWP))			#05: k1=hi of curlwp
    595 	jr	k0					#06
    596 	 PTR_L	k1, %lo(CPUVAR(CURLWP))(k1)		#07: k1=lo of curlwp
    597 _VECTOR_END(MIPSX(cache))
    598 
    599 /*
    600  *----------------------------------------------------------------------------
    601  *
    602  * mipsN_exception
    603  *
    604  *	Vector code for the general exception vector 0x80000180
    605  *	on an r4000 or r4400.
    606  *
    607  * This code is copied to the general exception vector address to
    608  * handle most exceptions.
    609  * NOTE: This code should be relocatable and max 32 instructions!!!
    610  *----------------------------------------------------------------------------
    611  */
    612 VECTOR(MIPSX(exception), unknown)
    613 /*
    614  * Find out what mode we came from and jump to the proper handler.
    615  */
    616 	.set	noat
    617 	mfc0	k0, MIPS_COP_0_STATUS		#00: get the status register
    618 	mfc0	k1, MIPS_COP_0_CAUSE		#01: get the cause register
    619 	and	k0, MIPS3_SR_KSU_USER		#02: test for user mode
    620 						#    sneaky but the bits are
    621 						#    with us........
    622 	sll	k0, 3				#03: shift user bit for cause index
    623 	and	k1, MIPS3_CR_EXC_CODE		#04: mask out the cause bits.
    624 	or	k1, k0				#05: change index to user table
    625 #if PTR_SCALESHIFT > MIPS_CR_EXC_CODE_SHIFT
    626 	PTR_SLL	k1, PTR_SCALESHIFT - MIPS_CR_EXC_CODE_SHIFT
    627 #endif
    628 	PTR_LA	k0, MIPSX(excpt_sw)		#06: get base of the jump table
    629 	PTR_ADDU k0, k1				#08: get the address of the
    630 						#  function entry.  Note that
    631 						#  the cause is already
    632 						#  shifted left by 2 bits so
    633 						#  we dont have to shift.
    634 	PTR_L	k0, 0(k0)			#09: get the function address
    635 	lui	k1, %hi(CPUVAR(CURLWP))		#0a: k1=hi of curlwp
    636 	jr	k0				#0b: jump to the function
    637 	 PTR_L	k1, %lo(CPUVAR(CURLWP))(k1)	#0c: k1=lo of curlwp
    638 	nop					#0d
    639 	nop					#0e
    640 #ifndef _LP64
    641 	nop					#0f
    642 #endif
    643 	.p2align 4
    644 MIPSX(nopagetable):
    645 	lui	k1, %hi(CPUVAR(CURLWP))		#10: k1=hi of curlwp
    646 	j	MIPSX(slowfault)		#11: no page table present
    647 	 PTR_L	k1, %lo(CPUVAR(CURLWP))(k1)	#12: k1=lo of curlwp
    648 	nop					#13: branch delay slot
    649 	.set	at
    650 _VECTOR_END(MIPSX(exception))
    651 
    652 /*
    653  * Handle MIPS32/MIPS64 style interrupt exception vector.
    654  */
    655 VECTOR(MIPSX(intr), unknown)
    656 	.set	noat
    657 	mfc0	k0, MIPS_COP_0_STATUS		#00: get the status register
    658 	MFC0_HAZARD				#01: stall
    659 	and	k0, k0, MIPS3_SR_KSU_USER	#02: test for user mode
    660 	bnez	k0, 1f				#03: yep, do it
    661 	 nop					#04:  branch deay
    662 	j	MIPSX(kern_intr)		#05: nope, kernel intr
    663 1:
    664 	lui	k1, %hi(CPUVAR(CURLWP))		#06: k1=hi of curlwp
    665 	j	MIPSX(user_intr)		#07: user intr
    666 	 PTR_L	k1, %lo(CPUVAR(CURLWP))(k1)	#08: k1=lo of curlwp
    667 	.set	at
    668 _VECTOR_END(MIPSX(intr))
    669 
    670 /*----------------------------------------------------------------------------
    671  *
    672  * mipsN_slowfault
    673  *
    674  * Alternate entry point into the mipsN_user_gen_exception or
    675  * mipsN_kern_gen_exception, when the UTLB miss handler couldn't
    676  * find a TLB entry.
    677  *
    678  * Find out what mode we came from and call the appropriate handler.
    679  *
    680  *----------------------------------------------------------------------------
    681  */
    682 	.org	((. + 31) & ~31) + 12
    683 MIPSX(slowfault):
    684 	.set	noat
    685 	mfc0	k0, MIPS_COP_0_STATUS
    686 	MFC0_HAZARD
    687 	and	k0, MIPS3_SR_KSU_USER
    688 	bnez	k0, _C_LABEL(MIPSX(user_gen_exception))
    689 	 nop
    690 	.set	at
    691 /*
    692  * Fall through ...
    693  */
    694 
    695 /*
    696  * mipsN_kern_gen_exception
    697  *
    698  * Handle an exception during kernel mode.
    699  * Build trapframe on stack to hold interrupted kernel context, then
    700  * call trap() to process the condition.
    701  *
    702  * trapframe is pointed to by the 5th arg and a dummy sixth argument is used
    703  * to avoid alignment problems
    704  * {
    705  *	register_t cf_args[4 + 1];
    706  *	register_t cf_pad;		(for 8 word alignment)
    707  *	register_t cf_sp;
    708  *	register_t cf_ra;
    709  *	struct reg cf_tf;
    710  * };
    711  */
    712 NESTED_NOPROFILE(MIPSX(kern_gen_exception), KERNFRAME_SIZ, ra)
    713 	.set	noat
    714 	.mask	0x80000000, -4
    715 #if defined(PARANOIA)
    716 	PTR_L	k0, L_PCB(MIPS_CURLWP)
    717 	slt	k0, k0, sp		# k0 = L_PCB(MIPS_CURLWP) < sp
    718 1:	beqz	k0, 1b			# loop forever if false
    719 	 nop
    720 	PTR_L	k0, L_PCB(MIPS_CURLWP)
    721 	PTR_ADDU k0, USPACE
    722 	slt	k0, sp, k0		# k0 = sp < L_PCB(MIPS_CURLWP) + USPACE
    723 2:	beqz	k0, 2b			# loop forever if false
    724 	 nop
    725 #endif /* PARANOIA */
    726 /*
    727  * Save the relevant kernel registers onto the stack.
    728  * We don't need to save s0 - s8, sp and gp because
    729  * the compiler does it for us.
    730  */
    731 	PTR_SUBU sp, KERNFRAME_SIZ
    732 	REG_S	AT, TF_BASE+TF_REG_AST(sp)
    733 	REG_S	v0, TF_BASE+TF_REG_V0(sp)
    734 	REG_S	v1, TF_BASE+TF_REG_V1(sp)
    735 	mflo	v0
    736 	mfhi	v1
    737 	REG_S	a0, TF_BASE+TF_REG_A0(sp)
    738 	REG_S	a1, TF_BASE+TF_REG_A1(sp)
    739 	REG_S	a2, TF_BASE+TF_REG_A2(sp)
    740 	REG_S	a3, TF_BASE+TF_REG_A3(sp)
    741 	mfc0	a0, MIPS_COP_0_STATUS		# 1st arg is STATUS
    742 	REG_S	t0, TF_BASE+TF_REG_T0(sp)
    743 	REG_S	t1, TF_BASE+TF_REG_T1(sp)
    744 	REG_S	t2, TF_BASE+TF_REG_T2(sp)
    745 	REG_S	t3, TF_BASE+TF_REG_T3(sp)
    746 	mfc0	a1, MIPS_COP_0_CAUSE		# 2nd arg is CAUSE
    747 	REG_S	ta0, TF_BASE+TF_REG_TA0(sp)
    748 	REG_S	ta1, TF_BASE+TF_REG_TA1(sp)
    749 	REG_S	ta2, TF_BASE+TF_REG_TA2(sp)
    750 	REG_S	ta3, TF_BASE+TF_REG_TA3(sp)
    751 	_MFC0	a2, MIPS_COP_0_BAD_VADDR	# 3rd arg is fault address
    752 #ifdef DDB
    753 	REG_S	t8, TF_BASE+TF_REG_T8(sp)	# is MIPS_CURLWP
    754 #endif
    755 	REG_S	t9, TF_BASE+TF_REG_T9(sp)
    756 	REG_S	ra, TF_BASE+TF_REG_RA(sp)
    757 	REG_S	a0, TF_BASE+TF_REG_SR(sp)
    758 	_MFC0	a3, MIPS_COP_0_EXC_PC		# 4th arg is exception PC
    759 	REG_S	v0, TF_BASE+TF_REG_MULLO(sp)
    760 	REG_S	v1, TF_BASE+TF_REG_MULHI(sp)
    761 	REG_S	a3, TF_BASE+TF_REG_EPC(sp)
    762 	REG_S	a1, TF_BASE+TF_REG_CAUSE(sp)
    763 #if defined(DDB) || defined(KGDB)
    764 	REG_S	s0, TF_BASE+TF_REG_S0(sp)
    765 	REG_S	s1, TF_BASE+TF_REG_S1(sp)
    766 	REG_S	s2, TF_BASE+TF_REG_S2(sp)
    767 	REG_S	s3, TF_BASE+TF_REG_S3(sp)
    768 	REG_S	s4, TF_BASE+TF_REG_S4(sp)
    769 	REG_S	s5, TF_BASE+TF_REG_S5(sp)
    770 	REG_S	s6, TF_BASE+TF_REG_S6(sp)
    771 	REG_S	s7, TF_BASE+TF_REG_S7(sp)
    772 	PTR_ADDU v0, sp, KERNFRAME_SIZ
    773 	REG_S	v0, TF_BASE+TF_REG_SP(sp)
    774 	REG_S	s8, TF_BASE+TF_REG_S8(sp)
    775 	REG_S	gp, TF_BASE+TF_REG_GP(sp)
    776 #endif
    777 #if defined(__mips_o32) || defined(__mips_o64)
    778 	PTR_ADDU v0, sp, TF_BASE
    779 	REG_S	v0, KERNFRAME_ARG5(sp)		# 5th arg is p. to trapframe
    780 #endif
    781 #if defined(__mips_n32) || defined(__mips_n64)
    782 	PTR_ADDU a4, sp, TF_BASE		# 5th arg is p. to trapframe
    783 #endif
    784 #ifdef PARANOIA
    785 	/*
    786 	 * save PPL in trapframe
    787 	 */
    788 	PTR_L	t0, L_CPU(MIPS_CURLWP)
    789 	INT_L	t1, CPU_INFO_CPL(t0)		# get current priority level
    790 	INT_S	t1, TF_BASE+TF_PPL(sp)		# save priority level
    791 #endif /* PARANOIA */
    792 
    793 #if defined(__mips_o32) && (defined(DDB) || defined(DEBUG) || defined(KGDB))
    794 	PTR_ADDU v0, sp, KERNFRAME_SIZ
    795 	REG_S	v0, KERNFRAME_SP(sp)
    796 #endif
    797 
    798 #ifdef PARANOIA
    799 	/*
    800 	 * Verify our existing interrupt level.
    801 	 */
    802 	jal	_C_LABEL(splcheck)
    803 	 nop
    804 #endif /* PARANOIA */
    805 
    806 	/*
    807 	 * We need to find out if this was due to a T_BREAK and if so
    808 	 * turn off interrupts in addition to clearing the exception level.
    809 	 */
    810 	li	v1, MIPS_SR_INT_IE << T_BREAK	# make a mask of T_BREAK
    811 	srl	t0, a1, MIPS_CR_EXC_CODE_SHIFT	# shift exc code to low 5 bits
    812 	srl	v1, t0				# shift break mask using it
    813 	and	v1, MIPS_SR_INT_IE		# restrict to IE bit
    814 	or	v1, MIPS_SR_EXL			# or in EXL bit
    815 	and	v1, a0				# extract bits from status
    816 	xor	v0, a0, v1 			# generate new status
    817 	mtc0	v0, MIPS_COP_0_STATUS		# update.
    818 	COP0_SYNC
    819 #ifdef MIPS3
    820 	nop
    821 	nop
    822 	nop
    823 #endif
    824 	/*
    825 	 * Call the trap handler.
    826 	 */
    827 	jal	_C_LABEL(trap)
    828 	 REG_S	a3, KERNFRAME_RA(sp)		# for debugging
    829 
    830 	/*
    831 	 * Restore registers and return from the exception.
    832 	 */
    833 	RESET_EXCEPTION_LEVEL_DISABLE_INTERRUPTS(v0)
    834 	COP0_SYNC
    835 #ifdef MIPS3
    836 	nop					# 3 nop delay
    837 	nop
    838 	nop
    839 #endif
    840 	REG_L	a0, TF_BASE+TF_REG_SR(sp)	# get SR with EXL set
    841 	mtc0	a0, MIPS_COP_0_STATUS		# restore the SR, disable intrs
    842 	COP0_SYNC
    843 
    844 	/*
    845 	 * Start of common kernel exception return code for both
    846 	 * mipxN_kern_gen_exception and mipsN_kern_intr.
    847 	 */
    848 MIPSX(kern_return):
    849 	REG_L	t0, TF_BASE+TF_REG_MULLO(sp)
    850 	REG_L	t1, TF_BASE+TF_REG_MULHI(sp)
    851 	REG_L	k1, TF_BASE+TF_REG_EPC(sp)	# might be changed inside trap
    852 	mtlo	t0
    853 	mthi	t1
    854 
    855 #ifdef PARANOIA
    856 	INT_L	t2, TF_BASE+TF_PPL(sp)		# get saved priority level
    857 	PTR_L	t0, L_CPU(MIPS_CURLWP)
    858 	INT_L	t1, CPU_INFO_CPL(t0)		# get current priority level
    859 11:	bne	t2, t1, 11b			# loop forever if unequal
    860 	 nop
    861 
    862 	/*
    863 	 * Verify our existing interrupt level.
    864 	 */
    865 	jal	_C_LABEL(splcheck)
    866 	 nop
    867 #endif /* PARANOIA */
    868 
    869 	/*
    870 	 * Check for kernel restartable atomic sequences.
    871 	 */
    872 	PTR_LA	t0, _C_LABEL(_lock_ras_start)
    873 	li	t1, -MIPS_LOCK_RAS_SIZE
    874 	and	t1, k1
    875 	bne	t1, t0, 1f			# exception PC in RAS area?
    876 	 nop
    877 	jal	_C_LABEL(_restart_lock_ras)	# fix the pc (k1)
    878 	 nop
    879 1:
    880 
    881 	_MTC0	k1, MIPS_COP_0_EXC_PC		# set return address
    882 	COP0_SYNC
    883 
    884 	REG_L	AT, TF_BASE+TF_REG_AST(sp)
    885 	REG_L	v0, TF_BASE+TF_REG_V0(sp)
    886 	REG_L	v1, TF_BASE+TF_REG_V1(sp)
    887 	REG_L	a0, TF_BASE+TF_REG_A0(sp)
    888 	REG_L	a1, TF_BASE+TF_REG_A1(sp)
    889 	REG_L	a2, TF_BASE+TF_REG_A2(sp)
    890 	REG_L	a3, TF_BASE+TF_REG_A3(sp)
    891 	REG_L	t0, TF_BASE+TF_REG_T0(sp)
    892 	REG_L	t1, TF_BASE+TF_REG_T1(sp)
    893 	REG_L	t2, TF_BASE+TF_REG_T2(sp)
    894 	REG_L	t3, TF_BASE+TF_REG_T3(sp)
    895 	REG_L	ta0, TF_BASE+TF_REG_TA0(sp)
    896 	REG_L	ta1, TF_BASE+TF_REG_TA1(sp)
    897 	REG_L	ta2, TF_BASE+TF_REG_TA2(sp)
    898 	REG_L	ta3, TF_BASE+TF_REG_TA3(sp)
    899 	#REG_L	t8, TF_BASE+TF_REG_T8(sp)	# is MIPS_CURLWP
    900 	REG_L	t9, TF_BASE+TF_REG_T9(sp)
    901 	REG_L	ra, TF_BASE+TF_REG_RA(sp)
    902 #ifdef DDBnotyet
    903 	REG_L	s0, TF_BASE+TF_REG_S0(sp)
    904 	REG_L	s1, TF_BASE+TF_REG_S1(sp)
    905 	REG_L	s2, TF_BASE+TF_REG_S2(sp)
    906 	REG_L	s3, TF_BASE+TF_REG_S3(sp)
    907 	REG_L	s4, TF_BASE+TF_REG_S4(sp)
    908 	REG_L	s5, TF_BASE+TF_REG_S5(sp)
    909 	REG_L	s6, TF_BASE+TF_REG_S6(sp)
    910 	REG_L	s7, TF_BASE+TF_REG_S7(sp)
    911 	REG_L	s8, TF_BASE+TF_REG_S8(sp)
    912 #endif
    913 	PTR_ADDU sp, KERNFRAME_SIZ
    914 	eret					# return to interrupted point
    915 	.set	at
    916 END(MIPSX(kern_gen_exception))
    917 
    918 #if NWDOG > 0 || defined(DDB)
    919 /*
    920  * mipsN_kern_nonmaskable_intr
    921  *
    922  * Handle a NMI during kernel mode.
    923  * Build trapframe on stack to hold interrupted kernel context, then
    924  * call trap() to process the condition.
    925  *
    926  * trapframe is pointed to by the 5th arg and a dummy sixth argument is used
    927  * to avoid alignment problems
    928  * {
    929  *	register_t cf_args[4 + 1];
    930  *	register_t cf_pad;		(for 8 word alignment)
    931  *	register_t cf_sp;
    932  *	register_t cf_ra;
    933  *	struct reg cf_tf;
    934  * };
    935  */
    936 NESTED_NOPROFILE(MIPSX(kern_nonmaskable_intr), KERNFRAME_SIZ, ra)
    937 	.set	noat
    938 	.mask	0x80000000, -4
    939 #if defined(PARANOIA)
    940 	PTR_L	k0, L_PCB(MIPS_CURLWP)
    941 	slt	k0, k0, sp		# k0 = L_PCB(MIPS_CURLWP) < sp
    942 1:	beqz	k0, 1b			# loop forever if false
    943 	 nop
    944 
    945 	PTR_L	k0, L_PCB(MIPS_CURLWP)
    946 	PTR_ADDU k0, USPACE
    947 	slt	k0, sp, k0		# k0 = sp < L_PCB(MIPS_CURLWP) + USPACE
    948 2:	beqz	k0, 2b			# loop forever if false
    949 	 nop
    950 #endif /* PARANOIA */
    951 
    952 /*
    953  * Save the relevant kernel registers onto the NMI stack.
    954  * We save s0 - s8, sp and gp so DDB can see them.
    955  */
    956 	move	k1, sp				# save for later
    957 	PTR_L	sp, CPU_INFO_NMI_STACK(k0)	# get NMI stack
    958 	REG_S	k1, TF_BASE+TF_REG_SP(sp)
    959 	REG_S	AT, TF_BASE+TF_REG_AST(sp)
    960 	REG_S	v0, TF_BASE+TF_REG_V0(sp)
    961 	REG_S	v1, TF_BASE+TF_REG_V1(sp)
    962 	mflo	v0
    963 	mfhi	v1
    964 
    965 	REG_S	a0, TF_BASE+TF_REG_A0(sp)
    966 	REG_S	a1, TF_BASE+TF_REG_A1(sp)
    967 	REG_S	a2, TF_BASE+TF_REG_A2(sp)
    968 	REG_S	a3, TF_BASE+TF_REG_A3(sp)
    969 	mfc0	a0, MIPS_COP_0_STATUS		# 1st arg is STATUS
    970 	REG_S	t0, TF_BASE+TF_REG_T0(sp)
    971 	REG_S	t1, TF_BASE+TF_REG_T1(sp)
    972 	REG_S	t2, TF_BASE+TF_REG_T2(sp)
    973 	REG_S	t3, TF_BASE+TF_REG_T3(sp)
    974 	mfc0	a1, MIPS_COP_0_CAUSE		# 2nd arg is CAUSE
    975 	REG_S	ta0, TF_BASE+TF_REG_TA0(sp)
    976 	REG_S	ta1, TF_BASE+TF_REG_TA1(sp)
    977 	REG_S	ta2, TF_BASE+TF_REG_TA2(sp)
    978 	REG_S	ta3, TF_BASE+TF_REG_TA3(sp)
    979 	_MFC0	a2, MIPS_COP_0_BAD_VADDR	# 3rd arg is fault address
    980 	REG_S	t8, TF_BASE+TF_REG_T8(sp)	# is MIPS_CURLWP
    981 	REG_S	t9, TF_BASE+TF_REG_T9(sp)
    982 	REG_S	ra, TF_BASE+TF_REG_RA(sp)
    983 	REG_S	a0, TF_BASE+TF_REG_SR(sp)
    984 	_MFC0	a3, MIPS_COP_0_ERROR_PC		# 4th arg is exception PC
    985 	REG_S	v0, TF_BASE+TF_REG_MULLO(sp)
    986 	REG_S	v1, TF_BASE+TF_REG_MULHI(sp)
    987 	REG_S	a3, TF_BASE+TF_REG_EPC(sp)
    988 	REG_S	a1, TF_BASE+TF_REG_CAUSE(sp)
    989 	REG_S	s0, TF_BASE+TF_REG_S0(sp)
    990 	REG_S	s1, TF_BASE+TF_REG_S1(sp)
    991 	REG_S	s2, TF_BASE+TF_REG_S2(sp)
    992 	REG_S	s3, TF_BASE+TF_REG_S3(sp)
    993 	REG_S	s4, TF_BASE+TF_REG_S4(sp)
    994 	REG_S	s5, TF_BASE+TF_REG_S5(sp)
    995 	REG_S	s6, TF_BASE+TF_REG_S6(sp)
    996 	REG_S	s7, TF_BASE+TF_REG_S7(sp)
    997 	//PTR_ADDU v0, sp, KERNFRAME_SIZ
    998 	REG_S	s8, TF_BASE+TF_REG_S8(sp)
    999 	REG_S	gp, TF_BASE+TF_REG_GP(sp)
   1000 	PTR_L	t8, CPU_INFO_CURLWP(k0)
   1001 #if defined(__mips_o32) || defined(__mips_o64)
   1002 	PTR_ADDU v0, sp, TF_BASE
   1003 	REG_S	v0, KERNFRAME_ARG5(sp)		# 5th arg is p. to trapframe
   1004 #endif
   1005 #if defined(__mips_n32) || defined(__mips_n64)
   1006 	PTR_ADDU a4, sp, TF_BASE		# 5th arg is p. to trapframe
   1007 #endif
   1008 
   1009 	/*
   1010 	 * save PPL in trapframe
   1011 	 */
   1012 	PTR_L	t0, L_CPU(MIPS_CURLWP)
   1013 	INT_L	t1, CPU_INFO_CPL(t0)		# get current priority level
   1014 	INT_S	t1, TF_BASE+TF_PPL(sp)		# save priority level
   1015 
   1016 #if defined(__mips_o32) && (defined(DDB) || defined(DEBUG) || defined(KGDB))
   1017 	PTR_ADDU v0, sp, KERNFRAME_SIZ
   1018 	REG_S	v0, KERNFRAME_SP(sp)
   1019 #endif
   1020 
   1021 #if defined(PARANOIA_SPL)
   1022 	/*
   1023 	 * Verify our existing interrupt level.
   1024 	 */
   1025 	jal	_C_LABEL(splcheck)
   1026 	 nop
   1027 #endif /* PARANOIA_SPL */
   1028 
   1029 	/*
   1030 	 * Clear exception level.
   1031 	 */
   1032 	li	v0, ~(MIPS_SR_EXL|MIPS3_SR_NMI)
   1033 	and	v0, a0				# zero NMI/EXL bits
   1034 	mtc0	v0, MIPS_COP_0_STATUS		# update.
   1035 	COP0_SYNC
   1036 #ifdef MIPS3
   1037 	nop
   1038 	nop
   1039 	nop
   1040 #endif
   1041 
   1042 	/*
   1043 	 * Call the trap handler.
   1044 	 */
   1045 	jal	_C_LABEL(trap)
   1046 	 REG_S	a3, KERNFRAME_RA(sp)		# for debugging
   1047 
   1048 	/*
   1049 	 * Wait for a reset
   1050 	 */
   1051 1:	wait
   1052 	b	1b
   1053 	 nop
   1054 	.set	at
   1055 END(MIPSX(kern_nonmaskable_intr))
   1056 #endif /* NWDOG > 0 || DDB */
   1057 
   1058 /*
   1059  * mipsN_kern_intr
   1060  *
   1061  * Handle an interrupt from kernel mode.
   1062  * Build kernframe on stack to hold interrupted kernel context, then
   1063  * call cpu_intr() to process it.
   1064  *
   1065  */
   1066 	.p2align 5
   1067 NESTED_NOPROFILE(MIPSX(kern_intr), KERNFRAME_SIZ, ra)
   1068 	.set	noat
   1069 	.mask	0x80000000, -4
   1070 #ifdef PARANOIA
   1071 	PTR_L	k0, L_PCB(MIPS_CURLWP)
   1072 	slt	k0, k0, sp			# k0 = L_PCB(MIPS_CURLWP) < sp
   1073 1:	beqz	k0, 1b				# loop forever if false
   1074 	 nop
   1075 	PTR_L	k0, L_PCB(MIPS_CURLWP)
   1076 	PTR_ADDU k0, USPACE
   1077 	slt	k0, sp, k0			# k0 = sp < L_PCB(MIPS_CURLWP) + USPACE
   1078 2:	beqz	k0, 2b				# loop forever if false
   1079 	 nop
   1080 	PTR_L	k0, L_CPU(MIPS_CURLWP)
   1081 	INT_L	k0, CPU_INFO_IDEPTH(k0)		# grab interrupt depth
   1082 	sltu	k0, k0, 3			# must be < 3
   1083 3:	beqz	k0, 3b				# loop forever if false
   1084 	 nop
   1085 #endif
   1086 	/*
   1087 	 * Save the relevant kernel registers onto the stack.  We don't need
   1088 	 * to save s0 - s8, sp, and gp because the compiler does it for us.
   1089 	 * But we use s0-s2 so need to save them.
   1090 	 */
   1091 	PTR_SUBU sp, KERNFRAME_SIZ
   1092 	REG_S	AT, TF_BASE+TF_REG_AST(sp)
   1093 	REG_S	v0, TF_BASE+TF_REG_V0(sp)
   1094 	REG_S	v1, TF_BASE+TF_REG_V1(sp)
   1095 	mflo	v0
   1096 	mfhi	v1
   1097 	REG_S	a0, TF_BASE+TF_REG_A0(sp)
   1098 	REG_S	a1, TF_BASE+TF_REG_A1(sp)
   1099 	REG_S	a2, TF_BASE+TF_REG_A2(sp)
   1100 	REG_S	a3, TF_BASE+TF_REG_A3(sp)
   1101 	REG_S	t0, TF_BASE+TF_REG_T0(sp)
   1102 	REG_S	t1, TF_BASE+TF_REG_T1(sp)
   1103 	REG_S	t2, TF_BASE+TF_REG_T2(sp)
   1104 	REG_S	t3, TF_BASE+TF_REG_T3(sp)
   1105 	REG_S	ta0, TF_BASE+TF_REG_TA0(sp)
   1106 	REG_S	ta1, TF_BASE+TF_REG_TA1(sp)
   1107 	REG_S	ta2, TF_BASE+TF_REG_TA2(sp)
   1108 	REG_S	ta3, TF_BASE+TF_REG_TA3(sp)
   1109 	REG_S	s0, TF_BASE+TF_REG_S0(sp)	# used for saved ipl/idepth
   1110 	REG_S	s1, TF_BASE+TF_REG_S1(sp)	# used for initial status
   1111 	mfc0	s1, MIPS_COP_0_STATUS
   1112 	REG_S	s2, TF_BASE+TF_REG_S2(sp)	# used for cpu_info
   1113 #ifdef DDB
   1114 	REG_S	t8, TF_BASE+TF_REG_T8(sp)	# already contains MIPS_CURLWP
   1115 #endif
   1116 	REG_S	t9, TF_BASE+TF_REG_T9(sp)
   1117 	REG_S	ra, TF_BASE+TF_REG_RA(sp)
   1118 	REG_S	s1, TF_BASE+TF_REG_SR(sp)
   1119 	REG_S	v0, TF_BASE+TF_REG_MULLO(sp)
   1120 	REG_S	v1, TF_BASE+TF_REG_MULHI(sp)
   1121 /*
   1122  * Call the interrupt handler.
   1123  */
   1124 	_MFC0	ta0, MIPS_COP_0_EXC_PC		# grab exception PC
   1125 	PTR_L	s2, L_CPU(MIPS_CURLWP)		# delay slot
   1126 	REG_S	ta0, TF_BASE+TF_REG_EPC(sp)	# and save it
   1127 
   1128 #if defined(DDB) || defined(DEBUG) || defined(KGDB)
   1129 	REG_S	ta0, KERNFRAME_RA(sp)		# for debugging
   1130 #endif
   1131 
   1132 #ifdef PARANOIA
   1133 	INT_L	s0, CPU_INFO_CPL(s2)
   1134 	INT_S	s0, TF_BASE+TF_PPL(sp)		# save priority level
   1135 
   1136 	/*
   1137 	 * Verify the current interrupt level
   1138 	 */
   1139 	jal	_C_LABEL(splcheck)
   1140 	 nop
   1141 #endif /* PARANOIA */
   1142 
   1143 	/*
   1144 	 * We first need to get to IPL_HIGH so that interrupts are masked.
   1145 	 */
   1146 	jal	_C_LABEL(splhigh_noprof)
   1147 	 nop
   1148 
   1149 #ifdef PARANOIA
   1150 1:	bne	s0, v0, 1b
   1151 	 nop
   1152 #endif /* PARANOIA */
   1153 
   1154 	sll	s0, v0, 8			# remember previous priority
   1155 						# low 8 bits used for idepth
   1156 
   1157 #ifdef PARANOIA
   1158 	/*
   1159 	 * Interrupts at IPL_HIGH are not allowed.
   1160 	 */
   1161 	li	v1, IPL_HIGH
   1162 	sltu	t0, v0, v1
   1163 2:	beqz	t0, 2b
   1164 	 nop
   1165 #endif /* PARANOIA */
   1166 
   1167 	INT_L	t1, CPU_INFO_IDEPTH(s2)		# we need to inc. intr depth
   1168 	or	s0, t1				#   save old interrupt depth
   1169 	INT_ADDU t1, 1
   1170 	INT_S	t1, CPU_INFO_IDEPTH(s2)		#   store new interrupt depth
   1171 
   1172 	/*
   1173 	 * Now we can clear exception level since no interrupts can be delivered
   1174 	 */
   1175 	mfc0	v1, MIPS_COP_0_STATUS
   1176 	MFC0_HAZARD
   1177 	and	v0, v1, MIPS_SR_EXL		# grab exception level bit
   1178 	xor	v0, v1				# clear it
   1179 	mtc0	v0, MIPS_COP_0_STATUS		# write new status
   1180 	COP0_SYNC
   1181 
   1182 	/*
   1183 	 * Now hard interrupts can be processed.
   1184 	 */
   1185 	move	a1, ta0				# 2nd arg is exception PC
   1186 	move	a2, s1				# 3rd arg is status
   1187 	jal	_C_LABEL(cpu_intr)		# cpu_intr(ppl, pc, status)
   1188 	 srl	a0, s0, 8			# 1st arg is previous pri level
   1189 
   1190 	and	t1, s0, 0xff			# get previous interrupt depth
   1191 	INT_S	t1, CPU_INFO_IDEPTH(s2)		# to it previous value
   1192 
   1193 #if defined(PARANOIA)
   1194 	mfc0	t0, MIPS_COP_0_STATUS		# verify INT_IE is still set
   1195 	MFC0_HAZARD
   1196 	and	t0, MIPS_SR_INT_IE
   1197 #if defined(MIPSNN)
   1198 	teqi	t0, 0
   1199 #else
   1200 3:	beqz	t0, 3b
   1201 	 nop
   1202 #endif
   1203 #endif /* PARANOIA */
   1204 
   1205 #ifdef __HAVE_FAST_SOFTINTS
   1206 	and	a0, s1, MIPS_SOFT_INT_MASK	# were softints enabled?
   1207 	beqz	a0, 4f				#   nope
   1208 	 nop
   1209 	mfc0	v0, MIPS_COP_0_CAUSE		# grab the pending softints
   1210 	MFC0_HAZARD
   1211 	and	a0, v0				# are softints pending
   1212 	beqz	a0, 4f				#   nope
   1213 	 nop
   1214 
   1215 	jal	_C_LABEL(softint_process)	# softint_process(pending)
   1216 	 nop
   1217 
   1218 #ifdef __HAVE_PREEMPTION
   1219 	srl	v1, s0, 8			# get saved priority level
   1220 	bnez	v1, 4f				# branch if not at IPL_NONE
   1221 	 nop
   1222 	INT_L	t0, CPU_INFO_SOFTINTS(s2)	# get pending softints
   1223 	and	v0, t0, 1 << SOFTINT_KPREEMPT	# do we need a kernel preempt?
   1224 	beqz	v0, 4f				#   nope
   1225 	 nop
   1226 	xor	t0, v0				# clear preempt bit
   1227 	INT_S	t0, CPU_INFO_SOFTINTS(s2)	# and save it.
   1228 
   1229 	jal	_C_LABEL(splx_noprof)		# drop to IPL_SCHED
   1230 	 li	a0, IPL_SCHED
   1231 
   1232 	jal	_C_LABEL(kpreempt)		# kpreempt(pc)
   1233 	 li	a0, -2
   1234 #endif /* __HAVE_PREEMPTION */
   1235 4:
   1236 #endif /* __HAVE_FAST_SOFTINTS */
   1237 	/*
   1238 	 * Interrupts handled, restore registers and return from the interrupt.
   1239 	 * First, clear interrupt enable
   1240 	 */
   1241 #ifdef MIPSNNR2
   1242 	di	v0				# disable interrupts
   1243 #else
   1244 	mfc0	v0, MIPS_COP_0_STATUS		# read it
   1245 	MFC0_HAZARD
   1246 	xor	v0, MIPS_SR_INT_IE		# disable interrupts
   1247 	mtc0	v0, MIPS_COP_0_STATUS		# write it
   1248 #endif
   1249 	COP0_SYNC
   1250 
   1251 	or	v0, MIPS_SR_EXL			# set exception mode
   1252 	mtc0	v0, MIPS_COP_0_STATUS		# write it
   1253 	COP0_SYNC
   1254 
   1255 	srl	a0, s0, 8			# get previous priority level
   1256 #ifdef PARANOIA
   1257 	INT_L	t0, TF_BASE+TF_PPL(sp)		# get saved priority level
   1258 9:	bne	t0, a0, 9b			# should still match
   1259 	 nop
   1260 
   1261 	li	t0, IPL_HIGH
   1262 	sltu	v0, a0, t0
   1263 8:	beqz	v0, 8b
   1264 	 nop
   1265 #endif /* PARANOIA */
   1266 
   1267 	/*
   1268 	 * Restore IPL knowing interrupts are disabled
   1269 	 */
   1270 	jal	_C_LABEL(splx_noprof)		# splx(ppl)
   1271 	 nop
   1272 
   1273 #ifdef PARANOIA
   1274 	mfc0	v0, MIPS_COP_0_STATUS
   1275 	MFC0_HAZARD
   1276 	or	v0, MIPS_SR_INT_IE
   1277 5:	bne	v0, s1, 5b
   1278 	 nop
   1279 #endif /* PARANOIA */
   1280 
   1281 	/*
   1282 	 * Restore SR
   1283 	 */
   1284 	mtc0	s1, MIPS_COP_0_STATUS
   1285 	COP0_SYNC
   1286 
   1287 	/*
   1288 	 * Restore s0-s2 and goto common kernel return code.
   1289 	 */
   1290 	REG_L	s0, TF_BASE+TF_REG_S0(sp)
   1291 	REG_L	s1, TF_BASE+TF_REG_S1(sp)
   1292 	b	MIPSX(kern_return)
   1293 	 REG_L	s2, TF_BASE+TF_REG_S2(sp)
   1294 	.set	at
   1295 END(MIPSX(kern_intr))
   1296 
   1297 /*
   1298  *
   1299  */
   1300 	.p2align 5
   1301 NESTED_NOPROFILE(MIPSX(user_reserved_insn), CALLFRAME_SIZ, ra)
   1302 	.set	noat
   1303 	.mask	0x80000000, -4
   1304 	/*
   1305 	 * Save a minimum of registers to see if this is rdhwr $3,$29
   1306 	 */
   1307 	KERN_ENTRY_ERRATA
   1308 	/* K1 already has CURLWP */
   1309 	PTR_L	k0, L_PCB(k1)			# XXXuvm_lwp_getuarea
   1310 	PTR_ADDU k0, USPACE - TF_SIZ - CALLFRAME_SIZ
   1311 
   1312 	/* Need two working registers */
   1313 	REG_S	AT, CALLFRAME_SIZ+TF_REG_AST(k0)
   1314 	REG_S	v0, CALLFRAME_SIZ+TF_REG_V0(k0)
   1315 
   1316 	/* If this was in a branch delay slot, take the slow path. */
   1317 	mfc0	v0, MIPS_COP_0_CAUSE
   1318 	MFC0_HAZARD
   1319 	bltz	v0, MIPSX(user_gen_exception_common)
   1320 	 nop
   1321 
   1322 	/*
   1323 	 * Get exception PC and fetch the instruction.  We know we can do
   1324 	 * this since the instruction actually got read.
   1325 	 */
   1326 	_MFC0	v0, MIPS_COP_0_EXC_PC
   1327 	MFC0_HAZARD
   1328 	INT_L	AT, 0(v0)
   1329 
   1330 	/*
   1331 	 * Was this rdhwr $3,$29?
   1332 	 */
   1333 	lui	v0, %hi(0x7c03e83b)	# 0x7c03e83b => rdhwr $3,$29
   1334 	addiu	v0, %lo(0x7c03e83b)	#        or ... rdhwr v1,ulr
   1335 	bne	AT, v0, MIPSX(user_gen_exception_common)
   1336 	 nop
   1337 
   1338 	/*
   1339 	 * Advance the PC (don't want to restart at the rdhwr).
   1340 	 */
   1341 	_MFC0	v0, MIPS_COP_0_EXC_PC
   1342 	MFC0_HAZARD
   1343 	PTR_ADDIU v0, 4
   1344 	_MTC0	v0, MIPS_COP_0_EXC_PC
   1345 	COP0_SYNC
   1346 
   1347 	PTR_L	v1, L_PRIVATE(k1)		# rdhwr $3,$29 updates v1
   1348 
   1349 	REG_L	AT, CALLFRAME_SIZ+TF_REG_AST(k0)# restore reg
   1350 	REG_L	v0, CALLFRAME_SIZ+TF_REG_V0(k0) # restore reg
   1351 	eret
   1352 END(MIPSX(user_reserved_insn))
   1353 
   1354 /*
   1355  * mipsN_user_gen_exception
   1356  *
   1357  * Handle an exception during user mode.
   1358  * Save user context atop the kernel stack, then call trap() to process
   1359  * the condition.  The context can be manipulated alternatively via
   1360  * curlwp->l_md.md_regs.
   1361  */
   1362 	.p2align 5
   1363 NESTED_NOPROFILE(MIPSX(user_gen_exception), CALLFRAME_SIZ, ra)
   1364 	.set	noat
   1365 	.mask	0x80000000, -4
   1366 	/*
   1367 	 * Save all the registers except the kernel temporaries onto the stack.
   1368 	 */
   1369 	KERN_ENTRY_ERRATA
   1370 	/* K1 already has CURLWP */
   1371 	PTR_L	k0, L_PCB(k1)			# XXXuvm_lwp_getuarea
   1372 	PTR_ADDU k0, USPACE - TF_SIZ - CALLFRAME_SIZ
   1373 	REG_S	AT, CALLFRAME_SIZ+TF_REG_AST(k0)
   1374 	REG_S	v0, CALLFRAME_SIZ+TF_REG_V0(k0)
   1375 MIPSX(user_gen_exception_common):
   1376 	REG_S	v1, CALLFRAME_SIZ+TF_REG_V1(k0)
   1377 	mflo	v0
   1378 	REG_S	a0, CALLFRAME_SIZ+TF_REG_A0(k0)
   1379 	REG_S	a1, CALLFRAME_SIZ+TF_REG_A1(k0)
   1380 	REG_S	a2, CALLFRAME_SIZ+TF_REG_A2(k0)
   1381 	REG_S	a3, CALLFRAME_SIZ+TF_REG_A3(k0)
   1382 	mfhi	v1
   1383 	REG_S	t0, CALLFRAME_SIZ+TF_REG_T0(k0)
   1384 	REG_S	t1, CALLFRAME_SIZ+TF_REG_T1(k0)
   1385 	REG_S	t2, CALLFRAME_SIZ+TF_REG_T2(k0)
   1386 	REG_S	t3, CALLFRAME_SIZ+TF_REG_T3(k0)
   1387 	mfc0	a0, MIPS_COP_0_STATUS		# 1st arg is STATUS
   1388 	REG_S	ta0, CALLFRAME_SIZ+TF_REG_TA0(k0)
   1389 	REG_S	ta1, CALLFRAME_SIZ+TF_REG_TA1(k0)
   1390 	REG_S	ta2, CALLFRAME_SIZ+TF_REG_TA2(k0)
   1391 	REG_S	ta3, CALLFRAME_SIZ+TF_REG_TA3(k0)
   1392 	mfc0	a1, MIPS_COP_0_CAUSE		# 2nd arg is CAUSE
   1393 	REG_S	s0, CALLFRAME_SIZ+TF_REG_S0(k0)
   1394 	REG_S	s1, CALLFRAME_SIZ+TF_REG_S1(k0)
   1395 	REG_S	s2, CALLFRAME_SIZ+TF_REG_S2(k0)
   1396 	REG_S	s3, CALLFRAME_SIZ+TF_REG_S3(k0)
   1397 	_MFC0	a2, MIPS_COP_0_BAD_VADDR	# 3rd arg is fault address
   1398 	REG_S	s4, CALLFRAME_SIZ+TF_REG_S4(k0)
   1399 	REG_S	s5, CALLFRAME_SIZ+TF_REG_S5(k0)
   1400 	REG_S	s6, CALLFRAME_SIZ+TF_REG_S6(k0)
   1401 	REG_S	s7, CALLFRAME_SIZ+TF_REG_S7(k0)
   1402 	_MFC0	a3, MIPS_COP_0_EXC_PC		# 4th arg is exception PC
   1403 	REG_S	t8, CALLFRAME_SIZ+TF_REG_T8(k0)	# will be MIPS_CURLWP
   1404 	REG_S	t9, CALLFRAME_SIZ+TF_REG_T9(k0)
   1405 	REG_S	v0, CALLFRAME_SIZ+TF_REG_MULLO(k0)
   1406 	REG_S	v1, CALLFRAME_SIZ+TF_REG_MULHI(k0)
   1407 	REG_S	gp, CALLFRAME_SIZ+TF_REG_GP(k0)
   1408 	REG_S	sp, CALLFRAME_SIZ+TF_REG_SP(k0)
   1409 	REG_S	s8, CALLFRAME_SIZ+TF_REG_S8(k0)
   1410 	REG_S	ra, CALLFRAME_SIZ+TF_REG_RA(k0)
   1411 	REG_S	a0, CALLFRAME_SIZ+TF_REG_SR(k0)
   1412 	REG_S	a3, CALLFRAME_SIZ+TF_REG_EPC(k0)
   1413 #ifdef __GP_SUPPORT__
   1414 	PTR_LA	gp, _C_LABEL(_gp)		# switch to kernel GP
   1415 #endif
   1416 	move	sp, k0				# switch to kernel SP
   1417 	move	MIPS_CURLWP, k1
   1418 #ifdef NOFPU
   1419 	/*
   1420 	 * enter kernel mode
   1421 	 */
   1422 	and	t0, a0, MIPS_SR_EXL|MIPS_SR_KSU_MASK # bits to clear
   1423 	xor	t0, a0				# clear them.
   1424 #else
   1425 	/*
   1426 	 * Turn off FPU and enter kernel mode
   1427 	 */
   1428 	lui	t0, %hi(~(MIPS_SR_COP_1_BIT|MIPS_SR_EXL|MIPS_SR_KSU_MASK))
   1429 	addiu	t0, %lo(~(MIPS_SR_COP_1_BIT|MIPS_SR_EXL|MIPS_SR_KSU_MASK))
   1430 	and	t0, a0
   1431 #endif
   1432 /*
   1433  * Call the trap handler.
   1434  */
   1435 	mtc0	t0, MIPS_COP_0_STATUS
   1436 	COP0_SYNC
   1437 
   1438 	jal	_C_LABEL(trap)
   1439 	 REG_S	a3, CALLFRAME_RA(sp)		# for debugging
   1440 /*
   1441  * Check pending asynchronous traps.
   1442  */
   1443 	INT_L	v0, L_MD_ASTPENDING(MIPS_CURLWP)# any pending ast?
   1444 	beqz	v0, MIPSX(user_return)		# if no, skip ast processing
   1445 	 nop
   1446 /*
   1447  * We have pending asynchronous traps; all the state is already saved.
   1448  */
   1449 	lui	ra, %hi(MIPSX(user_return))	# return directly to user return
   1450 	j	_C_LABEL(ast)
   1451 	 PTR_ADDIU ra, %lo(MIPSX(user_return))	# return directly to user return
   1452 	.set	at
   1453 END(MIPSX(user_gen_exception))
   1454 
   1455 /*----------------------------------------------------------------------------
   1456  *
   1457  * mipsN_user_intr
   1458  *
   1459  *	Handle an interrupt from user mode.
   1460  *	We save partial state onto the kernel stack since we know there will
   1461  *	always a kernel stack and chances are we won't need the registers we
   1462  *	don't save.  If there is a pending asynchronous system trap, then save
   1463  *	the remaining state and call ast().
   1464  *
   1465  * Results:
   1466  * 	None.
   1467  *
   1468  * Side effects:
   1469  *	None.
   1470  *
   1471  *----------------------------------------------------------------------------
   1472  */
   1473 	.p2align 5
   1474 NESTED_NOPROFILE(MIPSX(user_intr), CALLFRAME_SIZ, ra)
   1475 	.set	noat
   1476 	.mask	0x80000000, -4
   1477 /*
   1478  * Save the relevant user registers onto the kernel stack.
   1479  * We don't need to save s0 - s8 because the compiler does it for us.
   1480  */
   1481 	KERN_ENTRY_ERRATA
   1482 	/* k1 contains curlwp */
   1483 	PTR_L	k0, L_PCB(k1)			# XXXuvm_lwp_getuarea
   1484 	PTR_ADDU k0, USPACE - TF_SIZ - CALLFRAME_SIZ
   1485 	REG_S	AT, CALLFRAME_SIZ+TF_REG_AST(k0)	# $1
   1486 	REG_S	v0, CALLFRAME_SIZ+TF_REG_V0(k0)		# $2
   1487 	REG_S	v1, CALLFRAME_SIZ+TF_REG_V1(k0)		# $3
   1488 	mflo	v0
   1489 	REG_S	a0, CALLFRAME_SIZ+TF_REG_A0(k0)		# $4
   1490 	REG_S	a1, CALLFRAME_SIZ+TF_REG_A1(k0)		# $5
   1491 	REG_S	a2, CALLFRAME_SIZ+TF_REG_A2(k0)		# $6
   1492 	REG_S	a3, CALLFRAME_SIZ+TF_REG_A3(k0)		# $7
   1493 	mfhi	v1
   1494 	REG_S	t0, CALLFRAME_SIZ+TF_REG_T0(k0)		# $12
   1495 	REG_S	t1, CALLFRAME_SIZ+TF_REG_T1(k0)		# $13
   1496 	REG_S	t2, CALLFRAME_SIZ+TF_REG_T2(k0)		# $14
   1497 	REG_S	t3, CALLFRAME_SIZ+TF_REG_T3(k0)		# $15
   1498 	mfc0	t0, MIPS_COP_0_CAUSE
   1499 	REG_S	ta0, CALLFRAME_SIZ+TF_REG_TA0(k0)	# $8
   1500 	REG_S	ta1, CALLFRAME_SIZ+TF_REG_TA1(k0)	# $9
   1501 	REG_S	ta2, CALLFRAME_SIZ+TF_REG_TA2(k0)	# $10
   1502 	REG_S	ta3, CALLFRAME_SIZ+TF_REG_TA3(k0)	# $11
   1503 	REG_S	s0, CALLFRAME_SIZ+TF_REG_S0(k0)		# $16
   1504 	REG_S	s1, CALLFRAME_SIZ+TF_REG_S1(k0)		# $17
   1505 	mfc0	s1, MIPS_COP_0_STATUS
   1506 	REG_S	t8, CALLFRAME_SIZ+TF_REG_T8(k0)		# $24 MIPS_CURLWP
   1507 	REG_S	t9, CALLFRAME_SIZ+TF_REG_T9(k0)		# $25
   1508 	REG_S	gp, CALLFRAME_SIZ+TF_REG_GP(k0)		# $28
   1509 	REG_S	sp, CALLFRAME_SIZ+TF_REG_SP(k0)		# $29
   1510 	REG_S	ra, CALLFRAME_SIZ+TF_REG_RA(k0)		# $31
   1511 	REG_S	s1, CALLFRAME_SIZ+TF_REG_SR(k0)
   1512 	_MFC0	ta0, MIPS_COP_0_EXC_PC
   1513 	REG_S	v0, CALLFRAME_SIZ+TF_REG_MULLO(k0)
   1514 	REG_S	v1, CALLFRAME_SIZ+TF_REG_MULHI(k0)
   1515 	REG_S	ta0, CALLFRAME_SIZ+TF_REG_EPC(k0)
   1516 	REG_S	t0, CALLFRAME_SIZ+TF_REG_CAUSE(k0)
   1517 	move	sp, k0				# switch to kernel SP
   1518 	move	MIPS_CURLWP, k1			# set curlwp reg (t8)
   1519 #if defined(DDB) || defined(DEBUG) || defined(KGDB)
   1520 	REG_S	ta0, CALLFRAME_RA(sp)		# for debugging
   1521 #endif
   1522 #ifdef __GP_SUPPORT__
   1523 	PTR_LA	gp, _C_LABEL(_gp)		# switch to kernel GP
   1524 #endif
   1525 
   1526 	/*
   1527 	 * We first need to get to IPL_HIGH so that interrupts are masked.
   1528 	 */
   1529 	jal	_C_LABEL(splhigh_noprof)	# splhigh()
   1530 	 nop
   1531 	move	s0, v0				# remember previous priority
   1532 
   1533 	/*
   1534 	 * Now we can turn off the FPU, clear exception level, and enter
   1535 	 * kernel mode since no interrupts can be delivered
   1536 	 */
   1537 	mfc0	v1, MIPS_COP_0_STATUS
   1538 #ifdef NOFPU
   1539 	/*
   1540 	 * enter kernel mode
   1541 	 */
   1542 	MFC0_HAZARD
   1543 	and	v0, v1, MIPS_SR_EXL|MIPS_SR_KSU_MASK # bits to clear
   1544 	xor	v0, v1				# clear them.
   1545 #else
   1546 	/*
   1547 	 * Turn off FPU and enter kernel mode
   1548 	 */
   1549 	lui	v0, %hi(~(MIPS_SR_COP_1_BIT|MIPS_SR_EXL|MIPS_SR_KSU_MASK))
   1550 	addiu	v0, %lo(~(MIPS_SR_COP_1_BIT|MIPS_SR_EXL|MIPS_SR_KSU_MASK))
   1551 	and	v0, v1
   1552 #endif
   1553 	mtc0	v0, MIPS_COP_0_STATUS		# write new status
   1554 	COP0_SYNC
   1555 
   1556 	/*
   1557 	 * Since we interrupted user mode, the new interrupt depth must be 1.
   1558 	 */
   1559 	PTR_L	t0, L_CPU(MIPS_CURLWP)
   1560 	li	t1, 1
   1561 	INT_S	t1, CPU_INFO_IDEPTH(t0)		# store new interrupt depth (1)
   1562 
   1563 	/*
   1564 	 * Now hard interrupts can be processed.
   1565 	 */
   1566 	move	a1, ta0				# 2nd arg is exception pc
   1567 	move	a2, s1				# 3rd arg is status
   1568 	jal	_C_LABEL(cpu_intr)		# cpu_intr(ppl, pc, status)
   1569 	 move	a0, s0				# 1st arg is previous pri level
   1570 
   1571 	/*
   1572 	 * Interrupt depth is now back to 0.
   1573 	 */
   1574 	PTR_L	t0, L_CPU(MIPS_CURLWP)
   1575 	INT_S	zero, CPU_INFO_IDEPTH(t0)
   1576 
   1577 #ifdef __HAVE_FAST_SOFTINTS
   1578 	/*
   1579 	 * This an interrupt from user mode so both softints must be enabled.
   1580 	 * No need to check (unless we're being paranoid).
   1581 	 */
   1582 #ifdef PARANOIA
   1583 	and	a0, s1, MIPS_SOFT_INT_MASK	# get softints enabled bits
   1584 	xor	a0, MIPS_SOFT_INT_MASK		# invert them.
   1585 1:	bnez	a0, 1b				# loop forever if disabled
   1586 	 nop
   1587 #endif
   1588 	mfc0	a0, MIPS_COP_0_CAUSE		# grab the pending softints
   1589 	MFC0_HAZARD
   1590 	and	a0, MIPS_SOFT_INT_MASK		# are there softints pending
   1591 	beqz	a0, 4f				#   nope
   1592 	 nop
   1593 	jal	_C_LABEL(softint_process)	# softint_process(pending)
   1594 	 nop
   1595 4:
   1596 #endif
   1597 	/*
   1598 	 * Disable interrupts
   1599 	 */
   1600 #ifdef MIPSNNR2
   1601 	di	v1				# disable interrupts
   1602 #else
   1603 	mfc0	v1, MIPS_COP_0_STATUS
   1604 	MFC0_HAZARD
   1605 	and	v0, v1, MIPS_SR_INT_IE		# clear interrupt enable
   1606 	xor	v0, v1
   1607 	mtc0	v0, MIPS_COP_0_STATUS		# interrupts are disabled
   1608 #endif
   1609 	COP0_SYNC
   1610 
   1611 	/*
   1612 	 * Restore IPL knowing interrupts are off
   1613 	 */
   1614 	jal	_C_LABEL(splx_noprof)
   1615 	 move	a0, s0				# fetch previous priority level
   1616 
   1617 	/*
   1618 	 * Check pending asynchronous traps.
   1619 	 */
   1620 	REG_L	s0, CALLFRAME_SIZ+TF_REG_S0(sp)	# restore
   1621 	REG_L	s1, CALLFRAME_SIZ+TF_REG_S1(sp)	# restore
   1622 	INT_L	v0, L_MD_ASTPENDING(MIPS_CURLWP)# any pending ast?
   1623 	beqz	v0, MIPSX(user_intr_return)	# if no, skip ast processing
   1624 	 nop
   1625 
   1626 	/*
   1627 	 * We have a pending asynchronous trap; save remaining user state into
   1628 	 * trapframe.
   1629 	 */
   1630 	#REG_S	s0, CALLFRAME_SIZ+TF_REG_S0(sp)	# $16 (saved above)
   1631 	#REG_S	s1, CALLFRAME_SIZ+TF_REG_S1(sp)	# $17 (saved above)
   1632 	REG_S	s2, CALLFRAME_SIZ+TF_REG_S2(sp)	# $18
   1633 	REG_S	s3, CALLFRAME_SIZ+TF_REG_S3(sp)	# $19
   1634 	REG_S	s4, CALLFRAME_SIZ+TF_REG_S4(sp)	# $20
   1635 	REG_S	s5, CALLFRAME_SIZ+TF_REG_S5(sp)	# $21
   1636 	REG_S	s6, CALLFRAME_SIZ+TF_REG_S6(sp)	# $22
   1637 	REG_S	s7, CALLFRAME_SIZ+TF_REG_S7(sp)	# $23
   1638 	REG_S	s8, CALLFRAME_SIZ+TF_REG_S8(sp)	# $30
   1639 #if !defined(MIPS_DYNAMIC_STATUS_MASK) && defined(MIPSNNR2)
   1640 	ei					# enable interrupts
   1641 #else
   1642 	mfc0	t0, MIPS_COP_0_STATUS		#
   1643 	MFC0_HAZARD
   1644 	or	t0, MIPS_SR_INT_IE 		# enable interrupts
   1645 	DYNAMIC_STATUS_MASK(t0, t1)		# machine dependent masking
   1646 	mtc0	t0, MIPS_COP_0_STATUS		# enable interrupts (spl0)
   1647 #endif
   1648 	COP0_SYNC
   1649 
   1650 	PTR_LA	ra, MIPSX(user_return)
   1651 	j	_C_LABEL(ast)			# ast()
   1652 	 nop
   1653 	.set	at
   1654 END(MIPSX(user_intr))
   1655 
   1656 /*
   1657  * mipsN_systemcall
   1658  *
   1659  * Save user context atop of kernel stack, then call syscall() to process
   1660  * a system call.  The context can be manipulated alternatively via
   1661  * curlwp->l_md.md_utf->tf_regs.
   1662  */
   1663 	.p2align 5
   1664 NESTED_NOPROFILE(MIPSX(systemcall), CALLFRAME_SIZ, ra)
   1665 	.set	noat
   1666 	.mask	0x80000000, -4
   1667 	/*
   1668 	 * Save all the registers but kernel temporaries onto the stack.
   1669 	 */
   1670 	KERN_ENTRY_ERRATA
   1671 	/* k1 already contains curlwp */
   1672 	PTR_L	k0, L_PCB(k1)			# XXXuvm_lwp_getuarea
   1673 	PTR_ADDU k0, USPACE - TF_SIZ - CALLFRAME_SIZ
   1674 	#REG_S	AT, CALLFRAME_SIZ+TF_REG_AST(k0)
   1675 	#.set	at
   1676 	REG_S	v0, CALLFRAME_SIZ+TF_REG_V0(k0)		# syscall #
   1677 	REG_S	v1, CALLFRAME_SIZ+TF_REG_V1(k0)		# used by syscall()
   1678 	mflo	v0
   1679 	REG_S	a0, CALLFRAME_SIZ+TF_REG_A0(k0)
   1680 	REG_S	a1, CALLFRAME_SIZ+TF_REG_A1(k0)
   1681 	REG_S	a2, CALLFRAME_SIZ+TF_REG_A2(k0)
   1682 	REG_S	a3, CALLFRAME_SIZ+TF_REG_A3(k0)
   1683 	mfhi	v1
   1684 	mfc0	a1, MIPS_COP_0_STATUS			# 2nd arg is STATUS
   1685 	REG_S	s0, CALLFRAME_SIZ+TF_REG_S0(k0)
   1686 	REG_S	s1, CALLFRAME_SIZ+TF_REG_S1(k0)
   1687 	REG_S	s2, CALLFRAME_SIZ+TF_REG_S2(k0)
   1688 	REG_S	s3, CALLFRAME_SIZ+TF_REG_S3(k0)
   1689 	mfc0	a2, MIPS_COP_0_CAUSE			# 3rd arg is CAUSE
   1690 	REG_S	s4, CALLFRAME_SIZ+TF_REG_S4(k0)
   1691 	REG_S	s5, CALLFRAME_SIZ+TF_REG_S5(k0)
   1692 	REG_S	s6, CALLFRAME_SIZ+TF_REG_S6(k0)
   1693 	REG_S	s7, CALLFRAME_SIZ+TF_REG_S7(k0)
   1694 	_MFC0	a3, MIPS_COP_0_EXC_PC			# 4th arg is PC
   1695 	REG_S	t0, CALLFRAME_SIZ+TF_REG_T0(k0)
   1696 	REG_S	t1, CALLFRAME_SIZ+TF_REG_T1(k0)
   1697 	REG_S	t2, CALLFRAME_SIZ+TF_REG_T2(k0)
   1698 	REG_S	t3, CALLFRAME_SIZ+TF_REG_T3(k0)		# syscall saved gp for fork
   1699 #if defined(__mips_n32) || defined(__mips_n64)
   1700 	REG_S	a4, CALLFRAME_SIZ+TF_REG_A4(k0)
   1701 	REG_S	a5, CALLFRAME_SIZ+TF_REG_A5(k0)
   1702 	REG_S	a6, CALLFRAME_SIZ+TF_REG_A6(k0)
   1703 	REG_S	a7, CALLFRAME_SIZ+TF_REG_A7(k0)
   1704 #else
   1705 	REG_S	ta0, CALLFRAME_SIZ+TF_REG_TA0(k0)
   1706 	REG_S	ta1, CALLFRAME_SIZ+TF_REG_TA1(k0)
   1707 	REG_S	ta2, CALLFRAME_SIZ+TF_REG_TA2(k0)
   1708 	REG_S	ta3, CALLFRAME_SIZ+TF_REG_TA3(k0)
   1709 #endif
   1710 	REG_S	t8, CALLFRAME_SIZ+TF_REG_T8(k0)		# will be MIPS_CURLWP
   1711 	REG_S	t9, CALLFRAME_SIZ+TF_REG_T9(k0)
   1712 	REG_S	gp, CALLFRAME_SIZ+TF_REG_GP(k0)
   1713 	REG_S	sp, CALLFRAME_SIZ+TF_REG_SP(k0)
   1714 	REG_S	s8, CALLFRAME_SIZ+TF_REG_S8(k0)
   1715 	REG_S	ra, CALLFRAME_SIZ+TF_REG_RA(k0)
   1716 	REG_S	a1, CALLFRAME_SIZ+TF_REG_SR(k0)
   1717 	REG_S	v0, CALLFRAME_SIZ+TF_REG_MULLO(k0)
   1718 	REG_S	v1, CALLFRAME_SIZ+TF_REG_MULHI(k0)
   1719 	REG_S	a3, CALLFRAME_SIZ+TF_REG_EPC(k0)
   1720 	move	MIPS_CURLWP, k1			# set curlwp reg
   1721 	move	sp, k0				# switch to kernel SP
   1722 #ifdef __GP_SUPPORT__
   1723 	PTR_LA	gp, _C_LABEL(_gp)		# switch to kernel GP
   1724 #endif
   1725 #if defined(DDB) || defined(DEBUG) || defined(KGDB)
   1726 	move	ra, a3
   1727 	REG_S	ra, CALLFRAME_RA(sp)
   1728 #endif
   1729 	PTR_L	s0, L_PROC(MIPS_CURLWP)		# curlwp->l_proc
   1730 	PTR_L	t9, P_MD_SYSCALL(s0)		# t9 = syscall
   1731 #ifdef NOFPU
   1732 	/*
   1733 	 * enter kernel mode
   1734 	 */
   1735 	and	t0, a1, MIPS_SR_EXL|MIPS_SR_KSU_MASK # bits to clear
   1736 	xor	t0, a1				# clear them.
   1737 #else
   1738 	/*
   1739 	 * Turn off FPU and enter kernel mode
   1740 	 */
   1741 	lui	t0, %hi(~(MIPS_SR_COP_1_BIT|MIPS_SR_EXL|MIPS_SR_KSU_MASK))
   1742 	addiu	t0, %lo(~(MIPS_SR_COP_1_BIT|MIPS_SR_EXL|MIPS_SR_KSU_MASK))
   1743 	and	t0, a1
   1744 #endif
   1745 	mtc0	t0, MIPS_COP_0_STATUS
   1746 	COP0_SYNC
   1747 /*
   1748  * Call the system call handler.
   1749  */
   1750 	.set	at
   1751 	jalr	t9
   1752 	 move	a0, MIPS_CURLWP			# 1st arg is curlwp
   1753 
   1754 /*
   1755  * Check pending asynchronous traps.
   1756  */
   1757 	INT_L	v0, L_MD_ASTPENDING(MIPS_CURLWP)# any pending ast?
   1758 	beqz	v0, MIPSX(user_return)		# no, skip ast processing
   1759 	 nop
   1760 /*
   1761  * We have pending asynchronous traps; all the state is already saved.
   1762  */
   1763 	lui	ra, %hi(MIPSX(user_return))	# return directly to user return
   1764 	j	_C_LABEL(ast)
   1765 	 PTR_ADDIU ra, %lo(MIPSX(user_return))	# return directly to user return
   1766 END(MIPSX(systemcall))
   1767 
   1768 /*
   1769  * Panic on cache errors.  A lot more could be done to recover
   1770  * from some types of errors but it is tricky.
   1771  */
   1772 	.p2align 5
   1773 NESTED_NOPROFILE(MIPSX(cache_exception), KERNFRAME_SIZ, ra)
   1774 	.set	noat
   1775 	.mask	0x80000000, -4
   1776 #ifdef sbmips	/* XXX!  SB-1 needs a real cache error handler */
   1777 	eret
   1778 	nop
   1779 #endif
   1780 	PTR_LA	k0, panic			# return to panic
   1781 	PTR_LA	a0, 9f				# panicstr
   1782 	_MFC0	a1, MIPS_COP_0_ERROR_PC
   1783 #if defined(MIPS64_XLS) && defined(MIPS64)
   1784 	.set	push
   1785 	.set	arch=xlr
   1786 	li	k1, 0x309	/* L1D_CACHE_ERROR_LOG */
   1787 	mfcr	a2, k1
   1788 	li	k1, 0x30b	/* L1D_CACHE_INTERRUPT */
   1789 	mfcr	a3, k1
   1790 	.set	pop
   1791 #if defined(__mips_o32)
   1792 #error O32 not supported.
   1793 #endif
   1794 	mfc0	a4, MIPS_COP_0_STATUS
   1795 	mfc0	a5, MIPS_COP_0_CAUSE
   1796 #else
   1797 	mfc0	a2, MIPS_COP_0_ECC
   1798 	mfc0	a3, MIPS_COP_0_CACHE_ERR
   1799 #endif
   1800 
   1801 	_MTC0	k0, MIPS_COP_0_ERROR_PC		# set return address
   1802 	COP0_SYNC
   1803 
   1804 	mfc0	k0, MIPS_COP_0_STATUS		# restore status
   1805 	li	k1, MIPS3_SR_DIAG_PE		# ignore further errors
   1806 	or	k0, k1
   1807 	mtc0	k0, MIPS_COP_0_STATUS		# restore status
   1808 	COP0_SYNC
   1809 
   1810 	eret
   1811 
   1812 #if defined(MIPS64_XLS)
   1813 	MSG("cache error @ EPC %#lx\nL1D_CACHE_ERROR_LOG %#lx\nL1D_CACHE_INTERRUPT %#lx\nstatus %#x, cause %#x");
   1814 #else
   1815 	MSG("cache error @ EPC 0x%x ErrCtl 0x%x CacheErr 0x%x");
   1816 #endif
   1817 	.set	at
   1818 END(MIPSX(cache_exception))
   1819 
   1820 
   1821 /*----------------------------------------------------------------------------
   1822  *
   1823  *	R4000 TLB exception handlers
   1824  *
   1825  *----------------------------------------------------------------------------
   1826  */
   1827 
   1828 #if (PGSHIFT & 1) == 0
   1829 /*----------------------------------------------------------------------------
   1830  *
   1831  * mipsN_tlb_invalid_exception --
   1832  *
   1833  *	Handle a TLB invalid exception from kernel mode in kernel space.
   1834  *	The BaddVAddr, Context, and EntryHi registers contain the failed
   1835  *	virtual address.
   1836  *
   1837  *	If we are page sizes which use both TLB LO entries, either both
   1838  *	are valid or neither are.  So this exception should never happen.
   1839  *
   1840  * Results:
   1841  *	None.
   1842  *
   1843  * Side effects:
   1844  *	None.
   1845  *
   1846  *----------------------------------------------------------------------------
   1847  */
   1848 LEAF_NOPROFILE(MIPSX(kern_tlb_invalid_exception))
   1849 	.set	noat
   1850 	_MFC0	k0, MIPS_COP_0_BAD_VADDR	# get the fault address
   1851 #if !defined(_LP64) && (MIPS64 + MIPS64R2) > 0
   1852 #if VM_MIN_KERNEL_ADDRESS == MIPS_KSEG2_START
   1853 	li	k1, VM_MIN_KERNEL_ADDRESS	# compute index
   1854 	slt	k1, k0, k1
   1855 	bnez	k1, _C_LABEL(MIPSX(kern_gen_exception)) # full trap processing
   1856 	 nop
   1857 #elif VM_MIN_KERNEL_ADDRESS > MIPS_XKSEG_START
   1858 	li	k1, VM_MIN_KERNEL_ADDRESS>>32	# compute index
   1859 	dsll32	k1, k1, 0
   1860 	slt	k1, k0, k1
   1861 	bnez	k1, _C_LABEL(MIPSX(kern_gen_exception)) # full trap processing
   1862 	 nop
   1863 #endif
   1864 #endif /* !_LP64 && (MIPS64 + MIPS64R2) > 0 */
   1865 	PTR_LA	k1, _C_LABEL(pmap_limits)
   1866 	PTR_L	k1, PMAP_LIMITS_VIRTUAL_END(k1)
   1867 	PTR_SUBU k1, k0
   1868 	blez	k1, _C_LABEL(MIPSX(kern_gen_exception)) # full trap processing
   1869 	 nop
   1870 	PTR_LA	k1, _C_LABEL(pmap_kern_segtab)
   1871 #ifdef _LP64
   1872 #ifdef MIPSNNR2
   1873 	_EXT	k0, k0, XSEGSHIFT, XSEGLENGTH
   1874 	_INS	k1, k0, PTR_SCALESHIFT, XSEGLENGTH
   1875 #else
   1876 	PTR_SRL	k0, XSEGSHIFT - PTR_SCALESHIFT
   1877 	andi	k0, (NXSEGPG-1) << PTR_SCALESHIFT
   1878 	PTR_ADDU k1, k0
   1879 #endif
   1880 	_MFC0	k0, MIPS_COP_0_BAD_VADDR	# get the fault address (again)
   1881 	PTR_L	k1, (k1)			# load segtab address
   1882 	beqz	k1, _C_LABEL(MIPSX(kern_gen_exception))
   1883 	 nop
   1884 #endif /* _LP64 */
   1885 #ifdef MIPSNNR2
   1886 	_EXT	k0, k0, SEGSHIFT, SEGLENGTH
   1887 	_INS	k1, k0, PTR_SCALESHIFT, SEGLENGTH
   1888 #else
   1889 	PTR_SRL k0, SEGSHIFT - PTR_SCALESHIFT
   1890 	andi	k0, (NSEGPG-1) << PTR_SCALESHIFT
   1891 	PTR_ADDU k1, k0
   1892 #endif
   1893 	_MFC0	k0, MIPS_COP_0_BAD_VADDR	# get the fault address (again)
   1894 	PTR_L	k1, (k1)			# load page table address
   1895 	beqz	k1, _C_LABEL(MIPSX(kern_gen_exception))
   1896 	 nop
   1897 #ifdef MIPSNNR2
   1898 	_EXT	k0, k0, PGSHIFT, PTPLENGTH
   1899 	_INS	k1, k0, PTPSHIFT, PTPLENGTH
   1900 #else
   1901 	PTR_SRL k0, PTPLENGTH
   1902 	andi	k0, (NPTEPG-1) << PTPSHIFT
   1903 	PTR_ADDU k1, k0
   1904 #endif
   1905 	tlbp					# Probe the invalid entry
   1906 	COP0_SYNC
   1907 
   1908 	mfc0	k0, MIPS_COP_0_TLB_INDEX
   1909 	MFC0_HAZARD
   1910 	bltz	k0, _C_LABEL(MIPSX(kern_gen_exception)) # ASSERT(TLB entry exists)
   1911 	 nop					# - delay slot -
   1912 
   1913 	and	k0, k1, 4			# check even/odd page
   1914 #ifdef MIPS3
   1915 	nop					# required for QED 5230
   1916 #endif
   1917 	bnez	k0, MIPSX(kern_tlbi_odd)
   1918 	 nop
   1919 
   1920 	INT_L	k0, 0(k1)			# get PTE entry
   1921 #ifdef MIPSNNR2
   1922 	_EXT	k0, k0, 0, WIRED_POS		# get rid of "wired" bit
   1923 #else
   1924 	_SLL	k0, k0, WIRED_SHIFT		# get rid of "wired" bit
   1925 	_SRL	k0, k0, WIRED_SHIFT
   1926 #endif
   1927 	_MTC0	k0, MIPS_COP_0_TLB_LO0		# load PTE entry
   1928 	and	k0, k0, MIPS3_PG_V		# check for valid entry
   1929 #ifdef MIPS3
   1930 	nop					# required for QED5230
   1931 #endif
   1932 	beqz	k0, _C_LABEL(MIPSX(kern_gen_exception))	# PTE invalid
   1933 	 nop					# - delay slot -
   1934 
   1935 	INT_L	k0, 4(k1)			# get odd PTE entry
   1936 	mfc0	k1, MIPS_COP_0_TLB_INDEX
   1937 #ifdef MIPSNNR2
   1938 	_EXT	k0, k0, 0, WIRED_POS
   1939 #else
   1940 	_SLL	k0, k0, WIRED_SHIFT
   1941 	_SRL	k0, k0, WIRED_SHIFT
   1942 #endif
   1943 #if UPAGES == 1
   1944 	sltiu	k1, k1, MIPS3_TLB_WIRED_UPAGES	# Luckily this is MIPS3_PG_G
   1945 	or	k1, k1, k0
   1946 #endif
   1947 	_MTC0	k0, MIPS_COP_0_TLB_LO1		# load PTE entry
   1948 	COP0_SYNC
   1949 #ifdef MIPS3
   1950 	nop
   1951 	nop					# required for QED5230
   1952 #endif
   1953 	tlbwi					# write TLB
   1954 	COP0_SYNC
   1955 #ifdef MIPS3_LOONGSON2
   1956 	li	k0, MIPS_DIAG_ITLB_CLEAR
   1957 	mtc0	k0, MIPS_COP_0_DIAG		# invalidate ITLB
   1958 #elif defined(MIPS3)
   1959 	nop
   1960 	nop
   1961 #endif
   1962 	eret
   1963 
   1964 MIPSX(kern_tlbi_odd):
   1965 	INT_L	k0, 0(k1)			# get PTE entry
   1966 #ifdef MIPSNNR2
   1967 	_EXT	k0, k0, 0, WIRED_POS
   1968 #else
   1969 	_SLL	k0, k0, WIRED_SHIFT		# get rid of wired bit
   1970 	_SRL	k0, k0, WIRED_SHIFT
   1971 #endif
   1972 	_MTC0	k0, MIPS_COP_0_TLB_LO1		# load PTE entry
   1973 	COP0_SYNC
   1974 	and	k0, k0, MIPS3_PG_V		# check for valid entry
   1975 #ifdef MIPS3
   1976 	nop					# required for QED5230
   1977 #endif
   1978 	beqz	k0, _C_LABEL(MIPSX(kern_gen_exception))	# PTE invalid
   1979 	 nop					# - delay slot -
   1980 
   1981 	INT_L	k0, -4(k1)			# get even PTE entry
   1982 	mfc0	k1, MIPS_COP_0_TLB_INDEX
   1983 #ifdef MIPSNNR2
   1984 	_EXT	k0, k0, 0, WIRED_POS
   1985 #else
   1986 	_SLL	k0, k0, WIRED_SHIFT
   1987 	_SRL	k0, k0, WIRED_SHIFT
   1988 #endif
   1989 #if UPAGES == 1
   1990 	sltiu	k1, k1, MIPS3_TLB_WIRED_UPAGES	# Luckily this is MIPS3_PG_G
   1991 	or	k1, k1, k0
   1992 #endif
   1993 	_MTC0	k0, MIPS_COP_0_TLB_LO0		# load PTE entry
   1994 	COP0_SYNC
   1995 #ifdef MIPS3
   1996 	nop					# required for QED5230
   1997 #endif
   1998 	tlbwi					# update TLB
   1999 	COP0_SYNC
   2000 #ifdef MIPS3_LOONGSON2
   2001 	li	k0, MIPS_DIAG_ITLB_CLEAR
   2002 	mtc0	k0, MIPS_COP_0_DIAG		# invalidate ITLB
   2003 #elif defined(MIPS3)
   2004 	nop
   2005 	nop
   2006 #endif
   2007 	eret
   2008 END(MIPSX(kern_tlb_invalid_exception))
   2009 #endif /* (PGSHIFT & 1) == 0 */
   2010 
   2011 /*
   2012  * Mark where code entered from exception handler jumptable
   2013  * ends, for stack traceback code.
   2014  */
   2015 
   2016 	.globl	_C_LABEL(MIPSX(exceptionentry_end))
   2017 _C_LABEL(MIPSX(exceptionentry_end)):
   2018 
   2019 	.set	at
   2020 
   2021 /*--------------------------------------------------------------------------
   2022  *
   2023  * mipsN_tlb_get_asid --
   2024  *
   2025  *	Return the current ASID
   2026  *
   2027  *	tlb_asid_t mipsN_tlb_get_asid(void)
   2028  *
   2029  * Results:
   2030  *	Return the current ASID.
   2031  *
   2032  * Side effects:
   2033  *	None.
   2034  *
   2035  *--------------------------------------------------------------------------
   2036  */
   2037 LEAF(MIPSX(tlb_get_asid))
   2038 	_MFC0	v0, MIPS_COP_0_TLB_HI		# read the hi reg value
   2039 	MFC0_HAZARD
   2040 	jr	ra
   2041 	 and	v0, v0, MIPS3_TLB_ASID		# make off ASID
   2042 END(MIPSX(tlb_get_asid))
   2043 
   2044 /*--------------------------------------------------------------------------
   2045  *
   2046  * mipsN_tlb_set_asid --
   2047  *
   2048  *	Write the given pid into the TLB pid reg.
   2049  *
   2050  *	void mipsN_tlb_set_asid(tlb_asid_t pid)
   2051  *
   2052  * Results:
   2053  *	None.
   2054  *
   2055  * Side effects:
   2056  *	ASID set in the entry hi register.
   2057  *
   2058  *--------------------------------------------------------------------------
   2059  */
   2060 LEAF(MIPSX(tlb_set_asid))
   2061 	_MFC0	v0, MIPS_COP_0_TLB_HI		# read the hi reg value
   2062 #ifdef MIPSNNR2
   2063 	_INS	v0, a0, V_MIPS3_PG_ASID, S_MIPS3_PG_ASID
   2064 #else
   2065 	li	t0, MIPS3_PG_ASID
   2066 	not	t1, t0
   2067 	and	v0, v0, t1
   2068 	and	a0, a0, t0
   2069 	or	v0, v0, a0
   2070 #endif
   2071 	_MTC0	v0, MIPS_COP_0_TLB_HI		# Write the hi reg value
   2072 	JR_HB_RA
   2073 END(MIPSX(tlb_set_asid))
   2074 
   2075 /*--------------------------------------------------------------------------
   2076  *
   2077  * mipsN_tlb_update_addr --
   2078  *
   2079  *	Update the TLB if found; otherwise insert randomly if requested
   2080  *
   2081  *	bool mipsN_tlb_update(vaddr_t va, tlb_asid_t asid, pt_entry_t pte,
   2082  *	    bool insert)
   2083  *
   2084  * Results:
   2085  *	false (0) if skipped, true (1) if updated.
   2086  *
   2087  * Side effects:
   2088  *	None.
   2089  *
   2090  *--------------------------------------------------------------------------
   2091  */
   2092 LEAF(MIPSX(tlb_update_addr))
   2093 #ifdef MIPSNNR2
   2094 	di	ta0				# Disable interrupts
   2095 #else
   2096 	mfc0	ta0, MIPS_COP_0_STATUS		# Save the status register.
   2097 	mtc0	zero, MIPS_COP_0_STATUS		# Disable interrupts
   2098 #endif
   2099 	COP0_SYNC
   2100 #if (PGSHIFT & 1) == 0
   2101 	and	t1, a0, MIPS3_PG_ODDPG		# t1 = Even/Odd flag
   2102 #endif
   2103 	and	a1, a1, MIPS3_PG_ASID
   2104 #ifdef MIPSNNR2
   2105 	_INS	a0, a1, 0, V_MIPS3_PG_HVPN	# insert ASID + clear other bits
   2106 #else
   2107 	li	v0, MIPS3_PG_HVPN
   2108 	and	a0, a0, v0
   2109 	or	a0, a0, a1			# Merge ASID
   2110 #endif
   2111 	_MFC0	ta1, MIPS_COP_0_TLB_HI		# Save current ASID
   2112 	_MTC0	a0, MIPS_COP_0_TLB_HI		# Init high reg
   2113 	COP0_SYNC
   2114 #if (PGSHIFT & 1) == 0
   2115 	and	t0, a2, MIPS3_PG_G		# Copy global bit
   2116 #endif
   2117 	tlbp					# Probe for the entry.
   2118 	COP0_SYNC
   2119 #ifdef MIPSNNR2
   2120 	_EXT	a1, a2, 0, WIRED_POS		# clear top bits of new pte
   2121 #else
   2122 	_SLL	a2, WIRED_SHIFT			# clear top bits of new pte
   2123 	_SRL	a1, a2, WIRED_SHIFT
   2124 #endif
   2125 	mfc0	v1, MIPS_COP_0_TLB_INDEX	# See what we got
   2126 #ifdef MIPS3
   2127 	nop
   2128 	nop					# required for QED5230
   2129 #endif
   2130 
   2131 #if (PGSHIFT & 1)
   2132 	bgez	v1, 1f				# index < 0 => !present
   2133 	 REG_ADDU a2, a1, MIPS3_PG_NEXT
   2134 	beqz	a3, 7f
   2135 	 li	v0, 0
   2136 1:	_MTC0	a1, MIPS_COP_0_TLB_LO0		# init low reg0.
   2137 	_MTC0	a2, MIPS_COP_0_TLB_LO1		# init low reg1.
   2138 	bltz	v1, 5f				# index < 0 => !present
   2139 	 nop
   2140 	COP0_SYNC
   2141 	tlbwi					# overwrite entry
   2142 	b	6f
   2143 	 nop
   2144 #else /* (PGSHIFT & 1) == 0 */
   2145 	bltz	v1, 3f				# index < 0 => !found
   2146 	 nop
   2147 	tlbr					# update, read entry first
   2148 	COP0_SYNC
   2149 	bnez	t1, 1f				# Decide even odd
   2150 	 nop
   2151 # EVEN
   2152 	_MTC0	a1, MIPS_COP_0_TLB_LO0		# init low reg0.
   2153 	b	2f
   2154 	 nop
   2155 1:
   2156 # ODD
   2157 	_MTC0	a1, MIPS_COP_0_TLB_LO1		# init low reg1.
   2158 2:
   2159 	COP0_SYNC
   2160 	tlbwi					# update slot found
   2161 	b	6f
   2162 	 nop
   2163 3:
   2164 	beqz	a3, 7f				# not found and no insert
   2165 	 li	v0, 0				# assume failure
   2166 	bnez	t1, 4f				# Decide even odd
   2167 	 nop
   2168 	move	t3, a1				# swap a1 and t0
   2169 	move	a1, t0				#
   2170 	move	t0, t3				#
   2171 4:
   2172 	_MTC0	t0, MIPS_COP_0_TLB_LO0		# init low reg0.
   2173 	_MTC0	a1, MIPS_COP_0_TLB_LO1		# init low reg1.
   2174 #endif /* PGSHIFT & 1 */
   2175 5:
   2176 	COP0_SYNC
   2177 	tlbwr					# enter randomly
   2178 6:
   2179 	COP0_SYNC
   2180 #ifdef MIPS3_LOONGSON2
   2181 	li	t1, MIPS_DIAG_ITLB_CLEAR
   2182 	mtc0	t1, MIPS_COP_0_DIAG		# invalidate ITLB
   2183 #elif defined(MIPS3)
   2184 	nop					# required for QED5230
   2185 	nop					# required for QED5230
   2186 #endif
   2187 	li	v0, 1				# found or inserted
   2188 #ifdef MIPS3
   2189 	nop					# Make sure pipeline
   2190 	nop					# advances before we
   2191 	nop					# use the TLB.
   2192 	nop
   2193 #endif
   2194 7:
   2195 	_MTC0	ta1, MIPS_COP_0_TLB_HI		# restore ASID
   2196 	COP0_SYNC
   2197 #ifdef MIPS3
   2198 	nop					# required for QED5230
   2199 	nop					# required for QED5230
   2200 #endif
   2201 	mtc0	ta0, MIPS_COP_0_STATUS		# Restore the status register
   2202 	JR_HB_RA
   2203 END(MIPSX(tlb_update_addr))
   2204 
   2205 /*--------------------------------------------------------------------------
   2206  *
   2207  * mipsN_tlb_read_entry --
   2208  *
   2209  *	Read the TLB entry.
   2210  *
   2211  *	void mipsN_tlb_read_entry(size_t tlb_index, struct tlbmask *tlb);
   2212  *
   2213  * Results:
   2214  *	None.
   2215  *
   2216  * Side effects:
   2217  *	tlb will contain the TLB entry found.
   2218  *
   2219  *--------------------------------------------------------------------------
   2220  */
   2221 LEAF(MIPSX(tlb_read_entry))
   2222 	mfc0	v1, MIPS_COP_0_STATUS		# Save the status register.
   2223 	mtc0	zero, MIPS_COP_0_STATUS		# Disable interrupts
   2224 	COP0_SYNC
   2225 #ifdef MIPS3
   2226 	nop
   2227 #endif
   2228 	mfc0	ta2, MIPS_COP_0_TLB_PG_MASK	# save current pgMask
   2229 #ifdef MIPS3
   2230 	nop
   2231 #endif
   2232 	_MFC0	t0, MIPS_COP_0_TLB_HI		# Get current ASID
   2233 
   2234 	mtc0	a0, MIPS_COP_0_TLB_INDEX	# Set the index register
   2235 	COP0_SYNC
   2236 #ifdef MIPS3
   2237 	nop
   2238 	nop					# required for QED5230
   2239 #endif
   2240 	tlbr					# Read from the TLB
   2241 	COP0_SYNC
   2242 #ifdef MIPS3
   2243 	nop
   2244 	nop
   2245 	nop
   2246 #endif
   2247 	mfc0	t2, MIPS_COP_0_TLB_PG_MASK	# fetch the pgMask
   2248 	_MFC0	t3, MIPS_COP_0_TLB_HI		# fetch the hi entry
   2249 	_MFC0	ta0, MIPS_COP_0_TLB_LO0		# See what we got
   2250 	_MFC0	ta1, MIPS_COP_0_TLB_LO1		# See what we got
   2251 	_MTC0	t0, MIPS_COP_0_TLB_HI		# restore ASID
   2252 	mtc0	ta2, MIPS_COP_0_TLB_PG_MASK	# restore pgMask
   2253 	COP0_SYNC
   2254 	mtc0	v1, MIPS_COP_0_STATUS		# Restore the status register
   2255 	COP0_SYNC
   2256 	PTR_S	t3, TLBMASK_HI(a1)
   2257 	REG_S	ta0, TLBMASK_LO0(a1)
   2258 	REG_S	ta1, TLBMASK_LO1(a1)
   2259 	jr	ra
   2260 	 INT_S	t2, TLBMASK_MASK(a1)
   2261 END(MIPSX(tlb_read_entry))
   2262 
   2263 /*--------------------------------------------------------------------------
   2264  *
   2265  * void mipsN_tlb_invalidate_addr(vaddr_t va, tlb_asid_t asid)
   2266  *
   2267  * Invalidate a TLB entry which has the given vaddr and ASID if found.
   2268  *--------------------------------------------------------------------------
   2269  */
   2270 LEAF_NOPROFILE(MIPSX(tlb_invalidate_addr))
   2271 	mfc0	ta0, MIPS_COP_0_STATUS		# save status register
   2272 	mtc0	zero, MIPS_COP_0_STATUS		# disable interrupts
   2273 	COP0_SYNC
   2274 
   2275 #if (PGSHIFT & 1) == 0
   2276 	_SRL	a2, a0, V_MIPS3_PG_ODDPG - V_MIPS3_PG_V
   2277 	and	a2, MIPS3_PG_V			# lo0 V bit
   2278 	xor	a3, a2, MIPS3_PG_V		# lo1 V bit
   2279 #endif
   2280 	and	a1, a1, MIPS3_PG_ASID
   2281 #ifdef MIPSNNR2
   2282 	_INS	a0, a1, 0, V_MIPS3_PG_HVPN
   2283 #else
   2284 	_SRA	a0, V_MIPS3_PG_HVPN		# clear bottom bits of VA
   2285 	_SLL	a0, V_MIPS3_PG_HVPN		# clear bottom bits of VA
   2286 	or	a0, a0, a1
   2287 #endif
   2288 	_MFC0	ta1, MIPS_COP_0_TLB_HI		# save current ASID
   2289 	mfc0	ta2, MIPS_COP_0_TLB_PG_MASK	# save current pgMask
   2290 	_MTC0	a0, MIPS_COP_0_TLB_HI		# look for the vaddr & ASID
   2291 	COP0_SYNC
   2292 	tlbp					# probe the entry in question
   2293 	COP0_SYNC
   2294 	mfc0	v0, MIPS_COP_0_TLB_INDEX	# see what we got
   2295 	MFC0_HAZARD
   2296 	bltz	v0, 2f				# index < 0 then skip
   2297 	 li	t2, MIPS_KSEG0_START		# invalid address
   2298 	PTR_SLL	v0, PGSHIFT | 1			# PAGE_SHIFT | 1
   2299 	PTR_ADDU t2, v0
   2300 	move	t0, zero
   2301 	move	t1, zero
   2302 #if (PGSHIFT & 1) == 0
   2303 	tlbr					# read entry
   2304 	COP0_SYNC
   2305 	_MFC0	t0, MIPS_COP_0_TLB_LO0		# fetch entryLo0
   2306 	_MFC0	t1, MIPS_COP_0_TLB_LO1		# fetch entryLo1
   2307 #ifdef MIPS3
   2308 	nop
   2309 #endif
   2310 	and	a2, t0				# a2=valid entryLo0 afterwards
   2311 	and	a3, t1				# a3=valid entryLo1 afterwards
   2312 	or	v0, a2, a3			# will one be valid?
   2313 #ifdef MIPSNNX
   2314 #error Global bit is lost here when V==0 and it needs to be preserved
   2315 	movz	t0, zero, a2			# zero lo0 if V would not be set
   2316 	movz	t1, zero, a3			# zero lo1 if V would not be set
   2317 	movn	t2, a0, v0			# yes, keep VA the same
   2318 #else
   2319 	_SLL	a2, a2, PG_V_LSHIFT		# move V to MSB
   2320 	_SRA	a2, a2, PG_V_RSHIFT		# fill with MSB
   2321 	or	a2, MIPS3_PG_G			# mask needs to preserve G
   2322 	and	t0, t0, a2			# zero lo0 if V would not be set
   2323 	_SLL	a3, a3, PG_V_LSHIFT		# move V to MSB
   2324 	_SRA	a3, a3, PG_V_RSHIFT		# fill with MSB
   2325 	or	a3, MIPS3_PG_G			# mask needs to preserve G
   2326 	beqz	v0, 1f				# no valid entry
   2327 	 and	t1, t1, a3			# zero lo1 if V would not be set
   2328 	move	t2, a0				# we need entryHi to be valid
   2329 1:
   2330 #endif /* MIPSNN */
   2331 #endif /* (PGSHIFT & 1) == 0 */
   2332 	_MTC0	t0, MIPS_COP_0_TLB_LO0		# zero out entryLo0
   2333 	_MTC0	t1, MIPS_COP_0_TLB_LO1		# zero out entryLo1
   2334 	_MTC0	t2, MIPS_COP_0_TLB_HI		# make entryHi invalid
   2335 #if 0
   2336 	mtc0	zero, MIPS_COP_0_TLB_PG_MASK	# zero out pageMask
   2337 #endif
   2338 	COP0_SYNC
   2339 #ifdef MIPS3
   2340 	nop
   2341 	nop
   2342 #endif
   2343 
   2344 	tlbwi
   2345 	COP0_SYNC
   2346 #ifdef MIPS3_LOONGSON2
   2347 	li	v0, MIPS_DIAG_ITLB_CLEAR
   2348 	mtc0	v0, MIPS_COP_0_DIAG		# invalidate ITLB
   2349 #elif defined(MIPS3)
   2350 	nop
   2351 	nop
   2352 #endif
   2353 2:
   2354 	mtc0	ta2, MIPS_COP_0_TLB_PG_MASK	# restore pgMask
   2355 	_MTC0	ta1, MIPS_COP_0_TLB_HI		# restore current ASID
   2356 	COP0_SYNC
   2357 	mtc0	ta0, MIPS_COP_0_STATUS		# restore status register
   2358 	JR_HB_RA
   2359 END(MIPSX(tlb_invalidate_addr))
   2360 
   2361 /*
   2362  * void mipsN_tlb_invalidate_asids(uint32_t base, uint32_t limit);
   2363  *
   2364  * Invalidate TLB entries belong to per process user spaces with
   2365  * base <= ASIDs <= limit while leaving entries for kernel space
   2366  * marked global intact.
   2367  */
   2368 LEAF_NOPROFILE(MIPSX(tlb_invalidate_asids))
   2369 	mfc0	v1, MIPS_COP_0_STATUS		# save status register
   2370 	mtc0	zero, MIPS_COP_0_STATUS		# disable interrupts
   2371 	COP0_SYNC
   2372 
   2373 	_MFC0	t0, MIPS_COP_0_TLB_HI		# Save the current ASID.
   2374 	mfc0	t1, MIPS_COP_0_TLB_WIRED
   2375 	li	v0, MIPS_KSEG0_START		# invalid address
   2376 	INT_L	t2, _C_LABEL(mips_options) + MO_NUM_TLB_ENTRIES
   2377 	mfc0	t3, MIPS_COP_0_TLB_PG_MASK	# save current pgMask
   2378 
   2379 	# do {} while (t1 < t2)
   2380 1:
   2381 	mtc0	t1, MIPS_COP_0_TLB_INDEX	# set index
   2382 	COP0_SYNC
   2383 	sll	ta0, t1, PGSHIFT | 1		# PAGE_SHIFT | 1
   2384 	tlbr					# obtain an entry
   2385 	COP0_SYNC
   2386 	_MFC0	ta1, MIPS_COP_0_TLB_LO1
   2387 	MFC0_HAZARD
   2388 	and	ta1, MIPS3_PG_G			# check to see it has G bit
   2389 	bnez	ta1, 2f				# yep, skip this one.
   2390 	 nop
   2391 	_MFC0	ta1, MIPS_COP_0_TLB_HI		# get VA and ASID
   2392 	MFC0_HAZARD
   2393 	and	ta1, MIPS3_PG_ASID		# focus on ASID
   2394 	sltu	a3, ta1, a0			# asid < base?
   2395 	bnez	a3, 2f				# yes, skip this entry.
   2396 	 nop
   2397 	sltu	a3, a1, ta1			# limit < asid
   2398 	bnez	a3, 2f				# yes, skip this entry.
   2399 	 nop
   2400 	PTR_ADDU ta0, v0
   2401 
   2402 	_MTC0	ta0, MIPS_COP_0_TLB_HI		# make entryHi invalid
   2403 	_MTC0	zero, MIPS_COP_0_TLB_LO0	# zero out entryLo0
   2404 	_MTC0	zero, MIPS_COP_0_TLB_LO1	# zero out entryLo1
   2405 	mtc0	zero, MIPS_COP_0_TLB_PG_MASK	# zero out mask entry
   2406 	COP0_SYNC
   2407 	tlbwi					# invalidate the TLB entry
   2408 	COP0_SYNC
   2409 2:
   2410 	addu	t1, 1
   2411 	bne	t1, t2, 1b
   2412 	 nop
   2413 
   2414 	_MTC0	t0, MIPS_COP_0_TLB_HI		# restore ASID.
   2415 	mtc0	t3, MIPS_COP_0_TLB_PG_MASK	# restore pgMask
   2416 	COP0_SYNC
   2417 
   2418 #ifdef MIPS3_LOONGSON2
   2419 	li	v0, MIPS_DIAG_ITLB_CLEAR
   2420 	mtc0	v0, MIPS_COP_0_DIAG		# invalidate ITLB
   2421 #endif
   2422 
   2423 	mtc0	v1, MIPS_COP_0_STATUS		# restore status register
   2424 	JR_HB_RA				# new ASID will be set soon
   2425 END(MIPSX(tlb_invalidate_asids))
   2426 
   2427 #ifdef MULTIPROCESSOR
   2428 /*
   2429  * void mipsN_tlb_invalidate_globals(void);
   2430  *
   2431  * Invalidate the non-wired TLB entries belonging to kernel space while
   2432  * leaving entries for user space (not marked global) intact.
   2433  */
   2434 LEAF_NOPROFILE(MIPSX(tlb_invalidate_globals))
   2435 	mfc0	v1, MIPS_COP_0_STATUS		# save status register
   2436 	mtc0	zero, MIPS_COP_0_STATUS		# disable interrupts
   2437 	COP0_SYNC
   2438 
   2439 	_MFC0	t0, MIPS_COP_0_TLB_HI		# save current ASID
   2440 	mfc0	t1, MIPS_COP_0_TLB_WIRED
   2441 	li	v0, MIPS_KSEG0_START		# invalid address
   2442 	INT_L	t2, _C_LABEL(mips_options) + MO_NUM_TLB_ENTRIES
   2443 	mfc0	t3, MIPS_COP_0_TLB_PG_MASK	# save current pgMask
   2444 
   2445 	# do {} while (t1 < t2)
   2446 1:
   2447 	mtc0	t1, MIPS_COP_0_TLB_INDEX	# set index
   2448 	COP0_SYNC
   2449 	sll	ta0, t1, PGSHIFT | 1		# PAGE_SHIFT | 1
   2450 	tlbr					# obtain an entry
   2451 	COP0_SYNC
   2452 	_MFC0	a0, MIPS_COP_0_TLB_LO1
   2453 	MFC0_HAZARD
   2454 	and	a0, MIPS3_PG_G			# check to see it has G bit
   2455 	beqz	a0, 2f				# no, skip this entry
   2456 	 nop
   2457 	PTR_ADDU ta0, v0
   2458 
   2459 	_MTC0	ta0, MIPS_COP_0_TLB_HI		# make entryHi invalid
   2460 	_MTC0	zero, MIPS_COP_0_TLB_LO0	# zero out entryLo0
   2461 	_MTC0	zero, MIPS_COP_0_TLB_LO1	# zero out entryLo1
   2462 	mtc0	zero, MIPS_COP_0_TLB_PG_MASK	# zero out mask entry
   2463 	COP0_SYNC
   2464 	tlbwi					# invalidate the TLB entry
   2465 	COP0_SYNC
   2466 2:
   2467 	addu	t1, 1
   2468 	bne	t1, t2, 1b
   2469 	 nop
   2470 
   2471 	_MTC0	t0, MIPS_COP_0_TLB_HI		# restore current ASID
   2472 	mtc0	t3, MIPS_COP_0_TLB_PG_MASK	# restore pgMask
   2473 	COP0_SYNC
   2474 
   2475 #ifdef MIPS3_LOONGSON2
   2476 	li	v0, MIPS_DIAG_ITLB_CLEAR
   2477 	mtc0	v0, MIPS_COP_0_DIAG		# invalidate ITLB
   2478 #endif
   2479 
   2480 	mtc0	v1, MIPS_COP_0_STATUS		# restore status register
   2481 	JR_HB_RA
   2482 END(MIPSX(tlb_invalidate_globals))
   2483 #endif /* MULTIPROCESSOR */
   2484 
   2485 /*
   2486  * void mipsN_tlb_invalidate_all(void);
   2487  *
   2488  * Invalidate all of non-wired TLB entries.
   2489  */
   2490 LEAF_NOPROFILE(MIPSX(tlb_invalidate_all))
   2491 	mfc0	ta0, MIPS_COP_0_STATUS		# save status register
   2492 	mtc0	zero, MIPS_COP_0_STATUS		# disable interrupts
   2493 	COP0_SYNC
   2494 
   2495 	INT_L	a0, _C_LABEL(mips_options) + MO_NUM_TLB_ENTRIES
   2496 
   2497 	mfc0	t0, MIPS_COP_0_TLB_WIRED
   2498 	_MFC0	ta1, MIPS_COP_0_TLB_HI		# save current ASID
   2499 	mfc0	ta2, MIPS_COP_0_TLB_PG_MASK	# save current pgMask
   2500 	COP0_SYNC
   2501 	li	v0, MIPS_KSEG0_START		# invalid address
   2502 	sll	v1, t0, PGSHIFT | 1		# PAGE_SHIFT | 1
   2503 	PTR_ADDU v0, v1
   2504 #if (1 << (PGSHIFT|1)) >= 0x8000
   2505 	li	v1, 1
   2506 	sll	v1, PGSHIFT | 1			# PAGE_SHIFT | 1
   2507 #else
   2508 	li	v1, 1 << (PGSHIFT | 1)
   2509 #endif
   2510 
   2511 	_MTC0	zero, MIPS_COP_0_TLB_LO0	# zero out entryLo0
   2512 	_MTC0	zero, MIPS_COP_0_TLB_LO1	# zero out entryLo1
   2513 	mtc0	zero, MIPS_COP_0_TLB_PG_MASK	# zero out pageMask
   2514 
   2515 	# do {} while (t0 < a0)
   2516 1:
   2517 	mtc0	t0, MIPS_COP_0_TLB_INDEX	# set TLBindex
   2518 	_MTC0	v0, MIPS_COP_0_TLB_HI		# make entryHi invalid
   2519 	COP0_SYNC
   2520 	tlbwi					# clear the entry
   2521 	COP0_SYNC
   2522 	addu	t0, 1				# increment index
   2523 	bne	t0, a0, 1b
   2524 	 PTR_ADDU v0, v1
   2525 
   2526 	mtc0	ta2, MIPS_COP_0_TLB_PG_MASK	# restore pgMask
   2527 	_MTC0	ta1, MIPS_COP_0_TLB_HI		# restore ASID
   2528 	COP0_SYNC
   2529 
   2530 #ifdef MIPS3_LOONGSON2
   2531 	li	v0, MIPS_DIAG_ITLB_CLEAR
   2532 	mtc0	v0, MIPS_COP_0_DIAG		# invalidate ITLB
   2533 #endif
   2534 
   2535 	mtc0	ta0, MIPS_COP_0_STATUS		# restore status register
   2536 	JR_HB_RA
   2537 END(MIPSX(tlb_invalidate_all))
   2538 
   2539 /*
   2540  * u_int mipsN_tlb_record_asids(u_long *bitmap, tlb_asid_t asid_max)
   2541  *
   2542  * Record all the ASIDs in use in the TLB and return the number of different
   2543  * ASIDs present.
   2544  */
   2545 LEAF_NOPROFILE(MIPSX(tlb_record_asids))
   2546 	_MFC0	a3, MIPS_COP_0_TLB_HI		# Save the current ASID.
   2547 	mfc0	ta0, MIPS_COP_0_TLB_WIRED
   2548 	INT_L	ta1, _C_LABEL(mips_options) + MO_NUM_TLB_ENTRIES
   2549 	mfc0	t3, MIPS_COP_0_TLB_PG_MASK	# save current pgMask
   2550 	move	ta2, zero
   2551 	li	ta3, 1
   2552 	move	v0, zero			# start at zero ASIDs
   2553 
   2554 #ifdef MIPSNNR2
   2555 	di	v1				# disable interrupts
   2556 #else
   2557 	mfc0	v1, MIPS_COP_0_STATUS		# save status register
   2558 #ifdef _LP64
   2559 	and	t0, v1, MIPS_SR_INT_IE
   2560 	xor	t0, v1
   2561 	mtc0	t0, MIPS_COP_0_STATUS		# disable interrupts
   2562 #else
   2563 	mtc0	zero, MIPS_COP_0_STATUS		# disable interrupts
   2564 #endif
   2565 #endif
   2566 	COP0_SYNC
   2567 
   2568 	# do {} while (ta0 < ta1)
   2569 1:
   2570 	mtc0	ta0, MIPS_COP_0_TLB_INDEX	# set index
   2571 	COP0_SYNC
   2572 	tlbr					# obtain an entry
   2573 	COP0_SYNC
   2574 	_MFC0	t0, MIPS_COP_0_TLB_LO1
   2575 	MFC0_HAZARD
   2576 	and	t0, MIPS3_PG_G			# check to see it has G bit
   2577 	bnez	t0, 4f				# yep, skip this one.
   2578 	 nop
   2579 
   2580 	_MFC0	t0, MIPS_COP_0_TLB_HI		# get VA and ASID
   2581 	MFC0_HAZARD
   2582 	and	t0, t0, MIPS3_PG_ASID		# focus on ASID
   2583 	bgt	t0, a1, 4f			# > ASID max? skip
   2584 	 nop
   2585 
   2586 	srl	a2, t0, 3 + LONG_SCALESHIFT	# drop low 5 or 6 bits
   2587 	sll	a2, LONG_SCALESHIFT		# make an index for the bitmap
   2588 	_SLLV	t0, ta3, t0			# t0 is mask (ta3 == 1)
   2589 
   2590 	PTR_ADDU a2, a0				# index into the bitmap
   2591 	beq	a2, ta2, 3f			# is the desired cell loaded?
   2592 	 nop					#   yes, don't reload it
   2593 	beqz	ta2, 2f				# have we ever loaded it?
   2594 	 nop					#   nope, so don't save it
   2595 
   2596 	LONG_S	t2, 0(ta2)			# save the updated value.
   2597 2:
   2598 	move	ta2, a2				# remember the new cell's addr
   2599 	LONG_L	t2, 0(ta2)			# and load it
   2600 3:
   2601 	and	t1, t2, t0			# see if this asid was recorded
   2602 	sltu	t1, t1, ta3			# t1 = t1 < 1 (aka t1 == 0)
   2603 	addu	v0, t1				# v0 += t1
   2604 	or	t2, t0				# or in the new ASID bits
   2605 
   2606 4:
   2607 	addu	ta0, 1				# increment TLB entry #
   2608 	bne	ta0, ta1, 1b			# keep lookup if not limit
   2609 	 nop
   2610 
   2611 	beqz	ta2, 5f				# do we have a cell to write?
   2612 	 nop					#   nope, nothing.
   2613 
   2614 	LONG_S	t2, 0(ta2)			# save the updated value.
   2615 5:
   2616 	mtc0	t3, MIPS_COP_0_TLB_PG_MASK	# restore pgMask
   2617 	_MTC0	a3, MIPS_COP_0_TLB_HI		# restore ASID
   2618 	COP0_SYNC
   2619 
   2620 	mtc0	v1, MIPS_COP_0_STATUS		# restore status register
   2621 	JR_HB_RA
   2622 END(MIPSX(tlb_record_asids))
   2623 
   2624 /*
   2625  * mipsN_lwp_trampoline()
   2626  *
   2627  * Arrange for a function to be invoked neatly, after a cpu_switch().
   2628  * Call the service function with one argument, specified by the s0
   2629  * and s1 respectively.  There is no need register save operation.
   2630  * XXX - Not profiled because we pass an arg in with v0 which isn't
   2631  *       preserved by _mcount()
   2632  */
   2633 LEAF_NOPROFILE(MIPSX(lwp_trampoline))
   2634 	PTR_ADDU sp, -CALLFRAME_SIZ
   2635 
   2636 	# Call lwp_startup(), with args from cpu_switchto()/cpu_lwp_fork()
   2637 	move	a0, v0
   2638 	jal	_C_LABEL(lwp_startup)
   2639 	 move	a1, MIPS_CURLWP
   2640 
   2641 	# Call the routine specified by cpu_lwp_fork()
   2642 	jalr	s0
   2643 	 move	a0, s1
   2644 
   2645 	#
   2646 	# Return to user (won't happen if a kernel thread)
   2647 	#
   2648 	# Make sure to disable interrupts here, as otherwise
   2649 	# we can take an interrupt *after* EXL is set, and
   2650 	# end up returning to a bogus PC since the PC is not
   2651 	# saved if EXL=1.
   2652 	#
   2653 	.set	noat
   2654 MIPSX(user_return):
   2655 	REG_L	s0, CALLFRAME_SIZ+TF_REG_S0(sp)		# $16
   2656 	REG_L	s1, CALLFRAME_SIZ+TF_REG_S1(sp)		# $17
   2657 	REG_L	s2, CALLFRAME_SIZ+TF_REG_S2(sp)		# $18
   2658 	REG_L	s3, CALLFRAME_SIZ+TF_REG_S3(sp)		# $19
   2659 	REG_L	s4, CALLFRAME_SIZ+TF_REG_S4(sp)		# $20
   2660 	REG_L	s5, CALLFRAME_SIZ+TF_REG_S5(sp)		# $21
   2661 	REG_L	s6, CALLFRAME_SIZ+TF_REG_S6(sp)		# $22
   2662 	REG_L	s7, CALLFRAME_SIZ+TF_REG_S7(sp)		# $23
   2663 	REG_L	s8, CALLFRAME_SIZ+TF_REG_S8(sp)		# $30
   2664 MIPSX(user_intr_return):
   2665 #ifdef PARANOIA
   2666 	PTR_L	t0, L_CPU(MIPS_CURLWP)
   2667 	INT_L	t1, CPU_INFO_CPL(t0)			# get curcpu()->ci_cpl
   2668 2:	bnez	t1, 2b
   2669 	 nop
   2670 #endif
   2671 	RESET_EXCEPTION_LEVEL_DISABLE_INTERRUPTS(v0)
   2672 	COP0_SYNC
   2673 	SET_EXCEPTION_LEVEL(v0)			# set exception level
   2674 	COP0_SYNC
   2675 	REG_L	t0, CALLFRAME_SIZ+TF_REG_MULLO(sp)
   2676 	REG_L	t1, CALLFRAME_SIZ+TF_REG_MULHI(sp)
   2677 	REG_L	v0, CALLFRAME_SIZ+TF_REG_EPC(sp)
   2678 	mtlo	t0
   2679 	mthi	t1
   2680 	_MTC0	v0, MIPS_COP_0_EXC_PC
   2681 	COP0_SYNC
   2682 	move	k1, sp
   2683 	REG_L	AT, CALLFRAME_SIZ+TF_REG_AST(k1)	# $1
   2684 	REG_L	v0, CALLFRAME_SIZ+TF_REG_V0(k1)		# $2
   2685 	REG_L	v1, CALLFRAME_SIZ+TF_REG_V1(k1)		# $3
   2686 	REG_L	a0, CALLFRAME_SIZ+TF_REG_A0(k1)		# $4
   2687 	REG_L	a1, CALLFRAME_SIZ+TF_REG_A1(k1)		# $5
   2688 	REG_L	a2, CALLFRAME_SIZ+TF_REG_A2(k1)		# $6
   2689 	REG_L	a3, CALLFRAME_SIZ+TF_REG_A3(k1)		# $7
   2690 	REG_L	t0, CALLFRAME_SIZ+TF_REG_T0(k1)		# $12 /  $8
   2691 	REG_L	t1, CALLFRAME_SIZ+TF_REG_T1(k1)		# $13 /  $9
   2692 	REG_L	t2, CALLFRAME_SIZ+TF_REG_T2(k1)		# $14 / $10
   2693 	REG_L	t3, CALLFRAME_SIZ+TF_REG_T3(k1)		# $15 / $11
   2694 	REG_L	ta0, CALLFRAME_SIZ+TF_REG_TA0(k1)	#  $8 / $12
   2695 	REG_L	ta1, CALLFRAME_SIZ+TF_REG_TA1(k1)	#  $9 / $13
   2696 	REG_L	ta2, CALLFRAME_SIZ+TF_REG_TA2(k1)	# $10 / $14
   2697 	REG_L	ta3, CALLFRAME_SIZ+TF_REG_TA3(k1)	# $11 / $15
   2698 	REG_L	t8, CALLFRAME_SIZ+TF_REG_T8(k1)		# $24 MIPS_CURLWP
   2699 	REG_L	t9, CALLFRAME_SIZ+TF_REG_T9(k1)		# $25
   2700 	REG_L	k0, CALLFRAME_SIZ+TF_REG_SR(k1)		# status register
   2701 	DYNAMIC_STATUS_MASK(k0, sp)		# machine dependent masking
   2702 	REG_L	gp, CALLFRAME_SIZ+TF_REG_GP(k1)		# $28
   2703 	REG_L	sp, CALLFRAME_SIZ+TF_REG_SP(k1)		# $29
   2704 	REG_L	ra, CALLFRAME_SIZ+TF_REG_RA(k1)		# $31
   2705 	mtc0	k0, MIPS_COP_0_STATUS
   2706 	COP0_SYNC
   2707 	eret
   2708 	.set	at
   2709 END(MIPSX(lwp_trampoline))
   2710 
   2711 /*
   2712  * void mipsN_cpu_switch_resume(struct lwp *newlwp)
   2713  *
   2714  * Wiredown the USPACE of newproc in TLB entry#0.  Check whether target
   2715  * USPACE is already in another place of TLB before that, and make
   2716  * sure TBIS(it) in the case.
   2717  *
   2718  * Disable the optimisation for PGSHIFT == 14 (aka ENABLE_MIPS_16KB_PAGE)
   2719  * as the code needs fixing for this case
   2720  *
   2721  * A TLB entry isn't used for the following cases:
   2722  *  - 16kB USPACE
   2723  *  - LP64 - USPACE is always accessed directly via XKPHYS
   2724  */
   2725 
   2726 LEAF_NOPROFILE(MIPSX(cpu_switch_resume))
   2727 #if !defined(_LP64)
   2728 #if (PAGE_SIZE < 16384)
   2729 #if (USPACE > PAGE_SIZE) || !defined(_LP64)
   2730 	INT_L	a1, L_MD_UPTE_0(a0)		# a1 = upte[0]
   2731 #if (PGSHIFT & 1)
   2732 #if (USPACE > PAGE_SIZE)
   2733 #error Unsupported
   2734 #else
   2735 	/* even/odd are contiguaous */
   2736 	INT_ADD a2, a1, MIPS3_PG_NEXT		# a2 = upper half
   2737 #endif
   2738 #else
   2739 	INT_L	a2, L_MD_UPTE_1(a0)		# a2 = upte[1]
   2740 #endif /* (PGSHIFT & 1) */
   2741 	PTR_L	v0, L_PCB(a0)			# va = l->l_addr
   2742 #if VM_MIN_KERNEL_ADDRESS == MIPS_KSEG2_START
   2743 	li	t0, VM_MIN_KERNEL_ADDRESS	# compute index
   2744 	blt	v0, t0, MIPSX(resume)
   2745 	 nop
   2746 #else
   2747 	li	t0, MIPS_KSEG0_START		# below KSEG0?
   2748 	blt	t0, v0, MIPSX(resume)
   2749 	 nop
   2750 	li	t0, VM_MIN_KERNEL_ADDRESS>>32	# below XKSEG?
   2751 	dsll32	t0, t0, 0
   2752 	blt	v0, t0, MIPSX(resume)
   2753 	 nop
   2754 #endif
   2755 
   2756 #if (PGSHIFT & 1) == 0
   2757 	and	t0, v0, MIPS3_PG_ODDPG
   2758 	beqz	t0, MIPSX(entry0)
   2759 	 nop
   2760 
   2761 	break
   2762 
   2763 	PANIC("USPACE sat on odd page boundary")
   2764 
   2765 MIPSX(entry0):
   2766 #endif /* (PGSHIFT & 1) == 0 */
   2767 	_MFC0	ta1, MIPS_COP_0_TLB_HI		# save TLB_HI
   2768 	_MTC0	v0, MIPS_COP_0_TLB_HI		# VPN = va
   2769 
   2770 	COP0_SYNC
   2771 	tlbp					# probe VPN
   2772 	COP0_SYNC
   2773 	mfc0	t0, MIPS_COP_0_TLB_INDEX
   2774 	MFC0_HAZARD
   2775 	bltz	t0, MIPSX(entry0set)
   2776 	 sll	t0, t0, PGSHIFT | 1		# PAGE_SHIFT | 1
   2777 	PTR_LA	t0, MIPS_KSEG0_START(t0)
   2778 	_MTC0	t0, MIPS_COP_0_TLB_HI
   2779 	_MTC0	zero, MIPS_COP_0_TLB_LO0
   2780 	_MTC0	zero, MIPS_COP_0_TLB_LO1
   2781 	COP0_SYNC
   2782 	tlbwi
   2783 	COP0_SYNC
   2784 	_MTC0	v0, MIPS_COP_0_TLB_HI		# set VPN again
   2785 	COP0_SYNC
   2786 MIPSX(entry0set):
   2787 
   2788 #ifdef MULTIPROCESSOR
   2789 	PTR_L	t0, L_CPU(a0)			# get cpu_info
   2790 	INT_L	t1, CPU_INFO_KSP_TLB_SLOT(t0)	# get TLB# for KSP
   2791 	mtc0	t1, MIPS_COP_0_TLB_INDEX	# TLB entry (virtual)
   2792 #else
   2793 	mtc0	zero, MIPS_COP_0_TLB_INDEX	# TLB entry #0 (virtual)
   2794 #endif /* MULTIPROCESSOR */
   2795 	COP0_SYNC
   2796 	_MTC0	a1, MIPS_COP_0_TLB_LO0		# upte[0] | PG_G
   2797 	_MTC0	a2, MIPS_COP_0_TLB_LO1		# upte[1] | PG_G
   2798 	COP0_SYNC
   2799 	tlbwi					# set TLB entry #0
   2800 	COP0_SYNC
   2801 	_MTC0	ta1, MIPS_COP_0_TLB_HI		# restore TLB_HI
   2802 	COP0_SYNC
   2803 MIPSX(resume):
   2804 #endif /* (USPACE > PAGE_SIZE) || !defined(_LP64) */
   2805 #endif /* PAGE_SIZE < 16384 */
   2806 #endif /* ! LP64 */
   2807 #ifdef MIPSNNR2
   2808 	PTR_L	v0, L_PRIVATE(a0)		# get lwp private
   2809 	_MTC0	v0, MIPS_COP_0_USERLOCAL	# make available for rdhwr
   2810 #endif
   2811 	jr	ra
   2812 	 nop
   2813 END(MIPSX(cpu_switch_resume))
   2814 
   2815 /*--------------------------------------------------------------------------
   2816  *
   2817  * mipsN_tlb_write_entry --
   2818  *
   2819  *      Write the given entry into the TLB at the given index.
   2820  *      Pass full R4000 style TLB info including variable page size mask.
   2821  *
   2822  *      void mipsN_tlb_write_entry(size_t tlb_index, const struct tlbmask *tlb)
   2823  *
   2824  * Results:
   2825  *      None.
   2826  *
   2827  * Side effects:
   2828  *      TLB entry set.
   2829  *
   2830  *--------------------------------------------------------------------------
   2831  */
   2832 LEAF(MIPSX(tlb_write_entry))
   2833 	mfc0	ta0, MIPS_COP_0_STATUS		# Save the status register.
   2834 	RESET_EXCEPTION_LEVEL_DISABLE_INTERRUPTS(v0)
   2835 	COP0_SYNC
   2836 	REG_L	a2, TLBMASK_LO0(a1)		# fetch tlb->tlb_lo0
   2837 	REG_L	a3, TLBMASK_LO1(a1)		# fetch tlb->tlb_lo1
   2838 	mfc0	ta2, MIPS_COP_0_TLB_PG_MASK	# Save current page mask.
   2839 	_MFC0	ta1, MIPS_COP_0_TLB_HI		# Save the current ASID.
   2840 
   2841 	_MTC0	a2, MIPS_COP_0_TLB_LO0		# Set up entry low0.
   2842 	_MTC0	a3, MIPS_COP_0_TLB_LO1		# Set up entry low1.
   2843 	COP0_SYNC
   2844 	INT_L	a2, TLBMASK_MASK(a1)		# fetch tlb->tlb_mask
   2845 	INT_ADD	v0, a0, 1			# add 1 to it
   2846 #ifdef MIPSNNR2
   2847 	movz	a2, ta2, v0			# a2 = ta2 if v0 is 0
   2848 #else
   2849 	bnez	a2, 1f				# branch if tlb_mask != -1
   2850 	 nop					# --delay-slot--
   2851 	move	a2, ta2				# use existing tlb_mask
   2852 1:
   2853 #endif
   2854 	PTR_L	a3, TLBMASK_HI(a1)		# fetch tlb->tlb_hi
   2855 	mtc0	a0, MIPS_COP_0_TLB_INDEX	# Set the index.
   2856 	mtc0	a2, MIPS_COP_0_TLB_PG_MASK	# Set up entry pagemask.
   2857 	_MTC0	a3, MIPS_COP_0_TLB_HI		# Set up entry high.
   2858 	COP0_SYNC
   2859 	tlbwi					# Write the TLB
   2860 	COP0_SYNC
   2861 #ifdef MIPS3
   2862 	nop
   2863 #endif
   2864 
   2865 	_MTC0	ta1, MIPS_COP_0_TLB_HI		# Restore the ASID.
   2866 	mtc0	ta2, MIPS_COP_0_TLB_PG_MASK	# Restore page mask.
   2867 	COP0_SYNC
   2868 
   2869 #ifdef MIPS3_LOONGSON2
   2870 	li	v0, MIPS_DIAG_ITLB_CLEAR
   2871 	mtc0	v0, MIPS_COP_0_DIAG		# invalidate ITLB
   2872 #endif
   2873 
   2874 	mtc0	ta0, MIPS_COP_0_STATUS		# Restore the status register
   2875 	JR_HB_RA
   2876 END(MIPSX(tlb_write_entry))
   2877 
   2878 #if defined(MIPS3)
   2879 /*----------------------------------------------------------------------------
   2880  *
   2881  * mipsN_VCED --
   2882  *
   2883  *	Handle virtual coherency exceptions.
   2884  *	Called directly from the mips3 exception-table code.
   2885  *	only k0, k1 are available on entry
   2886  *
   2887  * Results:
   2888  *	None.
   2889  *
   2890  * Side effects:
   2891  *	Remaps the conflicting address as uncached and returns
   2892  *	from the exception.
   2893  *
   2894  *	NB: cannot be profiled, all registers are user registers on entry.
   2895  *
   2896  *----------------------------------------------------------------------------
   2897  */
   2898 LEAF_NOPROFILE(MIPSX(VCED))
   2899 	.set	noat
   2900 	_MFC0	k0, MIPS_COP_0_BAD_VADDR	# fault addr.
   2901 	li	k1, -16
   2902 	and	k0, k1
   2903 	cache	(CACHE_R4K_SD | CACHEOP_R4K_HIT_WB_INV), 0(k0)
   2904 	cache	(CACHE_R4K_D | CACHEOP_R4K_HIT_INV), 0(k0)
   2905 #ifdef DEBUG
   2906 	_MFC0	k0, MIPS_COP_0_BAD_VADDR
   2907 	PTR_LA	k1, MIPSX(VCED_vaddr)
   2908 	PTR_S	k0, 0(k1)
   2909 	_MFC0	k0, MIPS_COP_0_EXC_PC
   2910 	PTR_LA	k1, MIPSX(VCED_epc)
   2911 	PTR_S	k0, 0(k1)
   2912 	PTR_LA	k1, MIPSX(VCED_count)	# count number of exceptions
   2913 	PTR_SRL	k0, k0, 26		# position upper 4 bits of VA
   2914 	and	k0, k0, 0x3c		# mask it off
   2915 	PTR_ADDU k1, k0			# get address of count table
   2916 	LONG_L	k0, 0(k1)
   2917 	LONG_ADDU k0, 1
   2918 	LONG_S	k0, 0(k1)
   2919 #endif
   2920 	eret
   2921 	.set	at
   2922 
   2923 #ifdef DEBUG
   2924 	.data
   2925 	.globl	_C_LABEL(MIPSX(VCED_count))
   2926 _C_LABEL(MIPSX(VCED_count)):
   2927 	LONG_WORD	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
   2928 	.globl	_C_LABEL(MIPSX(VCED_epc))
   2929 _C_LABEL(MIPSX(VCED_epc)):
   2930 	PTR_WORD	0
   2931 	.globl	_C_LABEL(MIPSX(VCED_vaddr))
   2932 _C_LABEL(MIPSX(VCED_vaddr)):
   2933 	PTR_WORD	0
   2934 	.text
   2935 #endif
   2936 END(MIPSX(VCED))
   2937 
   2938 LEAF_NOPROFILE(MIPSX(VCEI))
   2939 	.set	noat
   2940 	_MFC0	k0, MIPS_COP_0_BAD_VADDR	# fault addr.
   2941 	cache	(CACHE_R4K_SD | CACHEOP_R4K_HIT_WB_INV), 0(k0)
   2942 	cache	(CACHE_R4K_I | CACHEOP_R4K_HIT_INV), 0(k0)
   2943 #ifdef DEBUG
   2944 	_MFC0	k0, MIPS_COP_0_BAD_VADDR
   2945 	PTR_LA	k1, MIPSX(VCEI_vaddr)
   2946 	PTR_S	k0, 0(k1)
   2947 	PTR_LA	k1, MIPSX(VCEI_count)	# count number of exceptions
   2948 	PTR_SRL	k0, k0, 26		# position upper 4 bits of VA
   2949 	and	k0, k0, 0x3c		# mask it off
   2950 	PTR_ADDU k1, k0			# get address of count table
   2951 	LONG_L	k0, 0(k1)
   2952 	PTR_ADDU k0, 1
   2953 	LONG_S	k0, 0(k1)
   2954 #endif
   2955 	eret
   2956 	.set	at
   2957 
   2958 #ifdef DEBUG
   2959 	.data
   2960 	.globl	_C_LABEL(MIPSX(VCEI_count))
   2961 _C_LABEL(MIPSX(VCEI_count)):
   2962 	LONG_WORD	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
   2963 	.globl	_C_LABEL(MIPSX(VCEI_vaddr))
   2964 _C_LABEL(MIPSX(VCEI_vaddr)):
   2965 	PTR_WORD	0
   2966 	.text
   2967 #endif
   2968 END(MIPSX(VCEI))
   2969 #endif /* MIPS3 */
   2970 
   2971 #ifdef USE_64BIT_INSTRUCTIONS
   2972 LEAF(MIPSX(pagezero))
   2973 	li	a1, PAGE_SIZE >> 6
   2974 
   2975 1:	sd	zero, 0(a0)			# try to miss cache first
   2976 	sd	zero, 32(a0)
   2977 	subu	a1, 1
   2978 	sd	zero, 16(a0)
   2979 	sd	zero, 48(a0)
   2980 	sd	zero, 8(a0)			# fill in cache lines
   2981 	sd	zero, 40(a0)
   2982 	sd	zero, 24(a0)
   2983 	sd	zero, 56(a0)
   2984 	bgtz	a1, 1b
   2985 	addu	a0, 64
   2986 
   2987 	jr	ra
   2988 	nop
   2989 END(MIPSX(pagezero))
   2990 #endif /* USE_64BIT_INSTRUCTIONS */
   2991 
   2992 	.rdata
   2993 
   2994 	.globl _C_LABEL(MIPSX(locore_vec))
   2995 _C_LABEL(MIPSX(locore_vec)):
   2996 	PTR_WORD _C_LABEL(MIPSX(cpu_switch_resume))
   2997 	PTR_WORD _C_LABEL(MIPSX(lwp_trampoline))
   2998 	PTR_WORD _C_LABEL(MIPSX(wbflush)) # wbflush
   2999 	PTR_WORD _C_LABEL(MIPSX(tlb_get_asid))
   3000 	PTR_WORD _C_LABEL(MIPSX(tlb_set_asid))
   3001 	PTR_WORD _C_LABEL(MIPSX(tlb_invalidate_asids))
   3002 	PTR_WORD _C_LABEL(MIPSX(tlb_invalidate_addr))
   3003 #ifdef MULTIPROCESSOR
   3004 	PTR_WORD _C_LABEL(MIPSX(tlb_invalidate_globals))
   3005 #else
   3006 	PTR_WORD _C_LABEL(nullop)
   3007 #endif
   3008 	PTR_WORD _C_LABEL(MIPSX(tlb_invalidate_all))
   3009 	PTR_WORD _C_LABEL(MIPSX(tlb_record_asids))
   3010 	PTR_WORD _C_LABEL(MIPSX(tlb_update_addr))
   3011 	PTR_WORD _C_LABEL(MIPSX(tlb_read_entry))
   3012 	PTR_WORD _C_LABEL(MIPSX(tlb_write_entry))
   3013 
   3014 	.globl _C_LABEL(MIPSX(locoresw))
   3015 _C_LABEL(MIPSX(locoresw)):
   3016 	PTR_WORD _C_LABEL(MIPSX(wbflush))	# lsw_wbflush
   3017 	PTR_WORD _C_LABEL(nullop)		# lsw_cpu_idle
   3018 	PTR_WORD _C_LABEL(nullop)		# lsw_send_ipi
   3019 	PTR_WORD _C_LABEL(nullop)		# lsw_cpu_offline_md
   3020 	PTR_WORD _C_LABEL(nullop)		# lsw_cpu_init
   3021 	PTR_WORD _C_LABEL(nullop)		# lsw_cpu_run
   3022 	PTR_WORD _C_LABEL(nullop)		# lsw_bus_error
   3023 
   3024 MIPSX(excpt_sw):
   3025 	####
   3026 	#### The kernel exception handlers.
   3027 	####
   3028 	PTR_WORD _C_LABEL(MIPSX(kern_intr))		#  0 external interrupt
   3029 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	#  1 TLB modification
   3030 #if (PGSHIFT & 1) == 0
   3031 	PTR_WORD _C_LABEL(MIPSX(kern_tlb_invalid_exception))	#  2 TLB miss (LW/I-fetch)
   3032 	PTR_WORD _C_LABEL(MIPSX(kern_tlb_invalid_exception))	#  3 TLB miss (SW)
   3033 #else
   3034 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	#  2 TLB miss (LW/I-fetch)
   3035 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	#  3 TLB miss (SW)
   3036 #endif
   3037 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	#  4 address error (LW/I-fetch)
   3038 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	#  5 address error (SW)
   3039 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	#  6 bus error (I-fetch)
   3040 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	#  7 bus error (load or store)
   3041 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	#  8 system call
   3042 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	#  9 breakpoint
   3043 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 10 reserved instruction
   3044 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 11 coprocessor unusable
   3045 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 12 arithmetic overflow
   3046 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 13 r4k trap exception
   3047 #if defined(MIPS3)
   3048 	PTR_WORD _C_LABEL(MIPSX(VCEI))			# 14 r4k virt coherence
   3049 #else
   3050 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 14 reserved
   3051 #endif
   3052 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 15 r4k FP exception
   3053 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 16 reserved
   3054 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 17 reserved
   3055 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 18 reserved
   3056 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 19 reserved
   3057 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 20 reserved
   3058 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 21 reserved
   3059 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 22 reserved
   3060 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 23 watch exception
   3061 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 24 reserved
   3062 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 25 reserved
   3063 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 26 reserved
   3064 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 27 reserved
   3065 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 28 reserved
   3066 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 29 reserved
   3067 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 30 reserved
   3068 #if defined(MIPS3)
   3069 	PTR_WORD _C_LABEL(MIPSX(VCED))			# 31 v. coherence exception data
   3070 #else
   3071 	PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))	# 31 reserved
   3072 #endif
   3073 	#####
   3074 	##### The user exception handlers.
   3075 	#####
   3076 	PTR_WORD _C_LABEL(MIPSX(user_intr))		#  0
   3077 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	#  1
   3078 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	#  2
   3079 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	#  3
   3080 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	#  4
   3081 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	#  5
   3082 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	#  6
   3083 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	#  7
   3084 	PTR_WORD _C_LABEL(MIPSX(systemcall))		#  8
   3085 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	#  9
   3086 #ifdef MIPS64_OCTEON	/* rdhwr emulation is haunted on Octeon, PR 59236 */
   3087 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 10
   3088 #else
   3089 	PTR_WORD _C_LABEL(MIPSX(user_reserved_insn))	# 10
   3090 #endif
   3091 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 11
   3092 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 12
   3093 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 13
   3094 #if defined(MIPS3)
   3095 	PTR_WORD _C_LABEL(MIPSX(VCEI))			# 14
   3096 #else
   3097 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 14
   3098 #endif
   3099 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 15
   3100 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 16
   3101 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 17
   3102 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 18
   3103 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 19
   3104 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 20
   3105 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 21
   3106 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 22
   3107 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 23
   3108 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 24
   3109 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 25
   3110 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 26
   3111 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 27
   3112 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 28
   3113 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 29
   3114 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 30
   3115 #if defined(MIPS3)
   3116 	PTR_WORD _C_LABEL(MIPSX(VCED))			# 31 v. coherence exception data
   3117 #else
   3118 	PTR_WORD _C_LABEL(MIPSX(user_gen_exception))	# 31
   3119 #endif
   3120 #ifdef MIPS3_LOONGSON2
   3121 loongson2_xtlb_miss_str:
   3122 	.string "loongson2_xtlb_miss"
   3123 #endif
   3124