Home | History | Annotate | Line # | Download | only in sparc64
      1 /*	$NetBSD: locore.s,v 1.439 2026/03/07 20:48:26 palle Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2006-2010 Matthew R. Green
      5  * Copyright (c) 1996-2002 Eduardo Horvath
      6  * Copyright (c) 1996 Paul Kranenburg
      7  * Copyright (c) 1996
      8  * 	The President and Fellows of Harvard College.
      9  *	All rights reserved.
     10  * Copyright (c) 1992, 1993
     11  *	The Regents of the University of California.
     12  *	All rights reserved.
     13  *
     14  * This software was developed by the Computer Systems Engineering group
     15  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
     16  * contributed to Berkeley.
     17  *
     18  * All advertising materials mentioning features or use of this software
     19  * must display the following acknowledgement:
     20  *	This product includes software developed by the University of
     21  *	California, Lawrence Berkeley Laboratory.
     22  *	This product includes software developed by Harvard University.
     23  *
     24  * Redistribution and use in source and binary forms, with or without
     25  * modification, are permitted provided that the following conditions
     26  * are met:
     27  * 1. Redistributions of source code must retain the above copyright
     28  *    notice, this list of conditions and the following disclaimer.
     29  * 2. Redistributions in binary form must reproduce the above copyright
     30  *    notice, this list of conditions and the following disclaimer in the
     31  *    documentation and/or other materials provided with the
     32  *    distribution.
     33  * 3. All advertising materials mentioning features or use of this
     34  *    software must display the following acknowledgement:
     35  *	This product includes software developed by the University of
     36  *	California, Berkeley and its contributors.
     37  *	This product includes software developed by Harvard University.
     38  *	This product includes software developed by Paul Kranenburg.
     39  * 4. Neither the name of the University nor the names of its
     40  *    contributors may be used to endorse or promote products derived
     41  *    from this software without specific prior written permission.
     42  *
     43  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
     44  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     45  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     46  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
     47  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     48  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     49  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     50  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     51  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
     52  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
     53  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
     54  * DAMAGE.
     55  *
     56  *	@(#)locore.s	8.4 (Berkeley) 12/10/93
     57  */
     58 
     59 #undef	PARANOID		/* Extremely expensive consistency checks */
     60 #undef	NO_VCACHE		/* Map w/D$ disabled */
     61 #undef	TRAPSTATS		/* Count traps */
     62 #undef	TRAPS_USE_IG		/* Use Interrupt Globals for all traps */
     63 #define	HWREF			/* Track ref/mod bits in trap handlers */
     64 #undef	DCACHE_BUG		/* Flush D$ around ASI_PHYS accesses */
     65 #undef	NO_TSB			/* Don't use TSB */
     66 #define	BB_ERRATA_1		/* writes to TICK_CMPR may fail */
     67 #undef	TLB_FLUSH_LOWVA		/* also flush 32-bit entries from the MMU */
     68 
     69 #include "opt_ddb.h"
     70 #include "opt_kgdb.h"
     71 #include "opt_multiprocessor.h"
     72 #include "opt_compat_netbsd.h"
     73 #include "opt_compat_netbsd32.h"
     74 #include "opt_lockdebug.h"
     75 
     76 #include "assym.h"
     77 #include <machine/param.h>
     78 #include <machine/types.h>
     79 #include <sparc64/sparc64/intreg.h>
     80 #include <sparc64/sparc64/timerreg.h>
     81 #include <machine/ctlreg.h>
     82 #include <machine/psl.h>
     83 #include <machine/signal.h>
     84 #include <machine/trap.h>
     85 #include <machine/frame.h>
     86 #include <machine/pmap.h>
     87 #include <machine/intr.h>
     88 #include <machine/asm.h>
     89 #include <machine/locore.h>
     90 #ifdef SUN4V
     91 #include <machine/hypervisor.h>
     92 #endif
     93 #include <sys/syscall.h>
     94 
     95 #define BLOCK_SIZE SPARC64_BLOCK_SIZE
     96 #define BLOCK_ALIGN SPARC64_BLOCK_ALIGN
     97 
     98 #ifdef SUN4V
     99 #define SUN4V_N_REG_WINDOWS    8  /* As per UA2005 spec */
    100 #define SUN4V_NWINDOWS           (SUN4V_N_REG_WINDOWS-1) /* This is an index number, so subtract one */
    101 #endif
    102 
    103 #include "ksyms.h"
    104 
    105 	/* Misc. macros */
    106 
    107 	.macro	GET_MAXCWP reg
    108 #ifdef SUN4V
    109 	sethi	%hi(cputyp), \reg
    110 	ld	[\reg + %lo(cputyp)], \reg
    111 	cmp	\reg, CPU_SUN4V
    112 	bne,pt	%icc, 2f
    113 	 nop
    114 	/* sun4v */
    115 	ba	3f
    116 	 mov	SUN4V_NWINDOWS, \reg
    117 2:
    118 #endif
    119 	/* sun4u */
    120 	rdpr	%ver, \reg
    121 	and	\reg, CWP, \reg
    122 3:
    123 	.endm
    124 
    125 	.macro	SET_MMU_CONTEXTID_SUN4U ctxid,ctx
    126 	stxa	\ctxid, [\ctx] ASI_DMMU;
    127 	.endm
    128 
    129 #ifdef SUN4V
    130 	.macro	SET_MMU_CONTEXTID_SUN4V ctxid,ctx
    131 	stxa	\ctxid, [\ctx] ASI_MMU_CONTEXTID;
    132 	.endm
    133 #endif
    134 
    135 	.macro	SET_MMU_CONTEXTID ctxid,ctx,scratch
    136 #ifdef SUN4V
    137 	sethi	%hi(cputyp), \scratch
    138 	ld	[\scratch + %lo(cputyp)], \scratch
    139 	cmp	\scratch, CPU_SUN4V
    140 	bne,pt	%icc, 2f
    141 	 nop
    142 	/* sun4v */
    143 	SET_MMU_CONTEXTID_SUN4V \ctxid,\ctx
    144 	ba	3f
    145 	 nop
    146 2:
    147 #endif
    148 	/* sun4u */
    149 	SET_MMU_CONTEXTID_SUN4U \ctxid,\ctx
    150 3:
    151 	.endm
    152 
    153 	.macro	GET_MMU_CONTEXTID_SUN4U ctxid,ctx
    154 	ldxa	[\ctx] ASI_DMMU, \ctxid
    155 	.endm
    156 
    157 #ifdef SUN4V
    158 	.macro	GET_MMU_CONTEXTID_SUN4V ctxid,ctx
    159 	ldxa	[\ctx] ASI_MMU_CONTEXTID, \ctxid
    160 	.endm
    161 #endif
    162 
    163 	.macro	GET_MMU_CONTEXTID ctxid,ctx,scratch
    164 #ifdef SUN4V
    165 	sethi	%hi(cputyp), \scratch
    166 	ld	[\scratch + %lo(cputyp)], \scratch
    167 	cmp	\scratch, CPU_SUN4V
    168 	bne,pt	%icc, 2f
    169 	 nop
    170 	/* sun4v */
    171 	GET_MMU_CONTEXTID_SUN4V \ctxid,\ctx
    172 	ba	3f
    173 	 nop
    174 2:
    175 #endif
    176 	/* sun4u */
    177 	GET_MMU_CONTEXTID_SUN4U \ctxid,\ctx
    178 3:
    179 	.endm
    180 
    181 #ifdef SUN4V
    182 	.macro	NORMAL_GLOBALS_SUN4V
    183 	 wrpr	%g0, 0, %gl				! Set globals to level 0
    184 	.endm
    185 #endif
    186 	.macro	NORMAL_GLOBALS_SUN4U
    187 	wrpr	%g0, PSTATE_KERN, %pstate		! Alternate Globals (AG) bit set to zero
    188 	.endm
    189 
    190 #ifdef SUN4V
    191 	.macro	ALTERNATE_GLOBALS_SUN4V
    192 	 wrpr	%g0, 1, %gl				! Set globals to level 1
    193 	.endm
    194 #endif
    195 	.macro	ALTERNATE_GLOBALS_SUN4U
    196 	 wrpr    %g0, PSTATE_KERN|PSTATE_AG, %pstate	! Alternate Globals (AG) bit set to one
    197 	.endm
    198 
    199 	.macro	ENABLE_INTERRUPTS scratch
    200 	rdpr	 %pstate, \scratch
    201 	or	\scratch, PSTATE_IE, \scratch	! Interrupt Enable (IE) bit set to one
    202 	wrpr	%g0, \scratch, %pstate
    203 	.endm
    204 
    205 	.macro	DISABLE_INTERRUPTS scratch
    206 	rdpr	 %pstate, \scratch
    207 	and	\scratch, ~PSTATE_IE, \scratch	! Interrupt Enable (IE) bit set to zero
    208 	wrpr	%g0, \scratch, %pstate
    209 	.endm
    210 
    211 
    212 #ifdef SUN4V
    213 	/* Misc. sun4v macros */
    214 
    215 	.macro	GET_MMFSA reg
    216 	sethi	%hi(CPUINFO_VA + CI_MMUFSA), \reg
    217 	LDPTR	[\reg + %lo(CPUINFO_VA + CI_MMUFSA)], \reg
    218 	.endm
    219 
    220 	.macro	GET_CTXBUSY reg
    221 	sethi	%hi(CPUINFO_VA + CI_CTXBUSY), \reg
    222 	LDPTR	[\reg + %lo(CPUINFO_VA + CI_CTXBUSY)], \reg
    223 	.endm
    224 
    225 	.macro	GET_TSB_DMMU reg
    226 	sethi	%hi(CPUINFO_VA + CI_TSB_DMMU), \reg
    227 	LDPTR	[\reg + %lo(CPUINFO_VA + CI_TSB_DMMU)], \reg
    228 	.endm
    229 
    230 	.macro sun4v_tl1_uspill_normal
    231 	ba,a,pt	%xcc, spill_normal_to_user_stack
    232 	 nop
    233 	.align 128
    234 	.endm
    235 
    236 	.macro sun4v_tl1_uspill_other
    237 	ba,a,pt	%xcc, pcbspill_other
    238 	 nop
    239 	.align 128
    240 	.endm
    241 
    242 #endif
    243 
    244 #if 1
    245 /*
    246  * Try to issue an elf note to ask the Solaris
    247  * bootloader to align the kernel properly.
    248  */
    249 	.section	.note
    250 	.word	0x0d
    251 	.word	4		! Dunno why
    252 	.word	1
    253 0:	.asciz	"SUNW Solaris"
    254 1:
    255 	.align	4
    256 	.word	0x0400000
    257 #endif
    258 
    259 	.register	%g2,#scratch
    260 	.register	%g3,#scratch
    261 
    262 
    263 	.data
    264 	.globl	_C_LABEL(data_start)
    265 _C_LABEL(data_start):					! Start of data segment
    266 
    267 #ifdef KGDB
    268 /*
    269  * Another item that must be aligned, easiest to put it here.
    270  */
    271 KGDB_STACK_SIZE = 2048
    272 	.globl	_C_LABEL(kgdb_stack)
    273 _C_LABEL(kgdb_stack):
    274 	.space	KGDB_STACK_SIZE		! hope this is enough
    275 #endif
    276 
    277 #ifdef NOTDEF_DEBUG
    278 /*
    279  * This stack is used when we detect kernel stack corruption.
    280  */
    281 	.space	USPACE
    282 	.align	16
    283 panicstack:
    284 #endif
    285 
    286 /*
    287  * romp is the prom entry pointer
    288  * romtba is the prom trap table base address
    289  */
    290 	.globl	romp
    291 romp:	POINTER	0
    292 	.globl	romtba
    293 romtba:	POINTER	0
    294 
    295 	.globl	cputyp
    296 cputyp:	.word	CPU_SUN4U ! Default to sun4u
    297 
    298 	_ALIGN
    299 	.text
    300 
    301 /*
    302  * The v9 trap frame is stored in the special trap registers.  The
    303  * register window is only modified on window overflow, underflow,
    304  * and clean window traps, where it points to the register window
    305  * needing service.  Traps have space for 8 instructions, except for
    306  * the window overflow, underflow, and clean window traps which are
    307  * 32 instructions long, large enough to in-line.
    308  *
    309  * The spitfire CPU (Ultra I) has 4 different sets of global registers.
    310  * (blah blah...)
    311  *
    312  * I used to generate these numbers by address arithmetic, but gas's
    313  * expression evaluator has about as much sense as your average slug
    314  * (oddly enough, the code looks about as slimy too).  Thus, all the
    315  * trap numbers are given as arguments to the trap macros.  This means
    316  * there is one line per trap.  Sigh.
    317  *
    318  * Hardware interrupt vectors can be `linked'---the linkage is to regular
    319  * C code---or rewired to fast in-window handlers.  The latter are good
    320  * for unbuffered hardware like the Zilog serial chip and the AMD audio
    321  * chip, where many interrupts can be handled trivially with pseudo-DMA
    322  * or similar.  Only one `fast' interrupt can be used per level, however,
    323  * and direct and `fast' interrupts are incompatible.  Routines in intr.c
    324  * handle setting these, with optional paranoia.
    325  */
    326 
    327 /*
    328  *	TA8 -- trap align for 8 instruction traps
    329  *	TA32 -- trap align for 32 instruction traps
    330  */
    331 #define TA8	.align 32
    332 #define TA32	.align 128
    333 
    334 /*
    335  * v9 trap macros:
    336  *
    337  *	We have a problem with v9 traps; we have no registers to put the
    338  *	trap type into.  But we do have a %tt register which already has
    339  *	that information.  Trap types in these macros are all dummys.
    340  */
    341 	/* regular vectored traps */
    342 
    343 #define	VTRAP(type, label) \
    344 	ba,a,pt	%icc,label; nop; NOTREACHED; TA8
    345 
    346 	/* hardware interrupts (can be linked or made `fast') */
    347 #define	HARDINT4U(lev) \
    348 	VTRAP(lev, _C_LABEL(sparc_interrupt))
    349 #ifdef SUN4V
    350 #define HARDINT4V(lev) HARDINT4U(lev)
    351 #endif
    352 
    353 	/* software interrupts (may not be made direct, sorry---but you
    354 	   should not be using them trivially anyway) */
    355 #define	SOFTINT4U(lev, bit) \
    356 	HARDINT4U(lev)
    357 
    358 	/* traps that just call trap() */
    359 #define	TRAP(type)	VTRAP(type, slowtrap)
    360 
    361 	/* architecturally undefined traps (cause panic) */
    362 #ifndef DEBUG
    363 #define	UTRAP(type)	sir; VTRAP(type, slowtrap)
    364 #else
    365 #define	UTRAP(type)	VTRAP(type, slowtrap)
    366 #endif
    367 
    368 	/* software undefined traps (may be replaced) */
    369 #define	STRAP(type)	VTRAP(type, slowtrap)
    370 
    371 /* breakpoint acts differently under kgdb */
    372 #ifdef KGDB
    373 #define	BPT		VTRAP(T_BREAKPOINT, bpt)
    374 #define	BPT_KGDB_EXEC	VTRAP(T_KGDB_EXEC, bpt)
    375 #else
    376 #define	BPT		TRAP(T_BREAKPOINT)
    377 #define	BPT_KGDB_EXEC	TRAP(T_KGDB_EXEC)
    378 #endif
    379 
    380 #define	SYSCALL		VTRAP(0x100, syscall_setup)
    381 #ifdef notyet
    382 #define	ZS_INTERRUPT	ba,a,pt %icc, zshard; nop; TA8
    383 #else
    384 #define	ZS_INTERRUPT4U	HARDINT4U(12)
    385 #endif
    386 
    387 
    388 /*
    389  * Macro to clear %tt so we don't get confused with old traps.
    390  */
    391 #ifdef DEBUG
    392 #define CLRTT	wrpr	%g0,0x1ff,%tt
    393 #else
    394 #define CLRTT
    395 #endif
    396 
    397 
    398 /*
    399  * Some macros to load and store a register window
    400  */
    401 
    402 	.macro	SPILL storer,base,size,asi
    403 
    404 	.irpc n,01234567
    405 		\storer %l\n, [\base + (\n * \size)] \asi
    406 	.endr
    407 	.irpc n,01234567
    408 		\storer %i\n, [\base + ((8+\n) * \size)] \asi
    409 	.endr
    410 
    411 	.endm
    412 
    413 
    414 	.macro FILL loader, base, size, asi
    415 
    416 	.irpc n,01234567
    417 		\loader [\base + (\n * \size)] \asi, %l\n
    418 	.endr
    419 
    420 	.irpc n,01234567
    421 		\loader [\base + ((8+\n) * \size)] \asi, %i\n
    422 	.endr
    423 
    424 	.endm
    425 
    426 /*
    427  * Here are some oft repeated traps as macros.
    428  */
    429 
    430 	/* spill a 64-bit register window */
    431 #define SPILL64(label,as) \
    432 label:	\
    433 	wr	%g0, as, %asi; \
    434 	stxa	%l0, [%sp+BIAS+0x00]%asi; \
    435 	stxa	%l1, [%sp+BIAS+0x08]%asi; \
    436 	stxa	%l2, [%sp+BIAS+0x10]%asi; \
    437 	stxa	%l3, [%sp+BIAS+0x18]%asi; \
    438 	stxa	%l4, [%sp+BIAS+0x20]%asi; \
    439 	stxa	%l5, [%sp+BIAS+0x28]%asi; \
    440 	stxa	%l6, [%sp+BIAS+0x30]%asi; \
    441 	\
    442 	stxa	%l7, [%sp+BIAS+0x38]%asi; \
    443 	stxa	%i0, [%sp+BIAS+0x40]%asi; \
    444 	stxa	%i1, [%sp+BIAS+0x48]%asi; \
    445 	stxa	%i2, [%sp+BIAS+0x50]%asi; \
    446 	stxa	%i3, [%sp+BIAS+0x58]%asi; \
    447 	stxa	%i4, [%sp+BIAS+0x60]%asi; \
    448 	stxa	%i5, [%sp+BIAS+0x68]%asi; \
    449 	stxa	%i6, [%sp+BIAS+0x70]%asi; \
    450 	\
    451 	stxa	%i7, [%sp+BIAS+0x78]%asi; \
    452 	saved; \
    453 	CLRTT; \
    454 	retry; \
    455 	NOTREACHED; \
    456 	TA32
    457 
    458 	/* spill a 32-bit register window */
    459 #define SPILL32(label,as) \
    460 label:	\
    461 	wr	%g0, as, %asi; \
    462 	srl	%sp, 0, %sp; /* fixup 32-bit pointers */ \
    463 	stwa	%l0, [%sp+0x00]%asi; \
    464 	stwa	%l1, [%sp+0x04]%asi; \
    465 	stwa	%l2, [%sp+0x08]%asi; \
    466 	stwa	%l3, [%sp+0x0c]%asi; \
    467 	stwa	%l4, [%sp+0x10]%asi; \
    468 	stwa	%l5, [%sp+0x14]%asi; \
    469 	\
    470 	stwa	%l6, [%sp+0x18]%asi; \
    471 	stwa	%l7, [%sp+0x1c]%asi; \
    472 	stwa	%i0, [%sp+0x20]%asi; \
    473 	stwa	%i1, [%sp+0x24]%asi; \
    474 	stwa	%i2, [%sp+0x28]%asi; \
    475 	stwa	%i3, [%sp+0x2c]%asi; \
    476 	stwa	%i4, [%sp+0x30]%asi; \
    477 	stwa	%i5, [%sp+0x34]%asi; \
    478 	\
    479 	stwa	%i6, [%sp+0x38]%asi; \
    480 	stwa	%i7, [%sp+0x3c]%asi; \
    481 	saved; \
    482 	CLRTT; \
    483 	retry; \
    484 	NOTREACHED; \
    485 	TA32
    486 
    487 	/* Spill either 32-bit or 64-bit register window. */
    488 #define SPILLBOTH(label64,label32,as) \
    489 	andcc	%sp, 1, %g0; \
    490 	bnz,pt	%xcc, label64+4;	/* Is it a v9 or v8 stack? */ \
    491 	 wr	%g0, as, %asi; \
    492 	ba,pt	%xcc, label32+8; \
    493 	 srl	%sp, 0, %sp; /* fixup 32-bit pointers */ \
    494 	NOTREACHED; \
    495 	TA32
    496 
    497 	/* fill a 64-bit register window */
    498 #define FILL64(label,as) \
    499 label: \
    500 	wr	%g0, as, %asi; \
    501 	ldxa	[%sp+BIAS+0x00]%asi, %l0; \
    502 	ldxa	[%sp+BIAS+0x08]%asi, %l1; \
    503 	ldxa	[%sp+BIAS+0x10]%asi, %l2; \
    504 	ldxa	[%sp+BIAS+0x18]%asi, %l3; \
    505 	ldxa	[%sp+BIAS+0x20]%asi, %l4; \
    506 	ldxa	[%sp+BIAS+0x28]%asi, %l5; \
    507 	ldxa	[%sp+BIAS+0x30]%asi, %l6; \
    508 	\
    509 	ldxa	[%sp+BIAS+0x38]%asi, %l7; \
    510 	ldxa	[%sp+BIAS+0x40]%asi, %i0; \
    511 	ldxa	[%sp+BIAS+0x48]%asi, %i1; \
    512 	ldxa	[%sp+BIAS+0x50]%asi, %i2; \
    513 	ldxa	[%sp+BIAS+0x58]%asi, %i3; \
    514 	ldxa	[%sp+BIAS+0x60]%asi, %i4; \
    515 	ldxa	[%sp+BIAS+0x68]%asi, %i5; \
    516 	ldxa	[%sp+BIAS+0x70]%asi, %i6; \
    517 	\
    518 	ldxa	[%sp+BIAS+0x78]%asi, %i7; \
    519 	restored; \
    520 	CLRTT; \
    521 	retry; \
    522 	NOTREACHED; \
    523 	TA32
    524 
    525 	/* fill a 32-bit register window */
    526 #define FILL32(label,as) \
    527 label:	\
    528 	wr	%g0, as, %asi; \
    529 	srl	%sp, 0, %sp; /* fixup 32-bit pointers */ \
    530 	lda	[%sp+0x00]%asi, %l0; \
    531 	lda	[%sp+0x04]%asi, %l1; \
    532 	lda	[%sp+0x08]%asi, %l2; \
    533 	lda	[%sp+0x0c]%asi, %l3; \
    534 	lda	[%sp+0x10]%asi, %l4; \
    535 	lda	[%sp+0x14]%asi, %l5; \
    536 	\
    537 	lda	[%sp+0x18]%asi, %l6; \
    538 	lda	[%sp+0x1c]%asi, %l7; \
    539 	lda	[%sp+0x20]%asi, %i0; \
    540 	lda	[%sp+0x24]%asi, %i1; \
    541 	lda	[%sp+0x28]%asi, %i2; \
    542 	lda	[%sp+0x2c]%asi, %i3; \
    543 	lda	[%sp+0x30]%asi, %i4; \
    544 	lda	[%sp+0x34]%asi, %i5; \
    545 	\
    546 	lda	[%sp+0x38]%asi, %i6; \
    547 	lda	[%sp+0x3c]%asi, %i7; \
    548 	restored; \
    549 	CLRTT; \
    550 	retry; \
    551 	NOTREACHED; \
    552 	TA32
    553 
    554 	/* fill either 32-bit or 64-bit register window. */
    555 #define FILLBOTH(label64,label32,as) \
    556 	andcc	%sp, 1, %i0; \
    557 	bnz	(label64)+4; /* See if it's a v9 stack or v8 */ \
    558 	 wr	%g0, as, %asi; \
    559 	ba	(label32)+8; \
    560 	 srl	%sp, 0, %sp; /* fixup 32-bit pointers */ \
    561 	NOTREACHED; \
    562 	TA32
    563 
    564 	/* handle clean window trap when trap level = 0 */
    565 	.macro CLEANWIN0
    566 	rdpr %cleanwin, %o7
    567 	inc %o7				!	This handler is in-lined and cannot fault
    568 #ifdef DEBUG
    569 	set	0xbadcafe, %l0		! DEBUG -- compiler should not rely on zero-ed registers.
    570 #else
    571 	clr	%l0
    572 #endif
    573 	wrpr %g0, %o7, %cleanwin	!       Nucleus (trap&IRQ) code does not need clean windows
    574 
    575 	mov %l0,%l1; mov %l0,%l2	!	Clear out %l0-%l8 and %o0-%o8 and inc %cleanwin and done
    576 	mov %l0,%l3; mov %l0,%l4
    577 #if 0
    578 #ifdef DIAGNOSTIC
    579 	!!
    580 	!! Check the sp redzone
    581 	!!
    582 	!! Since we can't spill the current window, we'll just keep
    583 	!! track of the frame pointer.  Problems occur when the routine
    584 	!! allocates and uses stack storage.
    585 	!!
    586 !	rdpr	%wstate, %l5	! User stack?
    587 !	cmp	%l5, WSTATE_KERN
    588 !	bne,pt	%icc, 7f
    589 	 sethi	%hi(CPCB), %l5
    590 	LDPTR	[%l5 + %lo(CPCB)], %l5	! If pcb < fp < pcb+sizeof(pcb)
    591 	inc	PCB_SIZE, %l5		! then we have a stack overflow
    592 	btst	%fp, 1			! 64-bit stack?
    593 	sub	%fp, %l5, %l7
    594 	bnz,a,pt	%icc, 1f
    595 	 inc	BIAS, %l7		! Remove BIAS
    596 1:
    597 	cmp	%l7, PCB_SIZE
    598 	blu	%xcc, cleanwin_overflow
    599 #endif
    600 #endif
    601 	mov %l0, %l5
    602 	mov %l0, %l6; mov %l0, %l7; mov %l0, %o0; mov %l0, %o1
    603 
    604 	mov %l0, %o2; mov %l0, %o3; mov %l0, %o4; mov %l0, %o5;
    605 	mov %l0, %o6; mov %l0, %o7
    606 	CLRTT
    607 	retry; nop; NOTREACHED; TA32
    608 	.endm
    609 
    610 	/* handle clean window trap when trap level = 1 */
    611 	.macro CLEANWIN1
    612 	clr	%l0
    613 #ifdef DEBUG
    614 	set	0xbadbeef, %l0		! DEBUG
    615 #endif
    616 	mov %l0, %l1; mov %l0, %l2
    617 	rdpr %cleanwin, %o7		!	This handler is in-lined and cannot fault
    618 	inc %o7; mov %l0, %l3		!       Nucleus (trap&IRQ) code does not need clean windows
    619 	wrpr %g0, %o7, %cleanwin	!	Clear out %l0-%l8 and %o0-%o8 and inc %cleanwin and done
    620 #ifdef NOT_DEBUG
    621 	!!
    622 	!! Check the sp redzone
    623 	!!
    624 	rdpr	%wstate, t1
    625 	cmp	t1, WSTATE_KERN
    626 	bne,pt	icc, 7f
    627 	 sethi	%hi(_C_LABEL(redzone)), t1
    628 	ldx	[t1 + %lo(_C_LABEL(redzone))], t2
    629 	cmp	%sp, t2			! if sp >= t2, not in red zone
    630 	blu	panic_red		! and can continue normally
    631 7:
    632 #endif
    633 	mov %l0, %l4; mov %l0, %l5; mov %l0, %l6; mov %l0, %l7
    634 	mov %l0, %o0; mov %l0, %o1; mov %l0, %o2; mov %l0, %o3
    635 
    636 	mov %l0, %o4; mov %l0, %o5; mov %l0, %o6; mov %l0, %o7
    637 	CLRTT
    638 	retry; nop; TA32
    639 	.endm
    640 
    641 	.globl	start, _C_LABEL(kernel_text)
    642 	_C_LABEL(kernel_text) = kernel_start		! for kvm_mkdb(8)
    643 kernel_start:
    644 	/* Traps from TL=0 -- traps from user mode */
    645 #ifdef __STDC__
    646 #define TABLE(name)	user_ ## name
    647 #else
    648 #define	TABLE(name)	user_/**/name
    649 #endif
    650 	.globl	_C_LABEL(trapbase)
    651 _C_LABEL(trapbase):
    652 	b dostart; nop; TA8	! 000 = reserved -- Use it to boot
    653 	/* We should not get the next 5 traps */
    654 	UTRAP(0x001)		! 001 = POR Reset -- ROM should get this
    655 	UTRAP(0x002)		! 002 = WDR -- ROM should get this
    656 	UTRAP(0x003)		! 003 = XIR -- ROM should get this
    657 	UTRAP(0x004)		! 004 = SIR -- ROM should get this
    658 	UTRAP(0x005)		! 005 = RED state exception
    659 	UTRAP(0x006); UTRAP(0x007)
    660 	VTRAP(T_INST_EXCEPT, textfault)	! 008 = instr. access except
    661 	VTRAP(T_TEXTFAULT, textfault)	! 009 = instr access MMU miss
    662 	VTRAP(T_INST_ERROR, textfault)	! 00a = instr. access err
    663 	UTRAP(0x00b); UTRAP(0x00c); UTRAP(0x00d); UTRAP(0x00e); UTRAP(0x00f)
    664 	TRAP(T_ILLINST)			! 010 = illegal instruction
    665 	TRAP(T_PRIVINST)		! 011 = privileged instruction
    666 	UTRAP(0x012)			! 012 = unimplemented LDD
    667 	UTRAP(0x013)			! 013 = unimplemented STD
    668 	UTRAP(0x014); UTRAP(0x015); UTRAP(0x016); UTRAP(0x017); UTRAP(0x018)
    669 	UTRAP(0x019); UTRAP(0x01a); UTRAP(0x01b); UTRAP(0x01c); UTRAP(0x01d)
    670 	UTRAP(0x01e); UTRAP(0x01f)
    671 	TRAP(T_FPDISABLED)		! 020 = fp instr, but EF bit off in psr
    672 	TRAP(T_FP_IEEE_754)		! 021 = ieee 754 exception
    673 	TRAP(T_FP_OTHER)		! 022 = other fp exception
    674 	TRAP(T_TAGOF)			! 023 = tag overflow
    675 	CLEANWIN0			! 024-027 = clean window trap
    676 	TRAP(T_DIV0)			! 028 = divide by zero
    677 	UTRAP(0x029)			! 029 = internal processor error
    678 	UTRAP(0x02a); UTRAP(0x02b); UTRAP(0x02c); UTRAP(0x02d); UTRAP(0x02e); UTRAP(0x02f)
    679 	VTRAP(T_DATAFAULT, winfault)	! 030 = data fetch fault
    680 	UTRAP(0x031)			! 031 = data MMU miss -- no MMU
    681 	VTRAP(T_DATA_ERROR, winfault)	! 032 = data access error
    682 	VTRAP(T_DATA_PROT, winfault)	! 033 = data protection fault
    683 	TRAP(T_ALIGN)			! 034 = address alignment error -- we could fix it inline...
    684 	TRAP(T_LDDF_ALIGN)		! 035 = LDDF address alignment error -- we could fix it inline...
    685 	TRAP(T_STDF_ALIGN)		! 036 = STDF address alignment error -- we could fix it inline...
    686 	TRAP(T_PRIVACT)			! 037 = privileged action
    687 	UTRAP(0x038); UTRAP(0x039); UTRAP(0x03a); UTRAP(0x03b); UTRAP(0x03c);
    688 	UTRAP(0x03d); UTRAP(0x03e); UTRAP(0x03f);
    689 	VTRAP(T_ASYNC_ERROR, winfault)	! 040 = data fetch fault
    690 	SOFTINT4U(1, IE_L1)		! 041 = level 1 interrupt
    691 	HARDINT4U(2)			! 042 = level 2 interrupt
    692 	HARDINT4U(3)			! 043 = level 3 interrupt
    693 	SOFTINT4U(4, IE_L4)		! 044 = level 4 interrupt
    694 	HARDINT4U(5)			! 045 = level 5 interrupt
    695 	SOFTINT4U(6, IE_L6)		! 046 = level 6 interrupt
    696 	HARDINT4U(7)			! 047 = level 7 interrupt
    697 	HARDINT4U(8)			! 048 = level 8 interrupt
    698 	HARDINT4U(9)			! 049 = level 9 interrupt
    699 	HARDINT4U(10)			! 04a = level 10 interrupt
    700 	HARDINT4U(11)			! 04b = level 11 interrupt
    701 	ZS_INTERRUPT4U			! 04c = level 12 (zs) interrupt
    702 	HARDINT4U(13)			! 04d = level 13 interrupt
    703 	HARDINT4U(14)			! 04e = level 14 interrupt
    704 	HARDINT4U(15)			! 04f = nonmaskable interrupt
    705 	UTRAP(0x050); UTRAP(0x051); UTRAP(0x052); UTRAP(0x053); UTRAP(0x054); UTRAP(0x055)
    706 	UTRAP(0x056); UTRAP(0x057); UTRAP(0x058); UTRAP(0x059); UTRAP(0x05a); UTRAP(0x05b)
    707 	UTRAP(0x05c); UTRAP(0x05d); UTRAP(0x05e); UTRAP(0x05f)
    708 	VTRAP(0x060, interrupt_vector); ! 060 = interrupt vector
    709 	TRAP(T_PA_WATCHPT)		! 061 = physical address data watchpoint
    710 	TRAP(T_VA_WATCHPT)		! 062 = virtual address data watchpoint
    711 	TRAP(T_ECCERR)			! 063 = corrected ECC error
    712 ufast_IMMU_miss:			! 064 = fast instr access MMU miss
    713 	ldxa	[%g0] ASI_IMMU_8KPTR, %g2 ! Load IMMU 8K TSB pointer
    714 #ifdef NO_TSB
    715 	ba,a	%icc, instr_miss
    716 #endif
    717 	ldxa	[%g0] ASI_IMMU, %g1	! Load IMMU tag target register
    718 	ldda	[%g2] ASI_NUCLEUS_QUAD_LDD, %g4	! Load TSB tag:data into %g4:%g5
    719 	brgez,pn %g5, instr_miss	! Entry invalid?  Punt
    720 	 cmp	%g1, %g4		! Compare TLB tags
    721 	bne,pn %xcc, instr_miss		! Got right tag?
    722 	 nop
    723 	CLRTT
    724 	stxa	%g5, [%g0] ASI_IMMU_DATA_IN ! Enter new mapping
    725 	retry				! Try new mapping
    726 1:
    727 	sir
    728 	TA32
    729 ufast_DMMU_miss:			! 068 = fast data access MMU miss
    730 	ldxa	[%g0] ASI_DMMU_8KPTR, %g2! Load DMMU 8K TSB pointer
    731 #ifdef NO_TSB
    732 	ba,a	%icc, data_miss
    733 #endif
    734 	ldxa	[%g0] ASI_DMMU, %g1	! Load DMMU tag target register
    735 	ldda	[%g2] ASI_NUCLEUS_QUAD_LDD, %g4	! Load TSB tag and data into %g4 and %g5
    736 	brgez,pn %g5, data_miss		! Entry invalid?  Punt
    737 	 cmp	%g1, %g4		! Compare TLB tags
    738 	bnz,pn	%xcc, data_miss		! Got right tag?
    739 	 nop
    740 	CLRTT
    741 #ifdef TRAPSTATS
    742 	sethi	%hi(_C_LABEL(udhit)), %g1
    743 	lduw	[%g1+%lo(_C_LABEL(udhit))], %g2
    744 	inc	%g2
    745 	stw	%g2, [%g1+%lo(_C_LABEL(udhit))]
    746 #endif
    747 	stxa	%g5, [%g0] ASI_DMMU_DATA_IN ! Enter new mapping
    748 	retry				! Try new mapping
    749 1:
    750 	sir
    751 	TA32
    752 ufast_DMMU_protection:			! 06c = fast data access MMU protection
    753 #ifdef TRAPSTATS
    754 	sethi	%hi(_C_LABEL(udprot)), %g1
    755 	lduw	[%g1+%lo(_C_LABEL(udprot))], %g2
    756 	inc	%g2
    757 	stw	%g2, [%g1+%lo(_C_LABEL(udprot))]
    758 #endif
    759 #ifdef HWREF
    760 	ba,a,pt	%xcc, dmmu_write_fault
    761 #else
    762 	ba,a,pt	%xcc, winfault
    763 #endif
    764 	nop
    765 	TA32
    766 	TRAP(0x070)			! 0x070 fast_ECC_error
    767 					! Implementation dependent traps
    768 	UTRAP(0x071); UTRAP(0x072); UTRAP(0x073); UTRAP(0x074); UTRAP(0x075); UTRAP(0x076)
    769 	UTRAP(0x077); UTRAP(0x078); UTRAP(0x079); UTRAP(0x07a); UTRAP(0x07b); UTRAP(0x07c)
    770 	UTRAP(0x07d); UTRAP(0x07e); UTRAP(0x07f)
    771 TABLE(uspill):
    772 	SPILL64(uspill8,ASI_AIUS)	! 0x080 spill_0_normal -- used to save user windows in user mode
    773 	SPILL32(uspill4,ASI_AIUS)	! 0x084 spill_1_normal
    774 	SPILLBOTH(uspill8,uspill4,ASI_AIUS)	 ! 0x088 spill_2_normal
    775 	UTRAP(0x08c); TA32		! 0x08c spill_3_normal
    776 TABLE(kspill):
    777 	SPILL64(kspill8,ASI_N)		! 0x090 spill_4_normal -- used to save supervisor windows
    778 	SPILL32(kspill4,ASI_N)		! 0x094 spill_5_normal
    779 	SPILLBOTH(kspill8,kspill4,ASI_N) ! 0x098 spill_6_normal
    780 	UTRAP(0x09c); TA32		! 0x09c spill_7_normal
    781 TABLE(uspillk):
    782 	SPILL64(uspillk8,ASI_AIUS)	! 0x0a0 spill_0_other -- used to save user windows in supervisor mode
    783 	SPILL32(uspillk4,ASI_AIUS)	! 0x0a4 spill_1_other
    784 	SPILLBOTH(uspillk8,uspillk4,ASI_AIUS) ! 0x0a8 spill_2_other
    785 	UTRAP(0x0ac); TA32		! 0x0ac spill_3_other
    786 	UTRAP(0x0b0); TA32		! 0x0b0 spill_4_other
    787 	UTRAP(0x0b4); TA32		! 0x0b4 spill_5_other
    788 	UTRAP(0x0b8); TA32		! 0x0b8 spill_6_other
    789 	UTRAP(0x0bc); TA32		! 0x0bc spill_7_other
    790 TABLE(ufill):
    791 	FILL64(ufill8,ASI_AIUS)		! 0x0c0 fill_0_normal -- used to fill windows when running user mode
    792 	FILL32(ufill4,ASI_AIUS)		! 0x0c4 fill_1_normal
    793 	FILLBOTH(ufill8,ufill4,ASI_AIUS) ! 0x0c8 fill_2_normal
    794 	UTRAP(0x0cc); TA32		! 0x0cc fill_3_normal
    795 TABLE(kfill):
    796 	FILL64(kfill8,ASI_N)		! 0x0d0 fill_4_normal -- used to fill windows when running supervisor mode
    797 	FILL32(kfill4,ASI_N)		! 0x0d4 fill_5_normal
    798 	FILLBOTH(kfill8,kfill4,ASI_N)	! 0x0d8 fill_6_normal
    799 	UTRAP(0x0dc); TA32		! 0x0dc fill_7_normal
    800 TABLE(ufillk):
    801 	FILL64(ufillk8,ASI_AIUS)	! 0x0e0 fill_0_other
    802 	FILL32(ufillk4,ASI_AIUS)	! 0x0e4 fill_1_other
    803 	FILLBOTH(ufillk8,ufillk4,ASI_AIUS) ! 0x0e8 fill_2_other
    804 	UTRAP(0x0ec); TA32		! 0x0ec fill_3_other
    805 	UTRAP(0x0f0); TA32		! 0x0f0 fill_4_other
    806 	UTRAP(0x0f4); TA32		! 0x0f4 fill_5_other
    807 	UTRAP(0x0f8); TA32		! 0x0f8 fill_6_other
    808 	UTRAP(0x0fc); TA32		! 0x0fc fill_7_other
    809 TABLE(syscall):
    810 	SYSCALL				! 0x100 = sun syscall
    811 	BPT				! 0x101 = pseudo breakpoint instruction
    812 	STRAP(0x102); STRAP(0x103); STRAP(0x104); STRAP(0x105); STRAP(0x106); STRAP(0x107)
    813 	SYSCALL				! 0x108 = svr4 syscall
    814 	SYSCALL				! 0x109 = bsd syscall
    815 	BPT_KGDB_EXEC			! 0x10a = enter kernel gdb on kernel startup
    816 	STRAP(0x10b); STRAP(0x10c); STRAP(0x10d); STRAP(0x10e); STRAP(0x10f);
    817 	STRAP(0x110); STRAP(0x111); STRAP(0x112); STRAP(0x113); STRAP(0x114); STRAP(0x115); STRAP(0x116); STRAP(0x117)
    818 	STRAP(0x118); STRAP(0x119); STRAP(0x11a); STRAP(0x11b); STRAP(0x11c); STRAP(0x11d); STRAP(0x11e); STRAP(0x11f)
    819 	STRAP(0x120); STRAP(0x121); STRAP(0x122); STRAP(0x123); STRAP(0x124); STRAP(0x125); STRAP(0x126); STRAP(0x127)
    820 	STRAP(0x128); STRAP(0x129); STRAP(0x12a); STRAP(0x12b); STRAP(0x12c); STRAP(0x12d); STRAP(0x12e); STRAP(0x12f)
    821 	STRAP(0x130); STRAP(0x131); STRAP(0x132); STRAP(0x133); STRAP(0x134); STRAP(0x135); STRAP(0x136); STRAP(0x137)
    822 	STRAP(0x138); STRAP(0x139); STRAP(0x13a); STRAP(0x13b); STRAP(0x13c); STRAP(0x13d); STRAP(0x13e); STRAP(0x13f)
    823 	SYSCALL				! 0x140 SVID syscall (Solaris 2.7)
    824 	SYSCALL				! 0x141 SPARC International syscall
    825 	SYSCALL				! 0x142	OS Vendor syscall
    826 	SYSCALL				! 0x143 HW OEM syscall
    827 	STRAP(0x144); STRAP(0x145); STRAP(0x146); STRAP(0x147)
    828 	STRAP(0x148); STRAP(0x149); STRAP(0x14a); STRAP(0x14b); STRAP(0x14c); STRAP(0x14d); STRAP(0x14e); STRAP(0x14f)
    829 	STRAP(0x150); STRAP(0x151); STRAP(0x152); STRAP(0x153); STRAP(0x154); STRAP(0x155); STRAP(0x156); STRAP(0x157)
    830 	STRAP(0x158); STRAP(0x159); STRAP(0x15a); STRAP(0x15b); STRAP(0x15c); STRAP(0x15d); STRAP(0x15e); STRAP(0x15f)
    831 	STRAP(0x160); STRAP(0x161); STRAP(0x162); STRAP(0x163); STRAP(0x164); STRAP(0x165); STRAP(0x166); STRAP(0x167)
    832 	STRAP(0x168); STRAP(0x169); STRAP(0x16a); STRAP(0x16b); STRAP(0x16c); STRAP(0x16d); STRAP(0x16e); STRAP(0x16f)
    833 	STRAP(0x170); STRAP(0x171); STRAP(0x172); STRAP(0x173); STRAP(0x174); STRAP(0x175); STRAP(0x176); STRAP(0x177)
    834 	STRAP(0x178); STRAP(0x179); STRAP(0x17a); STRAP(0x17b); STRAP(0x17c); STRAP(0x17d); STRAP(0x17e); STRAP(0x17f)
    835 	! Traps beyond 0x17f are reserved
    836 	UTRAP(0x180); UTRAP(0x181); UTRAP(0x182); UTRAP(0x183); UTRAP(0x184); UTRAP(0x185); UTRAP(0x186); UTRAP(0x187)
    837 	UTRAP(0x188); UTRAP(0x189); UTRAP(0x18a); UTRAP(0x18b); UTRAP(0x18c); UTRAP(0x18d); UTRAP(0x18e); UTRAP(0x18f)
    838 	UTRAP(0x190); UTRAP(0x191); UTRAP(0x192); UTRAP(0x193); UTRAP(0x194); UTRAP(0x195); UTRAP(0x196); UTRAP(0x197)
    839 	UTRAP(0x198); UTRAP(0x199); UTRAP(0x19a); UTRAP(0x19b); UTRAP(0x19c); UTRAP(0x19d); UTRAP(0x19e); UTRAP(0x19f)
    840 	UTRAP(0x1a0); UTRAP(0x1a1); UTRAP(0x1a2); UTRAP(0x1a3); UTRAP(0x1a4); UTRAP(0x1a5); UTRAP(0x1a6); UTRAP(0x1a7)
    841 	UTRAP(0x1a8); UTRAP(0x1a9); UTRAP(0x1aa); UTRAP(0x1ab); UTRAP(0x1ac); UTRAP(0x1ad); UTRAP(0x1ae); UTRAP(0x1af)
    842 	UTRAP(0x1b0); UTRAP(0x1b1); UTRAP(0x1b2); UTRAP(0x1b3); UTRAP(0x1b4); UTRAP(0x1b5); UTRAP(0x1b6); UTRAP(0x1b7)
    843 	UTRAP(0x1b8); UTRAP(0x1b9); UTRAP(0x1ba); UTRAP(0x1bb); UTRAP(0x1bc); UTRAP(0x1bd); UTRAP(0x1be); UTRAP(0x1bf)
    844 	UTRAP(0x1c0); UTRAP(0x1c1); UTRAP(0x1c2); UTRAP(0x1c3); UTRAP(0x1c4); UTRAP(0x1c5); UTRAP(0x1c6); UTRAP(0x1c7)
    845 	UTRAP(0x1c8); UTRAP(0x1c9); UTRAP(0x1ca); UTRAP(0x1cb); UTRAP(0x1cc); UTRAP(0x1cd); UTRAP(0x1ce); UTRAP(0x1cf)
    846 	UTRAP(0x1d0); UTRAP(0x1d1); UTRAP(0x1d2); UTRAP(0x1d3); UTRAP(0x1d4); UTRAP(0x1d5); UTRAP(0x1d6); UTRAP(0x1d7)
    847 	UTRAP(0x1d8); UTRAP(0x1d9); UTRAP(0x1da); UTRAP(0x1db); UTRAP(0x1dc); UTRAP(0x1dd); UTRAP(0x1de); UTRAP(0x1df)
    848 	UTRAP(0x1e0); UTRAP(0x1e1); UTRAP(0x1e2); UTRAP(0x1e3); UTRAP(0x1e4); UTRAP(0x1e5); UTRAP(0x1e6); UTRAP(0x1e7)
    849 	UTRAP(0x1e8); UTRAP(0x1e9); UTRAP(0x1ea); UTRAP(0x1eb); UTRAP(0x1ec); UTRAP(0x1ed); UTRAP(0x1ee); UTRAP(0x1ef)
    850 	UTRAP(0x1f0); UTRAP(0x1f1); UTRAP(0x1f2); UTRAP(0x1f3); UTRAP(0x1f4); UTRAP(0x1f5); UTRAP(0x1f6); UTRAP(0x1f7)
    851 	UTRAP(0x1f8); UTRAP(0x1f9); UTRAP(0x1fa); UTRAP(0x1fb); UTRAP(0x1fc); UTRAP(0x1fd); UTRAP(0x1fe); UTRAP(0x1ff)
    852 
    853 	/* Traps from TL>0 -- traps from supervisor mode */
    854 #undef TABLE
    855 #ifdef __STDC__
    856 #define	TABLE(name)	nucleus_ ## name
    857 #else
    858 #define	TABLE(name)	nucleus_/**/name
    859 #endif
    860 trapbase_priv:
    861 	UTRAP(0x000)			! 000 = reserved -- Use it to boot
    862 	/* We should not get the next 5 traps */
    863 	UTRAP(0x001)			! 001 = POR Reset -- ROM should get this
    864 	UTRAP(0x002)			! 002 = WDR Watchdog -- ROM should get this
    865 	UTRAP(0x003)			! 003 = XIR -- ROM should get this
    866 	UTRAP(0x004)			! 004 = SIR -- ROM should get this
    867 	UTRAP(0x005)			! 005 = RED state exception
    868 	UTRAP(0x006); UTRAP(0x007)
    869 ktextfault:
    870 	VTRAP(T_INST_EXCEPT, textfault)	! 008 = instr. access except
    871 	VTRAP(T_TEXTFAULT, textfault)	! 009 = instr access MMU miss -- no MMU
    872 	VTRAP(T_INST_ERROR, textfault)	! 00a = instr. access err
    873 	UTRAP(0x00b); UTRAP(0x00c); UTRAP(0x00d); UTRAP(0x00e); UTRAP(0x00f)
    874 	TRAP(T_ILLINST)			! 010 = illegal instruction
    875 	TRAP(T_PRIVINST)		! 011 = privileged instruction
    876 	UTRAP(0x012)			! 012 = unimplemented LDD
    877 	UTRAP(0x013)			! 013 = unimplemented STD
    878 	UTRAP(0x014); UTRAP(0x015); UTRAP(0x016); UTRAP(0x017); UTRAP(0x018)
    879 	UTRAP(0x019); UTRAP(0x01a); UTRAP(0x01b); UTRAP(0x01c); UTRAP(0x01d)
    880 	UTRAP(0x01e); UTRAP(0x01f)
    881 	TRAP(T_FPDISABLED)		! 020 = fp instr, but EF bit off in psr
    882 	TRAP(T_FP_IEEE_754)		! 021 = ieee 754 exception
    883 	TRAP(T_FP_OTHER)		! 022 = other fp exception
    884 	TRAP(T_TAGOF)			! 023 = tag overflow
    885 	CLEANWIN1			! 024-027 = clean window trap
    886 	TRAP(T_DIV0)			! 028 = divide by zero
    887 	UTRAP(0x029)			! 029 = internal processor error
    888 	UTRAP(0x02a); UTRAP(0x02b); UTRAP(0x02c); UTRAP(0x02d); UTRAP(0x02e); UTRAP(0x02f)
    889 kdatafault:
    890 	VTRAP(T_DATAFAULT, winfault)	! 030 = data fetch fault
    891 	UTRAP(0x031)			! 031 = data MMU miss -- no MMU
    892 	VTRAP(T_DATA_ERROR, winfault)	! 032 = data fetch fault
    893 	VTRAP(T_DATA_PROT, winfault)	! 033 = data fetch fault
    894 	VTRAP(T_ALIGN, checkalign)	! 034 = address alignment error -- we could fix it inline...
    895 	TRAP(T_LDDF_ALIGN)		! 035 = LDDF address alignment error -- we could fix it inline...
    896 	TRAP(T_STDF_ALIGN)		! 036 = STDF address alignment error -- we could fix it inline...
    897 	TRAP(T_PRIVACT)			! 037 = privileged action
    898 	UTRAP(0x038); UTRAP(0x039); UTRAP(0x03a); UTRAP(0x03b); UTRAP(0x03c);
    899 	UTRAP(0x03d); UTRAP(0x03e); UTRAP(0x03f);
    900 	VTRAP(T_ASYNC_ERROR, winfault)	! 040 = data fetch fault
    901 	SOFTINT4U(1, IE_L1)		! 041 = level 1 interrupt
    902 	HARDINT4U(2)			! 042 = level 2 interrupt
    903 	HARDINT4U(3)			! 043 = level 3 interrupt
    904 	SOFTINT4U(4, IE_L4)		! 044 = level 4 interrupt
    905 	HARDINT4U(5)			! 045 = level 5 interrupt
    906 	SOFTINT4U(6, IE_L6)		! 046 = level 6 interrupt
    907 	HARDINT4U(7)			! 047 = level 7 interrupt
    908 	HARDINT4U(8)			! 048 = level 8 interrupt
    909 	HARDINT4U(9)			! 049 = level 9 interrupt
    910 	HARDINT4U(10)			! 04a = level 10 interrupt
    911 	HARDINT4U(11)			! 04b = level 11 interrupt
    912 	ZS_INTERRUPT4U			! 04c = level 12 (zs) interrupt
    913 	HARDINT4U(13)			! 04d = level 13 interrupt
    914 	HARDINT4U(14)			! 04e = level 14 interrupt
    915 	HARDINT4U(15)			! 04f = nonmaskable interrupt
    916 	UTRAP(0x050); UTRAP(0x051); UTRAP(0x052); UTRAP(0x053); UTRAP(0x054); UTRAP(0x055)
    917 	UTRAP(0x056); UTRAP(0x057); UTRAP(0x058); UTRAP(0x059); UTRAP(0x05a); UTRAP(0x05b)
    918 	UTRAP(0x05c); UTRAP(0x05d); UTRAP(0x05e); UTRAP(0x05f)
    919 	VTRAP(0x060, interrupt_vector); ! 060 = interrupt vector
    920 	TRAP(T_PA_WATCHPT)		! 061 = physical address data watchpoint
    921 	TRAP(T_VA_WATCHPT)		! 062 = virtual address data watchpoint
    922 	TRAP(T_ECCERR)			! 063 = corrected ECC error
    923 kfast_IMMU_miss:			! 064 = fast instr access MMU miss
    924 	ldxa	[%g0] ASI_IMMU_8KPTR, %g2 ! Load IMMU 8K TSB pointer
    925 #ifdef NO_TSB
    926 	ba,a	%icc, instr_miss
    927 #endif
    928 	ldxa	[%g0] ASI_IMMU, %g1	! Load IMMU tag target register
    929 	ldda	[%g2] ASI_NUCLEUS_QUAD_LDD, %g4	! Load TSB tag:data into %g4:%g5
    930 	brgez,pn %g5, instr_miss	! Entry invalid?  Punt
    931 	 cmp	%g1, %g4		! Compare TLB tags
    932 	bne,pn %xcc, instr_miss		! Got right tag?
    933 	 nop
    934 	CLRTT
    935 	stxa	%g5, [%g0] ASI_IMMU_DATA_IN ! Enter new mapping
    936 	retry				! Try new mapping
    937 1:
    938 	sir
    939 	TA32
    940 kfast_DMMU_miss:			! 068 = fast data access MMU miss
    941 	ldxa	[%g0] ASI_DMMU_8KPTR, %g2! Load DMMU 8K TSB pointer
    942 #ifdef NO_TSB
    943 	ba,a	%icc, data_miss
    944 #endif
    945 	ldxa	[%g0] ASI_DMMU, %g1	! Load DMMU tag target register
    946 	ldda	[%g2] ASI_NUCLEUS_QUAD_LDD, %g4	! Load TSB tag and data into %g4 and %g5
    947 	brgez,pn %g5, data_miss		! Entry invalid?  Punt
    948 	 cmp	%g1, %g4		! Compare TLB tags
    949 	bnz,pn	%xcc, data_miss		! Got right tag?
    950 	 nop
    951 	CLRTT
    952 #ifdef TRAPSTATS
    953 	sethi	%hi(_C_LABEL(kdhit)), %g1
    954 	lduw	[%g1+%lo(_C_LABEL(kdhit))], %g2
    955 	inc	%g2
    956 	stw	%g2, [%g1+%lo(_C_LABEL(kdhit))]
    957 #endif
    958 	stxa	%g5, [%g0] ASI_DMMU_DATA_IN ! Enter new mapping
    959 	retry				! Try new mapping
    960 1:
    961 	sir
    962 	TA32
    963 kfast_DMMU_protection:			! 06c = fast data access MMU protection
    964 #ifdef TRAPSTATS
    965 	sethi	%hi(_C_LABEL(kdprot)), %g1
    966 	lduw	[%g1+%lo(_C_LABEL(kdprot))], %g2
    967 	inc	%g2
    968 	stw	%g2, [%g1+%lo(_C_LABEL(kdprot))]
    969 #endif
    970 #ifdef HWREF
    971 	ba,a,pt	%xcc, dmmu_write_fault
    972 #else
    973 	ba,a,pt	%xcc, winfault
    974 #endif
    975 	nop
    976 	TA32
    977 	TRAP(0x070)			! 0x070 fast_ECC_error
    978 					! Implementation dependent traps
    979 	UTRAP(0x071); UTRAP(0x072); UTRAP(0x073); UTRAP(0x074); UTRAP(0x075); UTRAP(0x076)
    980 	UTRAP(0x077); UTRAP(0x078); UTRAP(0x079); UTRAP(0x07a); UTRAP(0x07b); UTRAP(0x07c)
    981 	UTRAP(0x07d); UTRAP(0x07e); UTRAP(0x07f)
    982 TABLE(uspill):
    983 	SPILL64(1,ASI_AIUS)		! 0x080 spill_0_normal -- used to save user windows
    984 	SPILL32(2,ASI_AIUS)		! 0x084 spill_1_normal
    985 	SPILLBOTH(1b,2b,ASI_AIUS)	! 0x088 spill_2_normal
    986 	UTRAP(0x08c); TA32		! 0x08c spill_3_normal
    987 TABLE(kspill):
    988 	SPILL64(1,ASI_N)		! 0x090 spill_4_normal -- used to save supervisor windows
    989 	SPILL32(2,ASI_N)		! 0x094 spill_5_normal
    990 	SPILLBOTH(1b,2b,ASI_N)		! 0x098 spill_6_normal
    991 	UTRAP(0x09c); TA32		! 0x09c spill_7_normal
    992 TABLE(uspillk):
    993 	SPILL64(1,ASI_AIUS)		! 0x0a0 spill_0_other -- used to save user windows in nucleus mode
    994 	SPILL32(2,ASI_AIUS)		! 0x0a4 spill_1_other
    995 	SPILLBOTH(1b,2b,ASI_AIUS)	! 0x0a8 spill_2_other
    996 	UTRAP(0x0ac); TA32		! 0x0ac spill_3_other
    997 	UTRAP(0x0b0); TA32		! 0x0b0 spill_4_other
    998 	UTRAP(0x0b4); TA32		! 0x0b4 spill_5_other
    999 	UTRAP(0x0b8); TA32		! 0x0b8 spill_6_other
   1000 	UTRAP(0x0bc); TA32		! 0x0bc spill_7_other
   1001 TABLE(ufill):
   1002 	FILL64(nufill8,ASI_AIUS)	! 0x0c0 fill_0_normal -- used to fill windows when running nucleus mode from user
   1003 	FILL32(nufill4,ASI_AIUS)	! 0x0c4 fill_1_normal
   1004 	FILLBOTH(nufill8,nufill4,ASI_AIUS) ! 0x0c8 fill_2_normal
   1005 	UTRAP(0x0cc); TA32		! 0x0cc fill_3_normal
   1006 TABLE(sfill):
   1007 	FILL64(sfill8,ASI_N)		! 0x0d0 fill_4_normal -- used to fill windows when running nucleus mode from supervisor
   1008 	FILL32(sfill4,ASI_N)		! 0x0d4 fill_5_normal
   1009 	FILLBOTH(sfill8,sfill4,ASI_N)	! 0x0d8 fill_6_normal
   1010 	UTRAP(0x0dc); TA32		! 0x0dc fill_7_normal
   1011 TABLE(kfill):
   1012 	FILL64(nkfill8,ASI_AIUS)	! 0x0e0 fill_0_other -- used to fill user windows when running nucleus mode -- will we ever use this?
   1013 	FILL32(nkfill4,ASI_AIUS)	! 0x0e4 fill_1_other
   1014 	FILLBOTH(nkfill8,nkfill4,ASI_AIUS)! 0x0e8 fill_2_other
   1015 	UTRAP(0x0ec); TA32		! 0x0ec fill_3_other
   1016 	UTRAP(0x0f0); TA32		! 0x0f0 fill_4_other
   1017 	UTRAP(0x0f4); TA32		! 0x0f4 fill_5_other
   1018 	UTRAP(0x0f8); TA32		! 0x0f8 fill_6_other
   1019 	UTRAP(0x0fc); TA32		! 0x0fc fill_7_other
   1020 TABLE(syscall):
   1021 	SYSCALL				! 0x100 = sun syscall
   1022 	BPT				! 0x101 = pseudo breakpoint instruction
   1023 	STRAP(0x102); STRAP(0x103); STRAP(0x104); STRAP(0x105); STRAP(0x106); STRAP(0x107)
   1024 	SYSCALL				! 0x108 = svr4 syscall
   1025 	SYSCALL				! 0x109 = bsd syscall
   1026 	BPT_KGDB_EXEC			! 0x10a = enter kernel gdb on kernel startup
   1027 	STRAP(0x10b); STRAP(0x10c); STRAP(0x10d); STRAP(0x10e); STRAP(0x10f);
   1028 	STRAP(0x110); STRAP(0x111); STRAP(0x112); STRAP(0x113); STRAP(0x114); STRAP(0x115); STRAP(0x116); STRAP(0x117)
   1029 	STRAP(0x118); STRAP(0x119); STRAP(0x11a); STRAP(0x11b); STRAP(0x11c); STRAP(0x11d); STRAP(0x11e); STRAP(0x11f)
   1030 	STRAP(0x120); STRAP(0x121); STRAP(0x122); STRAP(0x123); STRAP(0x124); STRAP(0x125); STRAP(0x126); STRAP(0x127)
   1031 	STRAP(0x128); STRAP(0x129); STRAP(0x12a); STRAP(0x12b); STRAP(0x12c); STRAP(0x12d); STRAP(0x12e); STRAP(0x12f)
   1032 	STRAP(0x130); STRAP(0x131); STRAP(0x132); STRAP(0x133); STRAP(0x134); STRAP(0x135); STRAP(0x136); STRAP(0x137)
   1033 	STRAP(0x138); STRAP(0x139); STRAP(0x13a); STRAP(0x13b); STRAP(0x13c); STRAP(0x13d); STRAP(0x13e); STRAP(0x13f)
   1034 	STRAP(0x140); STRAP(0x141); STRAP(0x142); STRAP(0x143); STRAP(0x144); STRAP(0x145); STRAP(0x146); STRAP(0x147)
   1035 	STRAP(0x148); STRAP(0x149); STRAP(0x14a); STRAP(0x14b); STRAP(0x14c); STRAP(0x14d); STRAP(0x14e); STRAP(0x14f)
   1036 	STRAP(0x150); STRAP(0x151); STRAP(0x152); STRAP(0x153); STRAP(0x154); STRAP(0x155); STRAP(0x156); STRAP(0x157)
   1037 	STRAP(0x158); STRAP(0x159); STRAP(0x15a); STRAP(0x15b); STRAP(0x15c); STRAP(0x15d); STRAP(0x15e); STRAP(0x15f)
   1038 	STRAP(0x160); STRAP(0x161); STRAP(0x162); STRAP(0x163); STRAP(0x164); STRAP(0x165); STRAP(0x166); STRAP(0x167)
   1039 	STRAP(0x168); STRAP(0x169); STRAP(0x16a); STRAP(0x16b); STRAP(0x16c); STRAP(0x16d); STRAP(0x16e); STRAP(0x16f)
   1040 	STRAP(0x170); STRAP(0x171); STRAP(0x172); STRAP(0x173); STRAP(0x174); STRAP(0x175); STRAP(0x176); STRAP(0x177)
   1041 	STRAP(0x178); STRAP(0x179); STRAP(0x17a); STRAP(0x17b); STRAP(0x17c); STRAP(0x17d); STRAP(0x17e); STRAP(0x17f)
   1042 	! Traps beyond 0x17f are reserved
   1043 	UTRAP(0x180); UTRAP(0x181); UTRAP(0x182); UTRAP(0x183); UTRAP(0x184); UTRAP(0x185); UTRAP(0x186); UTRAP(0x187)
   1044 	UTRAP(0x188); UTRAP(0x189); UTRAP(0x18a); UTRAP(0x18b); UTRAP(0x18c); UTRAP(0x18d); UTRAP(0x18e); UTRAP(0x18f)
   1045 	UTRAP(0x190); UTRAP(0x191); UTRAP(0x192); UTRAP(0x193); UTRAP(0x194); UTRAP(0x195); UTRAP(0x196); UTRAP(0x197)
   1046 	UTRAP(0x198); UTRAP(0x199); UTRAP(0x19a); UTRAP(0x19b); UTRAP(0x19c); UTRAP(0x19d); UTRAP(0x19e); UTRAP(0x19f)
   1047 	UTRAP(0x1a0); UTRAP(0x1a1); UTRAP(0x1a2); UTRAP(0x1a3); UTRAP(0x1a4); UTRAP(0x1a5); UTRAP(0x1a6); UTRAP(0x1a7)
   1048 	UTRAP(0x1a8); UTRAP(0x1a9); UTRAP(0x1aa); UTRAP(0x1ab); UTRAP(0x1ac); UTRAP(0x1ad); UTRAP(0x1ae); UTRAP(0x1af)
   1049 	UTRAP(0x1b0); UTRAP(0x1b1); UTRAP(0x1b2); UTRAP(0x1b3); UTRAP(0x1b4); UTRAP(0x1b5); UTRAP(0x1b6); UTRAP(0x1b7)
   1050 	UTRAP(0x1b8); UTRAP(0x1b9); UTRAP(0x1ba); UTRAP(0x1bb); UTRAP(0x1bc); UTRAP(0x1bd); UTRAP(0x1be); UTRAP(0x1bf)
   1051 	UTRAP(0x1c0); UTRAP(0x1c1); UTRAP(0x1c2); UTRAP(0x1c3); UTRAP(0x1c4); UTRAP(0x1c5); UTRAP(0x1c6); UTRAP(0x1c7)
   1052 	UTRAP(0x1c8); UTRAP(0x1c9); UTRAP(0x1ca); UTRAP(0x1cb); UTRAP(0x1cc); UTRAP(0x1cd); UTRAP(0x1ce); UTRAP(0x1cf)
   1053 	UTRAP(0x1d0); UTRAP(0x1d1); UTRAP(0x1d2); UTRAP(0x1d3); UTRAP(0x1d4); UTRAP(0x1d5); UTRAP(0x1d6); UTRAP(0x1d7)
   1054 	UTRAP(0x1d8); UTRAP(0x1d9); UTRAP(0x1da); UTRAP(0x1db); UTRAP(0x1dc); UTRAP(0x1dd); UTRAP(0x1de); UTRAP(0x1df)
   1055 	UTRAP(0x1e0); UTRAP(0x1e1); UTRAP(0x1e2); UTRAP(0x1e3); UTRAP(0x1e4); UTRAP(0x1e5); UTRAP(0x1e6); UTRAP(0x1e7)
   1056 	UTRAP(0x1e8); UTRAP(0x1e9); UTRAP(0x1ea); UTRAP(0x1eb); UTRAP(0x1ec); UTRAP(0x1ed); UTRAP(0x1ee); UTRAP(0x1ef)
   1057 	UTRAP(0x1f0); UTRAP(0x1f1); UTRAP(0x1f2); UTRAP(0x1f3); UTRAP(0x1f4); UTRAP(0x1f5); UTRAP(0x1f6); UTRAP(0x1f7)
   1058 	UTRAP(0x1f8); UTRAP(0x1f9); UTRAP(0x1fa); UTRAP(0x1fb); UTRAP(0x1fc); UTRAP(0x1fd); UTRAP(0x1fe); UTRAP(0x1ff)
   1059 
   1060 #ifdef SUN4V
   1061 
   1062 /* Macros for sun4v traps */
   1063 
   1064 	.macro	sun4v_trap_entry count
   1065 	.rept	\count
   1066 	ba	slowtrap
   1067 	 nop
   1068 	.align	32
   1069 	.endr
   1070 	.endm
   1071 
   1072 	.macro	sun4v_trap_entry_fail count
   1073 	.rept	\count
   1074 	sir
   1075 	.align	32
   1076 	.endr
   1077 	.endm
   1078 
   1079 	.macro	sun4v_trap_entry_spill_fill_fail count
   1080 	.rept	\count
   1081 	sir
   1082 	.align	128
   1083 	.endr
   1084 	.endm
   1085 
   1086 /* The actual trap base for sun4v */
   1087 	.align	0x8000
   1088 	.globl	_C_LABEL(trapbase_sun4v)
   1089 _C_LABEL(trapbase_sun4v):
   1090 	!
   1091 	! trap level 0
   1092 	!
   1093 	sun4v_trap_entry 8					! 0x000-0x007
   1094 	VTRAP(T_INST_EXCEPT, sun4v_tl0_itsb_miss)		! 0x008 - inst except
   1095 	VTRAP(T_TEXTFAULT, sun4v_tl0_itsb_miss)			! 0x009 - inst MMU miss
   1096 	sun4v_trap_entry 26					! 0x00a-0x023
   1097 	CLEANWIN0						! 0x24-0x27 = clean window
   1098 	sun4v_trap_entry 8					! 0x028-0x02f
   1099 	VTRAP(T_DATAFAULT, sun4v_datatrap)	! 0x030 = data access exception (UA 2005)
   1100 	VTRAP(T_DATA_MMU_MISS, sun4v_dtsb_miss)			! 0x031 = data MMU miss
   1101 	sun4v_trap_entry 2					! 0x032-0x033
   1102 	TRAP(T_ALIGN)						! 0x034 = address alignment error
   1103 	sun4v_trap_entry 12					! 0x035-0x040
   1104 	HARDINT4V(1)						! 0x041 = level 1 interrupt
   1105 	HARDINT4V(2)						! 0x042 = level 2 interrupt
   1106 	HARDINT4V(3)						! 0x043 = level 3 interrupt
   1107 	HARDINT4V(4)						! 0x044 = level 4 interrupt
   1108 	HARDINT4V(5)						! 0x045 = level 5 interrupt
   1109 	HARDINT4V(6)						! 0x046 = level 6 interrupt
   1110 	HARDINT4V(7)						! 0x047 = level 7 interrupt
   1111 	HARDINT4V(8)						! 0x048 = level 8 interrupt
   1112 	HARDINT4V(9)						! 0x049 = level 9 interrupt
   1113 	HARDINT4V(10)						! 0x04a = level 10 interrupt
   1114 	HARDINT4V(11)						! 0x04b = level 11 interrupt
   1115 	HARDINT4V(12)						! 0x04c = level 12 interrupt
   1116 	HARDINT4V(13)						! 0x04d = level 13 interrupt
   1117 	HARDINT4V(14)						! 0x04e = level 14 interrupt
   1118 	HARDINT4V(15)						! 0x04f = level 15 interrupt
   1119 	sun4v_trap_entry 28					! 0x050-0x06b
   1120 	VTRAP(T_FDMMU_PROT, sun4v_tl0_dtsb_prot)		! 0x06c
   1121 	sun4v_trap_entry 15					! 0x06d-0x07b
   1122 	VTRAP(T_CPU_MONDO, sun4v_cpu_mondo)			! 0x07c = cpu mondo
   1123 	VTRAP(T_DEV_MONDO, sun4v_dev_mondo)			! 0x07d = dev mondo
   1124 	sun4v_trap_entry 2					! 0x07e-0x07f
   1125 	SPILL64(uspill8_sun4vt0,ASI_AIUS)			! 0x080 spill_0_normal -- used to save user windows in user mode
   1126 	SPILL32(uspill4_sun4vt0,ASI_AIUS)			! 0x084 spill_1_normal
   1127 	SPILLBOTH(uspill8_sun4vt0,uspill4_sun4vt0,ASI_AIUS)	! 0x088 spill_2_normal
   1128 	sun4v_trap_entry_spill_fill_fail 1			! 0x08c spill_3_normal
   1129 	SPILL64(kspill8_sun4vt0,ASI_N)				! 0x090 spill_4_normal  -- used to save supervisor windows
   1130 	SPILL32(kspill4_sun4vt0,ASI_N)				! 0x094 spill_5_normal
   1131 	SPILLBOTH(kspill8_sun4vt0,kspill4_sun4vt0,ASI_N)	! 0x098 spill_6_normal
   1132 	sun4v_trap_entry_spill_fill_fail 1			! 0x09c spill_7_normal
   1133 	SPILL64(uspillk8_sun4vt0,ASI_AIUS)			! 0x0a0 spill_0_other -- used to save user windows in supervisor mode
   1134 	SPILL32(uspillk4_sun4vt0,ASI_AIUS)			! 0x0a4 spill_1_other
   1135 	SPILLBOTH(uspillk8_sun4vt0,uspillk4_sun4vt0,ASI_AIUS)	! 0x0a8 spill_2_other
   1136 	sun4v_trap_entry_spill_fill_fail 1			! 0x0ac spill_3_other
   1137 	sun4v_trap_entry_spill_fill_fail 1			! 0x0b0 spill_4_other
   1138 	sun4v_trap_entry_spill_fill_fail 1			! 0x0b4 spill_5_other
   1139 	sun4v_trap_entry_spill_fill_fail 1			! 0x0b8 spill_6_other
   1140 	sun4v_trap_entry_spill_fill_fail 1			! 0x0bc spill_7_other
   1141 	FILL64(ufill8_sun4vt0,ASI_AIUS)				! 0x0c0 fill_0_normal -- used to fill windows when running user mode
   1142 	FILL32(ufill4_sun4vt0,ASI_AIUS)				! 0x0c4 fill_1_normal
   1143 	FILLBOTH(ufill8_sun4vt0,ufill4_sun4vt0,ASI_AIUS)	! 0x0c8 fill_2_normal
   1144 	sun4v_trap_entry_spill_fill_fail 1			! 0x0cc fill_3_normal
   1145 	FILL64(kfill8_sun4vt0,ASI_N)				! 0x0d0 fill_4_normal  -- used to fill windows when running supervisor mode
   1146 	FILL32(kfill4_sun4vt0,ASI_N)				! 0x0d4 fill_5_normal
   1147 	FILLBOTH(kfill8_sun4vt0,kfill4_sun4vt0,ASI_N)		! 0x0d8 fill_6_normal
   1148 	sun4v_trap_entry_spill_fill_fail 1			! 0x0dc fill_7_normal
   1149 	FILL64(ufillk8_sun4vt0,ASI_AIUS)			! 0x0e0 fill_0_other
   1150 	FILL32(ufillk4_sun4vt0,ASI_AIUS)			! 0x0e4 fill_1_other
   1151 	FILLBOTH(ufillk8_sun4vt0,ufillk4_sun4vt0,ASI_AIUS)	! 0x0e8 fill_2_other
   1152 	sun4v_trap_entry_spill_fill_fail 1			! 0x0ec fill_3_other
   1153 	sun4v_trap_entry_spill_fill_fail 1			! 0x0f0 fill_4_other
   1154 	sun4v_trap_entry_spill_fill_fail 1			! 0x0f4 fill_5_other
   1155 	sun4v_trap_entry_spill_fill_fail 1			! 0x0f8 fill_6_other
   1156 	sun4v_trap_entry_spill_fill_fail 1			! 0x0fc fill_7_other
   1157 	SYSCALL							! 0x100 = syscall
   1158 	BPT							! 0x101 = pseudo breakpoint instruction
   1159 	sun4v_trap_entry 254					! 0x102-0x1ff
   1160 	!
   1161 	! trap level 1
   1162 	!
   1163 	sun4v_trap_entry 36					! 0x000-0x023
   1164 	CLEANWIN1						! 0x24-0x27 = clean window
   1165 	sun4v_trap_entry 8					! 0x028-0x02F
   1166 	VTRAP(T_DATAFAULT, sun4v_tl1_ptbl_miss)			! 0x030 = ???
   1167 	VTRAP(T_DATA_MMU_MISS, sun4v_tl1_dtsb_miss)		! 0x031 = data MMU miss
   1168 	VTRAP(T_DATA_ERROR, sun4v_tl1_ptbl_miss)		! 0x032 = ???
   1169 	VTRAP(T_DATA_PROT, sun4v_tl1_ptbl_miss)			! 0x033 = ???
   1170 	sun4v_trap_entry 56					! 0x034-0x06b
   1171 	VTRAP(T_FDMMU_PROT, sun4v_tl1_dtsb_prot)		! 0x06c
   1172 	sun4v_trap_entry 19					! 0x06d-0x07f
   1173 	sun4v_tl1_uspill_normal					! 0x080 spill_0_normal -- save user windows
   1174 	sun4v_tl1_uspill_normal					! 0x084 spill_1_normal
   1175 	sun4v_tl1_uspill_normal					! 0x088 spill_2_normal
   1176 	sun4v_trap_entry_spill_fill_fail 1			! 0x08c spill_3_normal
   1177 	SPILL64(kspill8_sun4vt1,ASI_N)				! 0x090 spill_4_normal -- save supervisor windows
   1178 	SPILL32(kspill4_sun4vt1,ASI_N)				! 0x094 spill_5_normal
   1179 	SPILLBOTH(kspill8_sun4vt1,kspill4_sun4vt1,ASI_N)	! 0x098 spill_6_normal
   1180 	sun4v_trap_entry_spill_fill_fail 1			! 0x09c spill_7_normal
   1181 	sun4v_tl1_uspill_other					! 0x0a0 spill_0_other -- save user windows in nucleus mode
   1182 	sun4v_tl1_uspill_other					! 0x0a4 spill_1_other
   1183 	sun4v_tl1_uspill_other					! 0x0a8 spill_2_other
   1184 	sun4v_trap_entry_spill_fill_fail 1			! 0x0ac spill_3_other
   1185 	sun4v_trap_entry_spill_fill_fail 1			! 0x0b0 spill_4_other
   1186 	sun4v_trap_entry_spill_fill_fail 1			! 0x0b4 spill_5_other
   1187 	sun4v_trap_entry_spill_fill_fail 1			! 0x0b8 spill_6_other
   1188 	sun4v_trap_entry_spill_fill_fail 1			! 0x0bc spill_7_other
   1189 	FILL64(ufill8_sun4vt1,ASI_AIUS)				! 0x0c0 fill_0_normal -- fill windows when running nucleus mode from user
   1190 	FILL32(ufill4_sun4vt1,ASI_AIUS)				! 0x0c4 fill_1_normal
   1191 	FILLBOTH(ufill8_sun4vt1,ufill4_sun4vt1,ASI_AIUS)	! 0x0c8 fill_2_normal
   1192 	sun4v_trap_entry_spill_fill_fail 1			! 0x0cc fill_3_normal
   1193 	FILL64(kfill8_sun4vt1,ASI_N)				! 0x0d0 fill_4_normal -- fill windows when running nucleus mode from supervisor
   1194 	FILL32(kfill4_sun4vt1,ASI_N)				! 0x0d4 fill_5_normal
   1195 	FILLBOTH(kfill8_sun4vt1,kfill4_sun4vt1,ASI_N)		! 0x0d8 fill_6_normal
   1196 	sun4v_trap_entry_spill_fill_fail 1			! 0x0dc fill_7_normal
   1197 	FILL64(ufillk8_sun4vt1,ASI_AIUS)			! 0x0e0 fill_0_other -- fill user windows when running nucleus mode -- will we ever use this?
   1198 	FILL32(ufillk4_sun4vt1,ASI_AIUS)			! 0x0e4 fill_1_other
   1199 	FILLBOTH(ufillk8_sun4vt1,ufillk4_sun4vt1,ASI_AIUS)	! 0x0e8 fill_2_other
   1200 	sun4v_trap_entry_spill_fill_fail 1			! 0x0ec fill_3_other
   1201 	sun4v_trap_entry_spill_fill_fail 1			! 0x0f0 fill_4_other
   1202 	sun4v_trap_entry_spill_fill_fail 1			! 0x0f4 fill_5_other
   1203 	sun4v_trap_entry_spill_fill_fail 1			! 0x0f8 fill_6_other
   1204 	sun4v_trap_entry_spill_fill_fail 1			! 0x0fc fill_7_other
   1205 	sun4v_trap_entry_fail 256				! 0x100-0x1ff
   1206 
   1207 #endif
   1208 
   1209 #if 0
   1210 /*
   1211  * If the cleanwin trap handler detects an overflow we come here.
   1212  * We need to fix up the window registers, switch to the interrupt
   1213  * stack, and then trap to the debugger.
   1214  */
   1215 cleanwin_overflow:
   1216 	!! We've already incremented %cleanwin
   1217 	!! So restore %cwp
   1218 	rdpr	%cwp, %l0
   1219 	dec	%l0
   1220 	wrpr	%l0, %g0, %cwp
   1221 	set	EINTSTACK-STKB-CC64FSZ, %l0
   1222 	save	%l0, 0, %sp
   1223 
   1224 	ta	1		! Enter debugger
   1225 	sethi	%hi(1f), %o0
   1226 	call	_C_LABEL(panic)
   1227 	 or	%o0, %lo(1f), %o0
   1228 	restore
   1229 	retry
   1230 	.data
   1231 1:
   1232 	.asciz	"Kernel stack overflow!"
   1233 	_ALIGN
   1234 	.text
   1235 #endif
   1236 
   1237 #ifdef NOTDEF_DEBUG
   1238 /*
   1239  * A hardware red zone is impossible.  We simulate one in software by
   1240  * keeping a `red zone' pointer; if %sp becomes less than this, we panic.
   1241  * This is expensive and is only enabled when debugging.
   1242  */
   1243 #define	REDSIZE	(PCB_SIZE)	/* Mark used portion of pcb structure out of bounds */
   1244 #define	REDSTACK 2048		/* size of `panic: stack overflow' region */
   1245 	.data
   1246 	_ALIGN
   1247 redzone:
   1248 	.xword	_C_LABEL(XXX) + REDSIZE
   1249 redstack:
   1250 	.space	REDSTACK
   1251 eredstack:
   1252 Lpanic_red:
   1253 	.asciz	"kernel stack overflow"
   1254 	_ALIGN
   1255 	.text
   1256 
   1257 	/* set stack pointer redzone to base+minstack; alters base */
   1258 #define	SET_SP_REDZONE(base, tmp) \
   1259 	add	base, REDSIZE, base; \
   1260 	sethi	%hi(_C_LABEL(redzone)), tmp; \
   1261 	stx	base, [tmp + %lo(_C_LABEL(redzone))]
   1262 
   1263 	/* variant with a constant */
   1264 #define	SET_SP_REDZONE_CONST(const, tmp1, tmp2) \
   1265 	set	(const) + REDSIZE, tmp1; \
   1266 	sethi	%hi(_C_LABEL(redzone)), tmp2; \
   1267 	stx	tmp1, [tmp2 + %lo(_C_LABEL(redzone))]
   1268 
   1269 	/* check stack pointer against redzone (uses two temps) */
   1270 #define	CHECK_SP_REDZONE(t1, t2) \
   1271 	sethi	KERNBASE, t1;	\
   1272 	cmp	%sp, t1;	\
   1273 	blu,pt	%xcc, 7f;	\
   1274 	 sethi	%hi(_C_LABEL(redzone)), t1; \
   1275 	ldx	[t1 + %lo(_C_LABEL(redzone))], t2; \
   1276 	cmp	%sp, t2;	/* if sp >= t2, not in red zone */ \
   1277 	blu	panic_red; nop;	/* and can continue normally */ \
   1278 7:
   1279 
   1280 panic_red:
   1281 	/* move to panic stack */
   1282 	stx	%g0, [t1 + %lo(_C_LABEL(redzone))];
   1283 	set	eredstack - BIAS, %sp;
   1284 	/* prevent panic() from lowering ipl */
   1285 	sethi	%hi(_C_LABEL(panicstr)), t2;
   1286 	set	Lpanic_red, t2;
   1287 	st	t2, [t1 + %lo(_C_LABEL(panicstr))];
   1288 	wrpr	g0, 15, %pil		/* t1 = splhigh() */
   1289 	save	%sp, -CCF64SZ, %sp;	/* preserve current window */
   1290 	sethi	%hi(Lpanic_red), %o0;
   1291 	call	_C_LABEL(panic);
   1292 	 or %o0, %lo(Lpanic_red), %o0;
   1293 
   1294 
   1295 #else
   1296 
   1297 #define	SET_SP_REDZONE(base, tmp)
   1298 #define	SET_SP_REDZONE_CONST(const, t1, t2)
   1299 #define	CHECK_SP_REDZONE(t1, t2)
   1300 #endif
   1301 
   1302 #define TRACESIZ	0x01000
   1303 	.globl	_C_LABEL(trap_trace)
   1304 	.globl	_C_LABEL(trap_trace_ptr)
   1305 	.globl	_C_LABEL(trap_trace_end)
   1306 	.globl	_C_LABEL(trap_trace_dis)
   1307 	.data
   1308 _C_LABEL(trap_trace_dis):
   1309 	.word	1, 1		! Starts disabled.  DDB turns it on.
   1310 _C_LABEL(trap_trace_ptr):
   1311 	.word	0, 0, 0, 0
   1312 _C_LABEL(trap_trace):
   1313 	.space	TRACESIZ
   1314 _C_LABEL(trap_trace_end):
   1315 	.space	0x20		! safety margin
   1316 
   1317 
   1318 /*
   1319  * v9 machines do not have a trap window.
   1320  *
   1321  * When we take a trap the trap state is pushed on to the stack of trap
   1322  * registers, interrupts are disabled, then we switch to an alternate set
   1323  * of global registers.
   1324  *
   1325  * The trap handling code needs to allocate a trap frame on the kernel, or
   1326  * for interrupts, the interrupt stack, save the out registers to the trap
   1327  * frame, then switch to the normal globals and save them to the trap frame
   1328  * too.
   1329  *
   1330  * XXX it would be good to save the interrupt stack frame to the kernel
   1331  * stack so we wouldn't have to copy it later if we needed to handle a AST.
   1332  *
   1333  * Since kernel stacks are all on one page and the interrupt stack is entirely
   1334  * within the locked TLB, we can use physical addressing to save out our
   1335  * trap frame so we don't trap during the TRAP_SETUP() operation.  There
   1336  * is unfortunately no supportable method for issuing a non-trapping save.
   1337  *
   1338  * However, if we use physical addresses to save our trapframe, we will need
   1339  * to clear out the data cache before continuing much further.
   1340  *
   1341  * In short, what we need to do is:
   1342  *
   1343  *	all preliminary processing is done using the alternate globals
   1344  *
   1345  *	When we allocate our trap windows we must give up our globals because
   1346  *	their state may have changed during the save operation
   1347  *
   1348  *	we need to save our normal globals as soon as we have a stack
   1349  *
   1350  * Finally, we may now call C code.
   1351  *
   1352  * This macro will destroy %g5-%g7.  %g0-%g4 remain unchanged.
   1353  *
   1354  * In order to properly handle nested traps without lossage, alternate
   1355  * global %g6 is used as a kernel stack pointer.  It is set to the last
   1356  * allocated stack pointer (trapframe) and the old value is stored in
   1357  * tf_kstack.  It is restored when returning from a trap.  It is cleared
   1358  * on entering user mode.
   1359  */
   1360 
   1361  /*
   1362   * Other misc. design criteria:
   1363   *
   1364   * When taking an address fault, fault info is in the sfsr, sfar,
   1365   * TLB_TAG_ACCESS registers.  If we take another address fault
   1366   * while trying to handle the first fault then that information,
   1367   * the only information that tells us what address we trapped on,
   1368   * can potentially be lost.  This trap can be caused when allocating
   1369   * a register window with which to handle the trap because the save
   1370   * may try to store or restore a register window that corresponds
   1371   * to part of the stack that is not mapped.  Preventing this trap,
   1372   * while possible, is much too complicated to do in a trap handler,
   1373   * and then we will need to do just as much work to restore the processor
   1374   * window state.
   1375   *
   1376   * Possible solutions to the problem:
   1377   *
   1378   * Since we have separate AG, MG, and IG, we could have all traps
   1379   * above level-1 preserve AG and use other registers.  This causes
   1380   * a problem for the return from trap code which is coded to use
   1381   * alternate globals only.
   1382   *
   1383   * We could store the trapframe and trap address info to the stack
   1384   * using physical addresses.  Then we need to read it back using
   1385   * physical addressing, or flush the D$.
   1386   *
   1387   * We could identify certain registers to hold address fault info.
   1388   * this means that these registers need to be preserved across all
   1389   * fault handling.  But since we only have 7 useable globals, that
   1390   * really puts a cramp in our style.
   1391   *
   1392   * Finally, there is the issue of returning from kernel mode to user
   1393   * mode.  If we need to issue a restore of a user window in kernel
   1394   * mode, we need the window control registers in a user mode setup.
   1395   * If the trap handlers notice the register windows are in user mode,
   1396   * they will allocate a trapframe at the bottom of the kernel stack,
   1397   * overwriting the frame we were trying to return to.  This means that
   1398   * we must complete the restoration of all registers *before* switching
   1399   * to a user-mode window configuration.
   1400   *
   1401   * Essentially we need to be able to write re-entrant code w/no stack.
   1402   */
   1403 	.data
   1404 trap_setup_msg:
   1405 	.asciz	"TRAP_SETUP: tt=%x osp=%x nsp=%x tl=%x tpc=%x\n"
   1406 	_ALIGN
   1407 intr_setup_msg:
   1408 	.asciz	"INTR_SETUP: tt=%x osp=%x nsp=%x tl=%x tpc=%x\n"
   1409 	_ALIGN
   1410 	.text
   1411 
   1412 #ifdef DEBUG
   1413 	/* Only save a snapshot of locals and ins in DEBUG kernels */
   1414 #define	SAVE_LOCALS_INS	\
   1415 	/* Save local registers to trap frame */ \
   1416 	stx	%l0, [%g6 + CC64FSZ + STKB + TF_L + (0*8)]; \
   1417 	stx	%l1, [%g6 + CC64FSZ + STKB + TF_L + (1*8)]; \
   1418 	stx	%l2, [%g6 + CC64FSZ + STKB + TF_L + (2*8)]; \
   1419 	stx	%l3, [%g6 + CC64FSZ + STKB + TF_L + (3*8)]; \
   1420 	stx	%l4, [%g6 + CC64FSZ + STKB + TF_L + (4*8)]; \
   1421 	stx	%l5, [%g6 + CC64FSZ + STKB + TF_L + (5*8)]; \
   1422 	stx	%l6, [%g6 + CC64FSZ + STKB + TF_L + (6*8)]; \
   1423 	stx	%l7, [%g6 + CC64FSZ + STKB + TF_L + (7*8)]; \
   1424 \
   1425 	/* Save in registers to trap frame */ \
   1426 	stx	%i0, [%g6 + CC64FSZ + STKB + TF_I + (0*8)]; \
   1427 	stx	%i1, [%g6 + CC64FSZ + STKB + TF_I + (1*8)]; \
   1428 	stx	%i2, [%g6 + CC64FSZ + STKB + TF_I + (2*8)]; \
   1429 	stx	%i3, [%g6 + CC64FSZ + STKB + TF_I + (3*8)]; \
   1430 	stx	%i4, [%g6 + CC64FSZ + STKB + TF_I + (4*8)]; \
   1431 	stx	%i5, [%g6 + CC64FSZ + STKB + TF_I + (5*8)]; \
   1432 	stx	%i6, [%g6 + CC64FSZ + STKB + TF_I + (6*8)]; \
   1433 	stx	%i7, [%g6 + CC64FSZ + STKB + TF_I + (7*8)]; \
   1434 \
   1435 	stx	%g1, [%g6 + CC64FSZ + STKB + TF_FAULT];
   1436 #else
   1437 #define	SAVE_LOCALS_INS
   1438 #endif
   1439 
   1440 #ifdef _LP64
   1441 #define	FIXUP_TRAP_STACK \
   1442 	btst	1, %g6;						/* Fixup 64-bit stack if necessary */ \
   1443 	bnz,pt	%icc, 1f; \
   1444 	 add	%g6, %g5, %g6;					/* Allocate a stack frame */ \
   1445 	inc	-BIAS, %g6; \
   1446 1:
   1447 #else
   1448 #define	FIXUP_TRAP_STACK \
   1449 	srl	%g6, 0, %g6;					/* truncate at 32-bits */ \
   1450 	btst	1, %g6;						/* Fixup 64-bit stack if necessary */ \
   1451 	add	%g6, %g5, %g6;					/* Allocate a stack frame */ \
   1452 	add	%g6, BIAS, %g5; \
   1453 	movne	%icc, %g5, %g6;
   1454 #endif
   1455 
   1456 #ifdef _LP64
   1457 #define	TRAP_SETUP(stackspace) \
   1458 	sethi	%hi(CPCB), %g6; \
   1459 	sethi	%hi((stackspace)), %g5; \
   1460 	LDPTR	[%g6 + %lo(CPCB)], %g6; \
   1461 	sethi	%hi(USPACE), %g7;				/* Always multiple of page size */ \
   1462 	or	%g5, %lo((stackspace)), %g5; \
   1463 	add	%g6, %g7, %g6; \
   1464 	rdpr	%wstate, %g7;					/* Find if we're from user mode */ \
   1465 	sra	%g5, 0, %g5;					/* Sign extend the damn thing */ \
   1466 	\
   1467 	sub	%g7, WSTATE_KERN, %g7;				/* Compare & leave in register */ \
   1468 	movrz	%g7, %sp, %g6;					/* Select old (kernel) stack or base of kernel stack */ \
   1469 	FIXUP_TRAP_STACK \
   1470 	SAVE_LOCALS_INS	\
   1471 	save	%g6, 0, %sp;					/* If we fault we should come right back here */ \
   1472 	stx	%i0, [%sp + CC64FSZ + BIAS + TF_O + (0*8)];		/* Save out registers to trap frame */ \
   1473 	stx	%i1, [%sp + CC64FSZ + BIAS + TF_O + (1*8)]; \
   1474 	stx	%i2, [%sp + CC64FSZ + BIAS + TF_O + (2*8)]; \
   1475 	stx	%i3, [%sp + CC64FSZ + BIAS + TF_O + (3*8)]; \
   1476 	stx	%i4, [%sp + CC64FSZ + BIAS + TF_O + (4*8)]; \
   1477 	stx	%i5, [%sp + CC64FSZ + BIAS + TF_O + (5*8)]; \
   1478 \
   1479 	stx	%i6, [%sp + CC64FSZ + BIAS + TF_O + (6*8)]; \
   1480 	brz,pt	%g7, 1f;					/* If we were in kernel mode start saving globals */ \
   1481 	 stx	%i7, [%sp + CC64FSZ + BIAS + TF_O + (7*8)]; \
   1482 	mov	CTX_PRIMARY, %g7; \
   1483 	/* came from user mode -- switch to kernel mode stack */ \
   1484 	rdpr	%canrestore, %g5;				/* Fixup register window state registers */ \
   1485 	wrpr	%g0, 0, %canrestore; \
   1486 	wrpr	%g0, %g5, %otherwin; \
   1487 	wrpr	%g0, WSTATE_KERN, %wstate;			/* Enable kernel mode window traps -- now we can trap again */ \
   1488 \
   1489 	SET_MMU_CONTEXTID %g0, %g7,%g5; 			/* Switch MMU to kernel primary context */ \
   1490 	sethi	%hi(KERNBASE), %g5; \
   1491 	flush	%g5;						/* Some convenient address that won't trap */ \
   1492 1:
   1493 
   1494 /*
   1495  * Interrupt setup is almost exactly like trap setup, but we need to
   1496  * go to the interrupt stack if (a) we came from user mode or (b) we
   1497  * came from kernel mode on the kernel stack.
   1498  *
   1499  * We don't guarantee any registers are preserved during this operation.
   1500  * So we can be more efficient.
   1501  */
   1502 #define	INTR_SETUP(stackspace) \
   1503 	rdpr	%wstate, %g7;					/* Find if we're from user mode */ \
   1504 	\
   1505 	sethi	%hi(EINTSTACK-BIAS), %g6; \
   1506 	sethi	%hi(EINTSTACK-INTSTACK), %g4; \
   1507 	\
   1508 	or	%g6, %lo(EINTSTACK-BIAS), %g6;			/* Base of interrupt stack */ \
   1509 	dec	%g4;						/* Make it into a mask */ \
   1510 	\
   1511 	sub	%g6, %sp, %g1;					/* Offset from interrupt stack */ \
   1512 	sethi	%hi((stackspace)), %g5; \
   1513 	\
   1514 	or	%g5, %lo((stackspace)), %g5; \
   1515 \
   1516 	andn	%g1, %g4, %g4;					/* Are we out of the interrupt stack range? */ \
   1517 	xor	%g7, WSTATE_KERN, %g3;				/* Are we on the user stack ? */ \
   1518 	\
   1519 	sra	%g5, 0, %g5;					/* Sign extend the damn thing */ \
   1520 	orcc	%g3, %g4, %g0;					/* Definitely not off the interrupt stack */ \
   1521 	\
   1522 	sethi	%hi(CPUINFO_VA + CI_EINTSTACK), %g4; \
   1523 	bz,a,pt	%xcc, 1f; \
   1524 	 mov	%sp, %g6; \
   1525 	\
   1526 	ldx	[%g4 + %lo(CPUINFO_VA + CI_EINTSTACK)], %g4; \
   1527 	movrnz	%g4, %g4, %g6;					/* Use saved intr stack if exists */ \
   1528 	\
   1529 1:	add	%g6, %g5, %g5;					/* Allocate a stack frame */ \
   1530 	btst	1, %g6; \
   1531 	bnz,pt	%icc, 1f; \
   1532 \
   1533 	 mov	%g5, %g6; \
   1534 	\
   1535 	add	%g5, -BIAS, %g6; \
   1536 	\
   1537 1:	SAVE_LOCALS_INS	\
   1538 	save	%g6, 0, %sp;					/* If we fault we should come right back here */ \
   1539 	stx	%i0, [%sp + CC64FSZ + BIAS + TF_O + (0*8)];		/* Save out registers to trap frame */ \
   1540 	stx	%i1, [%sp + CC64FSZ + BIAS + TF_O + (1*8)]; \
   1541 	stx	%i2, [%sp + CC64FSZ + BIAS + TF_O + (2*8)]; \
   1542 	stx	%i3, [%sp + CC64FSZ + BIAS + TF_O + (3*8)]; \
   1543 	stx	%i4, [%sp + CC64FSZ + BIAS + TF_O + (4*8)]; \
   1544 \
   1545 	stx	%i5, [%sp + CC64FSZ + BIAS + TF_O + (5*8)]; \
   1546 	stx	%i6, [%sp + CC64FSZ + BIAS + TF_O + (6*8)]; \
   1547 	stx	%i6, [%sp + CC64FSZ + BIAS + TF_G + (0*8)];		/* Save fp in clockframe->cf_fp */ \
   1548 	brz,pt	%g3, 1f;					/* If we were in kernel mode start saving globals */ \
   1549 	 stx	%i7, [%sp + CC64FSZ + BIAS + TF_O + (7*8)]; \
   1550 	/* came from user mode -- switch to kernel mode stack */ \
   1551 	 rdpr	%otherwin, %g5;					/* Has this already been done? */ \
   1552 	\
   1553 	brnz,pn	%g5, 1f;					/* Don't set this twice */ \
   1554 	\
   1555 	 rdpr	%canrestore, %g5;				/* Fixup register window state registers */ \
   1556 \
   1557 	wrpr	%g0, 0, %canrestore; \
   1558 	\
   1559 	wrpr	%g0, %g5, %otherwin; \
   1560 	\
   1561 	mov	CTX_PRIMARY, %g7; \
   1562 	\
   1563 	wrpr	%g0, WSTATE_KERN, %wstate;			/* Enable kernel mode window traps -- now we can trap again */ \
   1564 	\
   1565 	SET_MMU_CONTEXTID %g0, %g7, %g5;			/* Switch MMU to kernel primary context */ \
   1566 	\
   1567 	sethi	%hi(KERNBASE), %g5; \
   1568 	flush	%g5;						/* Some convenient address that won't trap */ \
   1569 1:
   1570 
   1571 #else /* _LP64 */
   1572 
   1573 #define	TRAP_SETUP(stackspace) \
   1574 	sethi	%hi(CPCB), %g6; \
   1575 	sethi	%hi((stackspace)), %g5; \
   1576 	LDPTR	[%g6 + %lo(CPCB)], %g6; \
   1577 	sethi	%hi(USPACE), %g7; \
   1578 	or	%g5, %lo((stackspace)), %g5; \
   1579 	add	%g6, %g7, %g6; \
   1580 	rdpr	%wstate, %g7;					/* Find if we're from user mode */ \
   1581 	\
   1582 	sra	%g5, 0, %g5;					/* Sign extend the damn thing */ \
   1583 	subcc	%g7, WSTATE_KERN, %g7;				/* Compare & leave in register */ \
   1584 	movz	%icc, %sp, %g6;					/* Select old (kernel) stack or base of kernel stack */ \
   1585 	FIXUP_TRAP_STACK \
   1586 	SAVE_LOCALS_INS \
   1587 	save	%g6, 0, %sp;					/* If we fault we should come right back here */ \
   1588 	stx	%i0, [%sp + CC64FSZ + STKB + TF_O + (0*8)];		/* Save out registers to trap frame */ \
   1589 	stx	%i1, [%sp + CC64FSZ + STKB + TF_O + (1*8)]; \
   1590 	stx	%i2, [%sp + CC64FSZ + STKB + TF_O + (2*8)]; \
   1591 	stx	%i3, [%sp + CC64FSZ + STKB + TF_O + (3*8)]; \
   1592 	stx	%i4, [%sp + CC64FSZ + STKB + TF_O + (4*8)]; \
   1593 	stx	%i5, [%sp + CC64FSZ + STKB + TF_O + (5*8)]; \
   1594 	\
   1595 	stx	%i6, [%sp + CC64FSZ + STKB + TF_O + (6*8)]; \
   1596 	brz,pn	%g7, 1f;					/* If we were in kernel mode start saving globals */ \
   1597 	 stx	%i7, [%sp + CC64FSZ + STKB + TF_O + (7*8)]; \
   1598 	mov	CTX_PRIMARY, %g7; \
   1599 	/* came from user mode -- switch to kernel mode stack */ \
   1600 	rdpr	%canrestore, %g5;				/* Fixup register window state registers */ \
   1601 	wrpr	%g0, 0, %canrestore; \
   1602 	wrpr	%g0, %g5, %otherwin; \
   1603 	wrpr	%g0, WSTATE_KERN, %wstate;			/* Enable kernel mode window traps -- now we can trap again */ \
   1604 	\
   1605 	SET_MMU_CONTEXTID %g0, %g7, %g5;			/* Switch MMU to kernel primary context */ \
   1606 	sethi	%hi(KERNBASE), %g5; \
   1607 	flush	%g5;						/* Some convenient address that won't trap */ \
   1608 1:
   1609 
   1610 /*
   1611  * Interrupt setup is almost exactly like trap setup, but we need to
   1612  * go to the interrupt stack if (a) we came from user mode or (b) we
   1613  * came from kernel mode on the kernel stack.
   1614  *
   1615  * We don't guarantee any registers are preserved during this operation.
   1616  */
   1617 #define	INTR_SETUP(stackspace) \
   1618 	sethi	%hi(EINTSTACK), %g1; \
   1619 	sethi	%hi((stackspace)), %g5; \
   1620 	btst	1, %sp; \
   1621 	add	%sp, BIAS, %g6; \
   1622 	movz	%icc, %sp, %g6; \
   1623 	or	%g1, %lo(EINTSTACK), %g1; \
   1624 	srl	%g6, 0, %g6;					/* truncate at 32-bits */ \
   1625 	set	(EINTSTACK-INTSTACK), %g7; \
   1626 	or	%g5, %lo((stackspace)), %g5; \
   1627 	sub	%g1, %g6, %g2;					/* Determine if we need to switch to intr stack or not */ \
   1628 	dec	%g7;						/* Make it into a mask */ \
   1629 	sethi	%hi(CPUINFO_VA + CI_EINTSTACK), %g3; \
   1630 	andncc	%g2, %g7, %g0;					/* XXXXXXXXXX This assumes kernel addresses are unique from user addresses */ \
   1631 	LDPTR	[%g3 + %lo(CPUINFO_VA + CI_EINTSTACK)], %g3; \
   1632 	rdpr	%wstate, %g7;					/* Find if we're from user mode */ \
   1633 	movrnz	%g3, %g3, %g1;					/* Use saved intr stack if exists */ \
   1634 	sra	%g5, 0, %g5;					/* Sign extend the damn thing */ \
   1635 	movnz	%xcc, %g1, %g6;					/* Stay on interrupt stack? */ \
   1636 	cmp	%g7, WSTATE_KERN;				/* User or kernel sp? */ \
   1637 	movnz	%icc, %g1, %g6;					/* Stay on interrupt stack? */ \
   1638 	add	%g6, %g5, %g6;					/* Allocate a stack frame */ \
   1639 	\
   1640 	SAVE_LOCALS_INS \
   1641 	save	%g6, 0, %sp;					/* If we fault we should come right back here */ \
   1642 	stx	%i0, [%sp + CC64FSZ + STKB + TF_O + (0*8)];		/* Save out registers to trap frame */ \
   1643 	stx	%i1, [%sp + CC64FSZ + STKB + TF_O + (1*8)]; \
   1644 	stx	%i2, [%sp + CC64FSZ + STKB + TF_O + (2*8)]; \
   1645 	stx	%i3, [%sp + CC64FSZ + STKB + TF_O + (3*8)]; \
   1646 	stx	%i4, [%sp + CC64FSZ + STKB + TF_O + (4*8)]; \
   1647 	stx	%i5, [%sp + CC64FSZ + STKB + TF_O + (5*8)]; \
   1648 	stx	%i6, [%sp + CC64FSZ + STKB + TF_O + (6*8)]; \
   1649 	stx	%i6, [%sp + CC64FSZ + STKB + TF_G + (0*8)];		/* Save fp in clockframe->cf_fp */ \
   1650 	rdpr	%wstate, %g7;					/* Find if we're from user mode */ \
   1651 	stx	%i7, [%sp + CC64FSZ + STKB + TF_O + (7*8)]; \
   1652 	cmp	%g7, WSTATE_KERN;				/* Compare & leave in register */ \
   1653 	be,pn	%icc, 1f;					/* If we were in kernel mode start saving globals */ \
   1654 	/* came from user mode -- switch to kernel mode stack */ \
   1655 	 rdpr	%otherwin, %g5;					/* Has this already been done? */ \
   1656 	tst	%g5; tnz %xcc, 1; nop; /* DEBUG -- this should _NEVER_ happen */ \
   1657 	brnz,pn	%g5, 1f;					/* Don't set this twice */ \
   1658 	 rdpr	%canrestore, %g5;				/* Fixup register window state registers */ \
   1659 	wrpr	%g0, 0, %canrestore; \
   1660 	mov	CTX_PRIMARY, %g7; \
   1661 	wrpr	%g0, %g5, %otherwin; \
   1662 	wrpr	%g0, WSTATE_KERN, %wstate;			/* Enable kernel mode window traps -- now we can trap again */ \
   1663 	SET_MMU_CONTEXTID %g0, %g7, %g5;			/* Switch MMU to kernel primary context */ \
   1664 	sethi	%hi(KERNBASE), %g5; \
   1665 	flush	%g5;						/* Some convenient address that won't trap */ \
   1666 1:
   1667 #endif /* _LP64 */
   1668 
   1669 #ifdef DEBUG
   1670 
   1671 	/* Look up kpte to test algorithm */
   1672 	.globl	asmptechk
   1673 asmptechk:
   1674 	mov	%o0, %g4	! pmap->pm_segs
   1675 	mov	%o1, %g3	! Addr to lookup -- mind the context
   1676 
   1677 	srax	%g3, HOLESHIFT, %g5			! Check for valid address
   1678 	brz,pt	%g5, 0f					! Should be zero or -1
   1679 	 inc	%g5					! Make -1 -> 0
   1680 	brnz,pn	%g5, 1f					! Error!
   1681 0:
   1682 	 srlx	%g3, STSHIFT, %g5
   1683 	and	%g5, STMASK, %g5
   1684 	sll	%g5, 3, %g5
   1685 	add	%g4, %g5, %g4
   1686 	DLFLUSH(%g4,%g5)
   1687 	ldxa	[%g4] ASI_PHYS_CACHED, %g4		! Remember -- UNSIGNED
   1688 	DLFLUSH2(%g5)
   1689 	brz,pn	%g4, 1f					! NULL entry? check somewhere else
   1690 
   1691 	 srlx	%g3, PDSHIFT, %g5
   1692 	and	%g5, PDMASK, %g5
   1693 	sll	%g5, 3, %g5
   1694 	add	%g4, %g5, %g4
   1695 	DLFLUSH(%g4,%g5)
   1696 	ldxa	[%g4] ASI_PHYS_CACHED, %g4		! Remember -- UNSIGNED
   1697 	DLFLUSH2(%g5)
   1698 	brz,pn	%g4, 1f					! NULL entry? check somewhere else
   1699 
   1700 	 srlx	%g3, PTSHIFT, %g5			! Convert to ptab offset
   1701 	and	%g5, PTMASK, %g5
   1702 	sll	%g5, 3, %g5
   1703 	add	%g4, %g5, %g4
   1704 	DLFLUSH(%g4,%g5)
   1705 	ldxa	[%g4] ASI_PHYS_CACHED, %g6
   1706 	DLFLUSH2(%g5)
   1707 	brgez,pn %g6, 1f				! Entry invalid?  Punt
   1708 	 srlx	%g6, 32, %o0
   1709 	retl
   1710 	 srl	%g6, 0, %o1
   1711 1:
   1712 	mov	%g0, %o1
   1713 	retl
   1714 	 mov	%g0, %o0
   1715 
   1716 	.data
   1717 2:
   1718 	.asciz	"asmptechk: %x %x %x %x:%x\n"
   1719 	_ALIGN
   1720 	.text
   1721 #endif
   1722 
   1723 /*
   1724  * This is the MMU protection handler.  It's too big to fit
   1725  * in the trap table so I moved it here.  It's relatively simple.
   1726  * It looks up the page mapping in the page table associated with
   1727  * the trapping context.  It checks to see if the S/W writable bit
   1728  * is set.  If so, it sets the H/W write bit, marks the tte modified,
   1729  * and enters the mapping into the MMU.  Otherwise it does a regular
   1730  * data fault.
   1731  */
   1732 	ICACHE_ALIGN
   1733 dmmu_write_fault:
   1734 	mov	TLB_TAG_ACCESS, %g3
   1735 	sethi	%hi(0x1fff), %g6			! 8K context mask
   1736 	ldxa	[%g3] ASI_DMMU, %g3			! Get fault addr from Tag Target
   1737 	sethi	%hi(CPUINFO_VA+CI_CTXBUSY), %g4
   1738 	or	%g6, %lo(0x1fff), %g6
   1739 	LDPTR	[%g4 + %lo(CPUINFO_VA+CI_CTXBUSY)], %g4
   1740 	srax	%g3, HOLESHIFT, %g5			! Check for valid address
   1741 	and	%g3, %g6, %g6				! Isolate context
   1742 
   1743 	inc	%g5					! (0 or -1) -> (1 or 0)
   1744 	sllx	%g6, 3, %g6				! Make it into an offset into ctxbusy
   1745 	ldx	[%g4+%g6], %g4				! Load up our page table.
   1746 	srlx	%g3, STSHIFT, %g6
   1747 	cmp	%g5, 1
   1748 	bgu,pn %xcc, winfix				! Error!
   1749 	 srlx	%g3, PDSHIFT, %g5
   1750 	and	%g6, STMASK, %g6
   1751 	sll	%g6, 3, %g6
   1752 
   1753 	and	%g5, PDMASK, %g5
   1754 	sll	%g5, 3, %g5
   1755 	add	%g6, %g4, %g4
   1756 	DLFLUSH(%g4,%g6)
   1757 	ldxa	[%g4] ASI_PHYS_CACHED, %g4
   1758 	DLFLUSH2(%g6)
   1759 	srlx	%g3, PTSHIFT, %g6			! Convert to ptab offset
   1760 	and	%g6, PTMASK, %g6
   1761 	add	%g5, %g4, %g5
   1762 	brz,pn	%g4, winfix				! NULL entry? check somewhere else
   1763 	 nop
   1764 
   1765 	ldxa	[%g5] ASI_PHYS_CACHED, %g4
   1766 	sll	%g6, 3, %g6
   1767 	brz,pn	%g4, winfix				! NULL entry? check somewhere else
   1768 	 add	%g6, %g4, %g6
   1769 1:
   1770 	ldxa	[%g6] ASI_PHYS_CACHED, %g4
   1771 	brgez,pn %g4, winfix				! Entry invalid?  Punt
   1772 	 or	%g4, SUN4U_TTE_MODIFY|SUN4U_TTE_ACCESS|SUN4U_TTE_W, %g7	! Update the modified bit
   1773 
   1774 	btst	SUN4U_TTE_REAL_W|SUN4U_TTE_W, %g4			! Is it a ref fault?
   1775 	bz,pn	%xcc, winfix				! No -- really fault
   1776 #ifdef DEBUG
   1777 	/* Make sure we don't try to replace a kernel translation */
   1778 	/* This should not be necessary */
   1779 	sllx	%g3, 64-13, %g2				! Isolate context bits
   1780 	sethi	%hi(KERNBASE), %g5			! Don't need %lo
   1781 	brnz,pt	%g2, 0f					! Ignore context != 0
   1782 	 set	0x0800000, %g2				! 8MB
   1783 	sub	%g3, %g5, %g5
   1784 	cmp	%g5, %g2
   1785 	tlu	%xcc, 1; nop
   1786 	blu,pn	%xcc, winfix				! Next insn in delay slot is unimportant
   1787 0:
   1788 #endif
   1789 	/* Need to check for and handle large pages. */
   1790 	 srlx	%g4, 61, %g5				! Isolate the size bits
   1791 	ldxa	[%g0] ASI_DMMU_8KPTR, %g2		! Load DMMU 8K TSB pointer
   1792 	andcc	%g5, 0x3, %g5				! 8K?
   1793 	bnz,pn	%icc, winfix				! We punt to the pmap code since we can't handle policy
   1794 	 ldxa	[%g0] ASI_DMMU, %g1			! Load DMMU tag target register
   1795 	casxa	[%g6] ASI_PHYS_CACHED, %g4, %g7		!  and write it out
   1796 	membar	#StoreLoad
   1797 	cmp	%g4, %g7
   1798 	bne,pn	%xcc, 1b
   1799 	 or	%g4, SUN4U_TTE_MODIFY|SUN4U_TTE_ACCESS|SUN4U_TTE_W, %g4	! Update the modified bit
   1800 	stx	%g1, [%g2]				! Update TSB entry tag
   1801 	mov	SFSR, %g7
   1802 	stx	%g4, [%g2+8]				! Update TSB entry data
   1803 	nop
   1804 
   1805 #ifdef TRAPSTATS
   1806 	sethi	%hi(_C_LABEL(protfix)), %g1
   1807 	lduw	[%g1+%lo(_C_LABEL(protfix))], %g2
   1808 	inc	%g2
   1809 	stw	%g2, [%g1+%lo(_C_LABEL(protfix))]
   1810 #endif
   1811 	mov	DEMAP_PAGE_SECONDARY, %g1		! Secondary flush
   1812 	mov	DEMAP_PAGE_NUCLEUS, %g5			! Nucleus flush
   1813 	stxa	%g0, [%g7] ASI_DMMU			! clear out the fault
   1814 	sllx	%g3, (64-13), %g7			! Need to demap old entry first
   1815 	andn	%g3, 0xfff, %g6
   1816 	movrz	%g7, %g5, %g1				! Pick one
   1817 	or	%g6, %g1, %g6
   1818 	membar	#Sync
   1819 	stxa	%g6, [%g6] ASI_DMMU_DEMAP		! Do the demap
   1820 	membar	#Sync
   1821 
   1822 	stxa	%g4, [%g0] ASI_DMMU_DATA_IN		! Enter new mapping
   1823 	membar	#Sync
   1824 	retry
   1825 
   1826 /*
   1827  * Each memory data access fault from a fast access miss handler comes here.
   1828  * We will quickly check if this is an original prom mapping before going
   1829  * to the generic fault handler
   1830  *
   1831  * We will assume that %pil is not lost so we won't bother to save it
   1832  * unless we're in an interrupt handler.
   1833  *
   1834  * On entry:
   1835  *	We are on one of the alternate set of globals
   1836  *	%g1 = MMU tag target
   1837  *	%g2 = 8Kptr
   1838  *	%g3 = TLB TAG ACCESS
   1839  *
   1840  * On return:
   1841  *
   1842  */
   1843 	ICACHE_ALIGN
   1844 data_miss:
   1845 #ifdef TRAPSTATS
   1846 	set	_C_LABEL(kdmiss), %g3
   1847 	set	_C_LABEL(udmiss), %g4
   1848 	rdpr	%tl, %g6
   1849 	dec	%g6
   1850 	movrz	%g6, %g4, %g3
   1851 	lduw	[%g3], %g4
   1852 	inc	%g4
   1853 	stw	%g4, [%g3]
   1854 #endif
   1855 	mov	TLB_TAG_ACCESS, %g3			! Get real fault page
   1856 	sethi	%hi(0x1fff), %g6			! 8K context mask
   1857 	ldxa	[%g3] ASI_DMMU, %g3			! from tag access register
   1858 	sethi	%hi(CPUINFO_VA+CI_CTXBUSY), %g4
   1859 	or	%g6, %lo(0x1fff), %g6
   1860 	LDPTR	[%g4 + %lo(CPUINFO_VA+CI_CTXBUSY)], %g4
   1861 	srax	%g3, HOLESHIFT, %g5			! Check for valid address
   1862 	and	%g3, %g6, %g6				! Isolate context
   1863 
   1864 	inc	%g5					! (0 or -1) -> (1 or 0)
   1865 	sllx	%g6, 3, %g6				! Make it into an offset into ctxbusy
   1866 	ldx	[%g4+%g6], %g4				! Load up our page table.
   1867 #ifdef DEBUG
   1868 	/* Make sure we don't try to replace a kernel translation */
   1869 	/* This should not be necessary */
   1870 	brnz,pt	%g6, 1f			! If user context continue miss
   1871 	sethi	%hi(KERNBASE), %g7			! Don't need %lo
   1872 	set	0x0800000, %g6				! 8MB
   1873 	sub	%g3, %g7, %g7
   1874 	cmp	%g7, %g6
   1875 	tlu	%xcc, 1; nop
   1876 1:
   1877 #endif
   1878 	srlx	%g3, STSHIFT, %g6
   1879 	cmp	%g5, 1
   1880 	bgu,pn %xcc, winfix				! Error!
   1881 	 srlx	%g3, PDSHIFT, %g5
   1882 	and	%g6, STMASK, %g6
   1883 
   1884 	sll	%g6, 3, %g6
   1885 	and	%g5, PDMASK, %g5
   1886 	sll	%g5, 3, %g5
   1887 	add	%g6, %g4, %g4
   1888 	ldxa	[%g4] ASI_PHYS_CACHED, %g4
   1889 	srlx	%g3, PTSHIFT, %g6			! Convert to ptab offset
   1890 	and	%g6, PTMASK, %g6
   1891 	add	%g5, %g4, %g5
   1892 	brz,pn	%g4, data_nfo				! NULL entry? check somewhere else
   1893 
   1894 	 nop
   1895 	ldxa	[%g5] ASI_PHYS_CACHED, %g4
   1896 	sll	%g6, 3, %g6
   1897 	brz,pn	%g4, data_nfo				! NULL entry? check somewhere else
   1898 	 add	%g6, %g4, %g6
   1899 
   1900 1:
   1901 	ldxa	[%g6] ASI_PHYS_CACHED, %g4
   1902 	brgez,pn %g4, data_nfo				! Entry invalid?  Punt
   1903 	 or	%g4, SUN4U_TTE_ACCESS, %g7			! Update the access bit
   1904 
   1905 	btst	SUN4U_TTE_ACCESS, %g4				! Need to update access git?
   1906 	bne,pt	%xcc, 1f
   1907 	 nop
   1908 	casxa	[%g6] ASI_PHYS_CACHED, %g4, %g7		!  and write it out
   1909 	cmp	%g4, %g7
   1910 	bne,pn	%xcc, 1b
   1911 	 or	%g4, SUN4U_TTE_ACCESS, %g4			! Update the access bit
   1912 
   1913 1:
   1914 	stx	%g1, [%g2]				! Update TSB entry tag
   1915 	stx	%g4, [%g2+8]				! Update TSB entry data
   1916 	stxa	%g4, [%g0] ASI_DMMU_DATA_IN		! Enter new mapping
   1917 	membar	#Sync
   1918 	CLRTT
   1919 	retry
   1920 	NOTREACHED
   1921 /*
   1922  * We had a data miss but did not find a mapping.  Insert
   1923  * a NFO mapping to satisfy speculative loads and return.
   1924  * If this had been a real load, it will re-execute and
   1925  * result in a data fault or protection fault rather than
   1926  * a TLB miss.  We insert an 8K TTE with the valid and NFO
   1927  * bits set.  All others should zero.  The TTE looks like this:
   1928  *
   1929  *	0x9000000000000000
   1930  *
   1931  */
   1932 data_nfo:
   1933 	sethi	%hi(0x90000000), %g4			! V(0x8)|NFO(0x1)
   1934 	sllx	%g4, 32, %g4
   1935 	stxa	%g4, [%g0] ASI_DMMU_DATA_IN		! Enter new mapping
   1936 	membar	#Sync
   1937 	CLRTT
   1938 	retry
   1939 
   1940 /*
   1941  * Handler for making the trap window shiny clean.
   1942  *
   1943  * If the store that trapped was to a kernel address, panic.
   1944  *
   1945  * If the store that trapped was to a user address, stick it in the PCB.
   1946  * Since we don't want to force user code to use the standard register
   1947  * convention if we don't have to, we will not assume that %fp points to
   1948  * anything valid.
   1949  *
   1950  * On entry:
   1951  *	We are on one of the alternate set of globals
   1952  *	%g1 = %tl - 1, tstate[tl-1], scratch	- local
   1953  *	%g2 = %tl				- local
   1954  *	%g3 = MMU tag access			- in
   1955  *	%g4 = %cwp				- local
   1956  *	%g5 = scratch				- local
   1957  *	%g6 = cpcb				- local
   1958  *	%g7 = scratch				- local
   1959  *
   1960  * On return:
   1961  *
   1962  * NB:	 remove most of this from main codepath & cleanup I$
   1963  */
   1964 winfault:
   1965 	mov	TLB_TAG_ACCESS, %g3	! Get real fault page from tag access register
   1966 	ldxa	[%g3] ASI_DMMU, %g3	! And put it into the non-MMU alternate regs
   1967 winfix:
   1968 	rdpr	%tl, %g2
   1969 	subcc	%g2, 1, %g1
   1970 	ble,pt	%icc, datafault		! Don't go below trap level 1
   1971 	 sethi	%hi(CPCB), %g6		! get current pcb
   1972 
   1973 
   1974 	wrpr	%g1, 0, %tl		! Pop a trap level
   1975 	rdpr	%tt, %g7		! Read type of prev. trap
   1976 	rdpr	%tstate, %g4		! Try to restore prev %cwp if we were executing a restore
   1977 	andn	%g7, 0x3f, %g5		!   window fill traps are all 0b 0000 11xx xxxx
   1978 
   1979 #if 1
   1980 	cmp	%g7, 0x30		! If we took a datafault just before this trap
   1981 	bne,pt	%icc, winfixfill	! our stack's probably bad so we need to switch somewhere else
   1982 	 nop
   1983 
   1984 	!!
   1985 	!! Double data fault -- bad stack?
   1986 	!!
   1987 	wrpr	%g2, %tl		! Restore trap level.
   1988 	sir				! Just issue a reset and don't try to recover.
   1989 	mov	%fp, %l6		! Save the frame pointer
   1990 	set	EINTSTACK+USPACE+CC64FSZ-STKB, %fp ! Set the frame pointer to the middle of the idle stack
   1991 	add	%fp, -CC64FSZ, %sp	! Create a stackframe
   1992 	wrpr	%g0, 15, %pil		! Disable interrupts, too
   1993 	wrpr	%g0, %g0, %canrestore	! Our stack is hozed and our PCB
   1994 	wrpr	%g0, 7, %cansave	!  probably is too, so blow away
   1995 	ba	slowtrap		!  all our register windows.
   1996 	 wrpr	%g0, 0x101, %tt
   1997 #endif
   1998 
   1999 winfixfill:
   2000 	cmp	%g5, 0x0c0		!   so we mask lower bits & compare to 0b 0000 1100 0000
   2001 	bne,pt	%icc, winfixspill	! Dump our trap frame -- we will retry the fill when the page is loaded
   2002 	 cmp	%g5, 0x080		!   window spill traps are all 0b 0000 10xx xxxx
   2003 
   2004 	!!
   2005 	!! This was a fill
   2006 	!!
   2007 #ifdef TRAPSTATS
   2008 	set	_C_LABEL(wfill), %g1
   2009 	lduw	[%g1], %g5
   2010 	inc	%g5
   2011 	stw	%g5, [%g1]
   2012 #endif
   2013 	btst	TSTATE_PRIV, %g4	! User mode?
   2014 	and	%g4, CWP, %g5		! %g4 = %cwp of trap
   2015 	wrpr	%g7, 0, %tt
   2016 	bz,a,pt	%icc, datafault		! We were in user mode -- normal fault
   2017 	 wrpr	%g5, %cwp		! Restore cwp from before fill trap -- regs should now be consistent
   2018 
   2019 	/*
   2020 	 * We're in a pickle here.  We were trying to return to user mode
   2021 	 * and the restore of the user window failed, so now we have one valid
   2022 	 * kernel window and a user window state.  If we do a TRAP_SETUP() now,
   2023 	 * our kernel window will be considered a user window and cause a
   2024 	 * fault when we try to save it later due to an invalid user address.
   2025 	 * If we return to where we faulted, our window state will not be valid
   2026 	 * and we will fault trying to enter user with our primary context of zero.
   2027 	 *
   2028 	 * What we'll do is arrange to have us return to return_from_trap so we will
   2029 	 * start the whole business over again.  But first, switch to a kernel window
   2030 	 * setup.  Let's see, canrestore and otherwin are zero.  Set WSTATE_KERN and
   2031 	 * make sure we're in kernel context and we're done.
   2032 	 */
   2033 
   2034 #ifdef TRAPSTATS
   2035 	set	_C_LABEL(kwfill), %g4
   2036 	lduw	[%g4], %g7
   2037 	inc	%g7
   2038 	stw	%g7, [%g4]
   2039 #endif
   2040 #if 0 /* Need to switch over to new stuff to fix WDR bug */
   2041 	wrpr	%g5, %cwp				! Restore cwp from before fill trap -- regs should now be consistent
   2042 	wrpr	%g2, %g0, %tl				! Restore trap level -- we need to reuse it
   2043 	set	return_from_trap, %g4			! XXX - need to set %g1 to tstate
   2044 	set	CTX_PRIMARY, %g7
   2045 	wrpr	%g4, 0, %tpc
   2046 	stxa	%g0, [%g7] ASI_DMMU
   2047 	inc	4, %g4
   2048 	membar	#Sync
   2049 	flush	%g4					! Isn't this convenient?
   2050 	wrpr	%g0, WSTATE_KERN, %wstate
   2051 	wrpr	%g0, 0, %canrestore			! These should be zero but
   2052 	wrpr	%g0, 0, %otherwin			! clear them just in case
   2053 	rdpr	%ver, %g5
   2054 	and	%g5, CWP, %g5
   2055 	wrpr	%g0, 0, %cleanwin
   2056 	dec	1, %g5					! NWINDOWS-1-1
   2057 	wrpr	%g5, 0, %cansave			! Invalidate all windows
   2058 !	flushw						! DEBUG
   2059 	ba,pt	%icc, datafault
   2060 	 wrpr	%g4, 0, %tnpc
   2061 #else
   2062 	wrpr	%g2, %g0, %tl				! Restore trap level
   2063 	cmp	%g2, 3
   2064 	tne	%icc, 1
   2065 	rdpr	%tt, %g5
   2066 	wrpr	%g0, 1, %tl				! Revert to TL==1 XXX what if this wasn't in rft_user? Oh well.
   2067 	wrpr	%g5, %g0, %tt				! Set trap type correctly
   2068 /*
   2069  * Here we need to implement the beginning of datafault.
   2070  * TRAP_SETUP expects to come from either kernel mode or
   2071  * user mode with at least one valid register window.  It
   2072  * will allocate a trap frame, save the out registers, and
   2073  * fix the window registers to think we have one user
   2074  * register window.
   2075  *
   2076  * However, under these circumstances we don't have any
   2077  * valid register windows, so we need to clean up the window
   2078  * registers to prevent garbage from being saved to either
   2079  * the user stack or the PCB before calling the datafault
   2080  * handler.
   2081  *
   2082  * We could simply jump to datafault if we could somehow
   2083  * make the handler issue a `saved' instruction immediately
   2084  * after creating the trapframe.
   2085  *
   2086  * The following is duplicated from datafault:
   2087  */
   2088 #ifdef TRAPS_USE_IG
   2089 	wrpr	%g0, PSTATE_KERN|PSTATE_IG, %pstate	! We need to save volatile stuff to interrupt globals
   2090 #else
   2091 	wrpr	%g0, PSTATE_KERN|PSTATE_AG, %pstate	! We need to save volatile stuff to alternate globals
   2092 #endif
   2093 	wr	%g0, ASI_DMMU, %asi			! We need to re-load trap info
   2094 	ldxa	[%g0 + TLB_TAG_ACCESS] %asi, %g1	! Get fault address from tag access register
   2095 	ldxa	[SFAR] %asi, %g2			! sync virt addr; must be read first
   2096 	ldxa	[SFSR] %asi, %g3			! get sync fault status register
   2097 	stxa	%g0, [SFSR] %asi			! Clear out fault now
   2098 
   2099 	TRAP_SETUP(-CC64FSZ-TF_SIZE)
   2100 	saved						! Blow away that one register window we didn't ever use.
   2101 	ba,a,pt	%icc, Ldatafault_internal		! Now we should return directly to user mode
   2102 	 nop
   2103 #endif
   2104 winfixspill:
   2105 	bne,a,pt	%xcc, datafault			! Was not a spill -- handle it normally
   2106 	 wrpr	%g2, 0, %tl				! Restore trap level for now XXXX
   2107 
   2108 	!!
   2109 	!! This was a spill
   2110 	!!
   2111 #if 1
   2112 	btst	TSTATE_PRIV, %g4	! From user mode?
   2113 	wrpr	%g2, 0, %tl		! We need to load the fault type so we can
   2114 	rdpr	%tt, %g5		! overwrite the lower trap and get it to the fault handler
   2115 	wrpr	%g1, 0, %tl
   2116 	wrpr	%g5, 0, %tt		! Copy over trap type for the fault handler
   2117 	and	%g4, CWP, %g5		! find %cwp from trap
   2118 	be,a,pt	%xcc, datafault		! Let's do a regular datafault.  When we try a save in datafault we'll
   2119 	 wrpr	%g5, 0, %cwp		!  return here and write out all dirty windows.
   2120 #endif
   2121 	wrpr	%g2, 0, %tl				! Restore trap level for now XXXX
   2122 	LDPTR	[%g6 + %lo(CPCB)], %g6	! This is in the locked TLB and should not fault
   2123 #ifdef TRAPSTATS
   2124 	set	_C_LABEL(wspill), %g7
   2125 	lduw	[%g7], %g5
   2126 	inc	%g5
   2127 	stw	%g5, [%g7]
   2128 #endif
   2129 
   2130 	/*
   2131 	 * Traverse kernel map to find paddr of cpcb and only us ASI_PHYS_CACHED to
   2132 	 * prevent any faults while saving the windows.  BTW if it isn't mapped, we
   2133 	 * will trap and hopefully panic.
   2134 	 */
   2135 
   2136 !	ba	0f					! DEBUG -- don't use phys addresses
   2137 	 wr	%g0, ASI_NUCLEUS, %asi			! In case of problems finding PA
   2138 	sethi	%hi(CPUINFO_VA+CI_CTXBUSY), %g1
   2139 	LDPTR	[%g1 + %lo(CPUINFO_VA+CI_CTXBUSY)], %g1	! Load start of ctxbusy
   2140 #ifdef DEBUG
   2141 	srax	%g6, HOLESHIFT, %g7			! Check for valid address
   2142 	brz,pt	%g7, 1f					! Should be zero or -1
   2143 	 addcc	%g7, 1, %g7					! Make -1 -> 0
   2144 	tnz	%xcc, 1					! Invalid address??? How did this happen?
   2145 1:
   2146 #endif
   2147 	srlx	%g6, STSHIFT, %g7
   2148 	ldx	[%g1], %g1				! Load pointer to kernel_pmap
   2149 	and	%g7, STMASK, %g7
   2150 	sll	%g7, 3, %g7
   2151 	add	%g7, %g1, %g1
   2152 	DLFLUSH(%g1,%g7)
   2153 	ldxa	[%g1] ASI_PHYS_CACHED, %g1		! Load pointer to directory
   2154 	DLFLUSH2(%g7)
   2155 
   2156 	srlx	%g6, PDSHIFT, %g7			! Do page directory
   2157 	and	%g7, PDMASK, %g7
   2158 	sll	%g7, 3, %g7
   2159 	brz,pn	%g1, 0f
   2160 	 add	%g7, %g1, %g1
   2161 	DLFLUSH(%g1,%g7)
   2162 	ldxa	[%g1] ASI_PHYS_CACHED, %g1
   2163 	DLFLUSH2(%g7)
   2164 
   2165 	srlx	%g6, PTSHIFT, %g7			! Convert to ptab offset
   2166 	and	%g7, PTMASK, %g7
   2167 	brz	%g1, 0f
   2168 	 sll	%g7, 3, %g7
   2169 	add	%g1, %g7, %g7
   2170 	DLFLUSH(%g7,%g1)
   2171 	ldxa	[%g7] ASI_PHYS_CACHED, %g7		! This one is not
   2172 	DLFLUSH2(%g1)
   2173 	brgez	%g7, 0f
   2174 	 srlx	%g7, PGSHIFT, %g7			! Isolate PA part
   2175 	sll	%g6, 32-PGSHIFT, %g6			! And offset
   2176 	sllx	%g7, PGSHIFT+23, %g7			! There are 23 bits to the left of the PA in the TTE
   2177 	srl	%g6, 32-PGSHIFT, %g6
   2178 	srax	%g7, 23, %g7
   2179 	or	%g7, %g6, %g6				! Then combine them to form PA
   2180 
   2181 	wr	%g0, ASI_PHYS_CACHED, %asi		! Use ASI_PHYS_CACHED to prevent possible page faults
   2182 0:
   2183 	/*
   2184 	 * Now save all user windows to cpcb.
   2185 	 */
   2186 #ifdef NOTDEF_DEBUG
   2187 	add	%g6, PCB_NSAVED, %g7
   2188 	DLFLUSH(%g7,%g5)
   2189 	lduba	[%g6 + PCB_NSAVED] %asi, %g7		! make sure that pcb_nsaved
   2190 	DLFLUSH2(%g5)
   2191 	brz,pt	%g7, 1f					! is zero, else
   2192 	 nop
   2193 	wrpr	%g0, 4, %tl
   2194 	sir						! Force a watchdog
   2195 1:
   2196 #endif
   2197 	rdpr	%otherwin, %g7
   2198 	brnz,pt	%g7, 1f
   2199 	 rdpr	%canrestore, %g5
   2200 	rdpr	%cansave, %g1
   2201 	add	%g5, 1, %g7				! add the %cwp window to the list to save
   2202 !	movrnz	%g1, %g5, %g7				! If we're issuing a save
   2203 !	mov	%g5, %g7				! DEBUG
   2204 	wrpr	%g0, 0, %canrestore
   2205 	wrpr	%g7, 0, %otherwin			! Still in user mode -- need to switch to kernel mode
   2206 1:
   2207 	mov	%g7, %g1
   2208 	add	%g6, PCB_NSAVED, %g7
   2209 	DLFLUSH(%g7,%g5)
   2210 	lduba	[%g6 + PCB_NSAVED] %asi, %g7		! Start incrementing pcb_nsaved
   2211 	DLFLUSH2(%g5)
   2212 
   2213 #ifdef DEBUG
   2214 	wrpr	%g0, 5, %tl
   2215 #endif
   2216 	mov	%g6, %g5
   2217 	brz,pt	%g7, winfixsave				! If it's in use, panic
   2218 	 saved						! frob window registers
   2219 
   2220 	/* PANIC */
   2221 !	sir						! Force a watchdog
   2222 #ifdef DEBUG
   2223 	wrpr	%g2, 0, %tl
   2224 #endif
   2225 	mov	%g7, %o2
   2226 	rdpr	%ver, %o1
   2227 	sethi	%hi(2f), %o0
   2228 	and	%o1, CWP, %o1
   2229 	wrpr	%g0, %o1, %cleanwin
   2230 	dec	1, %o1
   2231 	wrpr	%g0, %o1, %cansave			! kludge away any more window problems
   2232 	wrpr	%g0, 0, %canrestore
   2233 	wrpr	%g0, 0, %otherwin
   2234 	or	%lo(2f), %o0, %o0
   2235 	wrpr	%g0, WSTATE_KERN, %wstate
   2236 	set	PANICSTACK-CC64FSZ-STKB, %sp
   2237 	ta	1; nop					! This helps out traptrace.
   2238 	call	_C_LABEL(panic)				! This needs to be fixed properly but we should panic here
   2239 	 mov	%g1, %o1
   2240 	NOTREACHED
   2241 	.data
   2242 2:
   2243 	.asciz	"winfault: double invalid window at %p, nsaved=%d"
   2244 	_ALIGN
   2245 	.text
   2246 3:
   2247 	saved
   2248 	save
   2249 winfixsave:
   2250 	stxa	%l0, [%g5 + PCB_RW + ( 0*8)] %asi	! Save the window in the pcb, we can schedule other stuff in here
   2251 	stxa	%l1, [%g5 + PCB_RW + ( 1*8)] %asi
   2252 	stxa	%l2, [%g5 + PCB_RW + ( 2*8)] %asi
   2253 	stxa	%l3, [%g5 + PCB_RW + ( 3*8)] %asi
   2254 	stxa	%l4, [%g5 + PCB_RW + ( 4*8)] %asi
   2255 	stxa	%l5, [%g5 + PCB_RW + ( 5*8)] %asi
   2256 	stxa	%l6, [%g5 + PCB_RW + ( 6*8)] %asi
   2257 	stxa	%l7, [%g5 + PCB_RW + ( 7*8)] %asi
   2258 
   2259 	stxa	%i0, [%g5 + PCB_RW + ( 8*8)] %asi
   2260 	stxa	%i1, [%g5 + PCB_RW + ( 9*8)] %asi
   2261 	stxa	%i2, [%g5 + PCB_RW + (10*8)] %asi
   2262 	stxa	%i3, [%g5 + PCB_RW + (11*8)] %asi
   2263 	stxa	%i4, [%g5 + PCB_RW + (12*8)] %asi
   2264 	stxa	%i5, [%g5 + PCB_RW + (13*8)] %asi
   2265 	stxa	%i6, [%g5 + PCB_RW + (14*8)] %asi
   2266 	stxa	%i7, [%g5 + PCB_RW + (15*8)] %asi
   2267 
   2268 !	rdpr	%otherwin, %g1	! Check to see if we's done
   2269 	dec	%g1
   2270 	wrpr	%g0, 7, %cleanwin			! BUGBUG -- we should not hardcode this, but I have no spare globals
   2271 	inc	16*8, %g5				! Move to next window
   2272 	inc	%g7					! inc pcb_nsaved
   2273 	brnz,pt	%g1, 3b
   2274 	 stxa	%o6, [%g5 + PCB_RW + (14*8)] %asi	! Save %sp so we can write these all out
   2275 
   2276 	/* fix up pcb fields */
   2277 	stba	%g7, [%g6 + PCB_NSAVED] %asi		! cpcb->pcb_nsaved = n
   2278 #if 0
   2279 	mov	%g7, %g5				! fixup window registers
   2280 5:
   2281 	dec	%g5
   2282 	brgz,a,pt	%g5, 5b
   2283 	 restore
   2284 #ifdef NOT_DEBUG
   2285 	rdpr	%wstate, %g5				! DEBUG
   2286 	wrpr	%g0, WSTATE_KERN, %wstate		! DEBUG
   2287 	wrpr	%g0, 4, %tl
   2288 	rdpr	%cansave, %g7
   2289 	rdpr	%canrestore, %g6
   2290 	flushw						! DEBUG
   2291 	wrpr	%g2, 0, %tl
   2292 	wrpr	%g5, 0, %wstate				! DEBUG
   2293 #endif
   2294 #else
   2295 	/*
   2296 	 * We just issued a bunch of saves, so %cansave is now 0,
   2297 	 * probably (if we were doing a flushw then we may have
   2298 	 * come in with only partially full register windows and
   2299 	 * it may not be 0).
   2300 	 *
   2301 	 * %g7 contains the count of the windows we just finished
   2302 	 * saving.
   2303 	 *
   2304 	 * What we need to do now is move some of the windows from
   2305 	 * %canrestore to %cansave.  What we should do is take
   2306 	 * min(%canrestore, %g7) and move that over to %cansave.
   2307 	 *
   2308 	 * %g7 is the number of windows we flushed, so we should
   2309 	 * use that as a base.  Clear out %otherwin, set %cansave
   2310 	 * to min(%g7, NWINDOWS - 2), set %cleanwin to %canrestore
   2311 	 * + %cansave and the rest follows:
   2312 	 *
   2313 	 * %otherwin = 0
   2314 	 * %cansave = NWINDOWS - 2 - %canrestore
   2315 	 */
   2316 	wrpr	%g0, 0, %otherwin
   2317 	rdpr	%canrestore, %g1
   2318 	sub	%g1, %g7, %g1				! Calculate %canrestore - %g7
   2319 	movrlz	%g1, %g0, %g1				! Clamp at zero
   2320 	wrpr	%g1, 0, %canrestore			! This is the new canrestore
   2321 	rdpr	%ver, %g5
   2322 	and	%g5, CWP, %g5				! NWINDOWS-1
   2323 	dec	%g5					! NWINDOWS-2
   2324 	wrpr	%g5, 0, %cleanwin			! Set cleanwin to max, since we're in-kernel
   2325 	sub	%g5, %g1, %g5				! NWINDOWS-2-%canrestore
   2326 	wrpr	%g5, 0, %cansave
   2327 #ifdef NOT_DEBUG
   2328 	rdpr	%wstate, %g5				! DEBUG
   2329 	wrpr	%g0, WSTATE_KERN, %wstate		! DEBUG
   2330 	wrpr	%g0, 4, %tl
   2331 	flushw						! DEBUG
   2332 	wrpr	%g2, 0, %tl
   2333 	wrpr	%g5, 0, %wstate				! DEBUG
   2334 #endif
   2335 #endif
   2336 
   2337 #ifdef NOTDEF_DEBUG
   2338 	set	panicstack-CC64FSZ, %g1
   2339 	save	%g1, 0, %sp
   2340 	GLOBTOLOC
   2341 	rdpr	%wstate, %l0
   2342 	wrpr	%g0, WSTATE_KERN, %wstate
   2343 	set	8f, %o0
   2344 	mov	%g7, %o1
   2345 	call	printf
   2346 	 mov	%g5, %o2
   2347 	wrpr	%l0, 0, %wstate
   2348 	LOCTOGLOB
   2349 	restore
   2350 	.data
   2351 8:
   2352 	.asciz	"winfix: spill fixup\n"
   2353 	_ALIGN
   2354 	.text
   2355 #endif
   2356 !	rdpr	%tl, %g2				! DEBUG DEBUG -- did we trap somewhere?
   2357 	sub	%g2, 1, %g1
   2358 	rdpr	%tt, %g2
   2359 	wrpr	%g1, 0, %tl				! We will not attempt to re-execute the spill, so dump our trap frame permanently
   2360 	wrpr	%g2, 0, %tt				! Move trap type from fault frame here, overwriting spill
   2361 
   2362 	/* Did we save a user or kernel window ? */
   2363 !	srax	%g3, 48, %g5				! User or kernel store? (TAG TARGET)
   2364 	sllx	%g3, (64-13), %g5			! User or kernel store? (TAG ACCESS)
   2365 	sethi	%hi(dcache_size), %g7
   2366 	ld	[%g7 + %lo(dcache_size)], %g7
   2367 	sethi	%hi(dcache_line_size), %g6
   2368 	ld	[%g6 + %lo(dcache_line_size)], %g6
   2369 	brnz,pt	%g5, 1f					! User fault -- save windows to pcb
   2370 	 sub	%g7, %g6, %g7
   2371 
   2372 	and	%g4, CWP, %g4				! %g4 = %cwp of trap
   2373 	wrpr	%g4, 0, %cwp				! Kernel fault -- restore %cwp and force and trap to debugger
   2374 	!!
   2375 	!! Here we managed to fault trying to access a kernel window
   2376 	!! This is a bug.  Switch to the interrupt stack if we aren't
   2377 	!! there already and then trap into the debugger or panic.
   2378 	!!
   2379 	sethi	%hi(EINTSTACK-BIAS), %g6
   2380 	btst	1, %sp
   2381 	bnz,pt	%icc, 0f
   2382 	 mov	%sp, %g1
   2383 	add	%sp, -BIAS, %g1
   2384 0:
   2385 	or	%g6, %lo(EINTSTACK-BIAS), %g6
   2386 	set	(EINTSTACK-INTSTACK), %g7	! XXXXXXXXXX This assumes kernel addresses are unique from user addresses
   2387 	sub	%g6, %g1, %g2				! Determine if we need to switch to intr stack or not
   2388 	dec	%g7					! Make it into a mask
   2389 	andncc	%g2, %g7, %g0				! XXXXXXXXXX This assumes kernel addresses are unique from user addresses */ \
   2390 	movz	%xcc, %g1, %g6				! Stay on interrupt stack?
   2391 	add	%g6, -CCFSZ, %g6			! Allocate a stack frame
   2392 	mov	%sp, %l6				! XXXXX Save old stack pointer
   2393 	mov	%g6, %sp
   2394 	ta	1; nop					! Enter debugger
   2395 	NOTREACHED
   2396 1:
   2397 #if 1
   2398 	/* Now we need to blast away the D$ to make sure we're in sync */
   2399 	stxa	%g0, [%g7] ASI_DCACHE_TAG
   2400 	brnz,pt	%g7, 1b
   2401 	 sub	%g7, %g6, %g7
   2402 #endif
   2403 
   2404 #ifdef NOTDEF_DEBUG
   2405 	set	panicstack-CC64FSZ, %g5
   2406 	save	%g5, 0, %sp
   2407 	GLOBTOLOC
   2408 	rdpr	%wstate, %l0
   2409 	wrpr	%g0, WSTATE_KERN, %wstate
   2410 	set	8f, %o0
   2411 	call	printf
   2412 	 mov	%fp, %o1
   2413 	wrpr	%l0, 0, %wstate
   2414 	LOCTOGLOB
   2415 	restore
   2416 	.data
   2417 8:
   2418 	.asciz	"winfix: kernel spill retry\n"
   2419 	_ALIGN
   2420 	.text
   2421 #endif
   2422 #ifdef TRAPSTATS
   2423 	set	_C_LABEL(wspillskip), %g4
   2424 	lduw	[%g4], %g5
   2425 	inc	%g5
   2426 	stw	%g5, [%g4]
   2427 #endif
   2428 	/*
   2429 	 * If we had WSTATE_KERN then we had at least one valid kernel window.
   2430 	 * We should re-execute the trapping save.
   2431 	 */
   2432 	rdpr	%wstate, %g3
   2433 	mov	%g3, %g3
   2434 	cmp	%g3, WSTATE_KERN
   2435 	bne,pt	%icc, 1f
   2436 	 nop
   2437 	retry						! Now we can complete the save
   2438 1:
   2439 	/*
   2440 	 * Since we had a WSTATE_USER, we had no valid kernel windows.  This should
   2441 	 * only happen inside TRAP_SETUP or INTR_SETUP. Emulate
   2442 	 * the instruction, clean up the register windows, then done.
   2443 	 */
   2444 	rdpr	%cwp, %g1
   2445 	inc	%g1
   2446 	rdpr	%tstate, %g2
   2447 	wrpr	%g1, %cwp
   2448 	andn	%g2, CWP, %g2
   2449 	wrpr	%g1, %g2, %tstate
   2450 #ifdef TRAPS_USE_IG
   2451 	wrpr	%g0, PSTATE_KERN|PSTATE_IG, %pstate	! DEBUG
   2452 #else
   2453 	wrpr	%g0, PSTATE_KERN|PSTATE_AG, %pstate
   2454 #endif
   2455 	mov	%g6, %sp
   2456 	done
   2457 
   2458 /*
   2459  * Each memory data access fault, from user or kernel mode,
   2460  * comes here.
   2461  *
   2462  * We will assume that %pil is not lost so we won't bother to save it
   2463  * unless we're in an interrupt handler.
   2464  *
   2465  * On entry:
   2466  *	We are on one of the alternate set of globals
   2467  *	%g1 = MMU tag target
   2468  *	%g2 = %tl
   2469  *
   2470  * On return:
   2471  *
   2472  */
   2473 datafault:
   2474 #ifdef TRAPS_USE_IG
   2475 	wrpr	%g0, PSTATE_KERN|PSTATE_IG, %pstate	! We need to save volatile stuff to interrupt globals
   2476 #else
   2477 	wrpr	%g0, PSTATE_KERN|PSTATE_AG, %pstate	! We need to save volatile stuff to alternate globals
   2478 #endif
   2479 	wr	%g0, ASI_DMMU, %asi			! We need to re-load trap info
   2480 	ldxa	[%g0 + TLB_TAG_ACCESS] %asi, %g1	! Get fault address from tag access register
   2481 	ldxa	[SFAR] %asi, %g2			! sync virt addr; must be read first
   2482 	ldxa	[SFSR] %asi, %g3			! get sync fault status register
   2483 	stxa	%g0, [SFSR] %asi			! Clear out fault now
   2484 
   2485 	TRAP_SETUP(-CC64FSZ-TF_SIZE)
   2486 Ldatafault_internal:
   2487 	INCR64(CPUINFO_VA+CI_NFAULT)			! cnt.v_faults++ (clobbers %o0,%o1)
   2488 !	ldx	[%sp + CC64FSZ + STKB + TF_FAULT], %g1	! DEBUG make sure this has not changed
   2489 	mov	%g1, %o0				! Move these to the out regs so we can save the globals
   2490 	mov	%g2, %o4
   2491 	mov	%g3, %o5
   2492 
   2493 	ldxa	[%g0] ASI_AFAR, %o2			! get async fault address
   2494 	ldxa	[%g0] ASI_AFSR, %o3			! get async fault status
   2495 	mov	-1, %g7
   2496 	stxa	%g7, [%g0] ASI_AFSR			! And clear this out, too
   2497 
   2498 	wrpr	%g0, PSTATE_KERN, %pstate		! Get back to normal globals
   2499 
   2500 	stx	%g1, [%sp + CC64FSZ + STKB + TF_G + (1*8)]	! save g1
   2501 	rdpr	%tt, %o1					! find out what trap brought us here
   2502 	stx	%g2, [%sp + CC64FSZ + STKB + TF_G + (2*8)]	! save g2
   2503 	rdpr	%tstate, %g1
   2504 	stx	%g3, [%sp + CC64FSZ + STKB + TF_G + (3*8)]	! (sneak g3 in here)
   2505 	rdpr	%tpc, %g2
   2506 	stx	%g4, [%sp + CC64FSZ + STKB + TF_G + (4*8)]	! sneak in g4
   2507 	rdpr	%tnpc, %g3
   2508 	stx	%g5, [%sp + CC64FSZ + STKB + TF_G + (5*8)]	! sneak in g5
   2509 	mov	%g2, %o7					! Make the fault address look like the return address
   2510 	stx	%g6, [%sp + CC64FSZ + STKB + TF_G + (6*8)]	! sneak in g6
   2511 	rd	%y, %g5						! save y
   2512 	stx	%g7, [%sp + CC64FSZ + STKB + TF_G + (7*8)]	! sneak in g7
   2513 
   2514 	sth	%o1, [%sp + CC64FSZ + STKB + TF_TT]
   2515 	stx	%g1, [%sp + CC64FSZ + STKB + TF_TSTATE]		! set tf.tf_psr, tf.tf_pc
   2516 	stx	%g2, [%sp + CC64FSZ + STKB + TF_PC]		! set tf.tf_npc
   2517 	stx	%g3, [%sp + CC64FSZ + STKB + TF_NPC]
   2518 
   2519 	rdpr	%pil, %g4
   2520 	stb	%g4, [%sp + CC64FSZ + STKB + TF_PIL]
   2521 	stb	%g4, [%sp + CC64FSZ + STKB + TF_OLDPIL]
   2522 
   2523 #if 1
   2524 	rdpr	%tl, %g7
   2525 	dec	%g7
   2526 	movrlz	%g7, %g0, %g7
   2527 	wrpr	%g0, %g7, %tl		! Revert to kernel mode
   2528 #else
   2529 	wrpr	%g0, 0, %tl		! Revert to kernel mode
   2530 #endif
   2531 	/* Finish stackframe, call C trap handler */
   2532 	flushw						! Get this clean so we won't take any more user faults
   2533 #ifdef NOTDEF_DEBUG
   2534 	set	CPCB, %o7
   2535 	LDPTR	[%o7], %o7
   2536 	ldub	[%o7 + PCB_NSAVED], %o7
   2537 	brz,pt	%o7, 2f
   2538 	 nop
   2539 	save	%sp, -CC64FSZ, %sp
   2540 	set	1f, %o0
   2541 	call printf
   2542 	 mov	%i7, %o1
   2543 	ta	1; nop
   2544 	 restore
   2545 	.data
   2546 1:	.asciz	"datafault: nsaved = %d\n"
   2547 	_ALIGN
   2548 	.text
   2549 2:
   2550 #endif
   2551 	!! In the EMBEDANY memory model %g4 points to the start of the data segment.
   2552 	!! In our case we need to clear it before calling any C-code
   2553 	clr	%g4
   2554 
   2555 	/*
   2556 	 * Right now the registers have the following values:
   2557 	 *
   2558 	 *	%o0 -- MMU_TAG_ACCESS
   2559 	 *	%o1 -- TT
   2560 	 *	%o2 -- afar
   2561 	 *	%o3 -- afsr
   2562 	 *	%o4 -- sfar
   2563 	 *	%o5 -- sfsr
   2564 	 */
   2565 
   2566 	cmp	%o1, T_DATA_ERROR
   2567 	st	%g5, [%sp + CC64FSZ + STKB + TF_Y]
   2568 	wr	%g0, ASI_PRIMARY_NOFAULT, %asi	! Restore default ASI
   2569 	be,pn	%icc, data_error
   2570 	 wrpr	%g0, PSTATE_INTR, %pstate	! reenable interrupts
   2571 
   2572 	mov	%o0, %o3			! (argument: trap address)
   2573 	mov	%g2, %o2			! (argument: trap pc)
   2574 	call	_C_LABEL(data_access_fault)	! data_access_fault(&tf, type,
   2575 						!	pc, addr, sfva, sfsr)
   2576 	 add	%sp, CC64FSZ + STKB, %o0	! (argument: &tf)
   2577 
   2578 data_recover:
   2579 #ifdef TRAPSTATS
   2580 	set	_C_LABEL(uintrcnt), %g1
   2581 	stw	%g0, [%g1]
   2582 	set	_C_LABEL(iveccnt), %g1
   2583 	stw	%g0, [%g1]
   2584 #endif
   2585 	wrpr	%g0, PSTATE_KERN, %pstate		! disable interrupts
   2586 	b	return_from_trap			! go return
   2587 	 ldx	[%sp + CC64FSZ + STKB + TF_TSTATE], %g1		! Load this for return_from_trap
   2588 	NOTREACHED
   2589 
   2590 data_error:
   2591 	call	_C_LABEL(data_access_error)	! data_access_error(&tf, type,
   2592 						!	afva, afsr, sfva, sfsr)
   2593 	 add	%sp, CC64FSZ + STKB, %o0	! (argument: &tf)
   2594 	ba	data_recover
   2595 	 nop
   2596 	NOTREACHED
   2597 
   2598 /*
   2599  * Each memory instruction access fault from a fast access handler comes here.
   2600  * We will quickly check if this is an original prom mapping before going
   2601  * to the generic fault handler
   2602  *
   2603  * We will assume that %pil is not lost so we won't bother to save it
   2604  * unless we're in an interrupt handler.
   2605  *
   2606  * On entry:
   2607  *	We are on one of the alternate set of globals
   2608  *	%g1 = MMU tag target
   2609  *	%g2 = TSB entry ptr
   2610  *	%g3 = TLB Tag Access
   2611  *
   2612  * On return:
   2613  *
   2614  */
   2615 
   2616 	ICACHE_ALIGN
   2617 instr_miss:
   2618 #ifdef TRAPSTATS
   2619 	set	_C_LABEL(ktmiss), %g3
   2620 	set	_C_LABEL(utmiss), %g4
   2621 	rdpr	%tl, %g6
   2622 	dec	%g6
   2623 	movrz	%g6, %g4, %g3
   2624 	lduw	[%g3], %g4
   2625 	inc	%g4
   2626 	stw	%g4, [%g3]
   2627 #endif
   2628 	mov	TLB_TAG_ACCESS, %g3			! Get real fault page
   2629 	sethi	%hi(0x1fff), %g7			! 8K context mask
   2630 	ldxa	[%g3] ASI_IMMU, %g3			! from tag access register
   2631 	sethi	%hi(CPUINFO_VA+CI_CTXBUSY), %g4
   2632 	or	%g7, %lo(0x1fff), %g7
   2633 	LDPTR	[%g4 + %lo(CPUINFO_VA+CI_CTXBUSY)], %g4
   2634 	srax	%g3, HOLESHIFT, %g5			! Check for valid address
   2635 	and	%g3, %g7, %g6				! Isolate context
   2636 	sllx	%g6, 3, %g6				! Make it into an offset into ctxbusy
   2637 	inc	%g5					! (0 or -1) -> (1 or 0)
   2638 	ldx	[%g4+%g6], %g4				! Load up our page table.
   2639 #ifdef DEBUG
   2640 	/* Make sure we don't try to replace a kernel translation */
   2641 	/* This should not be necessary */
   2642 	brnz,pt	%g6, 1f					! If user context continue miss
   2643 	sethi	%hi(KERNBASE), %g7			! Don't need %lo
   2644 	set	0x0800000, %g6				! 8MB
   2645 	sub	%g3, %g7, %g7
   2646 	cmp	%g7, %g6
   2647 	tlu	%xcc, 1; nop
   2648 1:
   2649 #endif
   2650 	srlx	%g3, STSHIFT, %g6
   2651 	cmp	%g5, 1
   2652 	bgu,pn %xcc, textfault				! Error!
   2653 	 srlx	%g3, PDSHIFT, %g5
   2654 	and	%g6, STMASK, %g6
   2655 	sll	%g6, 3, %g6
   2656 	and	%g5, PDMASK, %g5
   2657 	nop
   2658 
   2659 	sll	%g5, 3, %g5
   2660 	add	%g6, %g4, %g4
   2661 	ldxa	[%g4] ASI_PHYS_CACHED, %g4
   2662 	srlx	%g3, PTSHIFT, %g6			! Convert to ptab offset
   2663 	and	%g6, PTMASK, %g6
   2664 	add	%g5, %g4, %g5
   2665 	brz,pn	%g4, textfault				! NULL entry? check somewhere else
   2666 	 nop
   2667 
   2668 	ldxa	[%g5] ASI_PHYS_CACHED, %g4
   2669 	sll	%g6, 3, %g6
   2670 	brz,pn	%g4, textfault				! NULL entry? check somewhere else
   2671 	 add	%g6, %g4, %g6
   2672 1:
   2673 	ldxa	[%g6] ASI_PHYS_CACHED, %g4
   2674 	brgez,pn %g4, textfault
   2675 	 nop
   2676 
   2677 	/* Check if it's an executable mapping. */
   2678 	andcc	%g4, SUN4U_TTE_EXEC, %g0
   2679 	bz,pn	%xcc, textfault
   2680 	 nop
   2681 
   2682 	or	%g4, SUN4U_TTE_ACCESS, %g7			! Update accessed bit
   2683 	btst	SUN4U_TTE_ACCESS, %g4				! Need to update access git?
   2684 	bne,pt	%xcc, 1f
   2685 	 nop
   2686 	casxa	[%g6] ASI_PHYS_CACHED, %g4, %g7		!  and store it
   2687 	cmp	%g4, %g7
   2688 	bne,pn	%xcc, 1b
   2689 	 or	%g4, SUN4U_TTE_ACCESS, %g4			! Update accessed bit
   2690 1:
   2691 	stx	%g1, [%g2]				! Update TSB entry tag
   2692 	stx	%g4, [%g2+8]				! Update TSB entry data
   2693 	stxa	%g4, [%g0] ASI_IMMU_DATA_IN		! Enter new mapping
   2694 	membar	#Sync
   2695 	CLRTT
   2696 	retry
   2697 	NOTREACHED
   2698 	!!
   2699 	!!  Check our prom mappings -- temporary
   2700 	!!
   2701 
   2702 /*
   2703  * Each memory text access fault, from user or kernel mode,
   2704  * comes here.
   2705  *
   2706  * We will assume that %pil is not lost so we won't bother to save it
   2707  * unless we're in an interrupt handler.
   2708  *
   2709  * On entry:
   2710  *	We are on one of the alternate set of globals
   2711  *	%g1 = MMU tag target
   2712  *	%g2 = %tl
   2713  *	%g3 = %tl - 1
   2714  *
   2715  * On return:
   2716  *
   2717  */
   2718 
   2719 textfault:
   2720 #ifdef TRAPS_USE_IG
   2721 	wrpr	%g0, PSTATE_KERN|PSTATE_IG, %pstate	! We need to save volatile stuff to interrupt globals
   2722 #else
   2723 	wrpr	%g0, PSTATE_KERN|PSTATE_AG, %pstate	! We need to save volatile stuff to alternate globals
   2724 #endif
   2725 	wr	%g0, ASI_IMMU, %asi
   2726 	ldxa	[%g0 + TLB_TAG_ACCESS] %asi, %g1	! Get fault address from tag access register
   2727 	ldxa	[SFSR] %asi, %g3			! get sync fault status register
   2728 	membar	#LoadStore
   2729 	stxa	%g0, [SFSR] %asi			! Clear out old info
   2730 
   2731 	TRAP_SETUP(-CC64FSZ-TF_SIZE)
   2732 	INCR64(CPUINFO_VA+CI_NFAULT)			! cnt.v_faults++ (clobbers %o0,%o1)
   2733 
   2734 	mov	%g3, %o3
   2735 
   2736 	wrpr	%g0, PSTATE_KERN, %pstate		! Switch to normal globals
   2737 	ldxa	[%g0] ASI_AFSR, %o4			! get async fault status
   2738 	ldxa	[%g0] ASI_AFAR, %o5			! get async fault address
   2739 	mov	-1, %o0
   2740 	stxa	%o0, [%g0] ASI_AFSR			! Clear this out
   2741 	stx	%g1, [%sp + CC64FSZ + STKB + TF_G + (1*8)]	! save g1
   2742 	stx	%g2, [%sp + CC64FSZ + STKB + TF_G + (2*8)]	! save g2
   2743 	stx	%g3, [%sp + CC64FSZ + STKB + TF_G + (3*8)]	! (sneak g3 in here)
   2744 	rdpr	%tt, %o1					! Find out what caused this trap
   2745 	stx	%g4, [%sp + CC64FSZ + STKB + TF_G + (4*8)]	! sneak in g4
   2746 	rdpr	%tstate, %g1
   2747 	stx	%g5, [%sp + CC64FSZ + STKB + TF_G + (5*8)]	! sneak in g5
   2748 	rdpr	%tpc, %o2					! sync virt addr; must be read first
   2749 	stx	%g6, [%sp + CC64FSZ + STKB + TF_G + (6*8)]	! sneak in g6
   2750 	rdpr	%tnpc, %g3
   2751 	stx	%g7, [%sp + CC64FSZ + STKB + TF_G + (7*8)]	! sneak in g7
   2752 	rd	%y, %g5						! save y
   2753 
   2754 	/* Finish stackframe, call C trap handler */
   2755 	stx	%g1, [%sp + CC64FSZ + STKB + TF_TSTATE]		! set tf.tf_psr, tf.tf_pc
   2756 	sth	%o1, [%sp + CC64FSZ + STKB + TF_TT]		! debug
   2757 
   2758 	stx	%o2, [%sp + CC64FSZ + STKB + TF_PC]
   2759 	stx	%g3, [%sp + CC64FSZ + STKB + TF_NPC]		! set tf.tf_npc
   2760 
   2761 	rdpr	%pil, %g4
   2762 	stb	%g4, [%sp + CC64FSZ + STKB + TF_PIL]
   2763 	stb	%g4, [%sp + CC64FSZ + STKB + TF_OLDPIL]
   2764 
   2765 	rdpr	%tl, %g7
   2766 	dec	%g7
   2767 	movrlz	%g7, %g0, %g7
   2768 	wrpr	%g0, %g7, %tl		! Revert to kernel mode
   2769 
   2770 	wr	%g0, ASI_PRIMARY_NOFAULT, %asi		! Restore default ASI
   2771 	flushw						! Get rid of any user windows so we don't deadlock
   2772 
   2773 	!! In the EMBEDANY memory model %g4 points to the start of the data segment.
   2774 	!! In our case we need to clear it before calling any C-code
   2775 	clr	%g4
   2776 
   2777 	/* Use trap type to see what handler to call */
   2778 	cmp	%o1, T_INST_ERROR
   2779 	be,pn	%xcc, text_error
   2780 	 st	%g5, [%sp + CC64FSZ + STKB + TF_Y]		! set tf.tf_y
   2781 
   2782 	wrpr	%g0, PSTATE_INTR, %pstate	! reenable interrupts
   2783 	call	_C_LABEL(text_access_fault)	! mem_access_fault(&tf, type, pc, sfsr)
   2784 	 add	%sp, CC64FSZ + STKB, %o0	! (argument: &tf)
   2785 text_recover:
   2786 	wrpr	%g0, PSTATE_KERN, %pstate	! disable interrupts
   2787 	b	return_from_trap		! go return
   2788 	 ldx	[%sp + CC64FSZ + STKB + TF_TSTATE], %g1	! Load this for return_from_trap
   2789 	NOTREACHED
   2790 
   2791 text_error:
   2792 	wrpr	%g0, PSTATE_INTR, %pstate	! reenable interrupts
   2793 	call	_C_LABEL(text_access_error)	! mem_access_fault(&tfm type, sfva [pc], sfsr,
   2794 						!		afva, afsr);
   2795 	 add	%sp, CC64FSZ + STKB, %o0	! (argument: &tf)
   2796 	ba	text_recover
   2797 	 nop
   2798 	NOTREACHED
   2799 
   2800 #ifdef SUN4V
   2801 
   2802 /*
   2803  * Traps for sun4v.
   2804  */
   2805 
   2806 sun4v_dtsb_miss:
   2807 	GET_MMFSA %g1				! MMU Fault status area
   2808 	add	%g1, 0x48, %g3
   2809 	LDPTRA	[%g3] ASI_PHYS_CACHED, %g3	! Data fault address
   2810 	add	%g1, 0x50, %g6
   2811 	LDPTRA	[%g6] ASI_PHYS_CACHED, %g6	! Data fault context
   2812 
   2813 	GET_CTXBUSY %g4
   2814 	sllx	%g6, 3, %g6			! Make it into an offset into ctxbusy
   2815 	LDPTR	[%g4 + %g6], %g4		! Load up our page table.
   2816 
   2817 	srax	%g3, HOLESHIFT, %g5		! Check for valid address
   2818 	brz,pt	%g5, 0f				! Should be zero or -1
   2819 	 inc	%g5				! Make -1 -> 0
   2820 	brnz,pn	%g5, sun4v_datatrap		! Error! In hole!
   2821 0:
   2822 	srlx	%g3, STSHIFT, %g6
   2823 	and	%g6, STMASK, %g6		! Index into pm_segs
   2824 	sll	%g6, 3, %g6
   2825 	add	%g4, %g6, %g4
   2826 	LDPTRA	[%g4] ASI_PHYS_CACHED, %g4	! Load page directory pointer
   2827 	srlx	%g3, PDSHIFT, %g6
   2828 	and	%g6, PDMASK, %g6
   2829 	sll	%g6, 3, %g6
   2830 	brz,pn	%g4, sun4v_datatrap		! NULL entry? check somewhere else
   2831 	 add	%g4, %g6, %g4
   2832 	LDPTRA	[%g4] ASI_PHYS_CACHED, %g4	! Load page table pointer
   2833 
   2834 	srlx	%g3, PTSHIFT, %g6		! Convert to ptab offset
   2835 	and	%g6, PTMASK, %g6
   2836 	sll	%g6, 3, %g6
   2837 	brz,pn	%g4, sun4v_datatrap		! NULL entry? check somewhere else
   2838 	 add	%g4, %g6, %g6
   2839 1:
   2840 	LDPTRA	[%g6] ASI_PHYS_CACHED, %g4	! Fetch TTE
   2841 	brgez,pn %g4, sun4v_datatrap		! Entry invalid?  Punt
   2842 	 or	%g4, SUN4V_TLB_ACCESS, %g7	! Update the access bit
   2843 
   2844 	btst	SUN4V_TLB_ACCESS, %g4		! Need to update access bit?
   2845 	bne,pt	%xcc, 2f
   2846 	 nop
   2847 	casxa	[%g6] ASI_PHYS_CACHED, %g4, %g7	! and write it out
   2848 	cmp	%g4, %g7
   2849 	bne,pn	%xcc, 1b
   2850 	 or	%g4, SUN4V_TLB_ACCESS, %g4	! Update the access bit
   2851 2:
   2852 	GET_TSB_DMMU %g2
   2853 
   2854 	/* Construct TSB tag word. */
   2855 	add	%g1, 0x50, %g6
   2856 	LDPTRA	[%g6] ASI_PHYS_CACHED, %g6	! Data fault context
   2857 	mov	%g3, %g1			! Data fault address
   2858 	srlx	%g1, 22, %g1			! 63..22 of virt addr
   2859 	sllx	%g6, 48, %g6			! context_id in 63..48
   2860 	or	%g1, %g6, %g1			! construct TTE tag
   2861 	srlx	%g3, PTSHIFT, %g3
   2862 	sethi	%hi(_C_LABEL(tsbsize)), %g5
   2863 	mov	512, %g6
   2864 	ld	[%g5 + %lo(_C_LABEL(tsbsize))], %g5
   2865 	sllx	%g6, %g5, %g5			! %g5 = 512 << tsbsize = TSBENTS
   2866 	sub	%g5, 1, %g5			! TSBENTS -> offset
   2867 	and	%g3, %g5, %g3			! mask out TTE index
   2868 	sllx	%g3, 4, %g3			! TTE size is 16 bytes
   2869 	add	%g2, %g3, %g2			! location of TTE in ci_tsb_dmmu
   2870 
   2871 	membar	#StoreStore
   2872 
   2873 	STPTR	%g4, [%g2 + 8]			! store TTE data
   2874 	STPTR	%g1, [%g2]			! store TTE tag
   2875 
   2876 	retry
   2877 	NOTREACHED
   2878 
   2879 sun4v_tl1_dtsb_miss:
   2880 	GET_MMFSA %g1				! MMU Fault status area
   2881 	add	%g1, 0x48, %g3
   2882 	LDPTRA	[%g3] ASI_PHYS_CACHED, %g3	! Data fault address
   2883 	add	%g1, 0x50, %g6
   2884 	LDPTRA	[%g6] ASI_PHYS_CACHED, %g6	! Data fault context
   2885 
   2886 	GET_CTXBUSY %g4
   2887 	sllx	%g6, 3, %g6			! Make it into an offset into ctxbusy
   2888 	LDPTR	[%g4 + %g6], %g4		! Load up our page table.
   2889 
   2890 	srax	%g3, HOLESHIFT, %g5		! Check for valid address
   2891 	brz,pt	%g5, 0f				! Should be zero or -1
   2892 	 inc	%g5				! Make -1 -> 0
   2893 	brnz,pn	%g5, sun4v_tl1_ptbl_miss	! Error! In hole!
   2894 0:
   2895 	srlx	%g3, STSHIFT, %g6
   2896 	and	%g6, STMASK, %g6		! Index into pm_segs
   2897 	sll	%g6, 3, %g6
   2898 	add	%g4, %g6, %g4
   2899 	LDPTRA	[%g4] ASI_PHYS_CACHED, %g4	! Load page directory pointer
   2900 	srlx	%g3, PDSHIFT, %g6
   2901 	and	%g6, PDMASK, %g6
   2902 	sll	%g6, 3, %g6
   2903 	brz,pn	%g4, sun4v_tl1_ptbl_miss	! NULL entry? check somewhere else
   2904 	 add	%g4, %g6, %g4
   2905 	LDPTRA	[%g4] ASI_PHYS_CACHED, %g4	! Load page table pointer
   2906 
   2907 	srlx	%g3, PTSHIFT, %g6		! Convert to ptab offset
   2908 	and	%g6, PTMASK, %g6
   2909 	sll	%g6, 3, %g6
   2910 	brz,pn	%g4, sun4v_tl1_ptbl_miss	! NULL entry? check somewhere else
   2911 	 add	%g4, %g6, %g6
   2912 1:
   2913 	LDPTRA	[%g6] ASI_PHYS_CACHED, %g4	! Fetch TTE
   2914 	brgez,pn %g4, sun4v_tl1_ptbl_miss	! Entry invalid?  Punt
   2915 	 or	%g4, SUN4V_TLB_ACCESS, %g7	! Update the access bit
   2916 
   2917 	btst	SUN4V_TLB_ACCESS, %g4		! Need to update access bit?
   2918 	bne,pt	%xcc, 2f
   2919 	 nop
   2920 	casxa	[%g6] ASI_PHYS_CACHED, %g4, %g7	! and write it out
   2921 	cmp	%g4, %g7
   2922 	bne,pn	%xcc, 1b
   2923 	 or	%g4, SUN4V_TLB_ACCESS, %g4	! Update the access bit
   2924 2:
   2925 	GET_TSB_DMMU %g2
   2926 
   2927 	/* Construct TSB tag word. */
   2928 	add	%g1, 0x50, %g6
   2929 	LDPTRA	[%g6] ASI_PHYS_CACHED, %g6	! Data fault context
   2930 	mov	%g3, %g1			! Data fault address
   2931 	srlx	%g1, 22, %g1			! 63..22 of virt addr
   2932 	sllx	%g6, 48, %g6			! context_id in 63..48
   2933 	or	%g1, %g6, %g1			! construct TTE tag
   2934 	srlx	%g3, PTSHIFT, %g3
   2935 	sethi	%hi(_C_LABEL(tsbsize)), %g5
   2936 	mov	512, %g6
   2937 	ld	[%g5 + %lo(_C_LABEL(tsbsize))], %g5
   2938 	sllx	%g6, %g5, %g5			! %g5 = 512 << tsbsize = TSBENTS
   2939 	sub	%g5, 1, %g5			! TSBENTS -> offset
   2940 	and	%g3, %g5, %g3			! mask out TTE index
   2941 	sllx	%g3, 4, %g3			! TTE size is 16 bytes
   2942 	add	%g2, %g3, %g2			! location of TTE in ci_tsb_dmmu
   2943 
   2944 	membar	#StoreStore
   2945 
   2946 	STPTR	%g4, [%g2 + 8]			! store TTE data
   2947 	STPTR	%g1, [%g2]			! store TTE tag
   2948 
   2949 	retry
   2950 	NOTREACHED
   2951 
   2952 sun4v_datatrap:
   2953 	GET_MMFSA %g3				! MMU Fault status area
   2954 	add	%g3, 0x48, %g1
   2955 	LDPTRA	[%g1] ASI_PHYS_CACHED, %g1	! Data fault address
   2956 	add	%g3, 0x50, %g2
   2957 	LDPTRA	[%g2] ASI_PHYS_CACHED, %g2	! Data fault context
   2958 
   2959 	TRAP_SETUP(-CC64FSZ-TF_SIZE)
   2960 	or	%g1, %g2, %o3
   2961 	mov	%g1, %o4
   2962 
   2963 	rdpr	%tt, %g4
   2964 	rdpr	%tstate, %g1
   2965 	rdpr	%tpc, %g2
   2966 	rdpr	%tnpc, %g3
   2967 
   2968 	stx	%g1, [%sp + CC64FSZ + BIAS + TF_TSTATE]
   2969 	mov	%g4, %o1		! (type)
   2970 	stx	%g2, [%sp + CC64FSZ + BIAS + TF_PC]
   2971 	rd	%y, %g5
   2972 	stx	%g3, [%sp + CC64FSZ + BIAS + TF_NPC]
   2973 	st	%g5, [%sp + CC64FSZ + BIAS + TF_Y]
   2974 	mov	%g2, %o2		! (pc)
   2975 	sth	%o1, [%sp + CC64FSZ + BIAS + TF_TT]! debug
   2976 
   2977 	cmp	%o1, T_FDMMU_PROT
   2978 	bne,pn	%icc, 1f
   2979 	 mov	SFSR_FV, %o5
   2980 	or	%o5, SFSR_W, %o5
   2981 
   2982 1:
   2983 	NORMAL_GLOBALS_SUN4V
   2984 
   2985 	stx	%g1, [%sp + CC64FSZ + BIAS + TF_G + (1*8)]
   2986 	stx	%g2, [%sp + CC64FSZ + BIAS + TF_G + (2*8)]
   2987 	add	%sp, CC64FSZ + BIAS, %o0		! (&tf)
   2988 	stx	%g3, [%sp + CC64FSZ + BIAS + TF_G + (3*8)]
   2989 	stx	%g4, [%sp + CC64FSZ + BIAS + TF_G + (4*8)]
   2990 	stx	%g5, [%sp + CC64FSZ + BIAS + TF_G + (5*8)]
   2991 	rdpr	%pil, %g5
   2992 	stx	%g6, [%sp + CC64FSZ + BIAS + TF_G + (6*8)]
   2993 	stx	%g7, [%sp + CC64FSZ + BIAS + TF_G + (7*8)]
   2994 	stb	%g5, [%sp + CC64FSZ + BIAS + TF_PIL]
   2995 	stb	%g5, [%sp + CC64FSZ + BIAS + TF_OLDPIL]
   2996 
   2997 	/*
   2998 	 * Phew, ready to enable traps and call C code.
   2999 	 */
   3000 	wrpr	%g0, 0, %tl
   3001 
   3002 	wr	%g0, ASI_PRIMARY_NOFAULT, %asi	! Restore default ASI
   3003 	wrpr	%g0, PSTATE_INTR, %pstate	! traps on again
   3004 	call	_C_LABEL(data_access_fault)	! data_acces_fault(tf, type, ...)
   3005 	 nop
   3006 
   3007 	ba,a,pt	%icc, return_from_trap
   3008 	 nop
   3009 	NOTREACHED
   3010 
   3011 sun4v_tl0_dtsb_prot:
   3012 	GET_MMFSA %g1				! MMU Fault status area
   3013 	add	%g1, 0x48, %g3
   3014 	LDPTRA	[%g3] ASI_PHYS_CACHED, %g3	! Data fault address
   3015 	add	%g1, 0x50, %g6
   3016 	LDPTRA	[%g6] ASI_PHYS_CACHED, %g6	! Data fault context
   3017 
   3018 	GET_CTXBUSY %g4
   3019 	sllx	%g6, 3, %g6			! Make it into an offset into ctxbusy
   3020 	LDPTR	[%g4 + %g6], %g4		! Load up our page table.
   3021 
   3022 	srax	%g3, HOLESHIFT, %g5		! Check for valid address
   3023 	brz,pt	%g5, 0f				! Should be zero or -1
   3024 	 inc	%g5				! Make -1 -> 0
   3025 	brnz,pn	%g5, sun4v_datatrap		! Error! In hole!
   3026 0:
   3027 	srlx	%g3, STSHIFT, %g6
   3028 	and	%g6, STMASK, %g6		! Index into pm_segs
   3029 	sll	%g6, 3, %g6
   3030 	add	%g4, %g6, %g4
   3031 	LDPTRA	[%g4] ASI_PHYS_CACHED, %g4	! Load page directory pointer
   3032 
   3033 	srlx	%g3, PDSHIFT, %g6
   3034 	and	%g6, PDMASK, %g6
   3035 	sll	%g6, 3, %g6
   3036 	brz,pn	%g4, sun4v_datatrap		! NULL entry? check somewhere else
   3037 	 add	%g4, %g6, %g4
   3038 	LDPTRA	[%g4] ASI_PHYS_CACHED, %g4	! Load page table pointer
   3039 
   3040 	srlx	%g3, PTSHIFT, %g6		! Convert to ptab offset
   3041 	and	%g6, PTMASK, %g6
   3042 	sll	%g6, 3, %g6
   3043 	brz,pn	%g4, sun4v_datatrap		! NULL entry? check somewhere else
   3044 	 add	%g4, %g6, %g6
   3045 1:
   3046 	LDPTRA	[%g6] ASI_PHYS_CACHED, %g4	! Fetch TTE
   3047 	brgez,pn %g4, sun4v_datatrap		! Entry invalid?  Punt
   3048 	 or	%g4, SUN4V_TLB_MODIFY|SUN4V_TLB_ACCESS|SUN4V_TLB_W, %g7 ! Update the modified bit
   3049 
   3050 #	btst	SUN4V_TLB_REAL_W|SUN4V_TLB_W, %g4	! Is it a ref fault?
   3051 	mov	1, %g2
   3052 	sllx	%g2, 61, %g2			! %g2 is now SUN4V_TLB_REAL_W
   3053 	or	%g2, SUN4V_TLB_W, %g2
   3054 	btst	%g2, %g4
   3055 	bz,pn	%xcc, sun4v_datatrap			! No -- really fault
   3056 	 nop
   3057 	casxa	[%g6] ASI_PHYS_CACHED, %g4, %g7		!  and write it out
   3058 	cmp	%g4, %g7
   3059 	bne,pn	%xcc, 1b
   3060 	 or	%g4, SUN4V_TLB_MODIFY|SUN4V_TLB_ACCESS|SUN4V_TLB_W, %g4 ! Update the modified bit
   3061 2:
   3062 	GET_TSB_DMMU %g2
   3063 
   3064 	mov	%g1, %g7			! save MMFSA
   3065 
   3066 	/* Construct TSB tag word. */
   3067 	add	%g1, 0x50, %g6
   3068 	LDPTRA	[%g6] ASI_PHYS_CACHED, %g6	! Data fault context
   3069 	mov	%g3, %g1			! Data fault address
   3070 	srlx	%g1, 22, %g1			! 63..22 of virt addr
   3071 	sllx	%g6, 48, %g6			! context_id in 63..48
   3072 	or	%g1, %g6, %g1			! construct TTE tag
   3073 
   3074 	srlx	%g3, PTSHIFT, %g3
   3075 	sethi	%hi(_C_LABEL(tsbsize)), %g5
   3076 	mov	512, %g6
   3077 	ld	[%g5 + %lo(_C_LABEL(tsbsize))], %g5
   3078 	sllx	%g6, %g5, %g5			! %g5 = 512 << tsbsize = TSBENTS
   3079 	sub	%g5, 1, %g5			! TSBENTS -> offset
   3080 	and	%g3, %g5, %g3			! mask out TTE index
   3081 	sllx	%g3, 4, %g3			! TTE size is 16 bytes
   3082 	add	%g2, %g3, %g2			! location of TTE in ci_tsb_dmmu
   3083 
   3084 	membar	#StoreStore
   3085 
   3086 	STPTR	%g4, [%g2 + 8]		! store TTE data
   3087 	STPTR	%g1, [%g2]		! store TTE tag
   3088 
   3089 	mov	%o0, %g1
   3090 	mov	%o1, %g2
   3091 	mov	%o2, %g3
   3092 
   3093 	add	%g7, 0x48, %o0
   3094 	ldxa	[%o0] ASI_PHYS_CACHED, %o0	! Data fault address
   3095 	add	%g7, 0x50, %o1
   3096 	ldxa	[%o1] ASI_PHYS_CACHED, %o1	! Data fault context
   3097 	mov	MAP_DTLB, %o2
   3098 	ta	ST_MMU_UNMAP_ADDR
   3099 
   3100 	mov	%g1, %o0
   3101 	mov	%g2, %o1
   3102 	mov	%g3, %o2
   3103 
   3104 	retry
   3105 	NOTREACHED
   3106 
   3107 sun4v_tl0_itsb_miss:
   3108 	GET_MMFSA %g1				! MMU Fault status area
   3109 	add	%g1, 0x8, %g3
   3110 	LDPTRA	[%g3] ASI_PHYS_CACHED, %g3	! Instruction fault address
   3111 	add	%g1, 0x10, %g6
   3112 	LDPTRA	[%g6] ASI_PHYS_CACHED, %g6	! Data fault context
   3113 
   3114 	GET_CTXBUSY %g4
   3115 	sllx	%g6, 3, %g6			! Make it into an offset into ctxbusy
   3116 	LDPTR	[%g4 + %g6], %g4		! Load up our page table.
   3117 
   3118 	srax	%g3, HOLESHIFT, %g5		! Check for valid address
   3119 	brz,pt	%g5, 0f				! Should be zero or -1
   3120 	 inc	%g5				! Make -1 -> 0
   3121 	brnz,pn	%g5, sun4v_texttrap		! Error! In hole!
   3122 0:
   3123 	srlx	%g3, STSHIFT, %g6
   3124 	and	%g6, STMASK, %g6		! Index into pm_segs
   3125 	sll	%g6, 3, %g6
   3126 	add	%g4, %g6, %g4
   3127 	LDPTRA	[%g4] ASI_PHYS_CACHED, %g4	! Load page directory pointer
   3128 
   3129 	srlx	%g3, PDSHIFT, %g6
   3130 	and	%g6, PDMASK, %g6
   3131 	sll	%g6, 3, %g6
   3132 	brz,pn	%g4, sun4v_texttrap		! NULL entry? check somewhere else
   3133 	 add	%g4, %g6, %g4
   3134 	LDPTRA	[%g4] ASI_PHYS_CACHED, %g4	! Load page table pointer
   3135 
   3136 	srlx	%g3, PTSHIFT, %g6		! Convert to ptab offset
   3137 	and	%g6, PTMASK, %g6
   3138 	sll	%g6, 3, %g6
   3139 	brz,pn	%g4, sun4v_texttrap		! NULL entry? check somewhere else
   3140 	 add	%g4, %g6, %g6
   3141 1:
   3142 	LDPTRA	[%g6] ASI_PHYS_CACHED, %g4	! Fetch TTE
   3143 	brgez,pn %g4, sun4v_texttrap		! Entry invalid?  Punt
   3144 	 or	%g4, SUN4V_TLB_ACCESS, %g7	! Update the access bit
   3145 
   3146 	btst	SUN4V_TLB_EXEC, %g4		! Need to update exec bit?
   3147 	bz,pn	%xcc, sun4v_texttrap
   3148 	 nop
   3149 	btst	SUN4V_TLB_ACCESS, %g4		! Need to update access bit?
   3150 	bne,pt	%xcc, 2f
   3151 	 nop
   3152 	casxa	[%g6] ASI_PHYS_CACHED, %g4, %g7	! and write it out
   3153 	cmp	%g4, %g7
   3154 	bne,pn	%xcc, 1b
   3155 	 or	%g4, SUN4V_TLB_ACCESS, %g4	! Update the modified bit
   3156 2:
   3157 	GET_TSB_DMMU %g2
   3158 
   3159 	mov	%g1, %g7
   3160 	/* Construct TSB tag word. */
   3161 	add	%g1, 0x10, %g6
   3162 	LDPTRA	[%g6] ASI_PHYS_CACHED, %g6	! Instruction fault context
   3163 	mov	%g3, %g1			! Instruction fault address
   3164 	srlx	%g1, 22, %g1			! 63..22 of virt addr
   3165 	sllx	%g6, 48, %g6			! context_id in 63..48
   3166 	or	%g1, %g6, %g1			! construct TTE tag
   3167 
   3168 	srlx	%g3, PTSHIFT, %g3
   3169 	sethi	%hi(_C_LABEL(tsbsize)), %g5
   3170 	mov	512, %g6
   3171 	ld	[%g5 + %lo(_C_LABEL(tsbsize))], %g5
   3172 	sllx	%g6, %g5, %g5			! %g5 = 512 << tsbsize = TSBENTS
   3173 	sub	%g5, 1, %g5			! TSBENTS -> offset
   3174 	and	%g3, %g5, %g3			! mask out TTE index
   3175 	sllx	%g3, 4, %g3			! TTE size is 16 bytes
   3176 	add	%g2, %g3, %g2			! location of TTE in ci_tsb_dmmu (FIXME ci_tsb_immu?)
   3177 
   3178 	membar	#StoreStore
   3179 	STPTR	%g4, [%g2 + 8]			! store TTE data
   3180 	stx	%g1, [%g2]			! store TTE tag
   3181 
   3182 	retry
   3183 	NOTREACHED
   3184 
   3185 sun4v_texttrap:
   3186 	GET_MMFSA %g3				! MMU Fault status area
   3187 	add	%g3, 0x08, %g1
   3188 	LDPTRA	[%g1] ASI_PHYS_CACHED, %g1	! Instruction fault address
   3189 	add	%g3, 0x10, %g2
   3190 	LDPTRA	[%g2] ASI_PHYS_CACHED, %g2	! Instruction fault context
   3191 
   3192 	TRAP_SETUP(-CC64FSZ-TF_SIZE)
   3193 
   3194 	or	%g1, %g2, %o2
   3195 	clr	%o3
   3196 
   3197 	rdpr	%tt, %g4
   3198 	rdpr	%tstate, %g1
   3199 	rdpr	%tpc, %g2
   3200 	rdpr	%tnpc, %g3
   3201 
   3202 	stx	%g1, [%sp + CC64FSZ + BIAS + TF_TSTATE]
   3203 	mov	%g4, %o1		! (type)
   3204 	stx	%g2, [%sp + CC64FSZ + BIAS + TF_PC]
   3205 	rd	%y, %g5
   3206 	stx	%g3, [%sp + CC64FSZ + BIAS + TF_NPC]
   3207 	st	%g5, [%sp + CC64FSZ + BIAS + TF_Y]
   3208 	sth	%o1, [%sp + CC64FSZ + BIAS + TF_TT]! debug
   3209 
   3210 	! Get back to normal globals
   3211 	wrpr	%g0, PSTATE_KERN, %pstate
   3212 	NORMAL_GLOBALS_SUN4V
   3213 
   3214 	stx	%g1, [%sp + CC64FSZ + BIAS + TF_G + (1*8)]
   3215 	stx	%g2, [%sp + CC64FSZ + BIAS + TF_G + (2*8)]
   3216 	add	%sp, CC64FSZ + BIAS, %o0		! (&tf)
   3217 	stx	%g3, [%sp + CC64FSZ + BIAS + TF_G + (3*8)]
   3218 	stx	%g4, [%sp + CC64FSZ + BIAS + TF_G + (4*8)]
   3219 	stx	%g5, [%sp + CC64FSZ + BIAS + TF_G + (5*8)]
   3220 	rdpr	%pil, %g5
   3221 	stx	%g6, [%sp + CC64FSZ + BIAS + TF_G + (6*8)]
   3222 	stx	%g7, [%sp + CC64FSZ + BIAS + TF_G + (7*8)]
   3223 	stb	%g5, [%sp + CC64FSZ + BIAS + TF_PIL]
   3224 	stb	%g5, [%sp + CC64FSZ + BIAS + TF_OLDPIL]
   3225 
   3226 	/*
   3227 	 * Phew, ready to enable traps and call C code.
   3228 	 */
   3229 	wrpr	%g0, 0, %tl
   3230 
   3231 	wr	%g0, ASI_PRIMARY_NOFAULT, %asi	! Restore default ASI
   3232 	wrpr	%g0, PSTATE_INTR, %pstate	! traps on again
   3233 	call	_C_LABEL(text_access_fault)	! text_access_fault(tf, type, ...)
   3234 	 nop
   3235 
   3236 	ba,a,pt	%icc, return_from_trap
   3237 	 nop
   3238 	NOTREACHED
   3239 
   3240 sun4v_tl1_dtsb_prot:
   3241 	GET_MMFSA %g1				! MMU Fault status area
   3242 	add	%g1, 0x48, %g3
   3243 	LDPTRA	[%g3] ASI_PHYS_CACHED, %g3	! Data fault address
   3244 	add	%g1, 0x50, %g6
   3245 	LDPTRA	[%g6] ASI_PHYS_CACHED, %g6	! Data fault context
   3246 
   3247 	GET_CTXBUSY %g4
   3248 	sllx	%g6, 3, %g6			! Make it into an offset into ctxbusy
   3249 	LDPTR	[%g4 + %g6], %g4		! Load up our page table.
   3250 
   3251 	srax	%g3, HOLESHIFT, %g5		! Check for valid address
   3252 	brz,pt	%g5, 0f				! Should be zero or -1
   3253 	 inc	%g5				! Make -1 -> 0
   3254 	brnz,pn	%g5, sun4v_tl1_ptbl_miss	! Error! In hole!
   3255 0:
   3256 	srlx	%g3, STSHIFT, %g6
   3257 	and	%g6, STMASK, %g6		! Index into pm_segs
   3258 	sll	%g6, 3, %g6
   3259 	add	%g4, %g6, %g4
   3260 	LDPTRA	[%g4] ASI_PHYS_CACHED, %g4	! Load page directory pointer
   3261 
   3262 	srlx	%g3, PDSHIFT, %g6
   3263 	and	%g6, PDMASK, %g6
   3264 	sll	%g6, 3, %g6
   3265 	brz,pn	%g4, sun4v_tl1_ptbl_miss	! NULL entry? check somewhere else
   3266 	 add	%g4, %g6, %g4
   3267 	LDPTRA	[%g4] ASI_PHYS_CACHED, %g4	! Load page table pointer
   3268 
   3269 	srlx	%g3, PTSHIFT, %g6		! Convert to ptab offset
   3270 	and	%g6, PTMASK, %g6
   3271 	sll	%g6, 3, %g6
   3272 	brz,pn	%g4, sun4v_tl1_ptbl_miss	! NULL entry? check somewhere else
   3273 	 add	%g4, %g6, %g6
   3274 1:
   3275 	LDPTRA	[%g6] ASI_PHYS_CACHED, %g4	! Fetch TTE
   3276 	brgez,pn %g4, sun4v_tl1_ptbl_miss	! Entry invalid?  Punt
   3277 	 or	%g4, SUN4V_TLB_MODIFY|SUN4V_TLB_ACCESS|SUN4V_TLB_W, %g7 ! Update the modified bit
   3278 
   3279 #	btst	SUN4V_TLB_REAL_W|SUN4V_TLB_W, %g4	! Is it a ref fault?
   3280 	mov	1, %g2
   3281 	sllx	%g2, 61, %g2			! %g2 is now SUN4V_TLB_REAL_W
   3282 	or	%g2, SUN4V_TLB_W, %g2
   3283 	btst	%g2, %g4
   3284 	bz,pn	%xcc, sun4v_tl1_ptbl_miss		! No -- really fault
   3285 	 nop
   3286 	casxa	[%g6] ASI_PHYS_CACHED, %g4, %g7		!  and write it out
   3287 	cmp	%g4, %g7
   3288 	bne,pn	%xcc, 1b
   3289 	 or	%g4, SUN4V_TLB_MODIFY|SUN4V_TLB_ACCESS|SUN4V_TLB_W, %g4 ! Update the modified bit
   3290 2:
   3291 	GET_TSB_DMMU %g2
   3292 
   3293 	mov	%g1, %g7			! save MMFSA
   3294 
   3295 	/* Construct TSB tag word. */
   3296 	add	%g1, 0x50, %g6
   3297 	LDPTRA	[%g6] ASI_PHYS_CACHED, %g6	! Data fault context
   3298 	mov	%g3, %g1			! Data fault address
   3299 	srlx	%g1, 22, %g1			! 63..22 of virt addr
   3300 	sllx	%g6, 48, %g6			! context_id in 63..48
   3301 	or	%g1, %g6, %g1			! construct TTE tag
   3302 
   3303 	srlx	%g3, PTSHIFT, %g3
   3304 	sethi	%hi(_C_LABEL(tsbsize)), %g5
   3305 	mov	512, %g6
   3306 	ld	[%g5 + %lo(_C_LABEL(tsbsize))], %g5
   3307 	sllx	%g6, %g5, %g5			! %g5 = 512 << tsbsize = TSBENTS
   3308 	sub	%g5, 1, %g5			! TSBENTS -> offset
   3309 	and	%g3, %g5, %g3			! mask out TTE index
   3310 	sllx	%g3, 4, %g3			! TTE size is 16 bytes
   3311 	add	%g2, %g3, %g2			! location of TTE in ci_tsb_dmmu
   3312 
   3313 	membar	#StoreStore
   3314 
   3315 	STPTR	%g4, [%g2 + 8]		! store TTE data
   3316 	STPTR	%g1, [%g2]		! store TTE tag
   3317 
   3318 	mov	%o0, %g1
   3319 	mov	%o1, %g2
   3320 	mov	%o2, %g3
   3321 
   3322 	add	%g7, 0x48, %o0
   3323 	ldxa	[%o0] ASI_PHYS_CACHED, %o0	! Data fault address
   3324 	add	%g7, 0x50, %o1
   3325 	ldxa	[%o1] ASI_PHYS_CACHED, %o1	! Data fault context
   3326 	mov	MAP_DTLB, %o2
   3327 	ta	ST_MMU_UNMAP_ADDR
   3328 
   3329 	mov	%g1, %o0
   3330 	mov	%g2, %o1
   3331 	mov	%g3, %o2
   3332 
   3333 	retry
   3334 	NOTREACHED
   3335 
   3336 sun4v_tl1_ptbl_miss:
   3337 	rdpr	%tpc, %g1
   3338 
   3339 	set	rft_user_fault_start, %g2
   3340 	cmp	%g1, %g2
   3341 	blu,pt	%xcc, 1f
   3342 	 set	rft_user_fault_end, %g2
   3343 	cmp	%g1, %g2
   3344 	bgeu,pt	%xcc, 1f
   3345 	 nop
   3346 
   3347 	/* We had a miss inside rtf_user_fault_start/rtf_user_fault_end block (FILL) */
   3348 
   3349 	/* Fixup %cwp. */
   3350 	rdpr	%cwp, %g1
   3351 	inc	%g1
   3352 	wrpr	%g1, %cwp
   3353 
   3354 	rdpr	%tt, %g1
   3355 	wrpr	1, %tl
   3356 	wrpr	%g1, %tt
   3357 	rdpr	%cwp, %g1
   3358 	set	TSTATE_KERN, %g2
   3359 	wrpr	%g1, %g2, %tstate
   3360 	set	return_from_trap, %g1
   3361 	wrpr	%g1, %tpc
   3362 	add	%g1, 4, %g1
   3363 	wrpr	%g1, %tnpc
   3364 	wrpr	%g0, 1, %gl
   3365 
   3366 	ba,pt %xcc, sun4v_datatrap
   3367 	 wrpr	WSTATE_KERN, %wstate
   3368 
   3369 1:
   3370 	rdpr	%tstate, %g3
   3371 	rdpr	%tt, %g4
   3372 
   3373 	rdpr	%tl, %g1
   3374 	dec	%g1
   3375 	wrpr	%g1, %tl
   3376 	rdpr	%tt, %g2
   3377 	inc	%g1
   3378 	wrpr	%g1, %tl
   3379 
   3380 	wrpr	%g0, %g3, %tstate
   3381 	wrpr	%g0, %g4, %tt
   3382 
   3383 	andn	%g2, 0x00f, %g3
   3384 	cmp	%g3, 0x080
   3385 	be,pn	%icc, flush_normals
   3386 	 nop
   3387 	cmp	%g3, 0x0a0
   3388 	be,pn	%icc, flush_others
   3389 	 nop
   3390 	cmp	%g3, 0x0c0
   3391 	be,pn	%icc, ufill_trap
   3392 	 nop
   3393 
   3394 	Debugger()
   3395 	NOTREACHED
   3396 
   3397 flush_others:
   3398 	set	pcbspill_others, %g1
   3399 	wrpr	%g1, %tnpc
   3400 	done
   3401 	NOTREACHED
   3402 
   3403 flush_normals:
   3404 ufill_trap:
   3405 
   3406 	/*
   3407 	 * Rearrange our trap state such that it appears as if we got
   3408 	 * this trap directly from user mode.  Then process it at TL = 1.
   3409 	 * We'll take the spill/fill trap again once we return to user mode.
   3410 	 */
   3411 	rdpr	%tt, %g1
   3412 	rdpr	%tstate, %g3
   3413 	wrpr	%g0, 1, %tl
   3414 	wrpr	%g0, %g1, %tt
   3415 	rdpr	%tstate, %g2
   3416 	wrpr	%g0, 2, %tl
   3417 	and	%g2, TSTATE_CWP, %g2
   3418 	andn	%g3, TSTATE_CWP, %g3
   3419 	wrpr	%g2, %g3, %tstate
   3420 	set	sun4v_datatrap, %g4
   3421 	wrpr	%g0, %g4, %tnpc
   3422 	done
   3423 
   3424 /*
   3425  * Spill user windows into the PCB.
   3426  */
   3427 pcbspill_normals:
   3428 	ba,pt	%xcc, pcbspill
   3429 	 wrpr	0x80, %tt
   3430 
   3431 pcbspill_others:
   3432 	wrpr	0xa0, %tt
   3433 
   3434 pcbspill:
   3435 	set	CPUINFO_VA, %g6
   3436 	ldx	[%g6 + CI_CPCB], %g6
   3437 
   3438 	GET_CTXBUSY %g1
   3439 
   3440 	ldx	[%g1], %g1				! kernel pmap is ctx 0
   3441 
   3442 	srlx	%g6, STSHIFT, %g7
   3443 	and	%g7, STMASK, %g7
   3444 	sll	%g7, 3, %g7				! byte offset into ctxbusy
   3445 	add	%g7, %g1, %g1
   3446 	ldxa	[%g1] ASI_PHYS_CACHED, %g1		! Load pointer to directory
   3447 
   3448 	srlx	%g6, PDSHIFT, %g7			! Do page directory
   3449 	and	%g7, PDMASK, %g7
   3450 	sll	%g7, 3, %g7
   3451 	brz,pn	%g1, pcbspill_fail
   3452 	 add	%g7, %g1, %g1
   3453 	ldxa	[%g1] ASI_PHYS_CACHED, %g1
   3454 	srlx	%g6, PTSHIFT, %g7			! Convert to ptab offset
   3455 	and	%g7, PTMASK, %g7
   3456 	brz	%g1, pcbspill_fail
   3457 	 sll	%g7, 3, %g7
   3458 	add	%g1, %g7, %g7
   3459 	ldxa	[%g7] ASI_PHYS_CACHED, %g7		! This one is not
   3460 	brgez	%g7, pcbspill_fail
   3461 	 srlx	%g7, PGSHIFT, %g7			! Isolate PA part
   3462 	sll	%g6, 32-PGSHIFT, %g6			! And offset
   3463 	sllx	%g7, PGSHIFT+8, %g7			! There are 8 bits to the left of the PA in the TTE
   3464 	srl	%g6, 32-PGSHIFT, %g6
   3465 	srax	%g7, 8, %g7
   3466 	or	%g7, %g6, %g6				! Then combine them to form PA
   3467 
   3468 	wr	%g0, ASI_PHYS_CACHED, %asi		! Use ASI_PHYS_CACHED to prevent possible page faults
   3469 
   3470 	lduba	[%g6 + PCB_NSAVED] %asi, %g7		! Fetch current nsaved from the pcb
   3471 	sllx	%g7, 7, %g5				! 8+8 registers each 8 bytes = 128 bytes (2^7)
   3472 	add	%g6, %g5, %g5				! Offset into pcb_rw
   3473 1:
   3474 	SPILL	stxa, %g5 + PCB_RW, 8, %asi		! Store the locals and ins
   3475 
   3476 	add	%g5, 16*8, %g5				! Next location for saved register windows
   3477 
   3478 	stxa	%o6, [%g5 + PCB_RW + (14*8)] %asi	! Save %sp so we can write these all out
   3479 
   3480 	saved						! Increments %cansave and decrements %canrestore
   3481 							! or %otherwin
   3482 
   3483 	rdpr	%cwp, %g1				! shift register window forward
   3484 	inc	%g1
   3485 	wrpr	%g1, %cwp
   3486 	inc	%g7					! increment number of saved register windows
   3487 
   3488 	rdpr	%otherwin, %g1				! Check to see if done spill'ing otherwin
   3489 	brnz,pt	%g1, 1b
   3490 	 nop
   3491 
   3492 	stba	%g7, [%g6 + PCB_NSAVED] %asi
   3493 
   3494 	retry
   3495 	NOTREACHED
   3496 
   3497 pcbspill_fail:
   3498 	Debugger()
   3499 	NOTREACHED
   3500 
   3501 
   3502 pcbspill_other:
   3503 	set	CPUINFO_VA, %g6
   3504 	ldx	[%g6 + CI_CPCB], %g6
   3505 
   3506 	GET_CTXBUSY %g1
   3507 
   3508 	ldx	[%g1], %g1				! kernel pmap is ctx 0
   3509 
   3510 	srlx	%g6, STSHIFT, %g7
   3511 	and	%g7, STMASK, %g7
   3512 	sll	%g7, 3, %g7				! byte offset into ctxbusy
   3513 	add	%g7, %g1, %g1
   3514 	ldxa	[%g1] ASI_PHYS_CACHED, %g1		! Load pointer to directory
   3515 
   3516 	srlx	%g6, PDSHIFT, %g7			! Do page directory
   3517 	and	%g7, PDMASK, %g7
   3518 	sll	%g7, 3, %g7
   3519 	brz,pn	%g1, pcbspill_other_fail
   3520 	 add	%g7, %g1, %g1
   3521 	ldxa	[%g1] ASI_PHYS_CACHED, %g1
   3522 	srlx	%g6, PTSHIFT, %g7			! Convert to ptab offset
   3523 	and	%g7, PTMASK, %g7
   3524 	brz	%g1, pcbspill_other_fail
   3525 	 sll	%g7, 3, %g7
   3526 	add	%g1, %g7, %g7
   3527 	ldxa	[%g7] ASI_PHYS_CACHED, %g7		! This one is not
   3528 	brgez	%g7, pcbspill_other_fail
   3529 	 srlx	%g7, PGSHIFT, %g7			! Isolate PA part
   3530 	sll	%g6, 32-PGSHIFT, %g6			! And offset
   3531 	sllx	%g7, PGSHIFT+8, %g7			! There are 8 bits to the left of the PA in the TTE
   3532 	srl	%g6, 32-PGSHIFT, %g6
   3533 	srax	%g7, 8, %g7
   3534 	or	%g7, %g6, %g6				! Then combine them to form PA
   3535 
   3536 	wr	%g0, ASI_PHYS_CACHED, %asi		! Use ASI_PHYS_CACHED to prevent possible page faults
   3537 
   3538 	lduba	[%g6 + PCB_NSAVED] %asi, %g7		! Fetch current nsaved from the pcb
   3539 	sllx	%g7, 7, %g5				! 8+8 registers each 8 bytes = 128 bytes (2^7)
   3540 	add	%g6, %g5, %g5				! Offset into pcb_rw
   3541 1:
   3542 	SPILL	stxa, %g5 + PCB_RW, 8, %asi		! Store the locals and ins
   3543 
   3544 	add	%g5, 16*8, %g5				! Next location for saved register windows
   3545 
   3546 	stxa	%o6, [%g5 + PCB_RW + (14*8)] %asi	! Save %sp so we can write these all out
   3547 
   3548 	saved						! Increments %cansave and decrements %canrestore
   3549 							! or %otherwin
   3550 
   3551 	rdpr	%cwp, %g1				! shift register window forward
   3552 	inc	%g1
   3553 	wrpr	%g1, %cwp
   3554 
   3555 
   3556 	inc	%g7					! increment number of saved register windows
   3557 
   3558 	rdpr	%otherwin, %g1				! Check to see if done spill'ing otherwin
   3559 	brnz,pt	%g1, 1b
   3560 	 nop
   3561 
   3562 	stba	%g7, [%g6 + PCB_NSAVED] %asi
   3563 
   3564 	retry
   3565 	NOTREACHED
   3566 
   3567 pcbspill_other_fail:
   3568 	Debugger()
   3569 	NOTREACHED
   3570 
   3571 
   3572 spill_normal_to_user_stack:
   3573 	mov	%sp, %g6						! calculate virtual address of destination stack
   3574 	add	%g6, BIAS, %g6
   3575 
   3576 	mov	CTX_SECONDARY, %g2				! Is this context ok or should it be CTX_PRIMARY? XXX
   3577 	GET_MMU_CONTEXTID %g3, %g2, %g1
   3578 	sllx	%g3, 3, %g3					! Make it into an offset into ctxbusy (see below)
   3579 
   3580 	GET_CTXBUSY %g1
   3581 	ldx	[%g1 + %g3], %g1				! Fetch pmap for current context id
   3582 
   3583 	! Start of code to extract PA
   3584 	srlx	%g6, STSHIFT, %g7
   3585 	and	%g7, STMASK, %g7
   3586 	sll	%g7, 3, %g7						! byte offset into ctxbusy
   3587 	add	%g7, %g1, %g1
   3588 	ldxa	[%g1] ASI_PHYS_CACHED, %g1	! Load pointer to directory
   3589 	srlx	%g6, PDSHIFT, %g7			! Do page directory
   3590 	and	%g7, PDMASK, %g7
   3591 	sll	%g7, 3, %g7
   3592 	brz,pn	%g1, spill_normal_to_user_stack_fail
   3593 	 add	%g7, %g1, %g1
   3594 
   3595 	ldxa	[%g1] ASI_PHYS_CACHED, %g1
   3596 	srlx	%g6, PTSHIFT, %g7			! Convert to ptab offset
   3597 	and	%g7, PTMASK, %g7
   3598 	brz	%g1, spill_normal_to_user_stack_fail
   3599 	 sll	%g7, 3, %g7
   3600 
   3601 	add	%g1, %g7, %g7
   3602 	ldxa	[%g7] ASI_PHYS_CACHED, %g7	! This one is not
   3603 	brgez	%g7, spill_normal_to_user_stack_fail
   3604 	 srlx	%g7, PGSHIFT, %g7			! Isolate PA part
   3605 
   3606 	sll	%g6, 32-PGSHIFT, %g6			! And offset
   3607 	sllx	%g7, PGSHIFT+8, %g7			! There are 8 bits to the left of the PA in the TTE
   3608 	srl	%g6, 32-PGSHIFT, %g6
   3609 	srax	%g7, 8, %g7
   3610 	or	%g7, %g6, %g6					! Then combine them to form PA
   3611 	! End of code to extract PA
   3612 
   3613 	wr	%g0, ASI_PHYS_CACHED, %asi		! Use ASI_PHYS_CACHED to prevent possible page faults
   3614 	SPILL	stxa, %g6, 8, %asi			! Store the locals and ins
   3615 	saved
   3616 
   3617 	retry
   3618 	NOTREACHED
   3619 
   3620 spill_normal_to_user_stack_fail:
   3621 	sir
   3622 	 nop
   3623 
   3624 /*
   3625  * End of traps for sun4v.
   3626  */
   3627 
   3628 #endif
   3629 
   3630 /*
   3631  * We're here because we took an alignment fault in NUCLEUS context.
   3632  * This could be a kernel bug or it could be due to saving a user
   3633  * window to an invalid stack pointer.
   3634  *
   3635  * If the latter is the case, we could try to emulate unaligned accesses,
   3636  * but we really don't know where to store the registers since we can't
   3637  * determine if there's a stack bias.  Or we could store all the regs
   3638  * into the PCB and punt, until the user program uses up all the CPU's
   3639  * register windows and we run out of places to store them.  So for
   3640  * simplicity we'll just blow them away and enter the trap code which
   3641  * will generate a bus error.  Debugging the problem will be a bit
   3642  * complicated since lots of register windows will be lost, but what
   3643  * can we do?
   3644  */
   3645 checkalign:
   3646 	rdpr	%tl, %g2
   3647 	subcc	%g2, 1, %g1
   3648 	bneg,pn	%icc, slowtrap		! Huh?
   3649 	 sethi	%hi(CPCB), %g6		! get current pcb
   3650 
   3651 	wrpr	%g1, 0, %tl
   3652 	rdpr	%tt, %g7
   3653 	rdpr	%tstate, %g4
   3654 	andn	%g7, 0x3f, %g5
   3655 	cmp	%g5, 0x080		!   window spill traps are all 0b 0000 10xx xxxx
   3656 	bne,a,pn	%icc, slowtrap
   3657 	 wrpr	%g1, 0, %tl		! Revert TL  XXX wrpr in a delay slot...
   3658 
   3659 #ifdef DEBUG
   3660 	cmp	%g7, 0x34		! If we took a datafault just before this trap
   3661 	bne,pt	%icc, checkalignspill	! our stack's probably bad so we need to switch somewhere else
   3662 	 nop
   3663 
   3664 	!!
   3665 	!! Double data fault -- bad stack?
   3666 	!!
   3667 	wrpr	%g2, %tl		! Restore trap level.
   3668 	sir				! Just issue a reset and don't try to recover.
   3669 	mov	%fp, %l6		! Save the frame pointer
   3670 	set	EINTSTACK+USPACE+CC64FSZ-STKB, %fp ! Set the frame pointer to the middle of the idle stack
   3671 	add	%fp, -CC64FSZ, %sp	! Create a stackframe
   3672 	wrpr	%g0, 15, %pil		! Disable interrupts, too
   3673 	wrpr	%g0, %g0, %canrestore	! Our stack is hozed and our PCB
   3674 	wrpr	%g0, 7, %cansave	!  probably is too, so blow away
   3675 	ba	slowtrap		!  all our register windows.
   3676 	 wrpr	%g0, 0x101, %tt
   3677 #endif
   3678 checkalignspill:
   3679 	/*
   3680          * %g1 -- current tl
   3681 	 * %g2 -- original tl
   3682 	 * %g4 -- tstate
   3683          * %g7 -- tt
   3684 	 */
   3685 
   3686 	and	%g4, CWP, %g5
   3687 	wrpr	%g5, %cwp		! Go back to the original register win
   3688 
   3689 	/*
   3690 	 * Remember:
   3691 	 *
   3692 	 * %otherwin = 0
   3693 	 * %cansave = NWINDOWS - 2 - %canrestore
   3694 	 */
   3695 
   3696 	rdpr	%otherwin, %g6
   3697 	rdpr	%canrestore, %g3
   3698 	rdpr	%ver, %g5
   3699 	sub	%g3, %g6, %g3		! Calculate %canrestore - %g7
   3700 	and	%g5, CWP, %g5		! NWINDOWS-1
   3701 	movrlz	%g3, %g0, %g3		! Clamp at zero
   3702 	wrpr	%g0, 0, %otherwin
   3703 	wrpr	%g3, 0, %canrestore	! This is the new canrestore
   3704 	dec	%g5			! NWINDOWS-2
   3705 	wrpr	%g5, 0, %cleanwin	! Set cleanwin to max, since we're in-kernel
   3706 	sub	%g5, %g3, %g5		! NWINDOWS-2-%canrestore
   3707 	wrpr	%g5, 0, %cansave
   3708 
   3709 	wrpr	%g0, T_ALIGN, %tt	! This was an alignment fault
   3710 	/*
   3711 	 * Now we need to determine if this was a userland store or not.
   3712 	 * Userland stores occur in anything other than the kernel spill
   3713 	 * handlers (trap type 09x).
   3714 	 */
   3715 	and	%g7, 0xff0, %g5
   3716 	cmp	%g5, 0x90
   3717 	bz,pn	%icc, slowtrap
   3718 	 nop
   3719 	bclr	TSTATE_PRIV, %g4
   3720 	wrpr	%g4, 0, %tstate
   3721 	ba,a,pt	%icc, slowtrap
   3722 	 nop
   3723 
   3724 /*
   3725  * slowtrap() builds a trap frame and calls trap().
   3726  * This is called `slowtrap' because it *is*....
   3727  * We have to build a full frame for ptrace(), for instance.
   3728  *
   3729  * Registers:
   3730  *
   3731  */
   3732 slowtrap:
   3733 #ifdef TRAPS_USE_IG
   3734 	wrpr	%g0, PSTATE_KERN|PSTATE_IG, %pstate	! DEBUG
   3735 #endif
   3736 #ifdef DIAGNOSTIC
   3737 	/* Make sure kernel stack is aligned */
   3738 	btst	0x03, %sp		! 32-bit stack OK?
   3739 	 and	%sp, 0x07, %g4		! 64-bit stack OK?
   3740 	bz,pt	%icc, 1f
   3741 	cmp	%g4, 0x1		! Must end in 0b001
   3742 	be,pt	%icc, 1f
   3743 	 rdpr	%wstate, %g7
   3744 	cmp	%g7, WSTATE_KERN
   3745 	bnz,pt	%icc, 1f		! User stack -- we'll blow it away
   3746 	 nop
   3747 	set	PANICSTACK-CC64FSZ-STKB, %sp
   3748 1:
   3749 #endif
   3750 	rdpr	%tt, %g4
   3751 	rdpr	%tstate, %g1
   3752 	rdpr	%tpc, %g2
   3753 	rdpr	%tnpc, %g3
   3754 
   3755 	TRAP_SETUP(-CC64FSZ-TF_SIZE)
   3756 Lslowtrap_reenter:
   3757 	stx	%g1, [%sp + CC64FSZ + STKB + TF_TSTATE]
   3758 	mov	%g4, %o1		! (type)
   3759 	stx	%g2, [%sp + CC64FSZ + STKB + TF_PC]
   3760 	rd	%y, %g5
   3761 	stx	%g3, [%sp + CC64FSZ + STKB + TF_NPC]
   3762 	mov	%g1, %o3		! (pstate)
   3763 	st	%g5, [%sp + CC64FSZ + STKB + TF_Y]
   3764 	mov	%g2, %o2		! (pc)
   3765 	sth	%o1, [%sp + CC64FSZ + STKB + TF_TT]! debug
   3766 
   3767 	! Get back to normal globals
   3768 #ifdef SUN4V
   3769 	sethi	%hi(cputyp), %g5
   3770 	ld	[%g5 + %lo(cputyp)], %g5
   3771 	cmp	%g5, CPU_SUN4V
   3772 	bne,pt	%icc, 1f
   3773 	 nop
   3774 	NORMAL_GLOBALS_SUN4V
   3775 	ba	2f
   3776 	 nop
   3777 1:
   3778 #endif
   3779 	NORMAL_GLOBALS_SUN4U
   3780 2:
   3781 	stx	%g1, [%sp + CC64FSZ + STKB + TF_G + (1*8)]
   3782 	stx	%g2, [%sp + CC64FSZ + STKB + TF_G + (2*8)]
   3783 	add	%sp, CC64FSZ + STKB, %o0		! (&tf)
   3784 	stx	%g3, [%sp + CC64FSZ + STKB + TF_G + (3*8)]
   3785 	stx	%g4, [%sp + CC64FSZ + STKB + TF_G + (4*8)]
   3786 	stx	%g5, [%sp + CC64FSZ + STKB + TF_G + (5*8)]
   3787 	rdpr	%pil, %g5
   3788 	stx	%g6, [%sp + CC64FSZ + STKB + TF_G + (6*8)]
   3789 	stx	%g7, [%sp + CC64FSZ + STKB + TF_G + (7*8)]
   3790 	stb	%g5, [%sp + CC64FSZ + STKB + TF_PIL]
   3791 	stb	%g5, [%sp + CC64FSZ + STKB + TF_OLDPIL]
   3792 	/*
   3793 	 * Phew, ready to enable traps and call C code.
   3794 	 */
   3795 	rdpr	%tl, %g1
   3796 	dec	%g1
   3797 	movrlz	%g1, %g0, %g1
   3798 	wrpr	%g0, %g1, %tl		! Revert to kernel mode
   3799 	!! In the EMBEDANY memory model %g4 points to the start of the data segment.
   3800 	!! In our case we need to clear it before calling any C-code
   3801 	clr	%g4
   3802 
   3803 	wr	%g0, ASI_PRIMARY_NOFAULT, %asi		! Restore default ASI
   3804 	wrpr	%g0, PSTATE_INTR, %pstate	! traps on again
   3805 	call	_C_LABEL(trap)			! trap(tf, type, pc, pstate)
   3806 	 nop
   3807 
   3808 	b	return_from_trap
   3809 	 ldx	[%sp + CC64FSZ + STKB + TF_TSTATE], %g1	! Load this for return_from_trap
   3810 	NOTREACHED
   3811 #if 1
   3812 /*
   3813  * This code is no longer needed.
   3814  */
   3815 /*
   3816  * Do a `software' trap by re-entering the trap code, possibly first
   3817  * switching from interrupt stack to kernel stack.  This is used for
   3818  * scheduling and signal ASTs (which generally occur from softclock or
   3819  * tty or net interrupts).
   3820  *
   3821  * We enter with the trap type in %g1.  All we have to do is jump to
   3822  * Lslowtrap_reenter above, but maybe after switching stacks....
   3823  *
   3824  * We should be running alternate globals.  The normal globals and
   3825  * out registers were just loaded from the old trap frame.
   3826  *
   3827  *	Input Params:
   3828  *	%g1 = tstate
   3829  *	%g2 = tpc
   3830  *	%g3 = tnpc
   3831  *	%g4 = tt == T_AST
   3832  */
   3833 softtrap:
   3834 	sethi	%hi(EINTSTACK-STKB), %g5
   3835 	sethi	%hi(EINTSTACK-INTSTACK), %g7
   3836 	or	%g5, %lo(EINTSTACK-STKB), %g5
   3837 	dec	%g7
   3838 	sub	%g5, %sp, %g5
   3839 	sethi	%hi(CPCB), %g6
   3840 	andncc	%g5, %g7, %g0
   3841 	bnz,pt	%xcc, Lslowtrap_reenter
   3842 	 LDPTR	[%g6 + %lo(CPCB)], %g7
   3843 	set	USPACE-CC64FSZ-TF_SIZE-STKB, %g5
   3844 	add	%g7, %g5, %g6
   3845 	SET_SP_REDZONE(%g7, %g5)
   3846 #ifdef DEBUG
   3847 	stx	%g1, [%g6 + CC64FSZ + STKB + TF_FAULT]		! Generate a new trapframe
   3848 #endif
   3849 	stx	%i0, [%g6 + CC64FSZ + STKB + TF_O + (0*8)]	!	but don't bother with
   3850 	stx	%i1, [%g6 + CC64FSZ + STKB + TF_O + (1*8)]	!	locals and ins
   3851 	stx	%i2, [%g6 + CC64FSZ + STKB + TF_O + (2*8)]
   3852 	stx	%i3, [%g6 + CC64FSZ + STKB + TF_O + (3*8)]
   3853 	stx	%i4, [%g6 + CC64FSZ + STKB + TF_O + (4*8)]
   3854 	stx	%i5, [%g6 + CC64FSZ + STKB + TF_O + (5*8)]
   3855 	stx	%i6, [%g6 + CC64FSZ + STKB + TF_O + (6*8)]
   3856 	stx	%i7, [%g6 + CC64FSZ + STKB + TF_O + (7*8)]
   3857 #ifdef DEBUG
   3858 	ldx	[%sp + CC64FSZ + STKB + TF_I + (0*8)], %l0	! Copy over the rest of the regs
   3859 	ldx	[%sp + CC64FSZ + STKB + TF_I + (1*8)], %l1	! But just dirty the locals
   3860 	ldx	[%sp + CC64FSZ + STKB + TF_I + (2*8)], %l2
   3861 	ldx	[%sp + CC64FSZ + STKB + TF_I + (3*8)], %l3
   3862 	ldx	[%sp + CC64FSZ + STKB + TF_I + (4*8)], %l4
   3863 	ldx	[%sp + CC64FSZ + STKB + TF_I + (5*8)], %l5
   3864 	ldx	[%sp + CC64FSZ + STKB + TF_I + (6*8)], %l6
   3865 	ldx	[%sp + CC64FSZ + STKB + TF_I + (7*8)], %l7
   3866 	stx	%l0, [%g6 + CC64FSZ + STKB + TF_I + (0*8)]
   3867 	stx	%l1, [%g6 + CC64FSZ + STKB + TF_I + (1*8)]
   3868 	stx	%l2, [%g6 + CC64FSZ + STKB + TF_I + (2*8)]
   3869 	stx	%l3, [%g6 + CC64FSZ + STKB + TF_I + (3*8)]
   3870 	stx	%l4, [%g6 + CC64FSZ + STKB + TF_I + (4*8)]
   3871 	stx	%l5, [%g6 + CC64FSZ + STKB + TF_I + (5*8)]
   3872 	stx	%l6, [%g6 + CC64FSZ + STKB + TF_I + (6*8)]
   3873 	stx	%l7, [%g6 + CC64FSZ + STKB + TF_I + (7*8)]
   3874 	ldx	[%sp + CC64FSZ + STKB + TF_L + (0*8)], %l0
   3875 	ldx	[%sp + CC64FSZ + STKB + TF_L + (1*8)], %l1
   3876 	ldx	[%sp + CC64FSZ + STKB + TF_L + (2*8)], %l2
   3877 	ldx	[%sp + CC64FSZ + STKB + TF_L + (3*8)], %l3
   3878 	ldx	[%sp + CC64FSZ + STKB + TF_L + (4*8)], %l4
   3879 	ldx	[%sp + CC64FSZ + STKB + TF_L + (5*8)], %l5
   3880 	ldx	[%sp + CC64FSZ + STKB + TF_L + (6*8)], %l6
   3881 	ldx	[%sp + CC64FSZ + STKB + TF_L + (7*8)], %l7
   3882 	stx	%l0, [%g6 + CC64FSZ + STKB + TF_L + (0*8)]
   3883 	stx	%l1, [%g6 + CC64FSZ + STKB + TF_L + (1*8)]
   3884 	stx	%l2, [%g6 + CC64FSZ + STKB + TF_L + (2*8)]
   3885 	stx	%l3, [%g6 + CC64FSZ + STKB + TF_L + (3*8)]
   3886 	stx	%l4, [%g6 + CC64FSZ + STKB + TF_L + (4*8)]
   3887 	stx	%l5, [%g6 + CC64FSZ + STKB + TF_L + (5*8)]
   3888 	stx	%l6, [%g6 + CC64FSZ + STKB + TF_L + (6*8)]
   3889 	stx	%l7, [%g6 + CC64FSZ + STKB + TF_L + (7*8)]
   3890 #endif
   3891 	ba,pt	%xcc, Lslowtrap_reenter
   3892 	 mov	%g6, %sp
   3893 #endif
   3894 
   3895 #if 0
   3896 /*
   3897  * breakpoint:	capture as much info as possible and then call DDB
   3898  * or trap, as the case may be.
   3899  *
   3900  * First, we switch to interrupt globals, and blow away %g7.  Then
   3901  * switch down one stackframe -- just fiddle w/cwp, don't save or
   3902  * we'll trap.  Then slowly save all the globals into our static
   3903  * register buffer.  etc. etc.
   3904  */
   3905 
   3906 breakpoint:
   3907 	wrpr	%g0, PSTATE_KERN|PSTATE_IG, %pstate	! Get IG to use
   3908 	rdpr	%cwp, %g7
   3909 	inc	1, %g7					! Equivalent of save
   3910 	wrpr	%g7, 0, %cwp				! Now we have some unused locals to fiddle with
   3911 XXX ddb_regs is now ddb-regp and is a pointer not a symbol.
   3912 	set	_C_LABEL(ddb_regs), %l0
   3913 	stx	%g1, [%l0+DBR_IG+(1*8)]			! Save IGs
   3914 	stx	%g2, [%l0+DBR_IG+(2*8)]
   3915 	stx	%g3, [%l0+DBR_IG+(3*8)]
   3916 	stx	%g4, [%l0+DBR_IG+(4*8)]
   3917 	stx	%g5, [%l0+DBR_IG+(5*8)]
   3918 	stx	%g6, [%l0+DBR_IG+(6*8)]
   3919 	stx	%g7, [%l0+DBR_IG+(7*8)]
   3920 	wrpr	%g0, PSTATE_KERN|PSTATE_MG, %pstate	! Get MG to use
   3921 	stx	%g1, [%l0+DBR_MG+(1*8)]			! Save MGs
   3922 	stx	%g2, [%l0+DBR_MG+(2*8)]
   3923 	stx	%g3, [%l0+DBR_MG+(3*8)]
   3924 	stx	%g4, [%l0+DBR_MG+(4*8)]
   3925 	stx	%g5, [%l0+DBR_MG+(5*8)]
   3926 	stx	%g6, [%l0+DBR_MG+(6*8)]
   3927 	stx	%g7, [%l0+DBR_MG+(7*8)]
   3928 	wrpr	%g0, PSTATE_KERN|PSTATE_AG, %pstate	! Get AG to use
   3929 	stx	%g1, [%l0+DBR_AG+(1*8)]			! Save AGs
   3930 	stx	%g2, [%l0+DBR_AG+(2*8)]
   3931 	stx	%g3, [%l0+DBR_AG+(3*8)]
   3932 	stx	%g4, [%l0+DBR_AG+(4*8)]
   3933 	stx	%g5, [%l0+DBR_AG+(5*8)]
   3934 	stx	%g6, [%l0+DBR_AG+(6*8)]
   3935 	stx	%g7, [%l0+DBR_AG+(7*8)]
   3936 	wrpr	%g0, PSTATE_KERN, %pstate	! Get G to use
   3937 	stx	%g1, [%l0+DBR_G+(1*8)]			! Save Gs
   3938 	stx	%g2, [%l0+DBR_G+(2*8)]
   3939 	stx	%g3, [%l0+DBR_G+(3*8)]
   3940 	stx	%g4, [%l0+DBR_G+(4*8)]
   3941 	stx	%g5, [%l0+DBR_G+(5*8)]
   3942 	stx	%g6, [%l0+DBR_G+(6*8)]
   3943 	stx	%g7, [%l0+DBR_G+(7*8)]
   3944 	rdpr	%canrestore, %l1
   3945 	stb	%l1, [%l0+DBR_CANRESTORE]
   3946 	rdpr	%cansave, %l2
   3947 	stb	%l2, [%l0+DBR_CANSAVE]
   3948 	rdpr	%cleanwin, %l3
   3949 	stb	%l3, [%l0+DBR_CLEANWIN]
   3950 	rdpr	%wstate, %l4
   3951 	stb	%l4, [%l0+DBR_WSTATE]
   3952 	rd	%y, %l5
   3953 	stw	%l5, [%l0+DBR_Y]
   3954 	rdpr	%tl, %l6
   3955 	stb	%l6, [%l0+DBR_TL]
   3956 	dec	1, %g7
   3957 #endif
   3958 
   3959 /*
   3960  * I will not touch any of the DDB or KGDB stuff until I know what's going
   3961  * on with the symbol table.  This is all still v7/v8 code and needs to be fixed.
   3962  */
   3963 #ifdef KGDB
   3964 /*
   3965  * bpt is entered on all breakpoint traps.
   3966  * If this is a kernel breakpoint, we do not want to call trap().
   3967  * Among other reasons, this way we can set breakpoints in trap().
   3968  */
   3969 bpt:
   3970 	set	TSTATE_PRIV, %l4
   3971 	andcc	%l4, %l0, %g0		! breakpoint from kernel?
   3972 	bz	slowtrap		! no, go do regular trap
   3973 	 nop
   3974 
   3975 	/*
   3976 	 * Build a trap frame for kgdb_trap_glue to copy.
   3977 	 * Enable traps but set ipl high so that we will not
   3978 	 * see interrupts from within breakpoints.
   3979 	 */
   3980 	save	%sp, -CCFSZ-TF_SIZE, %sp		! allocate a trap frame
   3981 	TRAP_SETUP(-CCFSZ-TF_SIZE)
   3982 	or	%l0, PSR_PIL, %l4	! splhigh()
   3983 	wr	%l4, 0, %psr		! the manual claims that this
   3984 	wr	%l4, PSR_ET, %psr	! song and dance is necessary
   3985 	std	%l0, [%sp + CCFSZ + 0]	! tf.tf_psr, tf.tf_pc
   3986 	mov	%l3, %o0		! trap type arg for kgdb_trap_glue
   3987 	rd	%y, %l3
   3988 	std	%l2, [%sp + CCFSZ + 8]	! tf.tf_npc, tf.tf_y
   3989 	rd	%wim, %l3
   3990 	st	%l3, [%sp + CCFSZ + 16]	! tf.tf_wim (a kgdb-only r/o field)
   3991 	st	%g1, [%sp + CCFSZ + 20]	! tf.tf_global[1]
   3992 	std	%g2, [%sp + CCFSZ + 24]	! etc
   3993 	std	%g4, [%sp + CCFSZ + 32]
   3994 	std	%g6, [%sp + CCFSZ + 40]
   3995 	std	%i0, [%sp + CCFSZ + 48]	! tf.tf_in[0..1]
   3996 	std	%i2, [%sp + CCFSZ + 56]	! etc
   3997 	std	%i4, [%sp + CCFSZ + 64]
   3998 	std	%i6, [%sp + CCFSZ + 72]
   3999 
   4000 	/*
   4001 	 * Now call kgdb_trap_glue(); if it returns, call trap().
   4002 	 */
   4003 	mov	%o0, %l3		! gotta save trap type
   4004 	call	_C_LABEL(kgdb_trap_glue)		! kgdb_trap_glue(type, &trapframe)
   4005 	 add	%sp, CCFSZ, %o1		! (&trapframe)
   4006 
   4007 	/*
   4008 	 * Use slowtrap to call trap---but first erase our tracks
   4009 	 * (put the registers back the way they were).
   4010 	 */
   4011 	mov	%l3, %o0		! slowtrap will need trap type
   4012 	ld	[%sp + CCFSZ + 12], %l3
   4013 	wr	%l3, 0, %y
   4014 	ld	[%sp + CCFSZ + 20], %g1
   4015 	ldd	[%sp + CCFSZ + 24], %g2
   4016 	ldd	[%sp + CCFSZ + 32], %g4
   4017 	b	Lslowtrap_reenter
   4018 	 ldd	[%sp + CCFSZ + 40], %g6
   4019 
   4020 /*
   4021  * Enter kernel breakpoint.  Write all the windows (not including the
   4022  * current window) into the stack, so that backtrace works.  Copy the
   4023  * supplied trap frame to the kgdb stack and switch stacks.
   4024  *
   4025  * kgdb_trap_glue(type, tf0)
   4026  *	int type;
   4027  *	struct trapframe *tf0;
   4028  */
   4029 ENTRY_NOPROFILE(kgdb_trap_glue)
   4030 	save	%sp, -CCFSZ, %sp
   4031 
   4032 	flushw				! flush all windows
   4033 	mov	%sp, %l4		! %l4 = current %sp
   4034 
   4035 	/* copy trapframe to top of kgdb stack */
   4036 	set	_C_LABEL(kgdb_stack) + KGDB_STACK_SIZE - 80, %l0
   4037 					! %l0 = tfcopy -> end_of_kgdb_stack
   4038 	mov	80, %l1
   4039 1:	ldd	[%i1], %l2
   4040 	inc	8, %i1
   4041 	deccc	8, %l1
   4042 	std	%l2, [%l0]
   4043 	bg	1b
   4044 	 inc	8, %l0
   4045 
   4046 #ifdef NOTDEF_DEBUG
   4047 	/* save old red zone and then turn it off */
   4048 	sethi	%hi(_C_LABEL(redzone)), %l7
   4049 	ld	[%l7 + %lo(_C_LABEL(redzone))], %l6
   4050 	st	%g0, [%l7 + %lo(_C_LABEL(redzone))]
   4051 #endif
   4052 	/* switch to kgdb stack */
   4053 	add	%l0, -CCFSZ-TF_SIZE, %sp
   4054 
   4055 	/* if (kgdb_trap(type, tfcopy)) kgdb_rett(tfcopy); */
   4056 	mov	%i0, %o0
   4057 	call	_C_LABEL(kgdb_trap)
   4058 	add	%l0, -80, %o1
   4059 	tst	%o0
   4060 	bnz,a	kgdb_rett
   4061 	 add	%l0, -80, %g1
   4062 
   4063 	/*
   4064 	 * kgdb_trap() did not handle the trap at all so the stack is
   4065 	 * still intact.  A simple `restore' will put everything back,
   4066 	 * after we reset the stack pointer.
   4067 	 */
   4068 	mov	%l4, %sp
   4069 #ifdef NOTDEF_DEBUG
   4070 	st	%l6, [%l7 + %lo(_C_LABEL(redzone))]	! restore red zone
   4071 #endif
   4072 	ret
   4073 	 restore
   4074 
   4075 /*
   4076  * Return from kgdb trap.  This is sort of special.
   4077  *
   4078  * We know that kgdb_trap_glue wrote the window above it, so that we will
   4079  * be able to (and are sure to have to) load it up.  We also know that we
   4080  * came from kernel land and can assume that the %fp (%i6) we load here
   4081  * is proper.  We must also be sure not to lower ipl (it is at splhigh())
   4082  * until we have traps disabled, due to the SPARC taking traps at the
   4083  * new ipl before noticing that PSR_ET has been turned off.  We are on
   4084  * the kgdb stack, so this could be disastrous.
   4085  *
   4086  * Note that the trapframe argument in %g1 points into the current stack
   4087  * frame (current window).  We abandon this window when we move %g1->tf_psr
   4088  * into %psr, but we will not have loaded the new %sp yet, so again traps
   4089  * must be disabled.
   4090  */
   4091 kgdb_rett:
   4092 	rd	%psr, %g4		! turn off traps
   4093 	wr	%g4, PSR_ET, %psr
   4094 	/* use the three-instruction delay to do something useful */
   4095 	ld	[%g1], %g2		! pick up new %psr
   4096 	ld	[%g1 + 12], %g3		! set %y
   4097 	wr	%g3, 0, %y
   4098 #ifdef NOTDEF_DEBUG
   4099 	st	%l6, [%l7 + %lo(_C_LABEL(redzone))] ! and restore red zone
   4100 #endif
   4101 	wr	%g0, 0, %wim		! enable window changes
   4102 	nop; nop; nop
   4103 	/* now safe to set the new psr (changes CWP, leaves traps disabled) */
   4104 	wr	%g2, 0, %psr		! set rett psr (including cond codes)
   4105 	/* 3 instruction delay before we can use the new window */
   4106 /*1*/	ldd	[%g1 + 24], %g2		! set new %g2, %g3
   4107 /*2*/	ldd	[%g1 + 32], %g4		! set new %g4, %g5
   4108 /*3*/	ldd	[%g1 + 40], %g6		! set new %g6, %g7
   4109 
   4110 	/* now we can use the new window */
   4111 	mov	%g1, %l4
   4112 	ld	[%l4 + 4], %l1		! get new pc
   4113 	ld	[%l4 + 8], %l2		! get new npc
   4114 	ld	[%l4 + 20], %g1		! set new %g1
   4115 
   4116 	/* set up returnee's out registers, including its %sp */
   4117 	ldd	[%l4 + 48], %i0
   4118 	ldd	[%l4 + 56], %i2
   4119 	ldd	[%l4 + 64], %i4
   4120 	ldd	[%l4 + 72], %i6
   4121 
   4122 	/* load returnee's window, making the window above it be invalid */
   4123 	restore
   4124 	restore	%g0, 1, %l1		! move to inval window and set %l1 = 1
   4125 	rd	%psr, %l0
   4126 	srl	%l1, %l0, %l1
   4127 	wr	%l1, 0, %wim		! %wim = 1 << (%psr & 31)
   4128 	sethi	%hi(CPCB), %l1
   4129 	LDPTR	[%l1 + %lo(CPCB)], %l1
   4130 	and	%l0, 31, %l0		! CWP = %psr & 31;
   4131 !	st	%l0, [%l1 + PCB_WIM]	! cpcb->pcb_wim = CWP;
   4132 	save	%g0, %g0, %g0		! back to window to reload
   4133 !	LOADWIN(%sp)
   4134 	save	%g0, %g0, %g0		! back to trap window
   4135 	/* note, we have not altered condition codes; safe to just rett */
   4136 	RETT
   4137 #endif
   4138 
   4139 /*
   4140  * syscall_setup() builds a trap frame and calls syscall().
   4141  * sun_syscall is same but delivers sun system call number
   4142  * XXX	should not have to save&reload ALL the registers just for
   4143  *	ptrace...
   4144  */
   4145 syscall_setup:
   4146 #ifdef TRAPS_USE_IG
   4147 	wrpr	%g0, PSTATE_KERN|PSTATE_IG, %pstate	! DEBUG
   4148 #endif
   4149 	TRAP_SETUP(-CC64FSZ-TF_SIZE)
   4150 
   4151 #ifdef DEBUG
   4152 	rdpr	%tt, %o1	! debug
   4153 	sth	%o1, [%sp + CC64FSZ + STKB + TF_TT]! debug
   4154 #endif
   4155 
   4156 	! Get back to normal globals
   4157 #ifdef SUN4V
   4158 	sethi	%hi(cputyp), %g5
   4159 	ld	[%g5 + %lo(cputyp)], %g5
   4160 	cmp	%g5, CPU_SUN4V
   4161 	bne,pt	%icc, 1f
   4162 	 nop
   4163 	NORMAL_GLOBALS_SUN4V
   4164 	ba	2f
   4165 	 nop
   4166 1:
   4167 #endif
   4168 	NORMAL_GLOBALS_SUN4U
   4169 2:
   4170 
   4171 	stx	%g1, [%sp + CC64FSZ + STKB + TF_G + ( 1*8)]
   4172 	mov	%g1, %o1			! code
   4173 	rdpr	%tpc, %o2			! (pc)
   4174 	stx	%g2, [%sp + CC64FSZ + STKB + TF_G + ( 2*8)]
   4175 	rdpr	%tstate, %g1
   4176 	stx	%g3, [%sp + CC64FSZ + STKB + TF_G + ( 3*8)]
   4177 	rdpr	%tnpc, %o3
   4178 	stx	%g4, [%sp + CC64FSZ + STKB + TF_G + ( 4*8)]
   4179 	rd	%y, %o4
   4180 	stx	%g5, [%sp + CC64FSZ + STKB + TF_G + ( 5*8)]
   4181 	stx	%g6, [%sp + CC64FSZ + STKB + TF_G + ( 6*8)]
   4182 	wrpr	%g0, 0, %tl			! return to tl=0
   4183 	stx	%g7, [%sp + CC64FSZ + STKB + TF_G + ( 7*8)]
   4184 	add	%sp, CC64FSZ + STKB, %o0	! (&tf)
   4185 
   4186 	stx	%g1, [%sp + CC64FSZ + STKB + TF_TSTATE]
   4187 	stx	%o2, [%sp + CC64FSZ + STKB + TF_PC]
   4188 	stx	%o3, [%sp + CC64FSZ + STKB + TF_NPC]
   4189 	st	%o4, [%sp + CC64FSZ + STKB + TF_Y]
   4190 
   4191 	rdpr	%pil, %g5
   4192 	stb	%g5, [%sp + CC64FSZ + STKB + TF_PIL]
   4193 	stb	%g5, [%sp + CC64FSZ + STKB + TF_OLDPIL]
   4194 
   4195 	!! In the EMBEDANY memory model %g4 points to the start of the data segment.
   4196 	!! In our case we need to clear it before calling any C-code
   4197 	clr	%g4
   4198 	wr	%g0, ASI_PRIMARY_NOFAULT, %asi	! Restore default ASI
   4199 
   4200 	sethi	%hi(CURLWP), %l1
   4201 	LDPTR	[%l1 + %lo(CURLWP)], %l1
   4202 	LDPTR	[%l1 + L_PROC], %l1		! now %l1 points to p
   4203 	LDPTR	[%l1 + P_MD_SYSCALL], %l1
   4204 	call	%l1
   4205 	 wrpr	%g0, PSTATE_INTR, %pstate	! turn on interrupts
   4206 
   4207 	/* see `lwp_trampoline' for the reason for this label */
   4208 return_from_syscall:
   4209 	wrpr	%g0, PSTATE_KERN, %pstate	! Disable interrupts
   4210 	wrpr	%g0, 0, %tl			! Return to tl==0
   4211 	b	return_from_trap
   4212 	 nop
   4213 	NOTREACHED
   4214 
   4215 /*
   4216  * interrupt_vector:
   4217  *
   4218  * Spitfire chips never get level interrupts directly from H/W.
   4219  * Instead, all interrupts come in as interrupt_vector traps.
   4220  * The interrupt number or handler address is an 11 bit number
   4221  * encoded in the first interrupt data word.  Additional words
   4222  * are application specific and used primarily for cross-calls.
   4223  *
   4224  * The interrupt vector handler then needs to identify the
   4225  * interrupt source from the interrupt number and arrange to
   4226  * invoke the interrupt handler.  This can either be done directly
   4227  * from here, or a softint at a particular level can be issued.
   4228  *
   4229  * To call an interrupt directly and not overflow the trap stack,
   4230  * the trap registers should be saved on the stack, registers
   4231  * cleaned, trap-level decremented, the handler called, and then
   4232  * the process must be reversed.
   4233  *
   4234  * To simplify life all we do here is issue an appropriate softint.
   4235  *
   4236  * Note:	It is impossible to identify or change a device's
   4237  *		interrupt number until it is probed.  That's the
   4238  *		purpose for all the funny interrupt acknowledge
   4239  *		code.
   4240  *
   4241  */
   4242 
   4243 /*
   4244  * Vectored interrupts:
   4245  *
   4246  * When an interrupt comes in, interrupt_vector uses the interrupt
   4247  * vector number to lookup the appropriate intrhand from the intrlev
   4248  * array.  It then looks up the interrupt level from the intrhand
   4249  * structure.  It uses the level to index the intrpending array,
   4250  * which is 8 slots for each possible interrupt level (so we can
   4251  * shift instead of multiply for address calculation).  It hunts for
   4252  * any available slot at that level.  Available slots are NULL.
   4253  *
   4254  * Then interrupt_vector uses the interrupt level in the intrhand
   4255  * to issue a softint of the appropriate level.  The softint handler
   4256  * figures out what level interrupt it's handling and pulls the first
   4257  * intrhand pointer out of the intrpending array for that interrupt
   4258  * level, puts a NULL in its place, clears the interrupt generator,
   4259  * and invokes the interrupt handler.
   4260  */
   4261 
   4262 /* intrpending array is now in per-CPU structure. */
   4263 
   4264 #ifdef DEBUG
   4265 #define INTRDEBUG_VECTOR	0x1
   4266 #define INTRDEBUG_LEVEL		0x2
   4267 #define INTRDEBUG_FUNC		0x4
   4268 #define INTRDEBUG_SPUR		0x8
   4269 	.data
   4270 	.globl	_C_LABEL(intrdebug)
   4271 _C_LABEL(intrdebug):	.word 0x0
   4272 /*
   4273  * Note: we use the local label `97' to branch forward to, to skip
   4274  * actual debugging code following a `intrdebug' bit test.
   4275  */
   4276 #endif
   4277 	.text
   4278 interrupt_vector:
   4279 #ifdef TRAPSTATS
   4280 	set	_C_LABEL(kiveccnt), %g1
   4281 	set	_C_LABEL(iveccnt), %g2
   4282 	rdpr	%tl, %g3
   4283 	dec	%g3
   4284 	movrz	%g3, %g2, %g1
   4285 	lduw	[%g1], %g2
   4286 	inc	%g2
   4287 	stw	%g2, [%g1]
   4288 #endif
   4289 	ldxa	[%g0] ASI_IRSR, %g1
   4290 	mov	IRDR_0H, %g7
   4291 	ldxa	[%g7] ASI_IRDR, %g7	! Get interrupt number
   4292 	membar	#Sync
   4293 
   4294 	btst	IRSR_BUSY, %g1
   4295 	bz,pn	%icc, 3f		! spurious interrupt
   4296 #ifdef MULTIPROCESSOR
   4297 	 sethi	%hi(KERNBASE), %g1
   4298 
   4299 	cmp	%g7, %g1
   4300 	bl,a,pt	%xcc, Lsoftint_regular	! >= KERNBASE is a fast cross-call
   4301 	 and	%g7, (MAXINTNUM-1), %g7	! XXX make sun4us work
   4302 
   4303 	mov	IRDR_1H, %g2
   4304 	ldxa	[%g2] ASI_IRDR, %g2	! Get IPI handler argument 1
   4305 	mov	IRDR_2H, %g3
   4306 	ldxa	[%g3] ASI_IRDR, %g3	! Get IPI handler argument 2
   4307 
   4308 	stxa	%g0, [%g0] ASI_IRSR	! Ack IRQ
   4309 	membar	#Sync			! Should not be needed due to retry
   4310 
   4311 	jmpl	%g7, %g0
   4312 	 nop
   4313 #else
   4314 	and	%g7, (MAXINTNUM-1), %g7	! XXX make sun4us work
   4315 #endif
   4316 
   4317 Lsoftint_regular:
   4318 	stxa	%g0, [%g0] ASI_IRSR	! Ack IRQ
   4319 	membar	#Sync			! Should not be needed due to retry
   4320 	sethi	%hi(_C_LABEL(intrlev)), %g3
   4321 	sllx	%g7, PTRSHFT, %g5	! Calculate entry number
   4322 	or	%g3, %lo(_C_LABEL(intrlev)), %g3
   4323 	LDPTR	[%g3 + %g5], %g5	! We have a pointer to the handler
   4324 	brz,pn	%g5, 3f			! NULL means it isn't registered yet.  Skip it.
   4325 	 nop
   4326 
   4327 	! increment per-ivec counter
   4328 	ldx	[%g5 + IH_CNT], %g1
   4329 	inc	%g1
   4330 	stx	%g1, [%g5 + IH_CNT]
   4331 
   4332 setup_sparcintr:
   4333 	LDPTR	[%g5+IH_PEND], %g6	! Read pending flag
   4334 	brnz,pn	%g6, ret_from_intr_vector ! Skip it if it's running
   4335 	 ldub	[%g5+IH_PIL], %g6	! Read interrupt level
   4336 	sethi	%hi(CPUINFO_VA+CI_INTRPENDING), %g1
   4337 	sll	%g6, PTRSHFT, %g3	! Find start of table for this IPL
   4338 	or	%g1, %lo(CPUINFO_VA+CI_INTRPENDING), %g1
   4339 	add	%g1, %g3, %g1
   4340 1:
   4341 	LDPTR	[%g1], %g3		! Load list head
   4342 	STPTR	%g3, [%g5+IH_PEND]	! Link our intrhand node in
   4343 	mov	%g5, %g7
   4344 	CASPTRA	[%g1] ASI_N, %g3, %g7
   4345 	cmp	%g7, %g3		! Did it work?
   4346 	bne,pn	CCCR, 1b		! No, try again
   4347 	 .empty
   4348 2:
   4349 #ifdef NOT_DEBUG
   4350 	set	_C_LABEL(intrdebug), %g7
   4351 	ld	[%g7], %g7
   4352 	btst	INTRDEBUG_VECTOR, %g7
   4353 	bz,pt	%icc, 97f
   4354 	 nop
   4355 
   4356 	cmp	%g6, 0xa		! ignore clock interrupts?
   4357 	bz,pt	%icc, 97f
   4358 	 nop
   4359 
   4360 	STACKFRAME(-CC64FSZ)		! Get a clean register window
   4361 	LOAD_ASCIZ(%o0,\
   4362 	    "interrupt_vector: number %lx softint mask %lx pil %lu slot %p\n")
   4363 	mov	%g2, %o1
   4364 	rdpr	%pil, %o3
   4365 	mov	%g1, %o4
   4366 	GLOBTOLOC
   4367 	clr	%g4
   4368 	call	prom_printf
   4369 	 mov	%g6, %o2
   4370 	LOCTOGLOB
   4371 	restore
   4372 97:
   4373 #endif
   4374 	mov	1, %g7
   4375 	sll	%g7, %g6, %g6
   4376 	wr	%g6, 0, SET_SOFTINT	! Invoke a softint
   4377 
   4378 	.global ret_from_intr_vector
   4379 ret_from_intr_vector:
   4380 	retry
   4381 	NOTREACHED
   4382 
   4383 3:
   4384 #ifdef NOT_DEBUG	/* always do this */
   4385 	set	_C_LABEL(intrdebug), %g6
   4386 	ld	[%g6], %g6
   4387 	btst	INTRDEBUG_SPUR, %g6
   4388 	bz,pt	%icc, 97f
   4389 	 nop
   4390 #endif
   4391 #if 1
   4392 	set	PANICSTACK-STKB, %g1	! Use panic stack temporarily
   4393 	save	%g1, -CC64FSZ, %sp	! Get a clean register window
   4394 	LOAD_ASCIZ(%o0, "interrupt_vector: spurious vector %lx at pil %d\n")
   4395 	mov	%g7, %o1
   4396 	GLOBTOLOC
   4397 	clr	%g4
   4398 	call	prom_printf
   4399 	 rdpr	%pil, %o2
   4400 	LOCTOGLOB
   4401 	restore
   4402 97:
   4403 #endif
   4404 	ba,a	ret_from_intr_vector
   4405 	 nop				! XXX spitfire bug?
   4406 
   4407 sun4v_cpu_mondo:
   4408 ! XXX Rework this when a UP kernel works - crash for now
   4409 	sir
   4410 	mov	0x3c0, %g1			 ! CPU Mondo Queue Head
   4411 	ldxa	[%g1] ASI_QUEUE, %g2		 ! fetch index value for head
   4412 	set	CPUINFO_VA, %g3
   4413 	ldx	[%g3 + CI_PADDR], %g3
   4414 	add	%g3, CI_CPUMQ, %g3
   4415 	ldxa	[%g3] ASI_PHYS_CACHED, %g3	 ! fetch head element
   4416 	ldxa	[%g3 + %g2] ASI_PHYS_CACHED, %g4 ! fetch func
   4417 	add	%g2, 8, %g5
   4418 	ldxa	[%g3 + %g5] ASI_PHYS_CACHED, %g5 ! fetch arg1
   4419 	add	%g2, 16, %g6
   4420 	ldxa	[%g3 + %g6] ASI_PHYS_CACHED, %g6 ! fetch arg2
   4421 	add	%g2, 64, %g2			 ! point to next element in queue
   4422 	and	%g2, 0x7ff, %g2			 ! modulo queue size 2048 (32*64)
   4423 	stxa	%g2, [%g1] ASI_QUEUE		 ! update head index
   4424 	membar	#Sync
   4425 
   4426 	mov	%g4, %g2
   4427 	mov	%g5, %g3
   4428 	mov	%g6, %g5
   4429 	jmpl	%g2, %g0
   4430 	 nop			! No store here!
   4431 	retry
   4432 	NOTREACHED
   4433 
   4434 sun4v_dev_mondo:
   4435 	mov	0x3d0, %g1			! Dev Mondo Queue Head
   4436 	ldxa	[%g1] ASI_QUEUE, %g2		! fetch index value
   4437 	mov	0x3d8, %g1			! Dev Mondo Queue Tail
   4438 	ldxa	[%g1] ASI_QUEUE, %g4		! fetch index value
   4439 	cmp	%g2, %g4			! head = queue?
   4440 	bne,pt 	%xcc, 2f			! unusually not the case
   4441 	 nop
   4442 	retry					! unlikely, ignore interrupt
   4443 2:
   4444 	set	CPUINFO_VA, %g3			 ! fetch cpuinfo pa
   4445 	ldx	[%g3 + CI_PADDR], %g3		 ! fetch intstack pa
   4446 	set	CPUINFO_VA-INTSTACK, %g4	 ! offset to cpuinfo
   4447 	add	%g4, %g3, %g3			 ! %g3 is now cpuifo
   4448 	add	%g3, CI_DEVMQ, %g3		 ! calc offset to devmq
   4449 	ldxa	[%g3] ASI_PHYS_CACHED, %g3	 ! fetch address of devmq
   4450 	ldxa	[%g3 + %g2] ASI_PHYS_CACHED, %g5 !
   4451 	add	%g2, 64, %g2			 ! each element is 64 bytes
   4452 	and	%g2, 0x7ff, %g2			 ! assume 32 elements
   4453 	mov	0x3d0, %g1			 ! Dev Mondo Queue Head
   4454 	stxa	%g2, [%g1] ASI_QUEUE		 ! adjust head index value
   4455 	membar	#Sync
   4456 
   4457 	cmp	%g5, MAXINTNUM			! Handle both sun4v legacy (sysino) and cookies.
   4458 	bgeu,pn	%xcc, 1f			! See UltraSPARC Virtual Machine Specification
   4459 	 nop					! version 3 chapter 6 (Interrupt model)
   4460 
   4461 	sethi	%hi(_C_LABEL(intrlev)), %g3
   4462 	sllx	%g5, PTRSHFT, %g5	! Calculate entry number
   4463 	or	%g3, %lo(_C_LABEL(intrlev)), %g3
   4464 	LDPTR	[%g3 + %g5], %g5	! We have a pointer to the handler
   4465 1:
   4466 	brnz,pt	%g5, setup_sparcintr	! branch if valid handle
   4467 	 nop
   4468 
   4469 	ba,a	3b			! log if invalid handle
   4470 	 nop
   4471 
   4472 /*
   4473  * Ultra1 and Ultra2 CPUs use soft interrupts for everything.  What we do
   4474  * on a soft interrupt, is we should check which bits in SOFTINT(%asr22)
   4475  * are set, handle those interrupts, then clear them by setting the
   4476  * appropriate bits in CLEAR_SOFTINT(%asr21).
   4477  *
   4478  * We have an array of 8 interrupt vector slots for each of 15 interrupt
   4479  * levels.  If a vectored interrupt can be dispatched, the dispatch
   4480  * routine will place a pointer to an intrhand structure in one of
   4481  * the slots.  The interrupt handler will go through the list to look
   4482  * for an interrupt to dispatch.  If it finds one it will pull it off
   4483  * the list, free the entry, and call the handler.  The code is like
   4484  * this:
   4485  *
   4486  *	for (i=0; i<8; i++)
   4487  *		if (ih = intrpending[intlev][i]) {
   4488  *			intrpending[intlev][i] = NULL;
   4489  *			if ((*ih->ih_fun)(ih->ih_arg ? ih->ih_arg : &frame))
   4490  *				return;
   4491  *			strayintr(&frame);
   4492  *			return;
   4493  *		}
   4494  *
   4495  * Otherwise we go back to the old style of polled interrupts.
   4496  *
   4497  * After preliminary setup work, the interrupt is passed to each
   4498  * registered handler in turn.  These are expected to return nonzero if
   4499  * they took care of the interrupt.  If a handler claims the interrupt,
   4500  * we exit (hardware interrupts are latched in the requestor so we'll
   4501  * just take another interrupt in the unlikely event of simultaneous
   4502  * interrupts from two different devices at the same level).  If we go
   4503  * through all the registered handlers and no one claims it, we report a
   4504  * stray interrupt.  This is more or less done as:
   4505  *
   4506  *	for (ih = intrhand[intlev]; ih; ih = ih->ih_next)
   4507  *		if ((*ih->ih_fun)(ih->ih_arg ? ih->ih_arg : &frame))
   4508  *			return;
   4509  *	strayintr(&frame);
   4510  *
   4511  * Inputs:
   4512  *	%l0 = %tstate
   4513  *	%l1 = return pc
   4514  *	%l2 = return npc
   4515  *	%l3 = interrupt level
   4516  *	(software interrupt only) %l4 = bits to clear in interrupt register
   4517  *
   4518  * Internal:
   4519  *	%l4, %l5: local variables
   4520  *	%l6 = %y
   4521  *	%l7 = %g1
   4522  *	%g2..%g7 go to stack
   4523  *
   4524  * An interrupt frame is built in the space for a full trapframe;
   4525  * this contains the psr, pc, npc, and interrupt level.
   4526  *
   4527  * The level of this interrupt is determined by:
   4528  *
   4529  *       IRQ# = %tt - 0x40
   4530  */
   4531 
   4532 ENTRY_NOPROFILE(sparc_interrupt)
   4533 #ifdef TRAPS_USE_IG
   4534 	! This is for interrupt debugging
   4535 	wrpr	%g0, PSTATE_KERN|PSTATE_IG, %pstate	! DEBUG
   4536 #endif
   4537 	/*
   4538 	 * If this is a %tick or %stick softint, clear it then call
   4539 	 * interrupt_vector. Only one of them should be enabled at any given
   4540 	 * time.
   4541 	 */
   4542 	rd	SOFTINT, %g1
   4543 	set	TICK_INT|STICK_INT, %g5
   4544 	andcc	%g5, %g1, %g5
   4545 	bz,pt	%icc, 0f
   4546 	 sethi	%hi(CPUINFO_VA+CI_TICK_IH), %g3
   4547 	wr	%g0, %g5, CLEAR_SOFTINT
   4548 	ba,pt	%icc, setup_sparcintr
   4549 	 LDPTR	[%g3 + %lo(CPUINFO_VA+CI_TICK_IH)], %g5
   4550 0:
   4551 
   4552 #ifdef TRAPSTATS
   4553 	sethi	%hi(_C_LABEL(kintrcnt)), %g1
   4554 	sethi	%hi(_C_LABEL(uintrcnt)), %g2
   4555 	or	%g1, %lo(_C_LABEL(kintrcnt)), %g1
   4556 	or	%g1, %lo(_C_LABEL(uintrcnt)), %g2
   4557 	rdpr	%tl, %g3
   4558 	dec	%g3
   4559 	movrz	%g3, %g2, %g1
   4560 	lduw	[%g1], %g2
   4561 	inc	%g2
   4562 	stw	%g2, [%g1]
   4563 	/* See if we're on the interrupt stack already. */
   4564 	set	EINTSTACK, %g2
   4565 	set	(EINTSTACK-INTSTACK), %g1
   4566 	btst	1, %sp
   4567 	add	%sp, BIAS, %g3
   4568 	movz	%icc, %sp, %g3
   4569 	srl	%g3, 0, %g3
   4570 	sub	%g2, %g3, %g3
   4571 	cmp	%g3, %g1
   4572 	bgu	1f
   4573 	 set	_C_LABEL(intristk), %g1
   4574 	lduw	[%g1], %g2
   4575 	inc	%g2
   4576 	stw	%g2, [%g1]
   4577 1:
   4578 #endif
   4579 	INTR_SETUP(-CC64FSZ-TF_SIZE)
   4580 
   4581 	! Switch to normal globals so we can save them
   4582 #ifdef SUN4V
   4583 	sethi	%hi(cputyp), %g5
   4584 	ld	[%g5 + %lo(cputyp)], %g5
   4585 	cmp	%g5, CPU_SUN4V
   4586 	bne,pt	%icc, 1f
   4587 	 nop
   4588 	NORMAL_GLOBALS_SUN4V
   4589 	! Save the normal globals
   4590 	stx	%g1, [%sp + CC64FSZ + STKB + TF_G + ( 1*8)]
   4591 	stx	%g2, [%sp + CC64FSZ + STKB + TF_G + ( 2*8)]
   4592 	stx	%g3, [%sp + CC64FSZ + STKB + TF_G + ( 3*8)]
   4593 	stx	%g4, [%sp + CC64FSZ + STKB + TF_G + ( 4*8)]
   4594 	stx	%g5, [%sp + CC64FSZ + STKB + TF_G + ( 5*8)]
   4595 	stx	%g6, [%sp + CC64FSZ + STKB + TF_G + ( 6*8)]
   4596 	stx	%g7, [%sp + CC64FSZ + STKB + TF_G + ( 7*8)]
   4597 
   4598 	/*
   4599 	 * In the EMBEDANY memory model %g4 points to the start of the
   4600 	 * data segment.  In our case we need to clear it before calling
   4601 	 * any C-code.
   4602 	 */
   4603 	clr	%g4
   4604 
   4605 	ba	2f
   4606 	 nop
   4607 1:
   4608 #endif
   4609 	NORMAL_GLOBALS_SUN4U
   4610 	! Save the normal globals
   4611 	stx	%g1, [%sp + CC64FSZ + STKB + TF_G + ( 1*8)]
   4612 	stx	%g2, [%sp + CC64FSZ + STKB + TF_G + ( 2*8)]
   4613 	stx	%g3, [%sp + CC64FSZ + STKB + TF_G + ( 3*8)]
   4614 	stx	%g4, [%sp + CC64FSZ + STKB + TF_G + ( 4*8)]
   4615 	stx	%g5, [%sp + CC64FSZ + STKB + TF_G + ( 5*8)]
   4616 	stx	%g6, [%sp + CC64FSZ + STKB + TF_G + ( 6*8)]
   4617 	stx	%g7, [%sp + CC64FSZ + STKB + TF_G + ( 7*8)]
   4618 
   4619 	/*
   4620 	 * In the EMBEDANY memory model %g4 points to the start of the
   4621 	 * data segment.  In our case we need to clear it before calling
   4622 	 * any C-code.
   4623 	 */
   4624 	clr	%g4
   4625 
   4626 	flushw			! Do not remove this insn -- causes interrupt loss
   4627 
   4628 2:
   4629 	rd	%y, %l6
   4630 	INCR64(CPUINFO_VA+CI_NINTR)	! cnt.v_ints++ (clobbers %o0,%o1)
   4631 	rdpr	%tt, %l5		! Find out our current IPL
   4632 	rdpr	%tstate, %l0
   4633 	rdpr	%tpc, %l1
   4634 	rdpr	%tnpc, %l2
   4635 	rdpr	%tl, %l3		! Dump our trap frame now we have taken the IRQ
   4636 	stw	%l6, [%sp + CC64FSZ + STKB + TF_Y]	! Silly, but we need to save this for rft
   4637 	dec	%l3
   4638 	wrpr	%g0, %l3, %tl
   4639 	sth	%l5, [%sp + CC64FSZ + STKB + TF_TT]! debug
   4640 	stx	%l0, [%sp + CC64FSZ + STKB + TF_TSTATE]	! set up intrframe/clockframe
   4641 	stx	%l1, [%sp + CC64FSZ + STKB + TF_PC]
   4642 	btst	TSTATE_PRIV, %l0		! User mode?
   4643 	stx	%l2, [%sp + CC64FSZ + STKB + TF_NPC]
   4644 
   4645 	sub	%l5, 0x40, %l6			! Convert to interrupt level
   4646 	sethi	%hi(_C_LABEL(intr_evcnts)), %l4
   4647 	stb	%l6, [%sp + CC64FSZ + STKB + TF_PIL]	! set up intrframe/clockframe
   4648 	rdpr	%pil, %o1
   4649 	mulx	%l6, EVC_SIZE, %l3
   4650 	or	%l4, %lo(_C_LABEL(intr_evcnts)), %l4	! intrcnt[intlev]++;
   4651 	stb	%o1, [%sp + CC64FSZ + STKB + TF_OLDPIL]	! old %pil
   4652 	ldx	[%l4 + %l3], %o0
   4653 	add	%l4, %l3, %l4
   4654 	clr	%l5			! Zero handled count
   4655 #ifdef MULTIPROCESSOR
   4656 	mov	1, %l3			! Ack softint
   4657 1:	add	%o0, 1, %l7
   4658 	casxa	[%l4] ASI_N, %o0, %l7
   4659 	cmp	%o0, %l7
   4660 	bne,a,pn %xcc, 1b		! retry if changed
   4661 	 mov	%l7, %o0
   4662 #else
   4663 	inc	%o0
   4664 	mov	1, %l3			! Ack softint
   4665 	stx	%o0, [%l4]
   4666 #endif
   4667 	sll	%l3, %l6, %l3		! Generate IRQ mask
   4668 
   4669 	wrpr	%l6, %pil
   4670 
   4671 #define SOFTINT_INT \
   4672 	(1<<IPL_SOFTCLOCK|1<<IPL_SOFTBIO|1<<IPL_SOFTNET|1<<IPL_SOFTSERIAL)
   4673 
   4674 	! Increment the per-cpu interrupt depth in case of hardintrs
   4675 	btst	SOFTINT_INT, %l3
   4676 	bnz,pn	%icc, sparc_intr_retry
   4677 	 sethi	%hi(CPUINFO_VA+CI_IDEPTH), %l1
   4678 	ld	[%l1 + %lo(CPUINFO_VA+CI_IDEPTH)], %l2
   4679 	inc	%l2
   4680 	st	%l2, [%l1 + %lo(CPUINFO_VA+CI_IDEPTH)]
   4681 
   4682 sparc_intr_retry:
   4683 	wr	%l3, 0, CLEAR_SOFTINT	! (don't clear possible %tick IRQ)
   4684 	sethi	%hi(CPUINFO_VA+CI_INTRPENDING), %l4
   4685 	sll	%l6, PTRSHFT, %l2
   4686 	or	%l4, %lo(CPUINFO_VA+CI_INTRPENDING), %l4
   4687 	add	%l2, %l4, %l4
   4688 
   4689 1:
   4690 	membar	#StoreLoad		! Make sure any failed casxa insns complete
   4691 	LDPTR	[%l4], %l2		! Check a slot
   4692 	cmp	%l2, -1
   4693 	beq,pn	CCCR, intrcmplt		! Empty list?
   4694 	 mov	-1, %l7
   4695 	membar	#LoadStore
   4696 	CASPTRA	[%l4] ASI_N, %l2, %l7	! Grab the entire list
   4697 	cmp	%l7, %l2
   4698 	bne,pn	CCCR, 1b
   4699 	 add	%sp, CC64FSZ+STKB, %o2	! tf = %sp + CC64FSZ + STKB
   4700 	LDPTR	[%l2 + IH_PEND], %l7
   4701 	cmp	%l7, -1			! Last slot?
   4702 	be,pt	CCCR, 3f
   4703 	 membar	#LoadStore
   4704 
   4705 	/*
   4706 	 * Reverse a pending list since setup_sparcintr/send_softint
   4707 	 * makes it in a LIFO order.
   4708 	 */
   4709 	mov	-1, %o0			! prev = -1
   4710 1:	STPTR	%o0, [%l2 + IH_PEND]	! ih->ih_pending = prev
   4711 	mov	%l2, %o0		! prev = ih
   4712 	mov	%l7, %l2		! ih = ih->ih_pending
   4713 	LDPTR	[%l2 + IH_PEND], %l7
   4714 	cmp	%l7, -1			! Last slot?
   4715 	bne,pn	CCCR, 1b
   4716 	 membar	#LoadStore
   4717 	ba,pt	CCCR, 3f
   4718 	 mov	%o0, %l7		! save ih->ih_pending
   4719 
   4720 2:
   4721 	add	%sp, CC64FSZ+STKB, %o2	! tf = %sp + CC64FSZ + STKB
   4722 	LDPTR	[%l2 + IH_PEND], %l7	! save ih->ih_pending
   4723 	membar	#LoadStore
   4724 3:
   4725 	STPTR	%g0, [%l2 + IH_PEND]	! Clear pending flag
   4726 	membar	#Sync
   4727 	LDPTR	[%l2 + IH_FUN], %o4	! ih->ih_fun
   4728 	LDPTR	[%l2 + IH_ARG], %o0	! ih->ih_arg
   4729 
   4730 #ifdef NOT_DEBUG
   4731 	set	_C_LABEL(intrdebug), %o3
   4732 	ld	[%o2], %o3
   4733 	btst	INTRDEBUG_FUNC, %o3
   4734 	bz,a,pt	%icc, 97f
   4735 	 nop
   4736 
   4737 	cmp	%l6, 0xa		! ignore clock interrupts?
   4738 	bz,pt	%icc, 97f
   4739 	 nop
   4740 
   4741 	STACKFRAME(-CC64FSZ)		! Get a clean register window
   4742 	LOAD_ASCIZ(%o0, "sparc_interrupt: func %p arg %p\n")
   4743 	mov	%i0, %o2		! arg
   4744 	GLOBTOLOC
   4745 	call	prom_printf
   4746 	 mov	%i4, %o1		! func
   4747 	LOCTOGLOB
   4748 	restore
   4749 97:
   4750 	mov	%l4, %o1
   4751 #endif
   4752 
   4753 	wrpr	%g0, PSTATE_INTR, %pstate	! Reenable interrupts
   4754 	jmpl	%o4, %o7		! handled = (*ih->ih_fun)(...)
   4755 	 movrz	%o0, %o2, %o0		! arg = (arg == 0) ? arg : tf
   4756 	wrpr	%g0, PSTATE_KERN, %pstate	! Disable interrupts
   4757 	LDPTR	[%l2 + IH_CLR], %l1
   4758 	membar	#Sync
   4759 
   4760 	brz,pn	%l1, 0f
   4761 	 add	%l5, %o0, %l5
   4762 	stx	%g0, [%l1]		! Clear intr source
   4763 	membar	#Sync			! Should not be needed
   4764 0:
   4765 	LDPTR	[%l2 + IH_ACK], %l1	! ih->ih_ack
   4766 	brz,pn	%l1, 1f
   4767 	 nop
   4768 	jmpl	%l1, %o7		! (*ih->ih_ack)(ih)
   4769 	 mov	%l2, %o0
   4770 1:
   4771 	cmp	%l7, -1
   4772 	bne,pn	CCCR, 2b		! 'Nother?
   4773 	 mov	%l7, %l2
   4774 
   4775 intrcmplt:
   4776 	/*
   4777 	 * Re-read SOFTINT to see if any new  pending interrupts
   4778 	 * at this level.
   4779 	 */
   4780 	mov	1, %l3			! Ack softint
   4781 	rd	SOFTINT, %l7		! %l5 contains #intr handled.
   4782 	sll	%l3, %l6, %l3		! Generate IRQ mask
   4783 	btst	%l3, %l7		! leave mask in %l3 for retry code
   4784 	bnz,pn	%icc, sparc_intr_retry
   4785 	 mov	1, %l5			! initialize intr count for next run
   4786 
   4787 	! Decrement this cpu's interrupt depth in case of hardintrs
   4788 	btst	SOFTINT_INT, %l3
   4789 	bnz,pn	%icc, 1f
   4790 	 sethi	%hi(CPUINFO_VA+CI_IDEPTH), %l4
   4791 	ld	[%l4 + %lo(CPUINFO_VA+CI_IDEPTH)], %l5
   4792 	dec	%l5
   4793 	st	%l5, [%l4 + %lo(CPUINFO_VA+CI_IDEPTH)]
   4794 1:
   4795 
   4796 #ifdef NOT_DEBUG
   4797 	set	_C_LABEL(intrdebug), %o2
   4798 	ld	[%o2], %o2
   4799 	btst	INTRDEBUG_FUNC, %o2
   4800 	bz,a,pt	%icc, 97f
   4801 	 nop
   4802 
   4803 	cmp	%l6, 0xa		! ignore clock interrupts?
   4804 	bz,pt	%icc, 97f
   4805 	 nop
   4806 
   4807 	STACKFRAME(-CC64FSZ)		! Get a clean register window
   4808 	LOAD_ASCIZ(%o0, "sparc_interrupt:  done\n")
   4809 	GLOBTOLOC
   4810 	call	prom_printf
   4811 	 nop
   4812 	LOCTOGLOB
   4813 	restore
   4814 97:
   4815 #endif
   4816 
   4817 	ldub	[%sp + CC64FSZ + STKB + TF_OLDPIL], %l3	! restore old %pil
   4818 	wrpr	%l3, 0, %pil
   4819 
   4820 	b	return_from_trap
   4821 	 ldx	[%sp + CC64FSZ + STKB + TF_TSTATE], %g1	! Load this for return_from_trap
   4822 
   4823 #ifdef notyet
   4824 /*
   4825  * Level 12 (ZS serial) interrupt.  Handle it quickly, schedule a
   4826  * software interrupt, and get out.  Do the software interrupt directly
   4827  * if we would just take it on the way out.
   4828  *
   4829  * Input:
   4830  *	%l0 = %psr
   4831  *	%l1 = return pc
   4832  *	%l2 = return npc
   4833  * Internal:
   4834  *	%l3 = zs device
   4835  *	%l4, %l5 = temporary
   4836  *	%l6 = rr3 (or temporary data) + 0x100 => need soft int
   4837  *	%l7 = zs soft status
   4838  */
   4839 zshard:
   4840 #endif /* notyet */
   4841 
   4842 	.globl	return_from_trap, rft_kernel, rft_user
   4843 	.globl	softtrap, slowtrap
   4844 
   4845 /*
   4846  * Various return-from-trap routines (see return_from_trap).
   4847  */
   4848 
   4849 /*
   4850  * Return from trap.
   4851  * registers are:
   4852  *
   4853  *	[%sp + CC64FSZ + STKB] => trap frame
   4854  *      %g1 => tstate from trap frame
   4855  *
   4856  * We must load all global, out, and trap registers from the trap frame.
   4857  *
   4858  * If returning to kernel, we should be at the proper trap level because
   4859  * we don't touch %tl.
   4860  *
   4861  * When returning to user mode, the trap level does not matter, as it
   4862  * will be set explicitly.
   4863  *
   4864  * If we are returning to user code, we must:
   4865  *  1.  Check for register windows in the pcb that belong on the stack.
   4866  *	If there are any, reload them
   4867  */
   4868 return_from_trap:
   4869 #ifdef DEBUG
   4870 	!! Make sure we don't have pc == npc == 0 or we suck.
   4871 	ldx	[%sp + CC64FSZ + STKB + TF_PC], %g2
   4872 	ldx	[%sp + CC64FSZ + STKB + TF_NPC], %g3
   4873 	orcc	%g2, %g3, %g0
   4874 	tz	%icc, 1
   4875 #endif
   4876 
   4877 	!!
   4878 	!! We'll make sure we flush our pcb here, rather than later.
   4879 	!!
   4880 !	ldx	[%sp + CC64FSZ + STKB + TF_TSTATE], %g1	! already passed in, no need to reload
   4881 	btst	TSTATE_PRIV, %g1			! returning to userland?
   4882 
   4883 	!!
   4884 	!! Let all pending interrupts drain before returning to userland
   4885 	!!
   4886 	bnz,pn	%icc, 1f				! Returning to userland?
   4887 	 nop
   4888 	ENABLE_INTERRUPTS %g5
   4889 	wrpr	%g0, %g0, %pil				! Lower IPL
   4890 1:
   4891 	!! Make sure we have no IRQs
   4892 	DISABLE_INTERRUPTS %g5
   4893 
   4894 #ifdef SUN4V
   4895 	sethi	%hi(cputyp), %g5
   4896 	ld	[%g5 + %lo(cputyp)], %g5
   4897 	cmp	%g5, CPU_SUN4V
   4898 	bne,pt	%icc, 1f
   4899 	 nop
   4900 	!! Make sure we have normal globals
   4901 	NORMAL_GLOBALS_SUN4V
   4902 	/* Restore normal globals */
   4903 	ldx	[%sp + CC64FSZ + STKB + TF_G + (1*8)], %g1
   4904 	ldx	[%sp + CC64FSZ + STKB + TF_G + (2*8)], %g2
   4905 	ldx	[%sp + CC64FSZ + STKB + TF_G + (3*8)], %g3
   4906 	ldx	[%sp + CC64FSZ + STKB + TF_G + (4*8)], %g4
   4907 	ldx	[%sp + CC64FSZ + STKB + TF_G + (5*8)], %g5
   4908 	ldx	[%sp + CC64FSZ + STKB + TF_G + (6*8)], %g6
   4909 	ldx	[%sp + CC64FSZ + STKB + TF_G + (7*8)], %g7
   4910 	/* Switch to alternate globals */
   4911 	ALTERNATE_GLOBALS_SUN4V
   4912 	ba	2f
   4913 	 nop
   4914 1:
   4915 #endif
   4916 	!! Make sure we have normal globals
   4917 	NORMAL_GLOBALS_SUN4U
   4918 	/* Restore normal globals */
   4919 	ldx	[%sp + CC64FSZ + STKB + TF_G + (1*8)], %g1
   4920 	ldx	[%sp + CC64FSZ + STKB + TF_G + (2*8)], %g2
   4921 	ldx	[%sp + CC64FSZ + STKB + TF_G + (3*8)], %g3
   4922 	ldx	[%sp + CC64FSZ + STKB + TF_G + (4*8)], %g4
   4923 	ldx	[%sp + CC64FSZ + STKB + TF_G + (5*8)], %g5
   4924 	ldx	[%sp + CC64FSZ + STKB + TF_G + (6*8)], %g6
   4925 	ldx	[%sp + CC64FSZ + STKB + TF_G + (7*8)], %g7
   4926 	/* Switch to alternate globals */
   4927 #ifdef TRAPS_USE_IG
   4928 	wrpr	%g0, PSTATE_KERN|PSTATE_IG, %pstate	! DEBUG
   4929 #else
   4930 	ALTERNATE_GLOBALS_SUN4U
   4931 #endif
   4932 2:
   4933 
   4934 	/* Load outs */
   4935 	ldx	[%sp + CC64FSZ + STKB + TF_O + (0*8)], %i0
   4936 	ldx	[%sp + CC64FSZ + STKB + TF_O + (1*8)], %i1
   4937 	ldx	[%sp + CC64FSZ + STKB + TF_O + (2*8)], %i2
   4938 	ldx	[%sp + CC64FSZ + STKB + TF_O + (3*8)], %i3
   4939 	ldx	[%sp + CC64FSZ + STKB + TF_O + (4*8)], %i4
   4940 	ldx	[%sp + CC64FSZ + STKB + TF_O + (5*8)], %i5
   4941 	ldx	[%sp + CC64FSZ + STKB + TF_O + (6*8)], %i6
   4942 	ldx	[%sp + CC64FSZ + STKB + TF_O + (7*8)], %i7
   4943 	/* Now load trap registers into alternate globals */
   4944 	ld	[%sp + CC64FSZ + STKB + TF_Y], %g4
   4945 	ldx	[%sp + CC64FSZ + STKB + TF_TSTATE], %g1		! load new values
   4946 	wr	%g4, 0, %y
   4947 	ldx	[%sp + CC64FSZ + STKB + TF_PC], %g2
   4948 	ldx	[%sp + CC64FSZ + STKB + TF_NPC], %g3
   4949 
   4950 #ifdef NOTDEF_DEBUG
   4951 	ldub	[%sp + CC64FSZ + STKB + TF_PIL], %g5		! restore %pil
   4952 	wrpr	%g5, %pil				! DEBUG
   4953 #endif
   4954 
   4955 	/* Returning to user mode or kernel mode? */
   4956 	btst	TSTATE_PRIV, %g1		! returning to userland?
   4957 	bz,pt	%icc, rft_user
   4958 	 sethi	%hi(CPUINFO_VA+CI_WANT_AST), %g7	! first instr of rft_user
   4959 
   4960 /*
   4961  * Return from trap, to kernel.
   4962  *
   4963  * We will assume, for the moment, that all kernel traps are properly stacked
   4964  * in the trap registers, so all we have to do is insert the (possibly modified)
   4965  * register values into the trap registers then do a retry.
   4966  *
   4967  */
   4968 rft_kernel:
   4969 	rdpr	%tl, %g4			! Grab a set of trap registers
   4970 	inc	%g4
   4971 	wrpr	%g4, %g0, %tl
   4972 	wrpr	%g3, 0, %tnpc
   4973 	wrpr	%g2, 0, %tpc
   4974 	wrpr	%g1, 0, %tstate
   4975 
   4976 	rdpr	%canrestore, %g2
   4977 	brnz	%g2, 1f
   4978 	 nop
   4979 
   4980 	wr	%g0, ASI_NUCLEUS, %asi
   4981 	rdpr	%cwp, %g1
   4982 	dec	%g1
   4983 	wrpr	%g1, %cwp
   4984 #ifdef _LP64
   4985 	FILL	ldxa, %sp+BIAS, 8, %asi
   4986 #else
   4987 	FILL	lda, %sp, 4, %asi
   4988 #endif
   4989 	restored
   4990 	inc	%g1
   4991 	wrpr	%g1, %cwp
   4992 1:
   4993 	restore
   4994 	rdpr	%tstate, %g1			! Since we may have trapped our regs may be toast
   4995 	rdpr	%cwp, %g2
   4996 	andn	%g1, CWP, %g1
   4997 	wrpr	%g1, %g2, %tstate		! Put %cwp in %tstate
   4998 	CLRTT
   4999 #ifdef TRAPSTATS
   5000 	rdpr	%tl, %g2
   5001 	set	_C_LABEL(rftkcnt), %g1
   5002 	sllx	%g2, 2, %g2
   5003 	add	%g1, %g2, %g1
   5004 	lduw	[%g1], %g2
   5005 	inc	%g2
   5006 	stw	%g2, [%g1]
   5007 #endif
   5008 #if	0
   5009 	wrpr	%g0, 0, %cleanwin	! DEBUG
   5010 #endif
   5011 #if defined(DDB) && defined(MULTIPROCESSOR)
   5012 	set	sparc64_ipi_pause_trap_point, %g1
   5013 	rdpr	%tpc, %g2
   5014 	cmp	%g1, %g2
   5015 	bne,pt	%icc, 0f
   5016 	 nop
   5017 	done
   5018 0:
   5019 #endif
   5020 	retry
   5021 	NOTREACHED
   5022 /*
   5023  * Return from trap, to user.  Checks for scheduling trap (`ast') first;
   5024  * will re-enter trap() if set.  Note that we may have to switch from
   5025  * the interrupt stack to the kernel stack in this case.
   5026  *	%g1 = %tstate
   5027  *	%g2 = return %pc
   5028  *	%g3 = return %npc
   5029  * If returning to a valid window, just set psr and return.
   5030  */
   5031 	.data
   5032 rft_wcnt:	.word 0
   5033 	.text
   5034 
   5035 rft_user:
   5036 !	sethi	%hi(CPUINFO_VA+CI_WANT_AST), %g7	! (done above)
   5037 	lduw	[%g7 + %lo(CPUINFO_VA+CI_WANT_AST)], %g7! want AST trap?
   5038 	brnz,pn	%g7, softtrap			! yes, re-enter trap with type T_AST
   5039 	 mov	T_AST, %g4
   5040 
   5041 #ifdef NOTDEF_DEBUG
   5042 	sethi	%hi(CPCB), %g4
   5043 	LDPTR	[%g4 + %lo(CPCB)], %g4
   5044 	ldub	[%g4 + PCB_NSAVED], %g4		! nsaved
   5045 	brz,pt	%g4, 2f		! Only print if nsaved <> 0
   5046 	 nop
   5047 
   5048 	set	1f, %o0
   5049 	mov	%g4, %o1
   5050 	mov	%g2, %o2			! pc
   5051 	wr	%g0, ASI_DMMU, %asi		! restore the user context
   5052 	ldxa	[CTX_SECONDARY] %asi, %o3	! ctx
   5053 	GLOBTOLOC
   5054 	mov	%g3, %o5
   5055 	call	printf
   5056 	 mov	%i6, %o4			! sp
   5057 !	wrpr	%g0, PSTATE_INTR, %pstate		! Allow IRQ service
   5058 !	wrpr	%g0, PSTATE_KERN, %pstate		! DenyIRQ service
   5059 	LOCTOGLOB
   5060 1:
   5061 	.data
   5062 	.asciz	"rft_user: nsaved=%x pc=%d ctx=%x sp=%x npc=%p\n"
   5063 	_ALIGN
   5064 	.text
   5065 #endif
   5066 
   5067 	/*
   5068 	 * NB: only need to do this after a cache miss
   5069 	 */
   5070 #ifdef TRAPSTATS
   5071 	set	_C_LABEL(rftucnt), %g6
   5072 	lduw	[%g6], %g7
   5073 	inc	%g7
   5074 	stw	%g7, [%g6]
   5075 #endif
   5076 	/*
   5077 	 * Now check to see if any regs are saved in the pcb and restore them.
   5078 	 *
   5079 	 * Here we need to undo the damage caused by switching to a kernel
   5080 	 * stack.
   5081 	 *
   5082 	 * We will use alternate globals %g4..%g7 because %g1..%g3 are used
   5083 	 * by the data fault trap handlers and we don't want possible conflict.
   5084 	 */
   5085 
   5086 	sethi	%hi(CPCB), %g6
   5087 	rdpr	%otherwin, %g7			! restore register window controls
   5088 #ifdef DEBUG
   5089 	rdpr	%canrestore, %g5		! DEBUG
   5090 	tst	%g5				! DEBUG
   5091 	tnz	%icc, 1; nop			! DEBUG
   5092 !	mov	%g0, %g5			! There should be *NO* %canrestore
   5093 	add	%g7, %g5, %g7			! DEBUG
   5094 #endif
   5095 	wrpr	%g0, %g7, %canrestore
   5096 	LDPTR	[%g6 + %lo(CPCB)], %g6
   5097 	wrpr	%g0, 0, %otherwin
   5098 
   5099 	ldub	[%g6 + PCB_NSAVED], %g7		! Any saved reg windows?
   5100 	wrpr	%g0, WSTATE_USER, %wstate	! Need to know where our sp points
   5101 
   5102 #ifdef DEBUG
   5103 	set	rft_wcnt, %g4	! Keep track of all the windows we restored
   5104 	stw	%g7, [%g4]
   5105 #endif
   5106 
   5107 	brz,pt	%g7, 5f				! No saved reg wins
   5108 	 nop
   5109 	dec	%g7				! We can do this now or later.  Move to last entry
   5110 
   5111 #ifdef DEBUG
   5112 	rdpr	%canrestore, %g4			! DEBUG Make sure we've restored everything
   5113 	brnz,a,pn	%g4, 0f				! DEBUG
   5114 	 sir						! DEBUG we should NOT have any usable windows here
   5115 0:							! DEBUG
   5116 	wrpr	%g0, 5, %tl
   5117 #endif
   5118 	rdpr	%otherwin, %g4
   5119 	sll	%g7, 7, %g5			! calculate ptr into rw64 array 8*16 == 128 or 7 bits
   5120 	brz,pt	%g4, 6f				! We should not have any user windows left
   5121 	 add	%g5, %g6, %g5
   5122 
   5123 	set	1f, %o0
   5124 	mov	%g7, %o1
   5125 	mov	%g4, %o2
   5126 	call	printf
   5127 	 wrpr	%g0, PSTATE_KERN, %pstate
   5128 	set	2f, %o0
   5129 	call	panic
   5130 	 nop
   5131 	NOTREACHED
   5132 	.data
   5133 1:	.asciz	"pcb_nsaved=%x and otherwin=%x\n"
   5134 2:	.asciz	"rft_user\n"
   5135 	_ALIGN
   5136 	.text
   5137 6:
   5138 3:
   5139 	restored					! Load in the window
   5140 	restore						! This should not trap!
   5141 	ldx	[%g5 + PCB_RW + ( 0*8)], %l0		! Load the window from the pcb
   5142 	ldx	[%g5 + PCB_RW + ( 1*8)], %l1
   5143 	ldx	[%g5 + PCB_RW + ( 2*8)], %l2
   5144 	ldx	[%g5 + PCB_RW + ( 3*8)], %l3
   5145 	ldx	[%g5 + PCB_RW + ( 4*8)], %l4
   5146 	ldx	[%g5 + PCB_RW + ( 5*8)], %l5
   5147 	ldx	[%g5 + PCB_RW + ( 6*8)], %l6
   5148 	ldx	[%g5 + PCB_RW + ( 7*8)], %l7
   5149 
   5150 	ldx	[%g5 + PCB_RW + ( 8*8)], %i0
   5151 	ldx	[%g5 + PCB_RW + ( 9*8)], %i1
   5152 	ldx	[%g5 + PCB_RW + (10*8)], %i2
   5153 	ldx	[%g5 + PCB_RW + (11*8)], %i3
   5154 	ldx	[%g5 + PCB_RW + (12*8)], %i4
   5155 	ldx	[%g5 + PCB_RW + (13*8)], %i5
   5156 	ldx	[%g5 + PCB_RW + (14*8)], %i6
   5157 	ldx	[%g5 + PCB_RW + (15*8)], %i7
   5158 
   5159 #ifdef DEBUG
   5160 	stx	%g0, [%g5 + PCB_RW + (14*8)]		! DEBUG mark that we've saved this one
   5161 #endif
   5162 
   5163 	cmp	%g5, %g6
   5164 	bgu,pt	%xcc, 3b				! Next one?
   5165 	 dec	8*16, %g5
   5166 
   5167 	stb	%g0, [%g6 + PCB_NSAVED]			! Clear them out so we won't do this again
   5168 	GET_MAXCWP %g5
   5169 	add	%g5, %g7, %g4
   5170 	dec	1, %g5					! NWINDOWS-1-1
   5171 	wrpr	%g5, 0, %cansave
   5172 	wrpr	%g0, 0, %canrestore			! Make sure we have no freeloaders XXX
   5173 	wrpr	%g0, WSTATE_USER, %wstate		! Save things to user space
   5174 	mov	%g7, %g5				! We already did one restore
   5175 4:
   5176 	rdpr	%canrestore, %g4
   5177 	inc	%g4
   5178 	deccc	%g5
   5179 	wrpr	%g4, 0, %cleanwin			! Make *sure* we don't trap to cleanwin
   5180 	bge,a,pt	%xcc, 4b				! return to starting regwin
   5181 	 save	%g0, %g0, %g0				! This may force a datafault
   5182 
   5183 #ifdef DEBUG
   5184 	wrpr	%g0, 0, %tl
   5185 #endif
   5186 #ifdef TRAPSTATS
   5187 	set	_C_LABEL(rftuld), %g5
   5188 	lduw	[%g5], %g4
   5189 	inc	%g4
   5190 	stw	%g4, [%g5]
   5191 #endif
   5192 	!!
   5193 	!! We can't take any save faults in here 'cause they will never be serviced
   5194 	!!
   5195 
   5196 #ifdef DEBUG
   5197 	sethi	%hi(CPCB), %g5
   5198 	LDPTR	[%g5 + %lo(CPCB)], %g5
   5199 	ldub	[%g5 + PCB_NSAVED], %g5		! Any saved reg windows?
   5200 	tst	%g5
   5201 	tnz	%icc, 1; nop			! Debugger if we still have saved windows
   5202 	bne,a	rft_user			! Try starting over again
   5203 	 sethi	%hi(CPUINFO_VA+CI_WANT_AST), %g7
   5204 #endif
   5205 	/*
   5206 	 * Set up our return trapframe so we can recover if we trap from here
   5207 	 * on in.
   5208 	 */
   5209 	wrpr	%g0, 1, %tl			! Set up the trap state
   5210 	wrpr	%g2, 0, %tpc
   5211 	wrpr	%g3, 0, %tnpc
   5212 	ba,pt	%icc, 6f
   5213 	 wrpr	%g1, %g0, %tstate
   5214 
   5215 5:
   5216 	/*
   5217 	 * Set up our return trapframe so we can recover if we trap from here
   5218 	 * on in.
   5219 	 */
   5220 	wrpr	%g0, 1, %tl			! Set up the trap state
   5221 	wrpr	%g2, 0, %tpc
   5222 	wrpr	%g3, 0, %tnpc
   5223 	wrpr	%g1, %g0, %tstate
   5224 
   5225 	/*
   5226 	 * The restore instruction further down may cause the trap level
   5227 	 * to exceed the maximum trap level on sun4v, so a manual fill
   5228 	 * may be necessary.
   5229 	*/
   5230 
   5231 #ifdef SUN4V
   5232 	sethi	%hi(cputyp), %g5
   5233 	ld	[%g5 + %lo(cputyp)], %g5
   5234 	cmp	%g5, CPU_SUN4V
   5235 	bne,pt	%icc, 1f
   5236 	 nop
   5237 
   5238 	! Only manual fill if the restore instruction will cause a fill trap
   5239 	rdpr	%canrestore, %g5
   5240 	brnz	%g5, 1f
   5241 	 nop
   5242 
   5243 	! Do a manual fill
   5244 	wr	%g0, ASI_AIUS, %asi
   5245 	rdpr	%cwp, %g4
   5246 	dec	%g4
   5247 	wrpr	%g4, 0, %cwp
   5248 rft_user_fault_start:
   5249 	FILL	ldxa, %sp+BIAS, 8, %asi
   5250 rft_user_fault_end:
   5251 	restored
   5252 	inc	%g4
   5253 	wrpr	%g4, 0, %cwp
   5254 1:
   5255 #endif
   5256 	restore
   5257 6:
   5258 	rdpr	%canrestore, %g5
   5259 	wrpr	%g5, 0, %cleanwin			! Force cleanup of kernel windows
   5260 
   5261 #ifdef NOTDEF_DEBUG
   5262 	ldx	[%g6 + CC64FSZ + STKB + TF_L + (0*8)], %g5! DEBUG -- get proper value for %l0
   5263 	cmp	%l0, %g5
   5264 	be,a,pt %icc, 1f
   5265 	 nop
   5266 !	sir			! WATCHDOG
   5267 	set	badregs, %g1	! Save the suspect regs
   5268 	stw	%l0, [%g1+(4*0)]
   5269 	stw	%l1, [%g1+(4*1)]
   5270 	stw	%l2, [%g1+(4*2)]
   5271 	stw	%l3, [%g1+(4*3)]
   5272 	stw	%l4, [%g1+(4*4)]
   5273 	stw	%l5, [%g1+(4*5)]
   5274 	stw	%l6, [%g1+(4*6)]
   5275 	stw	%l7, [%g1+(4*7)]
   5276 	stw	%i0, [%g1+(4*8)+(4*0)]
   5277 	stw	%i1, [%g1+(4*8)+(4*1)]
   5278 	stw	%i2, [%g1+(4*8)+(4*2)]
   5279 	stw	%i3, [%g1+(4*8)+(4*3)]
   5280 	stw	%i4, [%g1+(4*8)+(4*4)]
   5281 	stw	%i5, [%g1+(4*8)+(4*5)]
   5282 	stw	%i6, [%g1+(4*8)+(4*6)]
   5283 	stw	%i7, [%g1+(4*8)+(4*7)]
   5284 	save
   5285 	inc	%g7
   5286 	wrpr	%g7, 0, %otherwin
   5287 	wrpr	%g0, 0, %canrestore
   5288 	wrpr	%g0, WSTATE_KERN, %wstate	! Need to know where our sp points
   5289 	set	rft_wcnt, %g4	! Restore nsaved before trapping
   5290 	sethi	%hi(CPCB), %g6
   5291 	LDPTR	[%g6 + %lo(CPCB)], %g6
   5292 	lduw	[%g4], %g4
   5293 	stb	%g4, [%g6 + PCB_NSAVED]
   5294 	ta	1
   5295 	sir
   5296 	.data
   5297 badregs:
   5298 	.space	16*4
   5299 	.text
   5300 1:
   5301 #endif
   5302 
   5303 	rdpr	%tstate, %g1
   5304 	rdpr	%cwp, %g7			! Find our cur window
   5305 	andn	%g1, CWP, %g1			! Clear it from %tstate
   5306 	wrpr	%g1, %g7, %tstate		! Set %tstate with %cwp
   5307 	mov	CTX_SECONDARY, %g1		! Restore the user context
   5308 	GET_MMU_CONTEXTID %g4, %g1, %g3
   5309 	mov	CTX_PRIMARY, %g2
   5310 	SET_MMU_CONTEXTID %g4, %g2, %g3
   5311 	sethi	%hi(KERNBASE), %g7		! Should not be needed due to retry
   5312 	membar	#Sync				! Should not be needed due to retry
   5313 	flush	%g7				! Should not be needed due to retry
   5314 
   5315 	CLRTT
   5316 #ifdef TRAPSTATS
   5317 	set	_C_LABEL(rftudone), %g1
   5318 	lduw	[%g1], %g2
   5319 	inc	%g2
   5320 	stw	%g2, [%g1]
   5321 #endif
   5322 #ifdef DEBUG
   5323 	sethi	%hi(CPCB), %g5
   5324 	LDPTR	[%g5 + %lo(CPCB)], %g5
   5325 	ldub	[%g5 + PCB_NSAVED], %g5		! Any saved reg windows?
   5326 	tst	%g5
   5327 	tnz	%icc, 1; nop			! Debugger if we still have saved windows!
   5328 #endif
   5329 	wrpr	%g0, 0, %pil			! Enable all interrupts
   5330 	retry
   5331 
   5332 ! exported end marker for kernel gdb
   5333 	.globl	_C_LABEL(endtrapcode)
   5334 _C_LABEL(endtrapcode):
   5335 
   5336 /*
   5337  * Kernel entry point.
   5338  *
   5339  * The contract between bootloader and kernel is:
   5340  *
   5341  * %o0		OpenFirmware entry point, to keep Sun's updaters happy
   5342  * %o1		Address of boot information vector (see bootinfo.h)
   5343  * %o2		Length of the vector, in bytes
   5344  * %o3		OpenFirmware entry point, to mimic Sun bootloader behavior
   5345  * %o4		OpenFirmware, to meet earlier NetBSD kernels expectations
   5346  */
   5347 	.align	8
   5348 start:
   5349 dostart:
   5350 	/*
   5351 	 * Startup.
   5352 	 *
   5353 	 * The Sun FCODE bootloader is nice and loads us where we want
   5354 	 * to be.  We have a full set of mappings already set up for us.
   5355 	 *
   5356 	 * I think we end up having an entire 16M allocated to us.
   5357 	 *
   5358 	 * We enter with the prom entry vector in %o0, dvec in %o1,
   5359 	 * and the bootops vector in %o2.
   5360 	 *
   5361 	 * All we need to do is:
   5362 	 *
   5363 	 *	1:	Save the prom vector
   5364 	 *
   5365 	 *	2:	Create a decent stack for ourselves
   5366 	 *
   5367 	 *	3:	Install the permanent 4MB kernel mapping
   5368 	 *
   5369 	 *	4:	Call the C language initialization code
   5370 	 *
   5371 	 */
   5372 
   5373 	/*
   5374 	 * Set the psr into a known state:
   5375 	 * Set supervisor mode, interrupt level >= 13, traps enabled
   5376 	 */
   5377 	wrpr	%g0, 13, %pil
   5378 	wrpr	%g0, PSTATE_INTR|PSTATE_PEF, %pstate
   5379 	wr	%g0, FPRS_FEF, %fprs		! Turn on FPU
   5380 
   5381 	/*
   5382 	 * Step 2: Set up a v8-like stack if we need to
   5383 	 */
   5384 
   5385 #ifdef _LP64
   5386 	btst	1, %sp
   5387 	bnz,pt	%icc, 0f
   5388 	 nop
   5389 	add	%sp, -BIAS, %sp
   5390 #else
   5391 	btst	1, %sp
   5392 	bz,pt	%icc, 0f
   5393 	 nop
   5394 	add	%sp, BIAS, %sp
   5395 #endif
   5396 0:
   5397 
   5398 	call	_C_LABEL(bootstrap)
   5399 	 clr	%g4				! Clear data segment pointer
   5400 
   5401 /*
   5402  * Initialize the boot CPU.  Basically:
   5403  *
   5404  *	Locate the cpu_info structure for this CPU.
   5405  *	Establish a locked mapping for interrupt stack.
   5406  *	Switch to the initial stack.
   5407  *	Call the routine passed in in cpu_info->ci_spinup
   5408  */
   5409 
   5410 #ifdef NO_VCACHE
   5411 #define	SUN4U_TTE_DATABITS	SUN4U_TTE_L|SUN4U_TTE_CP|SUN4U_TTE_P|SUN4U_TTE_W
   5412 #else
   5413 #define	SUN4U_TTE_DATABITS	SUN4U_TTE_L|SUN4U_TTE_CP|SUN4U_TTE_CV|SUN4U_TTE_P|SUN4U_TTE_W
   5414 #endif
   5415 
   5416 
   5417 ENTRY_NOPROFILE(cpu_initialize)	/* for cosmetic reasons - nicer backtrace */
   5418 
   5419 	/* Cache the cputyp in %l6 for later use below */
   5420 	sethi	%hi(cputyp), %l6
   5421 	ld	[%l6 + %lo(cputyp)], %l6
   5422 
   5423 	/*
   5424 	 * Step 5: is no more.
   5425 	 */
   5426 
   5427 	/*
   5428 	 * Step 6: hunt through cpus list and find the one that matches our cpuid
   5429 	 */
   5430 
   5431 	call	_C_LABEL(cpu_myid)	! Retrieve cpuid in %o0
   5432 	 mov	%g0, %o0
   5433 
   5434 	sethi	%hi(_C_LABEL(cpus)), %l1
   5435 	LDPTR	[%l1 + %lo(_C_LABEL(cpus))], %l1
   5436 0:
   5437 	ld	[%l1 + CI_CPUID], %l3		! Load CPUID
   5438 	cmp	%l3, %o0			! Does it match?
   5439 	bne,a,pt	%icc, 0b		! no
   5440 	 LDPTR	[%l1 + CI_NEXT], %l1		! Load next cpu_info pointer
   5441 
   5442 	/*
   5443 	 * Get pointer to our cpu_info struct
   5444 	 */
   5445 	mov	%l1, %l7			! save cpu_info pointer
   5446 	ldx	[%l1 + CI_PADDR], %l1		! Load the interrupt stack's PA
   5447 #ifdef SUN4V
   5448 	cmp	%l6, CPU_SUN4V
   5449 	bne,pt	%icc, 3f
   5450 	 nop
   5451 
   5452 	/* sun4v */
   5453 	call	_C_LABEL(pmap_setup_intstack_sun4v)	! Call nice C function for mapping INTSTACK
   5454 	 mov	%l1, %o0
   5455 	ba	4f
   5456 	 nop
   5457 3:
   5458 #endif
   5459 	/* sun4u */
   5460 	sethi	%hi(0xa0000000), %l2		! V=1|SZ=01|NFO=0|IE=0
   5461 	sllx	%l2, 32, %l2			! Shift it into place
   5462 
   5463 	mov	-1, %l3				! Create a nice mask
   5464 	sllx	%l3, 43, %l4			! Mask off high bits
   5465 	or	%l4, 0xfff, %l4			! We can just load this in 12 (of 13) bits
   5466 
   5467 	andn	%l1, %l4, %l1			! Mask the phys page number
   5468 
   5469 	or	%l2, %l1, %l1			! Now take care of the high bits
   5470 	or	%l1, SUN4U_TTE_DATABITS, %l2	! And low bits:	L=1|CP=1|CV=?|E=0|P=1|W=1|G=0
   5471 
   5472 	!!
   5473 	!!  Now, map in the interrupt stack as context==0
   5474 	!!
   5475 	set	TLB_TAG_ACCESS, %l5
   5476 	set	INTSTACK, %l0
   5477 	stxa	%l0, [%l5] ASI_DMMU		! Make DMMU point to it
   5478 	stxa	%l2, [%g0] ASI_DMMU_DATA_IN	! Store it
   5479 	membar	#Sync
   5480 4:
   5481 
   5482 	!! Setup kernel stack (we rely on curlwp on this cpu
   5483 	!! being lwp0 here and its uarea is mapped special
   5484 	!! and already accessible here)
   5485 	flushw
   5486 	LDPTR	[%l7 + CI_CPCB], %l0		! load PCB/uarea pointer
   5487 	set	2*USPACE - TF_SIZE - CC64FSZ, %l1
   5488  	add	%l1, %l0, %l0
   5489 #ifdef _LP64
   5490 	andn	%l0, 0x0f, %l0			! Needs to be 16-byte aligned
   5491 	sub	%l0, BIAS, %l0			! and biased
   5492 #endif
   5493 	mov	%l0, %sp
   5494 	flushw
   5495 
   5496 #ifdef DEBUG
   5497 	set	_C_LABEL(pmapdebug), %o1
   5498 	ld	[%o1], %o1
   5499 	sethi	%hi(0x40000), %o2
   5500 	btst	%o2, %o1
   5501 	bz	0f
   5502 
   5503 	set	1f, %o0		! Debug printf
   5504 	call	_C_LABEL(prom_printf)
   5505 	 nop
   5506 	.data
   5507 1:
   5508 	.asciz	"Setting trap base...\n"
   5509 	_ALIGN
   5510 	.text
   5511 0:
   5512 #endif
   5513 	/*
   5514 	 * Step 7: change the trap base register, and install our TSB pointers
   5515 	 */
   5516 
   5517 	/*
   5518 	 * install our TSB pointers
   5519 	 */
   5520 
   5521 #ifdef SUN4V
   5522 	cmp	%l6, CPU_SUN4V
   5523 	bne,pt	%icc, 5f
   5524 	 nop
   5525 
   5526 	/* sun4v */
   5527 	LDPTR	[%l7 + CI_TSB_DESC], %o0
   5528 	call	_C_LABEL(pmap_setup_tsb_sun4v)
   5529 	 nop
   5530 	ba	1f
   5531 	 nop
   5532 5:
   5533 #endif
   5534 	/* sun4u */
   5535 	sethi	%hi(_C_LABEL(tsbsize)), %l2
   5536 	sethi	%hi(0x1fff), %l3
   5537 	sethi	%hi(TSB), %l4
   5538 	LDPTR	[%l7 + CI_TSB_DMMU], %l0
   5539 	LDPTR	[%l7 + CI_TSB_IMMU], %l1
   5540 	ld	[%l2 + %lo(_C_LABEL(tsbsize))], %l2
   5541 	or	%l3, %lo(0x1fff), %l3
   5542 	or	%l4, %lo(TSB), %l4
   5543 
   5544 	andn	%l0, %l3, %l0			! Mask off size and split bits
   5545 	or	%l0, %l2, %l0			! Make a TSB pointer
   5546 	stxa	%l0, [%l4] ASI_DMMU		! Install data TSB pointer
   5547 
   5548 	andn	%l1, %l3, %l1			! Mask off size and split bits
   5549 	or	%l1, %l2, %l1			! Make a TSB pointer
   5550 	stxa	%l1, [%l4] ASI_IMMU		! Install instruction TSB pointer
   5551 	membar	#Sync
   5552 	set	1f, %l1
   5553 	flush	%l1
   5554 1:
   5555 
   5556 	/* set trap table */
   5557 #ifdef SUN4V
   5558 	cmp	%l6, CPU_SUN4V
   5559 	bne,pt	%icc, 6f
   5560 	 nop
   5561 	/* sun4v */
   5562 	set	_C_LABEL(trapbase_sun4v), %l1
   5563 	GET_MMFSA %o1
   5564 	call	_C_LABEL(prom_set_trap_table_sun4v)	! Now we should be running 100% from our handlers
   5565 	 mov	%l1, %o0
   5566 
   5567 	ba	7f
   5568 	 nop
   5569 6:
   5570 #endif
   5571 	/* sun4u */
   5572 	set	_C_LABEL(trapbase), %l1
   5573 	call	_C_LABEL(prom_set_trap_table_sun4u)	! Now we should be running 100% from our handlers
   5574 	 mov	%l1, %o0
   5575 7:
   5576 	wrpr	%l1, 0, %tba			! Make sure the PROM didn't foul up.
   5577 
   5578 	/*
   5579 	 * Switch to the kernel mode and run away.
   5580 	 */
   5581 	wrpr	%g0, WSTATE_KERN, %wstate
   5582 
   5583 #ifdef DEBUG
   5584 	wrpr	%g0, 1, %tl			! Debug -- start at tl==3 so we'll watchdog
   5585 	wrpr	%g0, 0x1ff, %tt			! Debug -- clear out unused trap regs
   5586 	wrpr	%g0, 0, %tpc
   5587 	wrpr	%g0, 0, %tnpc
   5588 	wrpr	%g0, 0, %tstate
   5589 	wrpr	%g0, 0, %tl
   5590 #endif
   5591 
   5592 #ifdef DEBUG
   5593 	set	_C_LABEL(pmapdebug), %o1
   5594 	ld	[%o1], %o1
   5595 	sethi	%hi(0x40000), %o2
   5596 	btst	%o2, %o1
   5597 	bz	0f
   5598 
   5599 	LDPTR	[%l7 + CI_SPINUP], %o1
   5600 	set	1f, %o0		! Debug printf
   5601 	call	_C_LABEL(prom_printf)
   5602 	 mov	%sp, %o2
   5603 
   5604 	.data
   5605 1:
   5606 	.asciz	"Calling startup routine %p with stack at %p...\n"
   5607 	_ALIGN
   5608 	.text
   5609 0:
   5610 #endif
   5611 	/*
   5612 	 * Call our startup routine.
   5613 	 */
   5614 
   5615 	LDPTR	[%l7 + CI_SPINUP], %o1
   5616 
   5617 	call	%o1				! Call routine
   5618 	 clr	%o0				! our frame arg is ignored
   5619 
   5620 	set	1f, %o0				! Main should never come back here
   5621 	call	_C_LABEL(panic)
   5622 	 nop
   5623 	.data
   5624 1:
   5625 	.asciz	"main() returned\n"
   5626 	_ALIGN
   5627 	.text
   5628 
   5629 	.align 8
   5630 ENTRY(get_romtba)
   5631 	retl
   5632 	 rdpr	%tba, %o0
   5633 
   5634 ENTRY(setcputyp)
   5635 	sethi	%hi(cputyp), %o1	! Trash %o1 assuming this is ok
   5636 	st	%o0, [%o1 + %lo(cputyp)]
   5637 	retl
   5638 	 nop
   5639 
   5640 #ifdef MULTIPROCESSOR
   5641 	/*
   5642 	 * cpu_mp_startup is called with:
   5643 	 *
   5644 	 *	%g2 = cpu_args
   5645 	 */
   5646 ENTRY(cpu_mp_startup)
   5647 	mov	1, %o0
   5648 	sllx	%o0, 63, %o0
   5649 	wr	%o0, TICK_CMPR	! XXXXXXX clear and disable %tick_cmpr for now
   5650 	wrpr    %g0, 0, %cleanwin
   5651 	wrpr	%g0, 0, %tl			! Make sure we're not in NUCLEUS mode
   5652 	wrpr	%g0, WSTATE_KERN, %wstate
   5653 	wrpr	%g0, PSTATE_KERN, %pstate
   5654 	flushw
   5655 
   5656 	/* Cache the cputyp in %l6 for later use below */
   5657 	sethi	%hi(cputyp), %l6
   5658 	ld	[%l6 + %lo(cputyp)], %l6
   5659 
   5660 	/*
   5661 	 * Get pointer to our cpu_info struct
   5662 	 */
   5663 	ldx	[%g2 + CBA_CPUINFO], %l1	! Load the interrupt stack's PA
   5664 
   5665 #ifdef SUN4V
   5666 	cmp	%l6, CPU_SUN4V
   5667 	bne,pt	%icc, 3f
   5668 	 nop
   5669 
   5670 	/* sun4v */
   5671 
   5672 	sethi	%hi(0x80000000), %l2		! V=1|NFO=0|SW=0
   5673 	sllx	%l2, 32, %l2			! Shift it into place
   5674 	mov	-1, %l3				! Create a nice mask
   5675 	sllx	%l3, 56, %l4			! Mask off high 8 bits
   5676 	or	%l4, 0xfff, %l4			! We can just load this in 12 (of 13) bits
   5677 	andn	%l1, %l4, %l1			! Mask the phys page number into RA
   5678 	or	%l2, %l1, %l1			! Now take care of the 8 high bits V|NFO|SW
   5679 	or	%l1, 0x0741, %l2		! And low 13 bits IE=0|E=0|CP=1|CV=1|P=1|
   5680 						!		  X=0|W=1|SW=00|SZ=0001
   5681 
   5682 	/*
   5683 	 *  Now, map in the interrupt stack & cpu_info as context==0
   5684 	 */
   5685 
   5686 	set	INTSTACK, %o0			! vaddr
   5687 	clr	%o1				! reserved
   5688 	mov	%l2, %o2			! tte
   5689 	mov	MAP_DTLB, %o3			! flags
   5690 	mov	FT_MMU_MAP_PERM_ADDR, %o5	! hv fast trap function
   5691 	ta	ST_FAST_TRAP
   5692 	cmp	%o0, 0
   5693 	be,pt	%icc, 5f
   5694 	 nop
   5695 	sir					! crash if mapping fails
   5696 5:
   5697 
   5698 	/*
   5699 	 * Set 0 as primary context XXX
   5700 	 */
   5701 
   5702 	mov	CTX_PRIMARY, %o0
   5703 	SET_MMU_CONTEXTID_SUN4V %g0, %o0
   5704 
   5705 	ba	4f
   5706 	 nop
   5707 3:
   5708 #endif
   5709 
   5710 	/* sun4u */
   5711 
   5712 	sethi	%hi(0xa0000000), %l2		! V=1|SZ=01|NFO=0|IE=0
   5713 	sllx	%l2, 32, %l2			! Shift it into place
   5714 	mov	-1, %l3				! Create a nice mask
   5715 	sllx	%l3, 43, %l4			! Mask off high bits
   5716 	or	%l4, 0xfff, %l4			! We can just load this in 12 (of 13) bits
   5717 	andn	%l1, %l4, %l1			! Mask the phys page number
   5718 	or	%l2, %l1, %l1			! Now take care of the high bits
   5719 	or	%l1, SUN4U_TTE_DATABITS, %l2	! And low bits:	L=1|CP=1|CV=?|E=0|P=1|W=1|G=0
   5720 
   5721 	/*
   5722 	 *  Now, map in the interrupt stack & cpu_info as context==0
   5723 	 */
   5724 
   5725 	set	TLB_TAG_ACCESS, %l5
   5726 	set	INTSTACK, %l0
   5727 	stxa	%l0, [%l5] ASI_DMMU		! Make DMMU point to it
   5728 	stxa	%l2, [%g0] ASI_DMMU_DATA_IN	! Store it
   5729 
   5730 	/*
   5731 	 * Set 0 as primary context XXX
   5732 	 */
   5733 
   5734 	mov	CTX_PRIMARY, %o0
   5735 	SET_MMU_CONTEXTID_SUN4U %g0, %o0
   5736 
   5737 4:
   5738 	membar	#Sync
   5739 
   5740 	/*
   5741 	 * Temporarily use the interrupt stack
   5742 	 */
   5743 #ifdef _LP64
   5744 	set	((EINTSTACK - CC64FSZ - TF_SIZE)) & ~0x0f - BIAS, %sp
   5745 #else
   5746 	set	EINTSTACK - CC64FSZ - TF_SIZE, %sp
   5747 #endif
   5748 	set	1, %fp
   5749 	clr	%i7
   5750 
   5751 #ifdef SUN4V
   5752 	cmp	%l6, CPU_SUN4V
   5753 	bne,pt	%icc, 2f
   5754 	 nop
   5755 
   5756 	/* sun4v */
   5757 
   5758 	/*
   5759 	 * install our TSB pointers
   5760 	 */
   5761 
   5762 	set	CPUINFO_VA, %o0
   5763 	LDPTR	[%o0 + CI_TSB_DESC], %o0
   5764 	call	_C_LABEL(pmap_setup_tsb_sun4v)
   5765 	 nop
   5766 
   5767 	/* set trap table */
   5768 
   5769 	set	_C_LABEL(trapbase_sun4v), %l1
   5770 	GET_MMFSA %o1
   5771 	call	_C_LABEL(prom_set_trap_table_sun4v)
   5772 	 mov	%l1, %o0
   5773 
   5774 	! Now we should be running 100% from our handlers
   5775 	ba	3f
   5776 	 nop
   5777 2:
   5778 #endif
   5779 	/* sun4u */
   5780 
   5781 	/*
   5782 	 * install our TSB pointers
   5783 	 */
   5784 
   5785 	sethi	%hi(CPUINFO_VA+CI_TSB_DMMU), %l0
   5786 	sethi	%hi(CPUINFO_VA+CI_TSB_IMMU), %l1
   5787 	sethi	%hi(_C_LABEL(tsbsize)), %l2
   5788 	sethi	%hi(0x1fff), %l3
   5789 	sethi	%hi(TSB), %l4
   5790 	LDPTR	[%l0 + %lo(CPUINFO_VA+CI_TSB_DMMU)], %l0
   5791 	LDPTR	[%l1 + %lo(CPUINFO_VA+CI_TSB_IMMU)], %l1
   5792 	ld	[%l2 + %lo(_C_LABEL(tsbsize))], %l2
   5793 	or	%l3, %lo(0x1fff), %l3
   5794 	or	%l4, %lo(TSB), %l4
   5795 
   5796 	andn	%l0, %l3, %l0			! Mask off size and split bits
   5797 	or	%l0, %l2, %l0			! Make a TSB pointer
   5798 	stxa	%l0, [%l4] ASI_DMMU		! Install data TSB pointer
   5799 	membar	#Sync
   5800 
   5801 	andn	%l1, %l3, %l1			! Mask off size and split bits
   5802 	or	%l1, %l2, %l1			! Make a TSB pointer
   5803 	stxa	%l1, [%l4] ASI_IMMU		! Install instruction TSB pointer
   5804 	membar	#Sync
   5805 	set	1f, %o0
   5806 	flush	%o0
   5807 1:
   5808 
   5809 	/* set trap table */
   5810 
   5811 	set	_C_LABEL(trapbase), %l1
   5812 	call	_C_LABEL(prom_set_trap_table_sun4u)
   5813 	 mov	%l1, %o0
   5814 3:
   5815 	wrpr	%l1, 0, %tba			! Make sure the PROM didn't
   5816 						! foul up.
   5817 	/*
   5818 	 * Use this CPUs idlelewp's uarea stack
   5819 	 */
   5820 	sethi	%hi(CPUINFO_VA+CI_IDLELWP), %l0
   5821 	LDPTR	[%l0 + %lo(CPUINFO_VA+CI_IDLELWP)], %l0
   5822 	set	USPACE - TF_SIZE - CC64FSZ, %l1
   5823 	LDPTR	[%l0 + L_PCB], %l0
   5824 	add	%l0, %l1, %l0
   5825 #ifdef _LP64
   5826 	andn	%l0, 0x0f, %l0			! Needs to be 16-byte aligned
   5827 	sub	%l0, BIAS, %l0			! and biased
   5828 #endif
   5829 	mov	%l0, %sp
   5830 	flushw
   5831 
   5832 	/*
   5833 	 * Switch to the kernel mode and run away.
   5834 	 */
   5835 	wrpr	%g0, 13, %pil
   5836 	wrpr	%g0, PSTATE_INTR|PSTATE_PEF, %pstate
   5837 	wr	%g0, FPRS_FEF, %fprs			! Turn on FPU
   5838 
   5839 	call	_C_LABEL(cpu_hatch)
   5840 	 clr %g4
   5841 
   5842 	b	_C_LABEL(idle_loop)
   5843 	 clr	%o0
   5844 
   5845 	NOTREACHED
   5846 
   5847 	.globl cpu_mp_startup_end
   5848 cpu_mp_startup_end:
   5849 #endif
   5850 
   5851 /*
   5852  * openfirmware(cell* param);
   5853  *
   5854  * OpenFirmware entry point
   5855  *
   5856  * If we're running in 32-bit mode we need to convert to a 64-bit stack
   5857  * and 64-bit cells.  The cells we'll allocate off the stack for simplicity.
   5858  */
   5859 	.align 8
   5860 ENTRY(openfirmware)
   5861 	sethi	%hi(romp), %o4
   5862 	andcc	%sp, 1, %g0
   5863 	bz,pt	%icc, 1f
   5864 	 LDPTR	[%o4+%lo(romp)], %o4		! v9 stack, just load the addr and callit
   5865 	save	%sp, -CC64FSZ, %sp
   5866 	rdpr	%pil, %i2
   5867 	mov	PIL_HIGH, %i3
   5868 	cmp	%i3, %i2
   5869 	movle	%icc, %i2, %i3
   5870 	wrpr	%g0, %i3, %pil
   5871 	mov	%i0, %o0
   5872 	mov	%g1, %l1
   5873 	mov	%g2, %l2
   5874 	mov	%g3, %l3
   5875 	mov	%g4, %l4
   5876 	mov	%g5, %l5
   5877 	mov	%g6, %l6
   5878 	mov	%g7, %l7
   5879 	rdpr	%pstate, %l0
   5880 	jmpl	%i4, %o7
   5881 #if !defined(_LP64)
   5882 	 wrpr	%g0, PSTATE_PROM, %pstate
   5883 #else
   5884 	 wrpr	%g0, PSTATE_PROM|PSTATE_IE, %pstate
   5885 #endif
   5886 	wrpr	%l0, %g0, %pstate
   5887 	mov	%l1, %g1
   5888 	mov	%l2, %g2
   5889 	mov	%l3, %g3
   5890 	mov	%l4, %g4
   5891 	mov	%l5, %g5
   5892 	mov	%l6, %g6
   5893 	mov	%l7, %g7
   5894 	wrpr	%i2, 0, %pil
   5895 	ret
   5896 	 restore	%o0, %g0, %o0
   5897 
   5898 1:	! v8 -- need to screw with stack & params
   5899 #ifdef NOTDEF_DEBUG
   5900 	mov	%o7, %o5
   5901 	call	globreg_check
   5902 	 nop
   5903 	mov	%o5, %o7
   5904 #endif
   5905 	save	%sp, -CC64FSZ, %sp		! Get a new 64-bit stack frame
   5906 	add	%sp, -BIAS, %sp
   5907 	rdpr	%pstate, %l0
   5908 	srl	%sp, 0, %sp
   5909 	rdpr	%pil, %i2	! s = splx(level)
   5910 	mov	%i0, %o0
   5911 	mov	PIL_HIGH, %i3
   5912 	mov	%g1, %l1
   5913 	mov	%g2, %l2
   5914 	cmp	%i3, %i2
   5915 	mov	%g3, %l3
   5916 	mov	%g4, %l4
   5917 	mov	%g5, %l5
   5918 	movle	%icc, %i2, %i3
   5919 	mov	%g6, %l6
   5920 	mov	%g7, %l7
   5921 	wrpr	%i3, %g0, %pil
   5922 	jmpl	%i4, %o7
   5923 	! Enable 64-bit addresses for the prom
   5924 #if defined(_LP64)
   5925 	 wrpr	%g0, PSTATE_PROM, %pstate
   5926 #else
   5927 	 wrpr	%g0, PSTATE_PROM|PSTATE_IE, %pstate
   5928 #endif
   5929 	wrpr	%l0, 0, %pstate
   5930 	wrpr	%i2, 0, %pil
   5931 	mov	%l1, %g1
   5932 	mov	%l2, %g2
   5933 	mov	%l3, %g3
   5934 	mov	%l4, %g4
   5935 	mov	%l5, %g5
   5936 	mov	%l6, %g6
   5937 	mov	%l7, %g7
   5938 	ret
   5939 	 restore	%o0, %g0, %o0
   5940 
   5941 /*
   5942  * void ofw_exit(cell_t args[])
   5943  */
   5944 ENTRY(openfirmware_exit)
   5945 	STACKFRAME(-CC64FSZ)
   5946 	flushw					! Flush register windows
   5947 
   5948 	wrpr	%g0, PIL_HIGH, %pil		! Disable interrupts
   5949 	sethi	%hi(romtba), %l5
   5950 	LDPTR	[%l5 + %lo(romtba)], %l5
   5951 	wrpr	%l5, 0, %tba			! restore the ofw trap table
   5952 
   5953 	/* Arrange locked kernel stack as PROM stack */
   5954 	set	EINTSTACK  - CC64FSZ, %l5
   5955 
   5956 	andn	%l5, 0x0f, %l5			! Needs to be 16-byte aligned
   5957 	sub	%l5, BIAS, %l5			! and biased
   5958 	mov	%l5, %sp
   5959 	flushw
   5960 
   5961 	sethi	%hi(romp), %l6
   5962 	LDPTR	[%l6 + %lo(romp)], %l6
   5963 
   5964 	mov     CTX_PRIMARY, %l3		! set context 0
   5965 	stxa    %g0, [%l3] ASI_DMMU
   5966 	membar	#Sync
   5967 
   5968 	wrpr	%g0, PSTATE_PROM, %pstate	! Disable interrupts
   5969 						! and enable 64-bit addresses
   5970 	wrpr	%g0, 0, %tl			! force trap level 0
   5971 	call	%l6
   5972 	 mov	%i0, %o0
   5973 	NOTREACHED
   5974 
   5975 /*
   5976  * sp_tlb_flush_pte_us(vaddr_t va, int ctx)
   5977  * sp_tlb_flush_pte_usiii(vaddr_t va, int ctx)
   5978  *
   5979  * Flush tte from both IMMU and DMMU.
   5980  *
   5981  * This uses %o0-%o5
   5982  */
   5983 	.align 8
   5984 ENTRY(sp_tlb_flush_pte_us)
   5985 #ifdef DEBUG
   5986 	set	pmapdebug, %o3
   5987 	lduw	[%o3], %o3
   5988 !	movrz	%o1, -1, %o3				! Print on either pmapdebug & PDB_DEMAP or ctx == 0
   5989 	btst	0x0020, %o3
   5990 	bz,pt	%icc, 2f
   5991 	 nop
   5992 	save	%sp, -CC64FSZ, %sp
   5993 	set	1f, %o0
   5994 	mov	%i1, %o1
   5995 	andn	%i0, 0xfff, %o3
   5996 	or	%o3, 0x010, %o3
   5997 	call	_C_LABEL(printf)
   5998 	 mov	%i0, %o2
   5999 	restore
   6000 	.data
   6001 1:
   6002 	.asciz	"sp_tlb_flush_pte_us:	demap ctx=%x va=%08x res=%x\n"
   6003 	_ALIGN
   6004 	.text
   6005 2:
   6006 #endif
   6007 #ifdef MULTIPROCESSOR
   6008 	rdpr	%pstate, %o3
   6009 	andn	%o3, PSTATE_IE, %o4			! disable interrupts
   6010 	wrpr	%o4, 0, %pstate
   6011 #endif
   6012 	srlx	%o0, PG_SHIFT4U, %o0			! drop unused va bits
   6013 	mov	CTX_SECONDARY, %o2
   6014 	sllx	%o0, PG_SHIFT4U, %o0
   6015 	ldxa	[%o2] ASI_DMMU, %o5			! Save secondary context
   6016 	sethi	%hi(KERNBASE), %o4
   6017 	membar	#LoadStore
   6018 	stxa	%o1, [%o2] ASI_DMMU			! Insert context to demap
   6019 	membar	#Sync
   6020 	or	%o0, DEMAP_PAGE_SECONDARY, %o0		! Demap page from secondary context only
   6021 	stxa	%o0, [%o0] ASI_DMMU_DEMAP		! Do the demap
   6022 	stxa	%o0, [%o0] ASI_IMMU_DEMAP		! to both TLBs
   6023 #ifdef TLB_FLUSH_LOWVA
   6024 	srl	%o0, 0, %o0				! and make sure it's both 32- and 64-bit entries
   6025 	stxa	%o0, [%o0] ASI_DMMU_DEMAP		! Do the demap
   6026 	stxa	%o0, [%o0] ASI_IMMU_DEMAP		! Do the demap
   6027 #endif
   6028 	flush	%o4
   6029 	stxa	%o5, [%o2] ASI_DMMU			! Restore secondary context
   6030 	membar	#Sync
   6031 	retl
   6032 #ifdef MULTIPROCESSOR
   6033 	 wrpr	%o3, %pstate				! restore interrupts
   6034 #else
   6035 	 nop
   6036 #endif
   6037 
   6038 ENTRY(sp_tlb_flush_pte_usiii)
   6039 #ifdef DEBUG
   6040 	set	pmapdebug, %o3
   6041 	lduw	[%o3], %o3
   6042 !	movrz	%o1, -1, %o3				! Print on either pmapdebug & PDB_DEMAP or ctx == 0
   6043 	btst	0x0020, %o3
   6044 	bz,pt	%icc, 2f
   6045 	 nop
   6046 	save	%sp, -CC64FSZ, %sp
   6047 	set	1f, %o0
   6048 	mov	%i1, %o1
   6049 	andn	%i0, 0xfff, %o3
   6050 	or	%o3, 0x010, %o3
   6051 	call	_C_LABEL(printf)
   6052 	 mov	%i0, %o2
   6053 	restore
   6054 	.data
   6055 1:
   6056 	.asciz	"sp_tlb_flush_pte_usiii:	demap ctx=%x va=%08x res=%x\n"
   6057 	_ALIGN
   6058 	.text
   6059 2:
   6060 #endif
   6061 	! %o0 = VA [in]
   6062 	! %o1 = ctx value [in] / KERNBASE
   6063 	! %o2 = CTX_PRIMARY
   6064 	! %o3 = saved %tl
   6065 	! %o4 = saved %pstate
   6066 	! %o5 = saved primary ctx
   6067 
   6068 	! Need this for UP as well
   6069 	rdpr	%pstate, %o4
   6070 	andn	%o4, PSTATE_IE, %o3			! disable interrupts
   6071 	wrpr	%o3, 0, %pstate
   6072 
   6073 	!!
   6074 	!! Cheetahs do not support flushing the IMMU from secondary context
   6075 	!!
   6076 	rdpr	%tl, %o3
   6077 	mov	CTX_PRIMARY, %o2
   6078 	brnz,pt	%o3, 1f
   6079 	 andn	%o0, 0xfff, %o0				! drop unused va bits
   6080 	wrpr	%g0, 1, %tl				! Make sure we're NUCLEUS
   6081 1:
   6082 	ldxa	[%o2] ASI_DMMU, %o5			! Save primary context
   6083 	membar	#LoadStore
   6084 	stxa	%o1, [%o2] ASI_DMMU			! Insert context to demap
   6085 	sethi	%hi(KERNBASE), %o1
   6086 	membar	#Sync
   6087 	or	%o0, DEMAP_PAGE_PRIMARY, %o0
   6088 	stxa	%o0, [%o0] ASI_DMMU_DEMAP		! Do the demap
   6089 	membar	#Sync
   6090 	stxa	%o0, [%o0] ASI_IMMU_DEMAP		! to both TLBs
   6091 	membar	#Sync
   6092 #ifdef TLB_FLUSH_LOWVA
   6093 	srl	%o0, 0, %o0				! and make sure it's both 32- and 64-bit entries
   6094 	stxa	%o0, [%o0] ASI_DMMU_DEMAP		! Do the demap
   6095 	membar	#Sync
   6096 	stxa	%o0, [%o0] ASI_IMMU_DEMAP		! Do the demap
   6097 	membar	#Sync
   6098 #endif
   6099 	flush	%o1
   6100 	stxa	%o5, [%o2] ASI_DMMU			! Restore primary context
   6101 	membar	#Sync
   6102 	brnz,pt	%o3, 1f
   6103 	 flush	%o1
   6104 	wrpr	%g0, %o3, %tl				! Return to kernel mode.
   6105 1:
   6106 	retl
   6107 	 wrpr	%o4, %pstate				! restore interrupts
   6108 
   6109 
   6110 /*
   6111  * sp_tlb_flush_all_us(void)
   6112  * sp_tlb_flush_all_usiii(void)
   6113  *
   6114  * Flush all user TLB entries from both IMMU and DMMU.
   6115  * We have both UltraSPARC I+II, and UltraSPARC >=III versions.
   6116  */
   6117 	.align 8
   6118 ENTRY(sp_tlb_flush_all_us)
   6119 	rdpr	%pstate, %o3
   6120 	andn	%o3, PSTATE_IE, %o4			! disable interrupts
   6121 	wrpr	%o4, 0, %pstate
   6122 	set	((TLB_SIZE_SPITFIRE-1) * 8), %o0
   6123 	set	CTX_SECONDARY, %o4
   6124 	ldxa	[%o4] ASI_DMMU, %o4			! save secondary context
   6125 	set	CTX_MASK, %o5
   6126 	membar	#Sync
   6127 
   6128 	! %o0 = loop counter
   6129 	! %o1 = ctx value
   6130 	! %o2 = TLB tag value
   6131 	! %o3 = saved %pstate
   6132 	! %o4 = saved primary ctx
   6133 	! %o5 = CTX_MASK
   6134 	! %xx = saved %tl
   6135 
   6136 0:
   6137 	ldxa	[%o0] ASI_DMMU_TLB_TAG, %o2		! fetch the TLB tag
   6138 	andcc	%o2, %o5, %o1				! context 0?
   6139 	bz,pt	%xcc, 1f				! if so, skip
   6140 	 mov	CTX_SECONDARY, %o2
   6141 
   6142 	stxa	%o1, [%o2] ASI_DMMU			! set the context
   6143 	set	DEMAP_CTX_SECONDARY, %o2
   6144 	membar	#Sync
   6145 	stxa	%o2, [%o2] ASI_DMMU_DEMAP		! do the demap
   6146 	membar	#Sync
   6147 
   6148 1:
   6149 	dec	8, %o0
   6150 	brgz,pt %o0, 0b					! loop over all entries
   6151 	 nop
   6152 
   6153 /*
   6154  * now do the IMMU
   6155  */
   6156 
   6157 	set	((TLB_SIZE_SPITFIRE-1) * 8), %o0
   6158 
   6159 0:
   6160 	ldxa	[%o0] ASI_IMMU_TLB_TAG, %o2		! fetch the TLB tag
   6161 	andcc	%o2, %o5, %o1				! context 0?
   6162 	bz,pt	%xcc, 1f				! if so, skip
   6163 	 mov	CTX_SECONDARY, %o2
   6164 
   6165 	stxa	%o1, [%o2] ASI_DMMU			! set the context
   6166 	set	DEMAP_CTX_SECONDARY, %o2
   6167 	membar	#Sync
   6168 	stxa	%o2, [%o2] ASI_IMMU_DEMAP		! do the demap
   6169 	membar	#Sync
   6170 
   6171 1:
   6172 	dec	8, %o0
   6173 	brgz,pt %o0, 0b					! loop over all entries
   6174 	 nop
   6175 
   6176 	set	CTX_SECONDARY, %o2
   6177 	stxa	%o4, [%o2] ASI_DMMU			! restore secondary ctx
   6178 	sethi	%hi(KERNBASE), %o4
   6179 	membar	#Sync
   6180 	flush	%o4
   6181 	retl
   6182 	 wrpr	%o3, %pstate
   6183 
   6184 	.align 8
   6185 ENTRY(sp_tlb_flush_all_usiii)
   6186 	rdpr	%tl, %o5
   6187 	brnz,pt	%o5, 1f
   6188 	 set	DEMAP_ALL, %o2
   6189 	wrpr	1, %tl
   6190 1:
   6191 	rdpr	%pstate, %o3
   6192 	andn	%o3, PSTATE_IE, %o4			! disable interrupts
   6193 	wrpr	%o4, 0, %pstate
   6194 
   6195 	stxa	%o2, [%o2] ASI_IMMU_DEMAP
   6196 	membar	#Sync
   6197 	stxa	%o2, [%o2] ASI_DMMU_DEMAP
   6198 
   6199 	sethi	%hi(KERNBASE), %o4
   6200 	membar	#Sync
   6201 	flush	%o4
   6202 
   6203 	wrpr	%o5, %tl
   6204 	retl
   6205 	 wrpr	%o3, %pstate
   6206 
   6207 /*
   6208  * sp_blast_dcache(int dcache_size, int dcache_line_size)
   6209  * sp_blast_dcache_disabled(int dcache_size, int dcache_line_size)
   6210  *
   6211  * Clear out all of D$ regardless of contents.  The latter one also
   6212  * disables the D$ while doing so.
   6213  */
   6214 	.align 8
   6215 ENTRY(sp_blast_dcache)
   6216 /*
   6217  * We turn off interrupts for the duration to prevent RED exceptions.
   6218  */
   6219 #ifdef PROF
   6220 	save	%sp, -CC64FSZ, %sp
   6221 #endif
   6222 
   6223 	rdpr	%pstate, %o3
   6224 	sub	%o0, %o1, %o0
   6225 	andn	%o3, PSTATE_IE, %o4			! Turn off PSTATE_IE bit
   6226 	wrpr	%o4, 0, %pstate
   6227 1:
   6228 	stxa	%g0, [%o0] ASI_DCACHE_TAG
   6229 	membar	#Sync
   6230 	brnz,pt	%o0, 1b
   6231 	 sub	%o0, %o1, %o0
   6232 
   6233 	sethi	%hi(KERNBASE), %o2
   6234 	flush	%o2
   6235 	membar	#Sync
   6236 #ifdef PROF
   6237 	wrpr	%o3, %pstate
   6238 	ret
   6239 	 restore
   6240 #else
   6241 	retl
   6242 	 wrpr	%o3, %pstate
   6243 #endif
   6244 
   6245 	.align 8
   6246 ENTRY(sp_blast_dcache_disabled)
   6247 /*
   6248  * We turn off interrupts for the duration to prevent RED exceptions.
   6249  */
   6250 #ifdef PROF
   6251 	save	%sp, -CC64FSZ, %sp
   6252 #endif
   6253 
   6254 	rdpr	%pstate, %o3
   6255 	sub	%o0, %o1, %o0
   6256 	andn	%o3, PSTATE_IE, %o4			! Turn off PSTATE_IE bit
   6257 	wrpr	%o4, 0, %pstate
   6258 
   6259 	ldxa    [%g0] ASI_MCCR, %o5
   6260 	andn	%o5, MCCR_DCACHE_EN, %o4		! Turn off the D$
   6261 	stxa	%o4, [%g0] ASI_MCCR
   6262 	flush 	%g0
   6263 
   6264 1:
   6265 	stxa	%g0, [%o0] ASI_DCACHE_TAG
   6266 	membar	#Sync
   6267 	brnz,pt	%o0, 1b
   6268 	 sub	%o0, %o1, %o0
   6269 
   6270 	sethi	%hi(KERNBASE), %o2
   6271 	flush	%o2
   6272 	membar	#Sync
   6273 
   6274 	stxa	%o5, [%g0] ASI_MCCR			! Restore the D$
   6275 	flush 	%g0
   6276 #ifdef PROF
   6277 	wrpr	%o3, %pstate
   6278 	ret
   6279 	 restore
   6280 #else
   6281 	retl
   6282 	 wrpr	%o3, %pstate
   6283 #endif
   6284 
   6285 #ifdef MULTIPROCESSOR
   6286 /*
   6287  * void sparc64_ipi_blast_dcache(int dcache_size, int dcache_line_size)
   6288  *
   6289  * Clear out all of D$ regardless of contents
   6290  *
   6291  * On entry:
   6292  *	%g2 = dcache_size
   6293  *	%g3 = dcache_line_size
   6294  */
   6295 	.align 8
   6296 ENTRY(sparc64_ipi_blast_dcache)
   6297 	sub	%g2, %g3, %g2
   6298 1:
   6299 	stxa	%g0, [%g2] ASI_DCACHE_TAG
   6300 	membar	#Sync
   6301 	brnz,pt	%g2, 1b
   6302 	 sub	%g2, %g3, %g2
   6303 
   6304 	sethi	%hi(KERNBASE), %g5
   6305 	flush	%g5
   6306 	membar	#Sync
   6307 
   6308 	ba,a	ret_from_intr_vector
   6309 	 nop
   6310 #endif /* MULTIPROCESSOR */
   6311 
   6312 /*
   6313  * blast_icache_us()
   6314  * blast_icache_usiii()
   6315  *
   6316  * Clear out all of I$ regardless of contents
   6317  * Does not modify %o0
   6318  *
   6319  * We turn off interrupts for the duration to prevent RED exceptions.
   6320  * For the Cheetah version, we also have to to turn off the I$ during this as
   6321  * ASI_ICACHE_TAG accesses interfere with coherency.
   6322  */
   6323 	.align 8
   6324 ENTRY(blast_icache_us)
   6325 	rdpr	%pstate, %o3
   6326 	sethi	%hi(icache_size), %o1
   6327 	ld	[%o1 + %lo(icache_size)], %o1
   6328 	sethi	%hi(icache_line_size), %o2
   6329 	ld	[%o2 + %lo(icache_line_size)], %o2
   6330 	sub	%o1, %o2, %o1
   6331 	andn	%o3, PSTATE_IE, %o4			! Turn off PSTATE_IE bit
   6332 	wrpr	%o4, 0, %pstate
   6333 1:
   6334 	stxa	%g0, [%o1] ASI_ICACHE_TAG
   6335 	brnz,pt	%o1, 1b
   6336 	 sub	%o1, %o2, %o1
   6337 	sethi	%hi(KERNBASE), %o5
   6338 	flush	%o5
   6339 	membar	#Sync
   6340 	retl
   6341 	 wrpr	%o3, %pstate
   6342 
   6343 	.align 8
   6344 ENTRY(blast_icache_usiii)
   6345 	rdpr	%pstate, %o3
   6346 	sethi	%hi(icache_size), %o1
   6347 	ld	[%o1 + %lo(icache_size)], %o1
   6348 	sethi	%hi(icache_line_size), %o2
   6349 	ld	[%o2 + %lo(icache_line_size)], %o2
   6350 	sub	%o1, %o2, %o1
   6351 	andn	%o3, PSTATE_IE, %o4			! Turn off PSTATE_IE bit
   6352 	wrpr	%o4, 0, %pstate
   6353 	ldxa    [%g0] ASI_MCCR, %o5
   6354 	andn	%o5, MCCR_ICACHE_EN, %o4		! Turn off the I$
   6355 	stxa	%o4, [%g0] ASI_MCCR
   6356 	flush 	%g0
   6357 1:
   6358 	stxa	%g0, [%o1] ASI_ICACHE_TAG
   6359 	membar	#Sync
   6360 	brnz,pt	%o1, 1b
   6361 	 sub	%o1, %o2, %o1
   6362 	stxa	%o5, [%g0] ASI_MCCR			! Restore the I$
   6363 	flush 	%g0
   6364 	retl
   6365 	 wrpr	%o3, %pstate
   6366 
   6367 /*
   6368  * dcache_flush_page_us(paddr_t pa)
   6369  * dcache_flush_page_usiii(paddr_t pa)
   6370  *
   6371  * Clear one page from D$.
   6372  *
   6373  */
   6374 	.align 8
   6375 ENTRY(dcache_flush_page_us)
   6376 #ifndef _LP64
   6377 	COMBINE(%o0, %o1, %o0)
   6378 #endif
   6379 	mov	-1, %o1		! Generate mask for tag: bits [29..2]
   6380 	srlx	%o0, 13-2, %o2	! Tag is PA bits <40:13> in bits <29:2>
   6381 	clr	%o4
   6382 	srl	%o1, 2, %o1	! Now we have bits <29:0> set
   6383 	set	(2*NBPG), %o5
   6384 	ba,pt	%icc, 1f
   6385 	 andn	%o1, 3, %o1	! Now we have bits <29:2> set
   6386 
   6387 	.align 8
   6388 1:
   6389 	ldxa	[%o4] ASI_DCACHE_TAG, %o3
   6390 	mov	%o4, %o0
   6391 	deccc	32, %o5
   6392 	bl,pn	%icc, 2f
   6393 	 inc	32, %o4
   6394 
   6395 	xor	%o3, %o2, %o3
   6396 	andcc	%o3, %o1, %g0
   6397 	bne,pt	%xcc, 1b
   6398 	 membar	#LoadStore
   6399 
   6400 	stxa	%g0, [%o0] ASI_DCACHE_TAG
   6401 	ba,pt	%icc, 1b
   6402 	 membar	#StoreLoad
   6403 2:
   6404 
   6405 	sethi	%hi(KERNBASE), %o5
   6406 	flush	%o5
   6407 	retl
   6408 	 membar	#Sync
   6409 
   6410 	.align 8
   6411 ENTRY(dcache_flush_page_usiii)
   6412 #ifndef _LP64
   6413 	COMBINE(%o0, %o1, %o0)
   6414 #endif
   6415 	set	NBPG, %o1
   6416 	sethi	%hi(dcache_line_size), %o2
   6417 	add	%o0, %o1, %o1	! end address
   6418 	ld	[%o2 + %lo(dcache_line_size)], %o2
   6419 
   6420 1:
   6421 	stxa	%g0, [%o0] ASI_DCACHE_INVALIDATE
   6422 	add	%o0, %o2, %o0
   6423 	cmp	%o0, %o1
   6424 	bl,pt	%xcc, 1b
   6425 	 nop
   6426 
   6427 	sethi	%hi(KERNBASE), %o5
   6428 	flush	%o5
   6429 	retl
   6430 	 membar	#Sync
   6431 
   6432 /*
   6433  *	cache_flush_phys_us(paddr_t, psize_t, int);
   6434  *	cache_flush_phys_usiii(paddr_t, psize_t, int);
   6435  *
   6436  *	Clear a set of paddrs from the D$, I$ and if param3 is
   6437  *	non-zero, E$.  (E$ is not supported yet).
   6438  */
   6439 
   6440 	.align 8
   6441 ENTRY(cache_flush_phys_us)
   6442 #ifndef _LP64
   6443 	COMBINE(%o0, %o1, %o0)
   6444 	COMBINE(%o2, %o3, %o1)
   6445 	mov	%o4, %o2
   6446 #endif
   6447 #ifdef DEBUG
   6448 	tst	%o2		! Want to clear E$?
   6449 	tnz	1		! Error!
   6450 #endif
   6451 	add	%o0, %o1, %o1	! End PA
   6452 	dec	%o1
   6453 
   6454 	!!
   6455 	!! Both D$ and I$ tags match pa bits 42-13, but
   6456 	!! they are shifted different amounts.  So we'll
   6457 	!! generate a mask for bits 40-13.
   6458 	!!
   6459 
   6460 	mov	-1, %o2		! Generate mask for tag: bits [40..13]
   6461 	srl	%o2, 5, %o2	! 32-5 = [27..0]
   6462 	sllx	%o2, 13, %o2	! 27+13 = [40..13]
   6463 
   6464 	and	%o2, %o0, %o0	! Mask away uninteresting bits
   6465 	and	%o2, %o1, %o1	! (probably not necessary)
   6466 
   6467 	set	(2*NBPG), %o5
   6468 	clr	%o4
   6469 1:
   6470 	ldxa	[%o4] ASI_DCACHE_TAG, %o3
   6471 	sllx	%o3, 40-29, %o3	! Shift D$ tag into place
   6472 	and	%o3, %o2, %o3	! Mask out trash
   6473 
   6474 	cmp	%o0, %o3
   6475 	blt,pt	%xcc, 2f	! Too low
   6476 	 cmp	%o1, %o3
   6477 	bgt,pt	%xcc, 2f	! Too high
   6478 	 nop
   6479 
   6480 	membar	#LoadStore
   6481 	stxa	%g0, [%o4] ASI_DCACHE_TAG ! Just right
   6482 	membar	#Sync
   6483 2:
   6484 	ldda	[%o4] ASI_ICACHE_TAG, %g0	! Tag goes in %g1
   6485 	sllx	%g1, 40-35, %g1			! Shift I$ tag into place
   6486 	and	%g1, %o2, %g1			! Mask out trash
   6487 	cmp	%o0, %g1
   6488 	blt,pt	%xcc, 3f
   6489 	 cmp	%o1, %g1
   6490 	bgt,pt	%xcc, 3f
   6491 	 nop
   6492 	stxa	%g0, [%o4] ASI_ICACHE_TAG
   6493 3:
   6494 	membar	#StoreLoad
   6495 	dec	32, %o5
   6496 	brgz,pt	%o5, 1b
   6497 	 inc	32, %o4
   6498 
   6499 	sethi	%hi(KERNBASE), %o5
   6500 	flush	%o5
   6501 	retl
   6502 	 membar	#Sync
   6503 
   6504 	.align 8
   6505 ENTRY(cache_flush_phys_usiii)
   6506 #ifndef _LP64
   6507 	COMBINE(%o0, %o1, %o0)
   6508 	COMBINE(%o2, %o3, %o1)
   6509 	mov	%o4, %o2
   6510 #endif
   6511 #ifdef DEBUG
   6512 	tst	%o2		! Want to clear E$?
   6513 	tnz	1		! Error!
   6514 #endif
   6515 	add	%o0, %o1, %o1	! End PA
   6516 	sethi	%hi(dcache_line_size), %o3
   6517 	ld	[%o3 + %lo(dcache_line_size)], %o3
   6518 	sethi	%hi(KERNBASE), %o5
   6519 1:
   6520 	stxa	%g0, [%o0] ASI_DCACHE_INVALIDATE
   6521 	add	%o0, %o3, %o0
   6522 	cmp	%o0, %o1
   6523 	bl,pt	%xcc, 1b
   6524 	 nop
   6525 
   6526 	/* don't need to flush the I$ on cheetah */
   6527 
   6528 	flush	%o5
   6529 	retl
   6530 	 membar	#Sync
   6531 
   6532 #ifdef COMPAT_16
   6533 #ifdef _LP64
   6534 /*
   6535  * XXXXX Still needs lotsa cleanup after sendsig is complete and offsets are known
   6536  *
   6537  * The following code is copied to the top of the user stack when each
   6538  * process is exec'ed, and signals are `trampolined' off it.
   6539  *
   6540  * When this code is run, the stack looks like:
   6541  *	[%sp]			128 bytes to which registers can be dumped
   6542  *	[%sp + 128]		signal number (goes in %o0)
   6543  *	[%sp + 128 + 4]		signal code (goes in %o1)
   6544  *	[%sp + 128 + 8]		first word of saved state (sigcontext)
   6545  *	    .
   6546  *	    .
   6547  *	    .
   6548  *	[%sp + NNN]	last word of saved state
   6549  * (followed by previous stack contents or top of signal stack).
   6550  * The address of the function to call is in %g1; the old %g1 and %o0
   6551  * have already been saved in the sigcontext.  We are running in a clean
   6552  * window, all previous windows now being saved to the stack.
   6553  *
   6554  * Note that [%sp + 128 + 8] == %sp + 128 + 16.  The copy at %sp+128+8
   6555  * will eventually be removed, with a hole left in its place, if things
   6556  * work out.
   6557  */
   6558 ENTRY_NOPROFILE(sigcode)
   6559 	/*
   6560 	 * XXX  the `save' and `restore' below are unnecessary: should
   6561 	 *	replace with simple arithmetic on %sp
   6562 	 *
   6563 	 * Make room on the stack for 64 %f registers + %fsr.  This comes
   6564 	 * out to 64*4+8 or 264 bytes, but this must be aligned to a multiple
   6565 	 * of 64, or 320 bytes.
   6566 	 */
   6567 	save	%sp, -CC64FSZ - 320, %sp
   6568 	mov	%g2, %l2		! save globals in %l registers
   6569 	mov	%g3, %l3
   6570 	mov	%g4, %l4
   6571 	mov	%g5, %l5
   6572 	mov	%g6, %l6
   6573 	mov	%g7, %l7
   6574 	/*
   6575 	 * Saving the fpu registers is expensive, so do it iff it is
   6576 	 * enabled and dirty.
   6577 	 */
   6578 	rd	%fprs, %l0
   6579 	btst	FPRS_DL|FPRS_DU, %l0	! All clean?
   6580 	bz,pt	%icc, 2f
   6581 	 btst	FPRS_DL, %l0		! test dl
   6582 	bz,pt	%icc, 1f
   6583 	 btst	FPRS_DU, %l0		! test du
   6584 
   6585 	! fpu is enabled, oh well
   6586 	stx	%fsr, [%sp + CC64FSZ + BIAS + 0]
   6587 	add	%sp, BIAS+CC64FSZ+BLOCK_SIZE, %l0	! Generate a pointer so we can
   6588 	andn	%l0, BLOCK_ALIGN, %l0	! do a block store
   6589 	stda	%f0, [%l0] ASI_BLK_P
   6590 	inc	BLOCK_SIZE, %l0
   6591 	stda	%f16, [%l0] ASI_BLK_P
   6592 1:
   6593 	bz,pt	%icc, 2f
   6594 	 add	%sp, BIAS+CC64FSZ+BLOCK_SIZE, %l0	! Generate a pointer so we can
   6595 	andn	%l0, BLOCK_ALIGN, %l0	! do a block store
   6596 	add	%l0, 2*BLOCK_SIZE, %l0	! and skip what we already stored
   6597 	stda	%f32, [%l0] ASI_BLK_P
   6598 	inc	BLOCK_SIZE, %l0
   6599 	stda	%f48, [%l0] ASI_BLK_P
   6600 2:
   6601 	membar	#Sync
   6602 	rd	%fprs, %l0		! reload fprs copy, for checking after
   6603 	rd	%y, %l1			! in any case, save %y
   6604 	lduw	[%fp + BIAS + 128], %o0	! sig
   6605 	lduw	[%fp + BIAS + 128 + 4], %o1	! code
   6606 	call	%g1			! (*sa->sa_handler)(sig,code,scp)
   6607 	 add	%fp, BIAS + 128 + 8, %o2	! scp
   6608 	wr	%l1, %g0, %y		! in any case, restore %y
   6609 
   6610 	/*
   6611 	 * Now that the handler has returned, re-establish all the state
   6612 	 * we just saved above, then do a sigreturn.
   6613 	 */
   6614 	btst	FPRS_DL|FPRS_DU, %l0	! All clean?
   6615 	bz,pt	%icc, 2f
   6616 	 btst	FPRS_DL, %l0		! test dl
   6617 	bz,pt	%icc, 1f
   6618 	 btst	FPRS_DU, %l0		! test du
   6619 
   6620 	ldx	[%sp + CC64FSZ + BIAS + 0], %fsr
   6621 	add	%sp, BIAS+CC64FSZ+BLOCK_SIZE, %l0	! Generate a pointer so we can
   6622 	andn	%l0, BLOCK_ALIGN, %l0	! do a block load
   6623 	ldda	[%l0] ASI_BLK_P, %f0
   6624 	inc	BLOCK_SIZE, %l0
   6625 	ldda	[%l0] ASI_BLK_P, %f16
   6626 1:
   6627 	bz,pt	%icc, 2f
   6628 	 nop
   6629 	add	%sp, BIAS+CC64FSZ+BLOCK_SIZE, %l0	! Generate a pointer so we can
   6630 	andn	%l0, BLOCK_ALIGN, %l0	! do a block load
   6631 	inc	2*BLOCK_SIZE, %l0	! and skip what we already loaded
   6632 	ldda	[%l0] ASI_BLK_P, %f32
   6633 	inc	BLOCK_SIZE, %l0
   6634 	ldda	[%l0] ASI_BLK_P, %f48
   6635 2:
   6636 	mov	%l2, %g2
   6637 	mov	%l3, %g3
   6638 	mov	%l4, %g4
   6639 	mov	%l5, %g5
   6640 	mov	%l6, %g6
   6641 	mov	%l7, %g7
   6642 	membar	#Sync
   6643 
   6644 	restore	%g0, SYS_compat_16___sigreturn14, %g1 ! get registers back & set syscall #
   6645 	add	%sp, BIAS + 128 + 8, %o0! compute scp
   6646 !	andn	%o0, 0x0f, %o0
   6647 	t	ST_SYSCALL		! sigreturn(scp)
   6648 	! sigreturn does not return unless it fails
   6649 	mov	SYS_exit, %g1		! exit(errno)
   6650 	t	ST_SYSCALL
   6651 	/* NOTREACHED */
   6652 
   6653 	.globl	_C_LABEL(esigcode)
   6654 _C_LABEL(esigcode):
   6655 #endif
   6656 
   6657 #if !defined(_LP64)
   6658 
   6659 #define SIGCODE_NAME		sigcode
   6660 #define ESIGCODE_NAME		esigcode
   6661 #define SIGRETURN_NAME		SYS_compat_16___sigreturn14
   6662 #define EXIT_NAME		SYS_exit
   6663 
   6664 #include "sigcode32.s"
   6665 
   6666 #endif
   6667 #endif
   6668 
   6669 /*
   6670  * getfp() - get stack frame pointer
   6671  */
   6672 ENTRY(getfp)
   6673 	retl
   6674 	 mov %fp, %o0
   6675 
   6676 /*
   6677  * Call optional cpu_idle handler if provided
   6678  */
   6679 ENTRY(cpu_idle)
   6680 	set	CPUINFO_VA, %o0
   6681 	LDPTR	[%o0 + CI_IDLESPIN], %o1
   6682 	tst	%o1
   6683 	bz	1f
   6684 	 nop
   6685 	jmp	%o1
   6686 	 nop
   6687 1:
   6688 	retl
   6689 	nop
   6690 
   6691 /*
   6692  * cpu_switchto() switches to an lwp to run and runs it, saving the
   6693  * current one away.
   6694  *
   6695  * struct lwp * cpu_switchto(struct lwp *current, struct lwp *next)
   6696  * Switch to the specified next LWP
   6697  * Arguments:
   6698  *	i0	'struct lwp *' of the current LWP
   6699  *	i1	'struct lwp *' of the LWP to switch to
   6700  *	i2	'bool' of the flag returning to a softint LWP or not
   6701  * Returns:
   6702  *	the old lwp switched away from
   6703  */
   6704 ENTRY(cpu_switchto)
   6705 	save	%sp, -CC64FSZ, %sp
   6706 	/*
   6707 	 * REGISTER USAGE AT THIS POINT:
   6708 	 *	%l1 = newpcb
   6709 	 *	%l3 = new trapframe
   6710 	 *	%l4 = new l->l_proc
   6711 	 *	%l5 = pcb of oldlwp
   6712 	 *	%l6 = %hi(CPCB)
   6713 	 *	%l7 = %hi(CURLWP)
   6714 	 *	%i0 = oldlwp
   6715 	 *	%i1 = lwp
   6716 	 *	%i2 = returning
   6717 	 *	%o0 = tmp 1
   6718 	 *	%o1 = tmp 2
   6719 	 *	%o2 = tmp 3
   6720 	 *	%o3 = tmp 4
   6721 	 */
   6722 
   6723 	flushw				! save all register windows except this one
   6724 	wrpr	%g0, PSTATE_KERN, %pstate	! make sure we're on normal globals
   6725 						! with traps turned off
   6726 
   6727 	sethi	%hi(CPCB), %l6
   6728 
   6729 	rdpr	%pstate, %o1			! oldpstate = %pstate;
   6730 	LDPTR	[%i0 + L_PCB], %l5
   6731 
   6732 	stx	%i7, [%l5 + PCB_PC]
   6733 	stx	%i6, [%l5 + PCB_SP]
   6734 	sth	%o1, [%l5 + PCB_PSTATE]
   6735 
   6736 	rdpr	%cwp, %o2		! Useless
   6737 	stb	%o2, [%l5 + PCB_CWP]
   6738 
   6739 	sethi	%hi(CURLWP), %l7
   6740 
   6741 	LDPTR   [%i1 + L_PCB], %l1	! newpcb = l->l_pcb;
   6742 
   6743 	/*
   6744 	 * Load the new lwp.  To load, we must change stacks and
   6745 	 * alter cpcb and the window control registers, hence we must
   6746 	 * keep interrupts disabled.
   6747 	 *
   6748 	 * Issue barriers to coordinate mutex_exit on this CPU with
   6749 	 * mutex_vector_enter on another CPU.
   6750 	 *
   6751 	 * 1. Any prior mutex_exit by oldlwp must be visible to other
   6752 	 *    CPUs before we set ci_curlwp := newlwp on this one,
   6753 	 *    requiring a store-before-store barrier.
   6754 	 *
   6755 	 * 2. ci_curlwp := newlwp must be visible on all other CPUs
   6756 	 *    before any subsequent mutex_exit by newlwp can even test
   6757 	 *    whether there might be waiters, requiring a
   6758 	 *    store-before-load barrier.
   6759 	 *
   6760 	 * See kern_mutex.c for details -- this is necessary for
   6761 	 * adaptive mutexes to detect whether the lwp is on the CPU in
   6762 	 * order to safely block without requiring atomic r/m/w in
   6763 	 * mutex_exit.
   6764 	 */
   6765 
   6766 	membar	#StoreStore
   6767 	STPTR	%i1, [%l7 + %lo(CURLWP)]	! curlwp = l;
   6768 	membar	#StoreLoad
   6769 	STPTR	%l1, [%l6 + %lo(CPCB)]		! cpcb = newpcb;
   6770 
   6771 	ldx	[%l1 + PCB_SP], %i6
   6772 	ldx	[%l1 + PCB_PC], %i7
   6773 
   6774 	wrpr	%g0, 0, %otherwin	! These two insns should be redundant
   6775 	wrpr	%g0, 0, %canrestore
   6776 	GET_MAXCWP %o3
   6777 	wrpr	%g0, %o3, %cleanwin
   6778 	dec	1, %o3			! CANSAVE + CANRESTORE + OTHERWIN = MAXCWP - 1
   6779 	/* Skip the rest if returning to a interrupted LWP. */
   6780 	brnz,pn	%i2, Lsw_noras
   6781 	 wrpr	%o3, %cansave
   6782 
   6783 	/* finally, enable traps */
   6784 	wrpr	%g0, PSTATE_INTR, %pstate
   6785 
   6786 	!flushw
   6787 	!membar #Sync
   6788 
   6789 	/*
   6790 	 * Check for restartable atomic sequences (RAS)
   6791 	 */
   6792 	LDPTR	[%i1 + L_PROC], %l4		! now %l4 points to p
   6793 	mov	%l4, %o0		! p is first arg to ras_lookup
   6794 	LDPTR	[%o0 + P_RASLIST], %o1	! any RAS in p?
   6795 	brz,pt	%o1, Lsw_noras		! no, skip RAS check
   6796 	 LDPTR	[%i1 + L_TF], %l3	! pointer to trap frame
   6797 	call	_C_LABEL(ras_lookup)
   6798 	 ldx	[%l3 + TF_PC], %o1
   6799 	cmp	%o0, -1
   6800 	be,pt	CCCR, Lsw_noras
   6801 	 add	%o0, 4, %o1
   6802 	stx	%o0, [%l3 + TF_PC]	! store rewound %pc
   6803 	stx	%o1, [%l3 + TF_NPC]	! and %npc
   6804 
   6805 Lsw_noras:
   6806 
   6807 	/*
   6808 	 * We are resuming the process that was running at the
   6809 	 * call to switch().  Just set psr ipl and return.
   6810 	 */
   6811 !	wrpr	%g0, 0, %cleanwin	! DEBUG
   6812 	clr	%g4		! This needs to point to the base of the data segment
   6813 	wr	%g0, ASI_PRIMARY_NOFAULT, %asi		! Restore default ASI
   6814 	!wrpr	%g0, PSTATE_INTR, %pstate
   6815 	ret
   6816 	 restore %i0, %g0, %o0				! return old curlwp
   6817 
   6818 #ifdef __HAVE_FAST_SOFTINTS
   6819 /*
   6820  * Switch to the LWP assigned to handle interrupts from the given
   6821  * source.  We borrow the VM context from the interrupted LWP.
   6822  *
   6823  * int softint_fastintr(void *l)
   6824  *
   6825  * Arguments:
   6826  *	i0	softint lwp
   6827  */
   6828 ENTRY(softint_fastintr)
   6829 	save	%sp, -CC64FSZ, %sp
   6830 	set	CPUINFO_VA, %l0			! l0 = curcpu()
   6831 	rdpr	%pil, %l7			! l7 = splhigh()
   6832 	wrpr	%g0, PIL_HIGH, %pil
   6833 	LDPTR	[%l0 + CI_EINTSTACK], %l6	! l6 = ci_eintstack
   6834 	add	%sp, -CC64FSZ, %l2		! ci_eintstack = sp - CC64FSZ
   6835 	STPTR	%l2, [%l0 + CI_EINTSTACK]	! save intstack for nested intr
   6836 
   6837 	mov	%i0, %o0			! o0/i0 = softint lwp
   6838 	mov	%l7, %o1			! o1/i1 = ipl
   6839 	save	%sp, -CC64FSZ, %sp		! make one more register window
   6840 	flushw					! and save all
   6841 
   6842 	sethi	%hi(CURLWP), %l7
   6843 	sethi	%hi(CPCB), %l6
   6844 	LDPTR	[%l7 + %lo(CURLWP)], %l0	! l0 = interrupted lwp (curlwp)
   6845 
   6846 	/* save interrupted lwp/pcb info */
   6847 	sethi	%hi(softint_fastintr_ret - 8), %o0	! trampoline function
   6848 	LDPTR	[%l0 + L_PCB], %l5		! l5 = interrupted pcb
   6849 	or	%o0, %lo(softint_fastintr_ret - 8), %o0
   6850 	stx	%i6, [%l5 + PCB_SP]
   6851 	stx	%o0, [%l5 + PCB_PC]
   6852 	rdpr	%pstate, %o1
   6853 	rdpr	%cwp, %o2
   6854 	sth	%o1, [%l5 + PCB_PSTATE]
   6855 	stb	%o2, [%l5 + PCB_CWP]
   6856 
   6857 	/* switch to softint lwp */
   6858 	sethi	%hi(USPACE - TF_SIZE - CC64FSZ - STKB), %o3
   6859 	LDPTR	[%i0 + L_PCB], %l1		! l1 = softint pcb
   6860 	or	%o3, %lo(USPACE - TF_SIZE - CC64FSZ - STKB), %o3
   6861 	membar	#StoreStore		/* for mutex_enter; see cpu_switchto */
   6862 	STPTR	%i0, [%l7 + %lo(CURLWP)]
   6863 	/*
   6864 	 * No need for barrier after ci->ci_curlwp = softlwp -- when we
   6865 	 * enter a softint lwp, it can't be holding any mutexes, so it
   6866 	 * can't release any until after it has acquired them, so we
   6867 	 * need not participate in the protocol with mutex_vector_enter
   6868 	 * barriers here.
   6869 	 */
   6870 	add	%l1, %o3, %i6
   6871 	STPTR	%l1, [%l6 + %lo(CPCB)]
   6872 	stx	%i6, [%l1 + PCB_SP]
   6873 	add	%i6, -CC64FSZ, %sp		! new stack
   6874 
   6875 	/* now switched, then invoke MI dispatcher */
   6876 	mov	%i1, %o1
   6877 	call	_C_LABEL(softint_dispatch)
   6878 	 mov	%l0, %o0
   6879 
   6880 	/* switch back to interrupted lwp */
   6881 	ldx	[%l5 + PCB_SP], %i6
   6882 	membar	#StoreStore		/* for mutex_enter; see cpu_switchto */
   6883 	STPTR	%l0, [%l7 + %lo(CURLWP)]
   6884 	membar	#StoreLoad		/* for mutex_enter; see cpu_switchto */
   6885 	STPTR	%l5, [%l6 + %lo(CPCB)]
   6886 
   6887 	restore					! rewind register window
   6888 
   6889 	STPTR	%l6, [%l0 + CI_EINTSTACK]	! restore ci_eintstack
   6890 	wrpr	%g0, %l7, %pil			! restore ipl
   6891 	ret
   6892 	 restore	%g0, 1, %o0
   6893 
   6894 /*
   6895  * Trampoline function that gets returned to by cpu_switchto() when
   6896  * an interrupt handler blocks.
   6897  *
   6898  * Arguments:
   6899  *	o0	old lwp from cpu_switchto()
   6900  *
   6901  * from softint_fastintr():
   6902  *	l0	CPUINFO_VA
   6903  *	l6	saved ci_eintstack
   6904  *	l7	saved ipl
   6905  */
   6906 softint_fastintr_ret:
   6907 	/* re-adjust after mi_switch() */
   6908 	ld	[%l0 + CI_MTX_COUNT], %o1
   6909 	inc	%o1				! ci_mtx_count++
   6910 	st	%o1, [%l0 + CI_MTX_COUNT]
   6911 
   6912 	STPTR	%l6, [%l0 + CI_EINTSTACK]	! restore ci_eintstack
   6913 	wrpr	%g0, %l7, %pil			! restore ipl
   6914 	ret
   6915 	 restore	%g0, 1, %o0
   6916 
   6917 #endif /* __HAVE_FAST_SOFTINTS */
   6918 
   6919 /*
   6920  * Snapshot the current process so that stack frames are up to date.
   6921  * Only used just before a crash dump.
   6922  */
   6923 ENTRY(snapshot)
   6924 	rdpr	%pstate, %o1		! save psr
   6925 	stx	%o7, [%o0 + PCB_PC]	! save pc
   6926 	stx	%o6, [%o0 + PCB_SP]	! save sp
   6927 	rdpr	%pil, %o2
   6928 	sth	%o1, [%o0 + PCB_PSTATE]
   6929 	rdpr	%cwp, %o3
   6930 	stb	%o2, [%o0 + PCB_PIL]
   6931 	stb	%o3, [%o0 + PCB_CWP]
   6932 
   6933 	flushw
   6934 	save	%sp, -CC64FSZ, %sp
   6935 	flushw
   6936 	ret
   6937 	 restore
   6938 
   6939 /*
   6940  * cpu_lwp_fork() arranges for lwp_trampoline() to run when the
   6941  * nascent lwp is selected by switch().
   6942  *
   6943  * The switch frame will contain pointer to struct lwp of this lwp in
   6944  * %l2, a pointer to the function to call in %l0, and an argument to
   6945  * pass to it in %l1 (we abuse the callee-saved registers).
   6946  *
   6947  * We enter lwp_trampoline as if we are "returning" from
   6948  * cpu_switchto(), so %o0 contains previous lwp (the one we are
   6949  * switching from) that we pass to lwp_startup().
   6950  *
   6951  * If the function *(%l0) returns, we arrange for an immediate return
   6952  * to user mode.  This happens in two known cases: after execve(2) of
   6953  * init, and when returning a child to user mode after a fork(2).
   6954  *
   6955  * If were setting up a kernel thread, the function *(%l0) will not
   6956  * return.
   6957  */
   6958 ENTRY(lwp_trampoline)
   6959 	/*
   6960 	 * Note: cpu_lwp_fork() has set up a stack frame for us to run
   6961 	 * in, so we can call other functions from here without using
   6962 	 * `save ... restore'.
   6963 	 */
   6964 
   6965 	! newlwp in %l2, oldlwp in %o0
   6966 	call    lwp_startup
   6967 	 mov    %l2, %o1
   6968 
   6969 	call	%l0			! re-use current frame
   6970 	 mov	%l1, %o0
   6971 
   6972 	/*
   6973 	 * Here we finish up as in syscall, but simplified.
   6974 	 */
   6975 	b	return_from_trap
   6976 	 nop
   6977 
   6978 /*
   6979  * pmap_zero_page_phys(pa)
   6980  *
   6981  * Zero one page physically addressed
   6982  *
   6983  * Block load/store ASIs do not exist for physical addresses,
   6984  * so we won't use them.
   6985  *
   6986  * We will execute a flush at the end to sync the I$.
   6987  *
   6988  * This version expects to have the dcache_flush_page_all(pa)
   6989  * to have been called before calling into here.
   6990  */
   6991 ENTRY(pmap_zero_page_phys)
   6992 #ifndef _LP64
   6993 	COMBINE(%o0, %o1, %o0)
   6994 #endif
   6995 #ifdef DEBUG
   6996 	set	pmapdebug, %o4
   6997 	ld	[%o4], %o4
   6998 	btst	0x80, %o4	! PDB_COPY
   6999 	bz,pt	%icc, 3f
   7000 	 nop
   7001 	save	%sp, -CC64FSZ, %sp
   7002 	set	2f, %o0
   7003 	call	printf
   7004 	 mov	%i0, %o1
   7005 !	ta	1; nop
   7006 	restore
   7007 	.data
   7008 2:	.asciz	"pmap_zero_page(%p)\n"
   7009 	_ALIGN
   7010 	.text
   7011 3:
   7012 #endif
   7013 	set	NBPG, %o2		! Loop count
   7014 	wr	%g0, ASI_PHYS_CACHED, %asi
   7015 1:
   7016 	/* Unroll the loop 8 times */
   7017 	stxa	%g0, [%o0 + 0x00] %asi
   7018 	deccc	0x40, %o2
   7019 	stxa	%g0, [%o0 + 0x08] %asi
   7020 	stxa	%g0, [%o0 + 0x10] %asi
   7021 	stxa	%g0, [%o0 + 0x18] %asi
   7022 	stxa	%g0, [%o0 + 0x20] %asi
   7023 	stxa	%g0, [%o0 + 0x28] %asi
   7024 	stxa	%g0, [%o0 + 0x30] %asi
   7025 	stxa	%g0, [%o0 + 0x38] %asi
   7026 	bg,pt	%icc, 1b
   7027 	 inc	0x40, %o0
   7028 
   7029 	sethi	%hi(KERNBASE), %o3
   7030 	flush	%o3
   7031 	retl
   7032 	 wr	%g0, ASI_PRIMARY_NOFAULT, %asi	! Make C code happy
   7033 
   7034 /*
   7035  * pmap_copy_page_phys(paddr_t src, paddr_t dst)
   7036  *
   7037  * Copy one page physically addressed
   7038  * We need to use a global reg for ldxa/stxa
   7039  * so the top 32-bits cannot be lost if we take
   7040  * a trap and need to save our stack frame to a
   7041  * 32-bit stack.  We will unroll the loop by 4 to
   7042  * improve performance.
   7043  *
   7044  * This version expects to have the dcache_flush_page_all(pa)
   7045  * to have been called before calling into here.
   7046  *
   7047  */
   7048 ENTRY(pmap_copy_page_phys)
   7049 #ifndef _LP64
   7050 	COMBINE(%o0, %o1, %o0)
   7051 	COMBINE(%o2, %o3, %o1)
   7052 #endif
   7053 #ifdef DEBUG
   7054 	set	pmapdebug, %o4
   7055 	ld	[%o4], %o4
   7056 	btst	0x80, %o4	! PDB_COPY
   7057 	bz,pt	%icc, 3f
   7058 	 nop
   7059 	save	%sp, -CC64FSZ, %sp
   7060 	mov	%i0, %o1
   7061 	set	2f, %o0
   7062 	call	printf
   7063 	 mov	%i1, %o2
   7064 !	ta	1; nop
   7065 	restore
   7066 	.data
   7067 2:	.asciz	"pmap_copy_page(%p,%p)\n"
   7068 	_ALIGN
   7069 	.text
   7070 3:
   7071 #endif
   7072 #if 1
   7073 	set	NBPG, %o2
   7074 	wr	%g0, ASI_PHYS_CACHED, %asi
   7075 1:
   7076 	ldxa	[%o0 + 0x00] %asi, %g1
   7077 	ldxa	[%o0 + 0x08] %asi, %o3
   7078 	ldxa	[%o0 + 0x10] %asi, %o4
   7079 	ldxa	[%o0 + 0x18] %asi, %o5
   7080 	inc	0x20, %o0
   7081 	deccc	0x20, %o2
   7082 	stxa	%g1, [%o1 + 0x00] %asi
   7083 	stxa	%o3, [%o1 + 0x08] %asi
   7084 	stxa	%o4, [%o1 + 0x10] %asi
   7085 	stxa	%o5, [%o1 + 0x18] %asi
   7086 	bg,pt	%icc, 1b		! We don't care about pages >4GB
   7087 	 inc	0x20, %o1
   7088 	retl
   7089 	 wr	%g0, ASI_PRIMARY_NOFAULT, %asi
   7090 #else
   7091 	set	NBPG, %o3
   7092 	add	%o3, %o0, %o3
   7093 	mov	%g1, %o4		! Save g1
   7094 1:
   7095 	ldxa	[%o0] ASI_PHYS_CACHED, %g1
   7096 	inc	8, %o0
   7097 	cmp	%o0, %o3
   7098 	stxa	%g1, [%o1] ASI_PHYS_CACHED
   7099 	bl,pt	%icc, 1b		! We don't care about pages >4GB
   7100 	 inc	8, %o1
   7101 	retl
   7102 	 mov	%o4, %g1		! Restore g1
   7103 #endif
   7104 
   7105 /*
   7106  * extern int64_t pseg_get_real(struct pmap *pm, vaddr_t addr);
   7107  *
   7108  * Return TTE at addr in pmap.  Uses physical addressing only.
   7109  * pmap->pm_physaddr must by the physical address of pm_segs
   7110  *
   7111  */
   7112 ENTRY(pseg_get_real)
   7113 !	flushw			! Make sure we don't have stack probs & lose hibits of %o
   7114 #ifndef _LP64
   7115 	clruw	%o1					! Zero extend
   7116 #endif
   7117 	ldx	[%o0 + PM_PHYS], %o2			! pmap->pm_segs
   7118 
   7119 	srax	%o1, HOLESHIFT, %o3			! Check for valid address
   7120 	brz,pt	%o3, 0f					! Should be zero or -1
   7121 	 inc	%o3					! Make -1 -> 0
   7122 	brnz,pn	%o3, 1f					! Error! In hole!
   7123 0:
   7124 	srlx	%o1, STSHIFT, %o3
   7125 	and	%o3, STMASK, %o3			! Index into pm_segs
   7126 	sll	%o3, 3, %o3
   7127 	add	%o2, %o3, %o2
   7128 	DLFLUSH(%o2,%o3)
   7129 	ldxa	[%o2] ASI_PHYS_CACHED, %o2		! Load page directory pointer
   7130 	DLFLUSH2(%o3)
   7131 
   7132 	srlx	%o1, PDSHIFT, %o3
   7133 	and	%o3, PDMASK, %o3
   7134 	sll	%o3, 3, %o3
   7135 	brz,pn	%o2, 1f					! NULL entry? check somewhere else
   7136 	 add	%o2, %o3, %o2
   7137 	DLFLUSH(%o2,%o3)
   7138 	ldxa	[%o2] ASI_PHYS_CACHED, %o2		! Load page table pointer
   7139 	DLFLUSH2(%o3)
   7140 
   7141 	srlx	%o1, PTSHIFT, %o3			! Convert to ptab offset
   7142 	and	%o3, PTMASK, %o3
   7143 	sll	%o3, 3, %o3
   7144 	brz,pn	%o2, 1f					! NULL entry? check somewhere else
   7145 	 add	%o2, %o3, %o2
   7146 	DLFLUSH(%o2,%o3)
   7147 	ldxa	[%o2] ASI_PHYS_CACHED, %o0
   7148 	DLFLUSH2(%o3)
   7149 	brgez,pn %o0, 1f				! Entry invalid?  Punt
   7150 	 btst	1, %sp
   7151 	bz,pn	%icc, 0f				! 64-bit mode?
   7152 	 nop
   7153 	retl						! Yes, return full value
   7154 	 nop
   7155 0:
   7156 #if 1
   7157 	srl	%o0, 0, %o1
   7158 	retl						! No, generate a %o0:%o1 double
   7159 	 srlx	%o0, 32, %o0
   7160 #else
   7161 	DLFLUSH(%o2,%o3)
   7162 	ldda	[%o2] ASI_PHYS_CACHED, %o0
   7163 	DLFLUSH2(%o3)
   7164 	retl						! No, generate a %o0:%o1 double
   7165 	 nop
   7166 #endif
   7167 1:
   7168 #ifndef _LP64
   7169 	clr	%o1
   7170 #endif
   7171 	retl
   7172 	 clr	%o0
   7173 
   7174 /*
   7175  * In 32-bit mode:
   7176  *
   7177  * extern int pseg_set_real(struct pmap* %o0, vaddr_t addr %o1,
   7178  *			    int64_t tte %o2:%o3, paddr_t spare %o4:%o5);
   7179  *
   7180  * In 64-bit mode:
   7181  *
   7182  * extern int pseg_set_real(struct pmap* %o0, vaddr_t addr %o1,
   7183  *			    int64_t tte %o2, paddr_t spare %o3);
   7184  *
   7185  * Set a pseg entry to a particular TTE value.  Return values are:
   7186  *
   7187  *	-2	addr in hole
   7188  *	0	success	(spare was not used if given)
   7189  *	1	failure	(spare was not given, but one is needed)
   7190  *	2	success	(spare was given, used for L2)
   7191  *	3	failure	(spare was given, used for L2, another is needed for L3)
   7192  *	4	success	(spare was given, used for L3)
   7193  *
   7194  *	rv == 0	success, spare not used if one was given
   7195  *	rv & 4	spare was used for L3
   7196  *	rv & 2	spare was used for L2
   7197  *	rv & 1	failure, spare is needed
   7198  *
   7199  * (NB: nobody in pmap checks for the virtual hole, so the system will hang.)
   7200  * The way to call this is:  first just call it without a spare page.
   7201  * If that fails, allocate a page and try again, passing the paddr of the
   7202  * new page as the spare.
   7203  * If spare is non-zero it is assumed to be the address of a zeroed physical
   7204  * page that can be used to generate a directory table or page table if needed.
   7205  *
   7206  * We keep track of valid (A_TLB_V bit set) and wired (A_TLB_TSB_LOCK bit set)
   7207  * mappings that are set here. We check both bits on the new data entered
   7208  * and increment counts, as well as decrementing counts if the bits are set
   7209  * in the value replaced by this call.
   7210  * The counters are 32 bit or 64 bit wide, depending on the kernel type we are
   7211  * running!
   7212  */
   7213 ENTRY(pseg_set_real)
   7214 #ifndef _LP64
   7215 	clruw	%o1					! Zero extend
   7216 	COMBINE(%o2, %o3, %o2)
   7217 	COMBINE(%o4, %o5, %o3)
   7218 #endif
   7219 	!!
   7220 	!! However we managed to get here we now have:
   7221 	!!
   7222 	!! %o0 = *pmap
   7223 	!! %o1 = addr
   7224 	!! %o2 = tte
   7225 	!! %o3 = paddr of spare page
   7226 	!!
   7227 	srax	%o1, HOLESHIFT, %o4			! Check for valid address
   7228 	brz,pt	%o4, 0f					! Should be zero or -1
   7229 	 inc	%o4					! Make -1 -> 0
   7230 	brz,pt	%o4, 0f
   7231 	 nop
   7232 #ifdef DEBUG
   7233 	ta	1					! Break into debugger
   7234 #endif
   7235 	retl
   7236 	 mov -2, %o0					! Error -- in hole!
   7237 
   7238 0:
   7239 	ldx	[%o0 + PM_PHYS], %o4			! pmap->pm_segs
   7240 	clr	%g1
   7241 	srlx	%o1, STSHIFT, %o5
   7242 	and	%o5, STMASK, %o5
   7243 	sll	%o5, 3, %o5
   7244 	add	%o4, %o5, %o4
   7245 0:
   7246 	DLFLUSH(%o4,%g5)
   7247 	ldxa	[%o4] ASI_PHYS_CACHED, %o5		! Load page directory pointer
   7248 	DLFLUSH2(%g5)
   7249 
   7250 	brnz,a,pt %o5, 0f				! Null pointer?
   7251 	 mov	%o5, %o4
   7252 	brz,pn	%o3, 9f					! Have a spare?
   7253 	 mov	%o3, %o5
   7254 	casxa	[%o4] ASI_PHYS_CACHED, %g0, %o5
   7255 	brnz,pn	%o5, 0b					! Something changed?
   7256 	DLFLUSH(%o4, %o5)
   7257 	mov	%o3, %o4
   7258 	mov	2, %g1					! record spare used for L2
   7259 	clr	%o3					! and not available for L3
   7260 0:
   7261 	srlx	%o1, PDSHIFT, %o5
   7262 	and	%o5, PDMASK, %o5
   7263 	sll	%o5, 3, %o5
   7264 	add	%o4, %o5, %o4
   7265 0:
   7266 	DLFLUSH(%o4,%g5)
   7267 	ldxa	[%o4] ASI_PHYS_CACHED, %o5		! Load table directory pointer
   7268 	DLFLUSH2(%g5)
   7269 
   7270 	brnz,a,pt %o5, 0f				! Null pointer?
   7271 	 mov	%o5, %o4
   7272 	brz,pn	%o3, 9f					! Have a spare?
   7273 	 mov	%o3, %o5
   7274 	casxa	[%o4] ASI_PHYS_CACHED, %g0, %o5
   7275 	brnz,pn	%o5, 0b					! Something changed?
   7276 	DLFLUSH(%o4, %o4)
   7277 	mov	%o3, %o4
   7278 	mov	4, %g1					! record spare used for L3
   7279 0:
   7280 	srlx	%o1, PTSHIFT, %o5			! Convert to ptab offset
   7281 	and	%o5, PTMASK, %o5
   7282 	sll	%o5, 3, %o5
   7283 	add	%o5, %o4, %o4
   7284 
   7285 	DLFLUSH(%o4,%g5)
   7286 	ldxa	[%o4] ASI_PHYS_CACHED, %o5		! save old value in %o5
   7287 	stxa	%o2, [%o4] ASI_PHYS_CACHED		! Easier than shift+or
   7288 	DLFLUSH2(%g5)
   7289 
   7290 	!! at this point we have:
   7291 	!!  %g1 = return value
   7292 	!!  %o0 = struct pmap * (where the counts are)
   7293 	!!  %o2 = new TTE
   7294 	!!  %o5 = old TTE
   7295 
   7296 	!! see if stats needs an update
   7297 #ifdef SUN4V
   7298 	sethi	%hi(cputyp), %g5
   7299 	ld	[%g5 + %lo(cputyp)], %g5
   7300 	cmp	%g5, CPU_SUN4V
   7301 	bne,pt	%icc, 0f
   7302 	 nop
   7303 	sethi	%hh(SUN4V_TLB_TSB_LOCK), %g5
   7304 	sllx	%g5, 32, %g5
   7305 	ba	1f
   7306 	 nop
   7307 0:
   7308 #endif
   7309 	set	SUN4U_TLB_TSB_LOCK, %g5
   7310 1:
   7311 	xor	%o2, %o5, %o3			! %o3 - what changed
   7312 
   7313 	brgez,pn %o3, 5f			! has resident changed? (we predict it has)
   7314 	 btst	%g5, %o3			! has wired changed?
   7315 
   7316 	LDPTR	[%o0 + PM_RESIDENT], %o1	! gonna update resident count
   7317 	brlz	%o2, 0f
   7318 	 mov	1, %o4
   7319 	neg	%o4				! new is not resident -> decrement
   7320 0:	add	%o1, %o4, %o1
   7321 	STPTR	%o1, [%o0 + PM_RESIDENT]
   7322 	btst	%g5, %o3			! has wired changed?
   7323 5:	bz,pt	%xcc, 8f			! we predict it's not
   7324 	 btst	%g5, %o2			! don't waste delay slot, check if new one is wired
   7325 	LDPTR	[%o0 + PM_WIRED], %o1		! gonna update wired count
   7326 	bnz,pt	%xcc, 0f			! if wired changes, we predict it increments
   7327 	 mov	1, %o4
   7328 	neg	%o4				! new is not wired -> decrement
   7329 0:	add	%o1, %o4, %o1
   7330 	STPTR	%o1, [%o0 + PM_WIRED]
   7331 8:	retl
   7332 	 mov	%g1, %o0			! return %g1
   7333 
   7334 9:	retl
   7335 	 or	%g1, 1, %o0			! spare needed, return flags + 1
   7336 
   7337 
   7338 /*
   7339  * clearfpstate()
   7340  *
   7341  * Drops the current fpu state, without saving it.
   7342  */
   7343 ENTRY(clearfpstate)
   7344 	rdpr	%pstate, %o1		! enable FPU
   7345 	wr	%g0, FPRS_FEF, %fprs
   7346 	or	%o1, PSTATE_PEF, %o1
   7347 	retl
   7348 	 wrpr	%o1, 0, %pstate
   7349 
   7350 /*
   7351  * savefpstate(f) struct fpstate *f;
   7352  *
   7353  * Store the current FPU state.
   7354  *
   7355  * Since the kernel may need to use the FPU and we have problems atomically
   7356  * testing and enabling the FPU, we leave here with the FPRS_FEF bit set.
   7357  * Normally this should be turned on in loadfpstate().
   7358  */
   7359  /* XXXXXXXXXX  Assume caller created a proper stack frame */
   7360 ENTRY(savefpstate)
   7361 !	flushw			! Make sure we don't have stack probs & lose hibits of %o
   7362 	rdpr	%pstate, %o1		! enable FP before we begin
   7363 	rd	%fprs, %o5
   7364 	wr	%g0, FPRS_FEF, %fprs
   7365 	or	%o1, PSTATE_PEF, %o1
   7366 	wrpr	%o1, 0, %pstate
   7367 
   7368 	stx	%fsr, [%o0 + FS_FSR]	! f->fs_fsr = getfsr();
   7369 	rd	%gsr, %o4		! Save %gsr
   7370 	st	%o4, [%o0 + FS_GSR]
   7371 
   7372 	add	%o0, FS_REGS, %o2
   7373 #ifdef DIAGNOSTIC
   7374 	btst	BLOCK_ALIGN, %o2	! Needs to be re-executed
   7375 	bnz,pn	%icc, 6f		! Check alignment
   7376 #endif
   7377 	 st	%g0, [%o0 + FS_QSIZE]	! f->fs_qsize = 0;
   7378 	btst	FPRS_DL|FPRS_DU, %o5	! Both FPU halves clean?
   7379 	bz,pt	%icc, 5f		! Then skip it
   7380 
   7381 	 btst	FPRS_DL, %o5		! Lower FPU clean?
   7382 	membar	#Sync
   7383 	bz,a,pt	%icc, 1f		! Then skip it, but upper FPU not clean
   7384 	 add	%o2, 2*BLOCK_SIZE, %o2	! Skip a block
   7385 
   7386 	stda	%f0, [%o2] ASI_BLK_P	! f->fs_f0 = etc;
   7387 	inc	BLOCK_SIZE, %o2
   7388 	stda	%f16, [%o2] ASI_BLK_P
   7389 
   7390 	btst	FPRS_DU, %o5		! Upper FPU clean?
   7391 	bz,pt	%icc, 2f		! Then skip it
   7392 	 inc	BLOCK_SIZE, %o2
   7393 1:
   7394 	stda	%f32, [%o2] ASI_BLK_P
   7395 	inc	BLOCK_SIZE, %o2
   7396 	stda	%f48, [%o2] ASI_BLK_P
   7397 2:
   7398 	membar	#Sync			! Finish operation so we can
   7399 5:
   7400 	retl
   7401 	 wr	%g0, FPRS_FEF, %fprs	! Mark FPU clean
   7402 
   7403 #ifdef DIAGNOSTIC
   7404 	!!
   7405 	!! Damn thing is *NOT* aligned on a 64-byte boundary
   7406 	!!
   7407 6:
   7408 	wr	%g0, FPRS_FEF, %fprs
   7409 	! XXX -- we should panic instead of silently entering debugger
   7410 	ta	1
   7411 	retl
   7412 	 nop
   7413 #endif
   7414 
   7415 /*
   7416  * Load FPU state.
   7417  */
   7418  /* XXXXXXXXXX  Should test to see if we only need to do a partial restore */
   7419 ENTRY(loadfpstate)
   7420 	flushw			! Make sure we don't have stack probs & lose hibits of %o
   7421 	rdpr	%pstate, %o1		! enable FP before we begin
   7422 	ld	[%o0 + FS_GSR], %o4	! Restore %gsr
   7423 	set	PSTATE_PEF, %o2
   7424 	wr	%g0, FPRS_FEF, %fprs
   7425 	or	%o1, %o2, %o1
   7426 	wrpr	%o1, 0, %pstate
   7427 	ldx	[%o0 + FS_FSR], %fsr	! setfsr(f->fs_fsr);
   7428 	add	%o0, FS_REGS, %o3	! This is zero...
   7429 #ifdef DIAGNOSTIC
   7430 	btst	BLOCK_ALIGN, %o3
   7431 	bne,pn	%icc, 1f	! Only use block loads on aligned blocks
   7432 #endif
   7433 	 wr	%o4, %g0, %gsr
   7434 	membar	#Sync
   7435 	ldda	[%o3] ASI_BLK_P, %f0
   7436 	inc	BLOCK_SIZE, %o3
   7437 	ldda	[%o3] ASI_BLK_P, %f16
   7438 	inc	BLOCK_SIZE, %o3
   7439 	ldda	[%o3] ASI_BLK_P, %f32
   7440 	inc	BLOCK_SIZE, %o3
   7441 	ldda	[%o3] ASI_BLK_P, %f48
   7442 	membar	#Sync			! Make sure loads are complete
   7443 	retl
   7444 	 wr	%g0, FPRS_FEF, %fprs	! Clear dirty bits
   7445 
   7446 #ifdef DIAGNOSTIC
   7447 	!!
   7448 	!! Damn thing is *NOT* aligned on a 64-byte boundary
   7449 	!!
   7450 1:
   7451 	wr	%g0, FPRS_FEF, %fprs	! Clear dirty bits
   7452 	! XXX -- we should panic instead of silently entering debugger
   7453 	ta	1
   7454 	retl
   7455 	 nop
   7456 #endif
   7457 
   7458 /*
   7459  * ienab_bis(bis) int bis;
   7460  * ienab_bic(bic) int bic;
   7461  *
   7462  * Set and clear bits in the interrupt register.
   7463  */
   7464 
   7465 /*
   7466  * sun4u has separate asr's for clearing/setting the interrupt mask.
   7467  */
   7468 ENTRY(ienab_bis)
   7469 	retl
   7470 	 wr	%o0, 0, SET_SOFTINT	! SET_SOFTINT
   7471 
   7472 ENTRY(ienab_bic)
   7473 	retl
   7474 	 wr	%o0, 0, CLEAR_SOFTINT	! CLEAR_SOFTINT
   7475 
   7476 /*
   7477  * send_softint(cpu, level, intrhand)
   7478  *
   7479  * Send a softint with an intrhand pointer so we can cause a vectored
   7480  * interrupt instead of a polled interrupt.  This does pretty much the same
   7481  * as interrupt_vector.  If cpu is -1 then send it to this CPU, if it's -2
   7482  * send it to any CPU, otherwise send it to a particular CPU.
   7483  *
   7484  * XXXX Dispatching to different CPUs is not implemented yet.
   7485  */
   7486 ENTRY(send_softint)
   7487 	rdpr	%pstate, %g1
   7488 	andn	%g1, PSTATE_IE, %g2	! clear PSTATE.IE
   7489 	wrpr	%g2, 0, %pstate
   7490 
   7491 	sethi	%hi(CPUINFO_VA+CI_INTRPENDING), %o3
   7492 	LDPTR	[%o2 + IH_PEND], %o5
   7493 	or	%o3, %lo(CPUINFO_VA+CI_INTRPENDING), %o3
   7494 	brnz	%o5, 1f
   7495 	 sll	%o1, PTRSHFT, %o5	! Find start of table for this IPL
   7496 	add	%o3, %o5, %o3
   7497 2:
   7498 	LDPTR	[%o3], %o5		! Load list head
   7499 	STPTR	%o5, [%o2+IH_PEND]	! Link our intrhand node in
   7500 	mov	%o2, %o4
   7501 	CASPTRA	[%o3] ASI_N, %o5, %o4
   7502 	cmp	%o4, %o5		! Did it work?
   7503 	bne,pn	CCCR, 2b		! No, try again
   7504 	 .empty
   7505 
   7506 	mov	1, %o4			! Change from level to bitmask
   7507 	sllx	%o4, %o1, %o4
   7508 	wr	%o4, 0, SET_SOFTINT	! SET_SOFTINT
   7509 1:
   7510 	retl
   7511 	 wrpr	%g1, 0, %pstate		! restore PSTATE.IE
   7512 
   7513 
   7514 #define MICROPERSEC	(1000000)
   7515 
   7516 /*
   7517  * delay function
   7518  *
   7519  * void delay(N)  -- delay N microseconds
   7520  *
   7521  * Register usage: %o0 = "N" number of usecs to go (counts down to zero)
   7522  *		   %o1 = "timerblurb" (stays constant)
   7523  *		   %o2 = counter for 1 usec (counts down from %o1 to zero)
   7524  *
   7525  *
   7526  *	ci_cpu_clockrate should be tuned during CPU probe to the CPU
   7527  *	clockrate in Hz
   7528  *
   7529  */
   7530 ENTRY(delay)			! %o0 = n
   7531 #if 1
   7532 	rdpr	%tick, %o1					! Take timer snapshot
   7533 	sethi	%hi(CPUINFO_VA + CI_CLOCKRATE), %o2
   7534 	sethi	%hi(MICROPERSEC), %o3
   7535 	ldx	[%o2 + %lo(CPUINFO_VA + CI_CLOCKRATE + 8)], %o4	! Get scale factor
   7536 	brnz,pt	%o4, 0f
   7537 	 or	%o3, %lo(MICROPERSEC), %o3
   7538 
   7539 	!! Calculate ticks/usec
   7540 	ldx	[%o2 + %lo(CPUINFO_VA + CI_CLOCKRATE)], %o4	! No, we need to calculate it
   7541 	udivx	%o4, %o3, %o4
   7542 	stx	%o4, [%o2 + %lo(CPUINFO_VA + CI_CLOCKRATE + 8)]	! Save it so we don't need to divide again
   7543 0:
   7544 
   7545 	mulx	%o0, %o4, %o0					! Convert usec -> ticks
   7546 	rdpr	%tick, %o2					! Top of next itr
   7547 1:
   7548 	sub	%o2, %o1, %o3					! How many ticks have gone by?
   7549 	sub	%o0, %o3, %o4					! Decrement count by that much
   7550 	movrgz	%o3, %o4, %o0					! But only if we're decrementing
   7551 	mov	%o2, %o1					! Remember last tick
   7552 	brgz,pt	%o0, 1b						! Done?
   7553 	 rdpr	%tick, %o2					! Get new tick
   7554 
   7555 	retl
   7556 	 nop
   7557 #else
   7558 /* This code only works if %tick does not wrap */
   7559 	rdpr	%tick, %g1					! Take timer snapshot
   7560 	sethi	%hi(CPUINFO_VA + CI_CLOCKRATE), %g2
   7561 	sethi	%hi(MICROPERSEC), %o2
   7562 	ldx	[%g2 + %lo(CPUINFO_VA + CI_CLOCKRATE)], %g2	! Get scale factor
   7563 	or	%o2, %lo(MICROPERSEC), %o2
   7564 !	sethi	%hi(_C_LABEL(timerblurb), %o5			! This is if we plan to tune the clock
   7565 !	ld	[%o5 + %lo(_C_LABEL(timerblurb))], %o5		!  with respect to the counter/timer
   7566 	mulx	%o0, %g2, %g2					! Scale it: (usec * Hz) / 1 x 10^6 = ticks
   7567 	udivx	%g2, %o2, %g2
   7568 	add	%g1, %g2, %g2
   7569 !	add	%o5, %g2, %g2			5, %g2, %g2					! But this gets complicated
   7570 	rdpr	%tick, %g1					! Top of next itr
   7571 	mov	%g1, %g1	! Erratum 50
   7572 1:
   7573 	cmp	%g1, %g2
   7574 	bl,a,pn %xcc, 1b					! Done?
   7575 	 rdpr	%tick, %g1
   7576 
   7577 	retl
   7578 	 nop
   7579 #endif
   7580 	/*
   7581 	 * If something's wrong with the standard setup do this stupid loop
   7582 	 * calibrated for a 143MHz processor.
   7583 	 */
   7584 Lstupid_delay:
   7585 	set	142857143/MICROPERSEC, %o1
   7586 Lstupid_loop:
   7587 	brnz,pt	%o1, Lstupid_loop
   7588 	 dec	%o1
   7589 	brnz,pt	%o0, Lstupid_delay
   7590 	 dec	%o0
   7591 	retl
   7592 	 nop
   7593 
   7594 /*
   7595  * next_tick(long increment)
   7596  *
   7597  * Sets the %tick_cmpr register to fire off in `increment' machine
   7598  * cycles in the future.  Also handles %tick wraparound.  In 32-bit
   7599  * mode we're limited to a 32-bit increment.
   7600  */
   7601 ENTRY(next_tick)
   7602 	rd	TICK_CMPR, %o2
   7603 	rdpr	%tick, %o1
   7604 
   7605 	mov	1, %o3		! Mask off high bits of these registers
   7606 	sllx	%o3, 63, %o3
   7607 	andn	%o1, %o3, %o1
   7608 	andn	%o2, %o3, %o2
   7609 	cmp	%o1, %o2	! Did we wrap?  (tick < tick_cmpr)
   7610 	bgt,pt	%icc, 1f
   7611 	 add	%o1, 1000, %o1	! Need some slack so we don't lose intrs.
   7612 
   7613 	/*
   7614 	 * Handle the unlikely case of %tick wrapping.
   7615 	 *
   7616 	 * This should only happen every 10 years or more.
   7617 	 *
   7618 	 * We need to increment the time base by the size of %tick in
   7619 	 * microseconds.  This will require some divides and multiplies
   7620 	 * which can take time.  So we re-read %tick.
   7621 	 *
   7622 	 */
   7623 
   7624 	/* XXXXX NOT IMPLEMENTED */
   7625 
   7626 
   7627 
   7628 1:
   7629 	add	%o2, %o0, %o2
   7630 	andn	%o2, %o3, %o4
   7631 	brlz,pn	%o4, Ltick_ovflw
   7632 	 cmp	%o2, %o1	! Has this tick passed?
   7633 	blt,pn	%xcc, 1b	! Yes
   7634 	 nop
   7635 
   7636 #ifdef BB_ERRATA_1
   7637 	ba,a	2f
   7638 	 nop
   7639 #else
   7640 	retl
   7641 	 wr	%o2, TICK_CMPR
   7642 #endif
   7643 
   7644 Ltick_ovflw:
   7645 /*
   7646  * When we get here tick_cmpr has wrapped, but we don't know if %tick
   7647  * has wrapped.  If bit 62 is set then we have not wrapped and we can
   7648  * use the current value of %o4 as %tick.  Otherwise we need to return
   7649  * to our loop with %o4 as %tick_cmpr (%o2).
   7650  */
   7651 	srlx	%o3, 1, %o5
   7652 	btst	%o5, %o1
   7653 	bz,pn	%xcc, 1b
   7654 	 mov	%o4, %o2
   7655 #ifdef BB_ERRATA_1
   7656 	ba,a	2f
   7657 	 nop
   7658 	.align	64
   7659 2:	wr	%o2, TICK_CMPR
   7660 	rd	TICK_CMPR, %g0
   7661 	retl
   7662 	 nop
   7663 #else
   7664 	retl
   7665 	 wr	%o2, TICK_CMPR
   7666 #endif
   7667 
   7668 /*
   7669  * next_stick(long increment)
   7670  *
   7671  * Sets the %stick_cmpr register to fire off in `increment' machine
   7672  * cycles in the future.  Also handles %stick wraparound.  In 32-bit
   7673  * mode we're limited to a 32-bit increment.
   7674  */
   7675 ENTRY(next_stick)
   7676 	rd	STICK_CMPR, %o2
   7677 	rd	STICK, %o1
   7678 
   7679 	mov	1, %o3		! Mask off high bits of these registers
   7680 	sllx	%o3, 63, %o3
   7681 	andn	%o1, %o3, %o1
   7682 	andn	%o2, %o3, %o2
   7683 	cmp	%o1, %o2	! Did we wrap?  (stick < stick_cmpr)
   7684 	bgt,pt	%xcc, 1f
   7685 	 add	%o1, 1000, %o1	! Need some slack so we don't lose intrs.
   7686 
   7687 	/*
   7688 	 * Handle the unlikely case of %stick wrapping.
   7689 	 *
   7690 	 * This should only happen every 10 years or more.
   7691 	 *
   7692 	 * We need to increment the time base by the size of %stick in
   7693 	 * microseconds.  This will require some divides and multiplies
   7694 	 * which can take time.  So we re-read %stick.
   7695 	 *
   7696 	 */
   7697 
   7698 	/* XXXXX NOT IMPLEMENTED */
   7699 
   7700 
   7701 
   7702 1:
   7703 	add	%o2, %o0, %o2
   7704 	andn	%o2, %o3, %o4
   7705 	brlz,pn	%o4, Lstick_ovflw
   7706 	 cmp	%o2, %o1	! Has this stick passed?
   7707 	blt,pn	%xcc, 1b	! Yes
   7708 	 nop
   7709 	retl
   7710 	 wr	%o2, STICK_CMPR
   7711 
   7712 Lstick_ovflw:
   7713 /*
   7714  * When we get here tick_cmpr has wrapped, but we don't know if %stick
   7715  * has wrapped.  If bit 62 is set then we have not wrapped and we can
   7716  * use the current value of %o4 as %stick.  Otherwise we need to return
   7717  * to our loop with %o4 as %stick_cmpr (%o2).
   7718  */
   7719 	srlx	%o3, 1, %o5
   7720 	btst	%o5, %o1
   7721 	bz,pn	%xcc, 1b
   7722 	 mov	%o4, %o2
   7723 	retl
   7724 	 wr	%o2, STICK_CMPR
   7725 
   7726 /*
   7727  * next_stick_init()
   7728  *
   7729  * Sets the %stick_cmpr register to the value retrieved from %stick so
   7730  * next_stick() does not spend too much time in the function when called
   7731  * for the first time.
   7732  * This has been observed on (at least) a SPARC-T5 (sun4v) system where
   7733  * the %stick_cmpr ends up being less than the %stick value and then
   7734  * the stickitr() interrupt is never triggered.
   7735  */
   7736 ENTRY(next_stick_init)
   7737 	rd	STICK, %o0
   7738 	mov	1, %o1		! Mask off high bits of the register
   7739 	sllx	%o1, 63, %o1
   7740 	andn	%o0, %o1, %o0
   7741 	retl
   7742 	 wr	%o0, STICK_CMPR
   7743 
   7744 ENTRY(setjmp)
   7745 	save	%sp, -CC64FSZ, %sp	! Need a frame to return to.
   7746 	flushw
   7747 	stx	%fp, [%i0+0]	! 64-bit stack pointer
   7748 	stx	%i7, [%i0+8]	! 64-bit return pc
   7749 	ret
   7750 	 restore	%g0, 0, %o0
   7751 
   7752 	.data
   7753 Lpanic_ljmp:
   7754 	.asciz	"longjmp botch"
   7755 	_ALIGN
   7756 	.text
   7757 
   7758 ENTRY(longjmp)
   7759 	save	%sp, -CC64FSZ, %sp	! prepare to restore to (old) frame
   7760 	flushw
   7761 	mov	1, %i2
   7762 	ldx	[%i0+0], %fp	! get return stack
   7763 	ldx	[%i0+8], %i7	! get rpc
   7764 	ret
   7765 	 restore	%i2, 0, %o0
   7766 
   7767 #if defined(DDB) || defined(KGDB)
   7768 	/*
   7769 	 * Debug stuff.  Dump the trap registers into buffer & set tl=0.
   7770 	 *
   7771 	 *  %o0 = *ts
   7772 	 */
   7773 ENTRY(savetstate)
   7774 	mov	%o0, %o1
   7775 	rdpr	%tl, %o0
   7776 	brz	%o0, 2f
   7777 	 mov	%o0, %o2
   7778 1:
   7779 	rdpr	%tstate, %o3
   7780 	stx	%o3, [%o1]
   7781 	deccc	%o2
   7782 	inc	8, %o1
   7783 	rdpr	%tpc, %o4
   7784 	stx	%o4, [%o1]
   7785 	inc	8, %o1
   7786 	rdpr	%tnpc, %o5
   7787 	stx	%o5, [%o1]
   7788 	inc	8, %o1
   7789 	rdpr	%tt, %o4
   7790 	stx	%o4, [%o1]
   7791 	inc	8, %o1
   7792 	bnz	1b
   7793 	 wrpr	%o2, 0, %tl
   7794 2:
   7795 	retl
   7796 	 nop
   7797 
   7798 	/*
   7799 	 * Debug stuff.  Restore trap registers from buffer.
   7800 	 *
   7801 	 *  %o0 = %tl
   7802 	 *  %o1 = *ts
   7803 	 *
   7804 	 * Maybe this should be re-written to increment tl instead of decrementing.
   7805 	 */
   7806 ENTRY(restoretstate)
   7807 	flushw			! Make sure we don't have stack probs & lose hibits of %o
   7808 	brz,pn	%o0, 2f
   7809 	 mov	%o0, %o2
   7810 	wrpr	%o0, 0, %tl
   7811 1:
   7812 	ldx	[%o1], %o3
   7813 	deccc	%o2
   7814 	inc	8, %o1
   7815 	wrpr	%o3, 0, %tstate
   7816 	ldx	[%o1], %o4
   7817 	inc	8, %o1
   7818 	wrpr	%o4, 0, %tpc
   7819 	ldx	[%o1], %o5
   7820 	inc	8, %o1
   7821 	wrpr	%o5, 0, %tnpc
   7822 	ldx	[%o1], %o4
   7823 	inc	8, %o1
   7824 	wrpr	%o4, 0, %tt
   7825 	bnz	1b
   7826 	 wrpr	%o2, 0, %tl
   7827 2:
   7828 	retl
   7829 	 wrpr	%o0, 0, %tl
   7830 
   7831 	/*
   7832 	 * Switch to context in abs(%o0)
   7833 	 */
   7834 ENTRY(switchtoctx_us)
   7835 	set	DEMAP_CTX_SECONDARY, %o3
   7836 	stxa	%o3, [%o3] ASI_DMMU_DEMAP
   7837 	mov	CTX_SECONDARY, %o4
   7838 	stxa	%o3, [%o3] ASI_IMMU_DEMAP
   7839 	membar	#Sync
   7840 	stxa	%o0, [%o4] ASI_DMMU		! Maybe we should invalid
   7841 	sethi	%hi(KERNBASE), %o2
   7842 	membar	#Sync
   7843 	flush	%o2
   7844 	retl
   7845 	 nop
   7846 
   7847 ENTRY(switchtoctx_usiii)
   7848 	mov	CTX_SECONDARY, %o4
   7849 	ldxa	[%o4] ASI_DMMU, %o2		! Load secondary context
   7850 	mov	CTX_PRIMARY, %o5
   7851 	ldxa	[%o5] ASI_DMMU, %o1		! Save primary context
   7852 	membar	#LoadStore
   7853 	stxa	%o2, [%o5] ASI_DMMU		! Insert secondary for demap
   7854 	membar	#Sync
   7855 	set	DEMAP_CTX_PRIMARY, %o3
   7856 	stxa	%o3, [%o3] ASI_DMMU_DEMAP
   7857 	membar	#Sync
   7858 	stxa	%o0, [%o4] ASI_DMMU		! Maybe we should invalid
   7859 	membar	#Sync
   7860 	stxa	%o1, [%o5] ASI_DMMU		! Restore primary context
   7861 	sethi	%hi(KERNBASE), %o2
   7862 	membar	#Sync
   7863 	flush	%o2
   7864 	retl
   7865 	 nop
   7866 
   7867 #ifndef _LP64
   7868 	/*
   7869 	 * Convert to 32-bit stack then call OF_sym2val()
   7870 	 */
   7871 ENTRY(OF_sym2val32)
   7872 	save	%sp, -CC64FSZ, %sp
   7873 	btst	7, %i0
   7874 	bnz,pn	%icc, 1f
   7875 	 add	%sp, BIAS, %o1
   7876 	btst	1, %sp
   7877 	movnz	%icc, %o1, %sp
   7878 	call	_C_LABEL(OF_sym2val)
   7879 	 mov	%i0, %o0
   7880 1:
   7881 	ret
   7882 	 restore	%o0, 0, %o0
   7883 
   7884 	/*
   7885 	 * Convert to 32-bit stack then call OF_val2sym()
   7886 	 */
   7887 ENTRY(OF_val2sym32)
   7888 	save	%sp, -CC64FSZ, %sp
   7889 	btst	7, %i0
   7890 	bnz,pn	%icc, 1f
   7891 	 add	%sp, BIAS, %o1
   7892 	btst	1, %sp
   7893 	movnz	%icc, %o1, %sp
   7894 	call	_C_LABEL(OF_val2sym)
   7895 	 mov	%i0, %o0
   7896 1:
   7897 	ret
   7898 	 restore	%o0, 0, %o0
   7899 #endif /* _LP64 */
   7900 #endif /* DDB */
   7901 
   7902 
   7903 #if defined(MULTIPROCESSOR)
   7904 /*
   7905  * IPI target function to setup a C compatible environment and call a MI function.
   7906  *
   7907  * On entry:
   7908  *	We are on one of the alternate set of globals
   7909  *	%g2 = function to call
   7910  *	%g3 = single argument to called function
   7911  */
   7912 ENTRY(sparc64_ipi_ccall)
   7913 #ifdef TRAPS_USE_IG
   7914 	wrpr	%g0, PSTATE_KERN|PSTATE_IG, %pstate	! DEBUG
   7915 #endif
   7916 	TRAP_SETUP(-CC64FSZ-TF_SIZE)
   7917 
   7918 #ifdef DEBUG
   7919 	rdpr	%tt, %o1	! debug
   7920 	sth	%o1, [%sp + CC64FSZ + STKB + TF_TT]! debug
   7921 #endif
   7922 	mov	%g3, %o0			! save argument of function to call
   7923 	mov	%g2, %o5			! save function pointer
   7924 
   7925 	wrpr	%g0, PSTATE_KERN, %pstate	! Get back to normal globals
   7926 	stx	%g1, [%sp + CC64FSZ + STKB + TF_G + ( 1*8)]
   7927 	rdpr	%tpc, %o2			! (pc)
   7928 	stx	%g2, [%sp + CC64FSZ + STKB + TF_G + ( 2*8)]
   7929 	rdpr	%tstate, %g1
   7930 	stx	%g3, [%sp + CC64FSZ + STKB + TF_G + ( 3*8)]
   7931 	rdpr	%tnpc, %o3
   7932 	stx	%g4, [%sp + CC64FSZ + STKB + TF_G + ( 4*8)]
   7933 	rd	%y, %o4
   7934 	stx	%g5, [%sp + CC64FSZ + STKB + TF_G + ( 5*8)]
   7935 	stx	%g6, [%sp + CC64FSZ + STKB + TF_G + ( 6*8)]
   7936 	stx	%g7, [%sp + CC64FSZ + STKB + TF_G + ( 7*8)]
   7937 
   7938 	stx	%g1, [%sp + CC64FSZ + STKB + TF_TSTATE]
   7939 	stx	%o2, [%sp + CC64FSZ + STKB + TF_PC]
   7940 	stx	%o3, [%sp + CC64FSZ + STKB + TF_NPC]
   7941 	st	%o4, [%sp + CC64FSZ + STKB + TF_Y]
   7942 
   7943 	rdpr	%pil, %g5
   7944 	stb	%g5, [%sp + CC64FSZ + STKB + TF_PIL]
   7945 	stb	%g5, [%sp + CC64FSZ + STKB + TF_OLDPIL]
   7946 
   7947 	rdpr	%tl, %g7
   7948 	dec	%g7
   7949 	movrlz	%g7, %g0, %g7
   7950 	wrpr	%g0, %g7, %tl
   7951 	!! In the EMBEDANY memory model %g4 points to the start of the data segment.
   7952 	!! In our case we need to clear it before calling any C-code
   7953 	clr	%g4
   7954 	wr	%g0, ASI_NUCLEUS, %asi			! default kernel ASI
   7955 
   7956 	call %o5					! call function
   7957 	 nop
   7958 
   7959 	b	return_from_trap			! and return from IPI
   7960 	 ldx	[%sp + CC64FSZ + STKB + TF_TSTATE], %g1	! Load this for return_from_trap
   7961 
   7962 #endif
   7963 
   7964 ENTRY(paravirt_membar_sync)
   7965 	/*
   7966 	 * Store-before-load ordering with respect to matching logic
   7967 	 * on the hypervisor side.
   7968 	 *
   7969 	 * This is the same as membar_sync, but without patching or
   7970 	 * conditionalizing away the MEMBAR instruction on uniprocessor
   7971 	 * builds or boots -- because under virtualization, we still
   7972 	 * have to coordinate with a `device' backed by a hypervisor
   7973 	 * that is potentially on another physical CPU even if we
   7974 	 * observe only one virtual CPU as the guest.
   7975 	 *
   7976 	 * See common/lib/libc/arch/sparc64/atomic/membar_ops.S for why
   7977 	 * we avoid using the delay slot and keep this in sync with the
   7978 	 * implementation of membar_sync there.
   7979 	 */
   7980 	membar	#StoreLoad
   7981 	retl
   7982 	 nop
   7983 END(paravirt_membar_sync)
   7984 
   7985 	.data
   7986 	_ALIGN
   7987 #if NKSYMS || defined(DDB) || defined(MODULAR)
   7988 	.globl	_C_LABEL(esym)
   7989 _C_LABEL(esym):
   7990 	POINTER	0
   7991 	.globl	_C_LABEL(ssym)
   7992 _C_LABEL(ssym):
   7993 	POINTER	0
   7994 #endif
   7995 	.comm	_C_LABEL(promvec), PTRSZ
   7996 
   7997 #ifdef DEBUG
   7998 	.comm	_C_LABEL(trapdebug), 4
   7999 	.comm	_C_LABEL(pmapdebug), 4
   8000 #endif
   8001