27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5febcc4a5Sjimand * Common Development and Distribution License (the "License").
6febcc4a5Sjimand * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
22*a4ca1d52SChristopher Baumbauer - Oracle America - San Diego United States * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate#if !defined(__lint)
267c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
277c478bd9Sstevel@tonic-gate#include <sys/trap.h>
287c478bd9Sstevel@tonic-gate#include <sys/mmu.h>
297c478bd9Sstevel@tonic-gate#include <sys/machasi.h>
307c478bd9Sstevel@tonic-gate#include <sys/intreg.h>
317c478bd9Sstevel@tonic-gate#define	_KERNEL
327c478bd9Sstevel@tonic-gate#include <sys/privregs.h>
337c478bd9Sstevel@tonic-gate#undef _KERNEL
347c478bd9Sstevel@tonic-gate#include <sys/machthread.h>
357c478bd9Sstevel@tonic-gate#include <sys/machtrap.h>
367c478bd9Sstevel@tonic-gate#include <sys/machparam.h>
397c478bd9Sstevel@tonic-gate#include <mdb/mdb_kreg_impl.h>
407c478bd9Sstevel@tonic-gate#include <kmdb/kaif_regs.h>
417c478bd9Sstevel@tonic-gate#include <kmdb/kaif_off.h>
427c478bd9Sstevel@tonic-gate#include <kmdb/kaif.h>
437c478bd9Sstevel@tonic-gate#include <kmdb/kaif_asmutil.h>
457c478bd9Sstevel@tonic-gate#define	KAIF_CPU_INDEX				\
467c478bd9Sstevel@tonic-gate	set	mdb, %g1;			\
477c478bd9Sstevel@tonic-gate	ldx	[%g1 + MDB_KDI], %g1;		\
487c478bd9Sstevel@tonic-gate	ldx	[%g1 + MKDI_CPU_INDEX], %g1;	\
497c478bd9Sstevel@tonic-gate	set	1f, %g7;			\
507c478bd9Sstevel@tonic-gate	jmp	%g1;				\
517c478bd9Sstevel@tonic-gate	nop;					\
547c478bd9Sstevel@tonic-gate#define	KAIF_CPU_GETADDR_TL1			\
557c478bd9Sstevel@tonic-gate	set	kaif_cpusave_getaddr, %g6;	\
567c478bd9Sstevel@tonic-gate	sethi	%hi(1f), %g7;			\
577c478bd9Sstevel@tonic-gate	jmp	%g6;				\
587c478bd9Sstevel@tonic-gate	or	%g7, %lo(1f), %g7;		\
617c478bd9Sstevel@tonic-gate#define	KAIF_COPY_KREG(src, tgt, idx, tmp)	\
627c478bd9Sstevel@tonic-gate	ldx	[src + KREG_OFF(idx)], tmp;	\
637c478bd9Sstevel@tonic-gate	stx	tmp, [tgt + KREG_OFF(idx)]
65febcc4a5Sjimand#ifndef sun4v
67febcc4a5Sjimand * Creates a new primary context register value by copying the nucleus page
68febcc4a5Sjimand * size bits to the primary context page size bits and setting the primary
69febcc4a5Sjimand * context to zero.  The updated value is stored in the ctx parameter.
70febcc4a5Sjimand */
71febcc4a5Sjimand#define	KAIF_MAKE_NEW_CTXREG(ctx, tmp)		\
72febcc4a5Sjimand	srlx	ctx, CTXREG_NEXT_SHIFT, ctx ;	\
73febcc4a5Sjimand	sllx 	ctx, CTXREG_NEXT_SHIFT, ctx;	\
74febcc4a5Sjimand	sllx	ctx, 3, tmp;			\
75febcc4a5Sjimand	srlx	tmp, CTXREG_NEXT_SHIFT, tmp;	\
76febcc4a5Sjimand	sllx	tmp, CTXREG_EXT_SHIFT, tmp;	\
77febcc4a5Sjimand	or	ctx, tmp, ctx;			\
78febcc4a5Sjimand	srlx	ctx, CTXREG_NEXT_SHIFT + 3, tmp; \
79febcc4a5Sjimand	sllx	tmp, CTXREG_EXT_SHIFT, tmp;	\
80febcc4a5Sjimand	or	ctx, tmp, ctx
81febcc4a5Sjimand#endif /* sun4v */
837c478bd9Sstevel@tonic-gate#if !defined(__lint)
857c478bd9Sstevel@tonic-gate	/*
867c478bd9Sstevel@tonic-gate	 * Calculate the address of the save area for the current CPU.  This
877c478bd9Sstevel@tonic-gate	 * would be a macro, but for need to call platform-specific CPU ID
887c478bd9Sstevel@tonic-gate	 * routines.  The kernel provides, via the KDI, a TL=1-safe "function"
897c478bd9Sstevel@tonic-gate	 * for CPU ID retrieval, which we call here.  The retrieval code returns
907c478bd9Sstevel@tonic-gate	 * the ID in %g1, and is allowed to clobber %g2.  It also assumes that
917c478bd9Sstevel@tonic-gate	 * the return address is in %g7.
927c478bd9Sstevel@tonic-gate	 *
937c478bd9Sstevel@tonic-gate	 * Arguments:
947c478bd9Sstevel@tonic-gate	 *   %g7 - return address
957c478bd9Sstevel@tonic-gate	 * Returns:
967c478bd9Sstevel@tonic-gate	 *   %g6 - address of save area
977c478bd9Sstevel@tonic-gate	 *
987c478bd9Sstevel@tonic-gate	 * %g4 will be preserved.
997c478bd9Sstevel@tonic-gate	 */
1007c478bd9Sstevel@tonic-gate	ENTRY_NP(kaif_cpusave_getaddr)
1027c478bd9Sstevel@tonic-gate	mov	%g7, %g5	! we'll need %g7 for the ID retriever
1037c478bd9Sstevel@tonic-gate	KAIF_CPU_INDEX		! index returned in %g1, clobbers %g2, %g7
1057c478bd9Sstevel@tonic-gate	set	KRS_SIZE, %g2
1067c478bd9Sstevel@tonic-gate	mulx	%g1, %g2, %g2
1077c478bd9Sstevel@tonic-gate	set	kaif_cpusave, %g6
1087c478bd9Sstevel@tonic-gate	ldx	[%g6], %g6
1107c478bd9Sstevel@tonic-gate	jmp	%g5		! return to caller-provided address
1117c478bd9Sstevel@tonic-gate	add	%g6, %g2, %g6
1137c478bd9Sstevel@tonic-gate	SET_SIZE(kaif_cpusave_getaddr)
1157c478bd9Sstevel@tonic-gate	/*
1167c478bd9Sstevel@tonic-gate	 * Save volatile state - state that won't be available when we switch
1177c478bd9Sstevel@tonic-gate	 * back to TL=0.  We're currently at TL=1, and are on either the
1187c478bd9Sstevel@tonic-gate	 * alternate or interrupt globals, so we'll need to do a bit of a
1197c478bd9Sstevel@tonic-gate	 * dance in order to save the normal globals.
1207c478bd9Sstevel@tonic-gate	 *
1217c478bd9Sstevel@tonic-gate	 * NOTE: This routine and kaif_trap_obp must be equivalent.
1227c478bd9Sstevel@tonic-gate	 *
1237c478bd9Sstevel@tonic-gate	 * Parameters:
1247c478bd9Sstevel@tonic-gate	 *  %g7 - return address
1257c478bd9Sstevel@tonic-gate	 *  %g6 - cpusave area
1267c478bd9Sstevel@tonic-gate	 *  %g4 - the %pstate value to get us back to our current globals set
1277c478bd9Sstevel@tonic-gate	 *  %g4 not applicable on sun4v as it uses %gl
1287c478bd9Sstevel@tonic-gate	 */
1307c478bd9Sstevel@tonic-gate	ENTRY_NP(kaif_save_tl1_state)
1327c478bd9Sstevel@tonic-gate	add	%g6, KRS_GREGS + GREG_KREGS, %g5
1347c478bd9Sstevel@tonic-gate	rdpr	%tstate, %g2
1357c478bd9Sstevel@tonic-gate	stx	%g2, [%g6 + KRS_TSTATE]
1367c478bd9Sstevel@tonic-gate	rdpr	%tpc, %g2
1377c478bd9Sstevel@tonic-gate	stx	%g2, [%g5 + KREG_OFF(KREG_PC)]
1387c478bd9Sstevel@tonic-gate	rdpr	%tnpc, %g2
1397c478bd9Sstevel@tonic-gate	stx	%g2, [%g5 + KREG_OFF(KREG_NPC)]
1407c478bd9Sstevel@tonic-gate	rdpr	%tt, %g2
1417c478bd9Sstevel@tonic-gate	stx	%g2, [%g5 + KREG_OFF(KREG_TT)]
1437c478bd9Sstevel@tonic-gate	/*
1447c478bd9Sstevel@tonic-gate	 * Switch over to the normal globals, so we can save them.  We'll need
1457c478bd9Sstevel@tonic-gate	 * our gregs pointer and the return %pstate value, so stash them in
1467c478bd9Sstevel@tonic-gate	 * registers that will be available to us on both sides.
1477c478bd9Sstevel@tonic-gate	 *
1487c478bd9Sstevel@tonic-gate	 * NOTE: Global register sets is selected by %gl register in sun4v.
1497c478bd9Sstevel@tonic-gate	 *	 There is no PSTATE.AG bit in sun4v to select global set.
1507c478bd9Sstevel@tonic-gate	 *       - Normal globals is the set when %gl = 0.
1517c478bd9Sstevel@tonic-gate	 *	 - TL1 globals is the set when %gl = 1.
1527c478bd9Sstevel@tonic-gate	 */
1537c478bd9Sstevel@tonic-gate	SWITCH_TO_NORMAL_GLOBALS();	/* saves %o5 and %o4 */
1547c478bd9Sstevel@tonic-gate	stx	%g1, [%o5 + KREG_OFF(KREG_G1)]
1557c478bd9Sstevel@tonic-gate	stx	%g2, [%o5 + KREG_OFF(KREG_G2)]
1567c478bd9Sstevel@tonic-gate	stx	%g3, [%o5 + KREG_OFF(KREG_G3)]
1577c478bd9Sstevel@tonic-gate	stx	%g4, [%o5 + KREG_OFF(KREG_G4)]
1587c478bd9Sstevel@tonic-gate	stx	%g5, [%o5 + KREG_OFF(KREG_G5)]
1597c478bd9Sstevel@tonic-gate	stx	%g6, [%o5 + KREG_OFF(KREG_G6)]
1607c478bd9Sstevel@tonic-gate	stx	%g7, [%o5 + KREG_OFF(KREG_G7)]
1627c478bd9Sstevel@tonic-gate	/*
1637c478bd9Sstevel@tonic-gate	 * Restore saved %o registers and return.
1647c478bd9Sstevel@tonic-gate	 */
1657c478bd9Sstevel@tonic-gate	SWITCH_TO_TL1_GLOBALS_AND_RET();	/* restores %o5 and %o4 */
1667c478bd9Sstevel@tonic-gate	SET_SIZE(kaif_save_tl1_state)
1687c478bd9Sstevel@tonic-gate	/*
1697c478bd9Sstevel@tonic-gate	 * Save the remaining state, and prepare to enter the debugger.
1707c478bd9Sstevel@tonic-gate	 */
1727c478bd9Sstevel@tonic-gate	ENTRY_NP(kaif_trap_common)
1747c478bd9Sstevel@tonic-gate	/* Make sure the world is as it should be */
1757c478bd9Sstevel@tonic-gate	wrpr	%g0, PTSTATE_KERN_COMMON, %pstate
1767c478bd9Sstevel@tonic-gate	wrpr	%g0, %tl
1787c478bd9Sstevel@tonic-gate	SET_GL(0);
1797c478bd9Sstevel@tonic-gate	set	1f, %g7
1807c478bd9Sstevel@tonic-gate	set	kaif_cpusave_getaddr, %g6
1817c478bd9Sstevel@tonic-gate	jmp	%g6
1827c478bd9Sstevel@tonic-gate	nop
1837c478bd9Sstevel@tonic-gate1:	/* CPU save area address is now in %g6 */
1847c478bd9Sstevel@tonic-gate	add	%g6, KRS_GREGS + GREG_KREGS, %g5
1867c478bd9Sstevel@tonic-gate	ldx	[%g5 + KREG_OFF(KREG_PC)], %g4
1877c478bd9Sstevel@tonic-gate	ADD_CRUMB(%g6, KRM_PC, %g4, %g1)
1887c478bd9Sstevel@tonic-gate	ldx	[%g5 + KREG_OFF(KREG_TT)], %g4
1897c478bd9Sstevel@tonic-gate	ADD_CRUMB(%g6, KRM_TT, %g4, %g1)
1917c478bd9Sstevel@tonic-gate	/*
1927c478bd9Sstevel@tonic-gate	 * The %tba is special.  With normal entry, we're on the same trap table
1937c478bd9Sstevel@tonic-gate	 * the kernel is using (this could be OBP's table if we're early enough
1947c478bd9Sstevel@tonic-gate	 * in the boot process).  We want to save it, but we don't want to
1957c478bd9Sstevel@tonic-gate	 * switch to OBP's table just yet, as we need to ensure that only one
1967c478bd9Sstevel@tonic-gate	 * CPU uses OBP's table at a time.  We do this by waiting until we've
1977c478bd9Sstevel@tonic-gate	 * selected the master before switching.
1987c478bd9Sstevel@tonic-gate	 *
1997c478bd9Sstevel@tonic-gate	 * Single-step is a bit different.  Everything about the CPU's state is
2007c478bd9Sstevel@tonic-gate	 * as it should be, with the exception of %tba.  We need to step on
2017c478bd9Sstevel@tonic-gate	 * OBP's trap table, so we didn't restore %tba during resume.  The save
2027c478bd9Sstevel@tonic-gate	 * state area still contains the real %tba value - the one we had when
2037c478bd9Sstevel@tonic-gate	 * we first entered the debugger.  We don't want to clobber that, so
2047c478bd9Sstevel@tonic-gate	 * we'll only save %tba if we're not stepping.
2057c478bd9Sstevel@tonic-gate	 */
2077c478bd9Sstevel@tonic-gate	set	kaif_master_cpuid, %g1
2087c478bd9Sstevel@tonic-gate	ld	[%g1], %g1
2097c478bd9Sstevel@tonic-gate	ld	[%g6 + KRS_CPU_ID], %g2
2107c478bd9Sstevel@tonic-gate	cmp	%g1, %g2
2117c478bd9Sstevel@tonic-gate	be	1f
2127c478bd9Sstevel@tonic-gate	nop
2147c478bd9Sstevel@tonic-gate	rdpr	%tba, %g2
2157c478bd9Sstevel@tonic-gate	stx	%g2, [%g5 + KREG_OFF(KREG_TBA)]
218*a4ca1d52SChristopher Baumbauer - Oracle America - San Diego United States	/* Update the PIL to 15 to block out most interrupts */
2197c478bd9Sstevel@tonic-gate	rdpr	%pil, %g4
2207c478bd9Sstevel@tonic-gate	stx	%g4, [%g5 + KREG_OFF(KREG_PIL)]
221*a4ca1d52SChristopher Baumbauer - Oracle America - San Diego United States	wrpr	%g0, 15, %pil
2237c478bd9Sstevel@tonic-gate	rd	%y, %g4
2247c478bd9Sstevel@tonic-gate	stx	%g4, [%g5 + KREG_OFF(KREG_Y)]
2267c478bd9Sstevel@tonic-gate	/*
2277c478bd9Sstevel@tonic-gate	 * Save window state and windows
2287c478bd9Sstevel@tonic-gate	 */
2297c478bd9Sstevel@tonic-gate	rdpr	%cwp, %g4
2307c478bd9Sstevel@tonic-gate	stx	%g4, [%g5 + KREG_OFF(KREG_CWP)]
2317c478bd9Sstevel@tonic-gate	rdpr	%otherwin, %g4
2327c478bd9Sstevel@tonic-gate	stx	%g4, [%g5 + KREG_OFF(KREG_OTHERWIN)]
2337c478bd9Sstevel@tonic-gate	rdpr	%cleanwin, %g4
2347c478bd9Sstevel@tonic-gate	stx	%g4, [%g5 + KREG_OFF(KREG_CLEANWIN)]
2357c478bd9Sstevel@tonic-gate	rdpr	%cansave, %g4
2367c478bd9Sstevel@tonic-gate	stx	%g4, [%g5 + KREG_OFF(KREG_CANSAVE)]
2377c478bd9Sstevel@tonic-gate	rdpr	%canrestore, %g4
2387c478bd9Sstevel@tonic-gate	stx	%g4, [%g5 + KREG_OFF(KREG_CANRESTORE)]
2397c478bd9Sstevel@tonic-gate	rdpr	%wstate, %g4
2407c478bd9Sstevel@tonic-gate	stx	%g4, [%g5 + KREG_OFF(KREG_WSTATE)]
2427c478bd9Sstevel@tonic-gate	GET_NWIN(%g1, %g4);	! %g1 is scratch, %g4 set to nwin-1
2447c478bd9Sstevel@tonic-gate	wrpr	%g4, %cleanwin
2467c478bd9Sstevel@tonic-gate	sub	%g4, 1, %g1
2477c478bd9Sstevel@tonic-gate	wrpr	%g1, %cansave
2487c478bd9Sstevel@tonic-gate	wrpr	%g0, %otherwin
2497c478bd9Sstevel@tonic-gate	wrpr	%g0, %canrestore
2507c478bd9Sstevel@tonic-gate	wrpr	%g0, %cwp
2527c478bd9Sstevel@tonic-gate	clr	%g2
2537c478bd9Sstevel@tonic-gate	ldx	[%g6 + KRS_RWINS], %g3
2547c478bd9Sstevel@tonic-gate1:	SAVE_V9WINDOW(%g3)
2557c478bd9Sstevel@tonic-gate	inc	%g2
2567c478bd9Sstevel@tonic-gate	add	%g3, RWIN_SIZE, %g3
2577c478bd9Sstevel@tonic-gate	cmp	%g2, %g4
2587c478bd9Sstevel@tonic-gate	ble	1b
2597c478bd9Sstevel@tonic-gate	wrpr	%g2, %cwp
2617c478bd9Sstevel@tonic-gate	/*
2627c478bd9Sstevel@tonic-gate	 * Save FP state
2637c478bd9Sstevel@tonic-gate	 */
2647c478bd9Sstevel@tonic-gate	add	%g6, KRS_FPREGS, %g4
2657c478bd9Sstevel@tonic-gate	rd	%fprs, %g1
2667c478bd9Sstevel@tonic-gate	stx	%g1, [%g4 + FPU_FPRS]
2677c478bd9Sstevel@tonic-gate	btst	FPRS_FEF, %g1		! is FP enabled?
2687c478bd9Sstevel@tonic-gate	bz	%icc, 1f		! if not, don't save FP regs
2697c478bd9Sstevel@tonic-gate	wr	%g0, FPRS_FEF, %fprs	! enable FP
2717c478bd9Sstevel@tonic-gate	STORE_FPREGS(%g4)
2727c478bd9Sstevel@tonic-gate	stx	%fsr, [%g4 + FPU_FSR]
2747c478bd9Sstevel@tonic-gate1:	/*
2757c478bd9Sstevel@tonic-gate	 * We're almost done saving state.  Go back to the starting window, and
2767c478bd9Sstevel@tonic-gate	 * switch to the CPU-specific stack.  We'll use this stack to finish
2777c478bd9Sstevel@tonic-gate	 * saving state, and for the next stage of debugger startup/resumption,
2787c478bd9Sstevel@tonic-gate	 * when we designate the master.  The slaves will continue to run on
2797c478bd9Sstevel@tonic-gate	 * this stack until released or turned into masters.
2807c478bd9Sstevel@tonic-gate	 */
2817c478bd9Sstevel@tonic-gate	ldx	[%g5 + KREG_OFF(KREG_CWP)], %g4
2827c478bd9Sstevel@tonic-gate	wrpr	%g4, %cwp
2847c478bd9Sstevel@tonic-gate	set	KRS_CPUSTACK + KAIF_CPU_STKSZ - 1, %g1
2857c478bd9Sstevel@tonic-gate	add	%g1, %g6, %g1
2867c478bd9Sstevel@tonic-gate	and	%g1, -STACK_ALIGN64, %g1
2877c478bd9Sstevel@tonic-gate	sub	%g1, SA64(MINFRAME) + V9BIAS64, %sp
2887c478bd9Sstevel@tonic-gate	clr	%fp
2897c478bd9Sstevel@tonic-gate	save	%sp, -SA64(MINFRAME64), %sp
2917c478bd9Sstevel@tonic-gate	/*
2927c478bd9Sstevel@tonic-gate	 * We'll need to access cpusave and gregs for our final state-saving,
2937c478bd9Sstevel@tonic-gate	 * so stash them where they won't be clobbered by function calls.
2947c478bd9Sstevel@tonic-gate	 */
2957c478bd9Sstevel@tonic-gate	mov	%g6, %l6
2967c478bd9Sstevel@tonic-gate	mov	%g5, %l5
2987c478bd9Sstevel@tonic-gate	/*
2997c478bd9Sstevel@tonic-gate	 * Now that we have a stack, we can save %stick.  %stick isn't present
3007c478bd9Sstevel@tonic-gate	 * on all of our target machines, so we have to use the KDI to fetch the
3017c478bd9Sstevel@tonic-gate	 * current value (if any).  We save %tick here too, because they get
3027c478bd9Sstevel@tonic-gate	 * lonely if separated.
3037c478bd9Sstevel@tonic-gate	 */
3047c478bd9Sstevel@tonic-gate	rd	%tick, %g4
3057c478bd9Sstevel@tonic-gate	stx	%g4, [%l5 + KREG_OFF(KREG_TICK)]
3077c478bd9Sstevel@tonic-gate	call	kmdb_kdi_get_stick
3087c478bd9Sstevel@tonic-gate	add	%l5, KREG_OFF(KREG_STICK), %o0
3097c478bd9Sstevel@tonic-gate	brnz	%o0, 1f
3107c478bd9Sstevel@tonic-gate	nop
3127c478bd9Sstevel@tonic-gate	/*
3137c478bd9Sstevel@tonic-gate	 * We found %stick.  Set the %stick-found flag.
3147c478bd9Sstevel@tonic-gate	 */
3157c478bd9Sstevel@tonic-gate	ld	[%l5 + GREG_FLAGS], %g1
3167c478bd9Sstevel@tonic-gate	or	%g1, MDB_V9GREG_F_STICK_VALID, %g1
3177c478bd9Sstevel@tonic-gate	st	%g1, [%l5 + GREG_FLAGS]
3197c478bd9Sstevel@tonic-gate1:	/*
3207c478bd9Sstevel@tonic-gate	 * Enter the next phase of debugger startup
3217c478bd9Sstevel@tonic-gate	 */
3227c478bd9Sstevel@tonic-gate	call	kaif_debugger_entry
3237c478bd9Sstevel@tonic-gate	mov	%l6, %o0
3257c478bd9Sstevel@tonic-gate	ba,a	kaif_resume	! expects valid %l5, %l6
3277c478bd9Sstevel@tonic-gate	/*NOTREACHED*/
3297c478bd9Sstevel@tonic-gate	SET_SIZE(kaif_trap_common)
3317c478bd9Sstevel@tonic-gate#endif	/* !__lint */
3337c478bd9Sstevel@tonic-gate	/*
3347c478bd9Sstevel@tonic-gate	 * The primary debugger-entry routine.  This routine is the trap handler
3357c478bd9Sstevel@tonic-gate	 * for programmed entry, watchpoints, and breakpoints, and is entered at
3367c478bd9Sstevel@tonic-gate	 * TL=1, on the kernel's trap table, with PSTATE.AG set.  It is used in
3377c478bd9Sstevel@tonic-gate	 * the following cases:
3387c478bd9Sstevel@tonic-gate	 *
3397c478bd9Sstevel@tonic-gate	 * 1. (common case) - intentional entry by a CPU intending to be the
3407c478bd9Sstevel@tonic-gate	 *    master.  The CPU may have encountered a watchpoint, a breakpoint,
3417c478bd9Sstevel@tonic-gate	 *    or a programmed entry trap, and is *NOT* coming from OBP.  The CPU
3427c478bd9Sstevel@tonic-gate	 *    is allowed direct entry into the debugger.
3437c478bd9Sstevel@tonic-gate	 *
3447c478bd9Sstevel@tonic-gate	 * 2. A CPU was cross-called into kaif_slave_entry while executing in
3457c478bd9Sstevel@tonic-gate	 *    OBP.  The CPU was released, but a programmed entry trap was
3467c478bd9Sstevel@tonic-gate	 *    activated, designed to be encountered when the cross-called CPU
3477c478bd9Sstevel@tonic-gate	 *    returned from OBP.  The CPU is allowed to enter the debugger.  We
3487c478bd9Sstevel@tonic-gate	 *    don't know how many other CPUs need the PROM-return trap, so we'll
3497c478bd9Sstevel@tonic-gate	 *    leave it active until everyone arrives.
3507c478bd9Sstevel@tonic-gate	 *
3517c478bd9Sstevel@tonic-gate	 * The remaining cases deal with instances where OBP got in the way.
3527c478bd9Sstevel@tonic-gate	 * We can't allow a CPU into the debugger if it is currently executing
3537c478bd9Sstevel@tonic-gate	 * in OBP, as chaos would ensue (OBP isn't re-entrant).  As such, we
3547c478bd9Sstevel@tonic-gate	 * have to ask the CPU to come back when it has finished with OBP (or
3557c478bd9Sstevel@tonic-gate	 * vice versa).  Depending on the circumstances, we'll need to dance
3567c478bd9Sstevel@tonic-gate	 * around it.
3577c478bd9Sstevel@tonic-gate	 *
3587c478bd9Sstevel@tonic-gate	 * 3. A bystander CPU runs into the PROM-return trap described above
3597c478bd9Sstevel@tonic-gate	 *    before being cross-called.  We'll let it into the debugger now, as
3607c478bd9Sstevel@tonic-gate	 *    it would have ended up here anyway.
3617c478bd9Sstevel@tonic-gate	 *
3627c478bd9Sstevel@tonic-gate	 * 4. An innocent CPU encounters a watchpoint while executing in OBP.
3637c478bd9Sstevel@tonic-gate	 *    We can't let the CPU into the debugger for the reasons given
3647c478bd9Sstevel@tonic-gate	 *    above, so we'll need to ignore the watchpoint.  We disable
3657c478bd9Sstevel@tonic-gate	 *    watchpoints, place a programmed-entry trap at %npc, and release
3667c478bd9Sstevel@tonic-gate	 *    the CPU.
3677c478bd9Sstevel@tonic-gate	 *
3687c478bd9Sstevel@tonic-gate	 * 5. The stepping CPU described in case 4 encounters the programmed-
3697c478bd9Sstevel@tonic-gate	 *    entry trap.  We'll remove the trap, re-enable watchpoints, and
3707c478bd9Sstevel@tonic-gate	 *    send the CPU on its way.
3717c478bd9Sstevel@tonic-gate	 *
3727c478bd9Sstevel@tonic-gate	 * 6. Someone encounters a breakpoint or a programmed-entry trap in OBP.
3737c478bd9Sstevel@tonic-gate	 *    We can step through watchpoints, as the text hasn't been touched.
3747c478bd9Sstevel@tonic-gate	 *    With breakpoints and programmed-entry traps, however, chances are
3757c478bd9Sstevel@tonic-gate	 *    high that someone replaced an instruction in the text with the
3767c478bd9Sstevel@tonic-gate	 *    trap instruction.  We don't know where they stashed the
3777c478bd9Sstevel@tonic-gate	 *    (presumably) saved instruction, so we can't step through it.  This
3787c478bd9Sstevel@tonic-gate	 *    is a very unlikely scenario, so we're going to throw up our hands,
3797c478bd9Sstevel@tonic-gate	 *    and will attempt to trigger a panic.
3807c478bd9Sstevel@tonic-gate	 */
3827c478bd9Sstevel@tonic-gate#if defined(__lint)
3877c478bd9Sstevel@tonic-gate#else	/* __lint */
3897c478bd9Sstevel@tonic-gate	ENTRY_NP(kaif_ktrap)
3917c478bd9Sstevel@tonic-gate	set	1f, %g7
3927c478bd9Sstevel@tonic-gate	set	kaif_cpusave_getaddr, %g6
3937c478bd9Sstevel@tonic-gate	jmp	%g6
3947c478bd9Sstevel@tonic-gate	nop
3957c478bd9Sstevel@tonic-gate1:	/* CPU save area address is now in %g6 */
3977c478bd9Sstevel@tonic-gate	ADVANCE_CRUMB_POINTER(%g6, %g1, %g2)
3987c478bd9Sstevel@tonic-gate	ADD_CRUMB_CONST(%g6, KRM_SRC, KAIF_CRUMB_SRC_MAIN, %g1, %g2)
4007c478bd9Sstevel@tonic-gate	rdpr	%tpc, %g2
4017c478bd9Sstevel@tonic-gate	set	OFW_START_ADDR, %g1
4027c478bd9Sstevel@tonic-gate	cmp	%g2, %g1
4037c478bd9Sstevel@tonic-gate	bl	main_not_in_obp
4047c478bd9Sstevel@tonic-gate	nop
4067c478bd9Sstevel@tonic-gate	set	OFW_END_ADDR, %g1
4077c478bd9Sstevel@tonic-gate	cmp	%g2, %g1
4087c478bd9Sstevel@tonic-gate	bg	main_not_in_obp
4097c478bd9Sstevel@tonic-gate	nop
4117c478bd9Sstevel@tonic-gate	/*
4127c478bd9Sstevel@tonic-gate	 * The CPU was in OBP when it encountered the trap that sent it here.
4137c478bd9Sstevel@tonic-gate	 * See cases 3-6 above.
4147c478bd9Sstevel@tonic-gate	 */
4157c478bd9Sstevel@tonic-gate	rdpr	%tt, %g4
4167c478bd9Sstevel@tonic-gate	cmp	%g4, T_PA_WATCHPOINT
4177c478bd9Sstevel@tonic-gate	be	main_obp_wapt
4197c478bd9Sstevel@tonic-gate	cmp	%g4, T_VA_WATCHPOINT
4207c478bd9Sstevel@tonic-gate	be	main_obp_wapt
4227c478bd9Sstevel@tonic-gate	cmp	%g4, T_SOFTWARE_TRAP|ST_KMDB_TRAP
4237c478bd9Sstevel@tonic-gate	be	main_obp_progent
4257c478bd9Sstevel@tonic-gate	cmp	%g4, T_SOFTWARE_TRAP|ST_BREAKPOINT
4267c478bd9Sstevel@tonic-gate	be	main_obp_breakpoint
4277c478bd9Sstevel@tonic-gate	nop
4297c478bd9Sstevel@tonic-gate	/* This shouldn't happen - all valid traps should be checked above */
4307c478bd9Sstevel@tonic-gate1:	ldx	[%g0], %g0
4317c478bd9Sstevel@tonic-gate	ba,a	1b
4337c478bd9Sstevel@tonic-gate	/* Cases 1 and 2 - head into the debugger, via the state-saver */
4357c478bd9Sstevel@tonic-gate	ADD_CRUMB_FLAG(%g6, KAIF_CRUMB_F_MAIN_NORMAL, %g1, %g2, %g3)
4377c478bd9Sstevel@tonic-gate	/* A formality - we know we came from kernel context */
4387c478bd9Sstevel@tonic-gate	mov	MMU_PCONTEXT, %g3
4397c478bd9Sstevel@tonic-gate	ldxa	[%g3]ASI_MMU_CTX, %g2	! ASI_MMU_CTX == ASI_DMMU for sun4u
4407c478bd9Sstevel@tonic-gate	stx	%g2, [%g6 + KRS_MMU_PCONTEXT]
442febcc4a5Sjimand#ifndef sun4v
443febcc4a5Sjimand	/*
444febcc4a5Sjimand	 * If OBP supports preserving the Solaris kernel context register,
445febcc4a5Sjimand	 * then shift the nucleus bits into the primary and set context to 0,
446febcc4a5Sjimand	 * Otherwise, flush TLBs and clear the entire context register since
447febcc4a5Sjimand	 * OBP will clear it without flushing on entry to OBP.
448febcc4a5Sjimand	 */
449febcc4a5Sjimand	sethi	%hi(kmdb_prom_preserve_kctx), %g4
450febcc4a5Sjimand	ld	[%g4 + %lo(kmdb_prom_preserve_kctx)], %g4
451febcc4a5Sjimand	brz	%g4, 1f
452febcc4a5Sjimand	  nop
453febcc4a5Sjimand	/*
454febcc4a5Sjimand	 * Move nucleus context page size bits into primary context page size
455febcc4a5Sjimand	 * and set context to 0.  Use %g4 as a temporary.
456febcc4a5Sjimand	 */
457febcc4a5Sjimand	KAIF_MAKE_NEW_CTXREG(%g2, %g4)		! new context reg in %g2
459febcc4a5Sjimand	stxa	%g2, [%g3]ASI_MMU_CTX
460febcc4a5Sjimand	membar	#Sync
461febcc4a5Sjimand	ba	2f
462febcc4a5Sjimand	  nop
464febcc4a5Sjimand#endif /* sun4v */
465febcc4a5Sjimand	/*
466febcc4a5Sjimand	 * Flush TLBs and clear primary context register.
467febcc4a5Sjimand	 */
4687c478bd9Sstevel@tonic-gate	KAIF_DEMAP_TLB_ALL(%g4)
4697c478bd9Sstevel@tonic-gate	stxa	%g0, [%g3]ASI_MMU_CTX	! ASI_MMU_CTX == ASI_DMMU for sun4u
4707c478bd9Sstevel@tonic-gate	membar	#Sync
4737c478bd9Sstevel@tonic-gate	set	kaif_trap_common, %g7
4757c478bd9Sstevel@tonic-gate	KAIF_SAVE_TL1_STATE();
4767c478bd9Sstevel@tonic-gate	/*NOTREACHED*/
4787c478bd9Sstevel@tonic-gate	/* Case 4 - watchpoint in OBP - step over it */
4807c478bd9Sstevel@tonic-gate	ADD_CRUMB_FLAG(%g6, KAIF_CRUMB_F_MAIN_OBPWAPT, %g1, %g2, %g3)
4827c478bd9Sstevel@tonic-gate#ifndef sun4v
4837c478bd9Sstevel@tonic-gate	/* Turn off watchpoints */
4847c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_LSU, %g4
4857c478bd9Sstevel@tonic-gate	stx	%g4, [%g6 + KRS_LSUCR_SAVE]
4867c478bd9Sstevel@tonic-gate	setx	KAIF_LSUCTL_WAPT_MASK, %g1, %g3
4877c478bd9Sstevel@tonic-gate	andn	%g4, %g3, %g4
4887c478bd9Sstevel@tonic-gate	stxa	%g4, [%g0]ASI_LSU
4897c478bd9Sstevel@tonic-gate#endif /* sun4v */
4917c478bd9Sstevel@tonic-gate	/*
4927c478bd9Sstevel@tonic-gate	 * SPARC only supports data watchpoints, and we know that only certain
4937c478bd9Sstevel@tonic-gate	 * types of instructions, none of which include branches, can trigger
4947c478bd9Sstevel@tonic-gate	 * memory reads.  As such, we can simply place a breakpoint at %npc.
4957c478bd9Sstevel@tonic-gate	 */
4967c478bd9Sstevel@tonic-gate	rdpr	%tnpc, %g4
4977c478bd9Sstevel@tonic-gate	ld	[%g4], %g3
4987c478bd9Sstevel@tonic-gate	st	%g3, [%g6 + KRS_INSTR_SAVE]
4997c478bd9Sstevel@tonic-gate	set	0x91d0207d, %g3	! ta ST_KMDB_TRAP
5007c478bd9Sstevel@tonic-gate	st	%g3, [%g4]
5017c478bd9Sstevel@tonic-gate	flush	%g4
5027c478bd9Sstevel@tonic-gate	membar	#Sync
5047c478bd9Sstevel@tonic-gate	/* Back into the pool */
5057c478bd9Sstevel@tonic-gate	retry
5077c478bd9Sstevel@tonic-gate	/* Case 5 - programmed entry from wapt step - restore and resume */
5097c478bd9Sstevel@tonic-gate	ADD_CRUMB_FLAG(%g6, KAIF_CRUMB_F_MAIN_OBPPENT, %g1, %g2, %g3)
5117c478bd9Sstevel@tonic-gate	rdpr	%tpc, %g4
5127c478bd9Sstevel@tonic-gate	ld	[%g6 + KRS_INSTR_SAVE], %g3
5137c478bd9Sstevel@tonic-gate	brz	%g3, main_obp_fail ! we don't have any open wapt steps
5147c478bd9Sstevel@tonic-gate	nop
5167c478bd9Sstevel@tonic-gate	st	%g3, [%g4]
5177c478bd9Sstevel@tonic-gate	membar	#Sync
5187c478bd9Sstevel@tonic-gate	st	%g0, [%g6 + KRS_INSTR_SAVE]
5207c478bd9Sstevel@tonic-gate	/* XXX I$ invalidate? */
5227c478bd9Sstevel@tonic-gate#ifndef sun4v
5237c478bd9Sstevel@tonic-gate	ldx	[%g6 + KRS_LSUCR_SAVE], %g4
5247c478bd9Sstevel@tonic-gate	stxa	%g4, [%g0]ASI_LSU
5257c478bd9Sstevel@tonic-gate#endif /* sun4v */
5277c478bd9Sstevel@tonic-gate	/* Restored - throw it back */
5287c478bd9Sstevel@tonic-gate	retry
5307c478bd9Sstevel@tonic-gate	/* Case 6 - breakpoint or unclaimed programmed entry */
5337c478bd9Sstevel@tonic-gate	ldx	[%g0], %g0
5347c478bd9Sstevel@tonic-gate	ba,a	main_obp_fail
5367c478bd9Sstevel@tonic-gate	SET_SIZE(kaif_ktrap)
5387c478bd9Sstevel@tonic-gate#endif	/* __lint */
5407c478bd9Sstevel@tonic-gate	/*
5417c478bd9Sstevel@tonic-gate	 * The target for slave-stopping cross calls.  This routine is entered at
5427c478bd9Sstevel@tonic-gate	 * TL=1, on the kernel's trap table, with PSTATE.IG set.  CPUs entering
5437c478bd9Sstevel@tonic-gate	 * this handler will fall into one of the following categories:
5447c478bd9Sstevel@tonic-gate	 *
5457c478bd9Sstevel@tonic-gate	 * 1. (common case) - the CPU was not executing in OBP when it entered
5467c478bd9Sstevel@tonic-gate	 *    this routine.  It will be allowed direct entry into the debugger.
5477c478bd9Sstevel@tonic-gate	 *
5487c478bd9Sstevel@tonic-gate	 * 2. The CPU had already entered the debugger, and was spinning in the
5497c478bd9Sstevel@tonic-gate	 *    slave loop (at TL=0) when it was cross-called by the debugger's
5507c478bd9Sstevel@tonic-gate	 *    world-stopper.  This could happen if two CPUs encountered
5517c478bd9Sstevel@tonic-gate	 *    breakpoints simultaneously, triggering a race to become master.
5527c478bd9Sstevel@tonic-gate	 *    One would lose, and would already be in the slave loop when the
5537c478bd9Sstevel@tonic-gate	 *    master started trying to stop the world.  The CPU is already where
5547c478bd9Sstevel@tonic-gate	 *    it is supposed to be, so we ignore the trap.
5557c478bd9Sstevel@tonic-gate	 *
5567c478bd9Sstevel@tonic-gate	 * 3. The CPU was executing in OBP.  We can't allow it to go directly
5577c478bd9Sstevel@tonic-gate	 *    into OBP (see the kaif_ktrap comment), but we want to grab it when
5587c478bd9Sstevel@tonic-gate	 *    it leaves OBP.  Arm the PROM-return programmed entry trap and
5597c478bd9Sstevel@tonic-gate	 *    release the CPU.
5607c478bd9Sstevel@tonic-gate	 */
5627c478bd9Sstevel@tonic-gate#if defined(__lint)
5677c478bd9Sstevel@tonic-gate#else	/* __lint */
5697c478bd9Sstevel@tonic-gate	ENTRY_NP(kaif_slave_entry)
5717c478bd9Sstevel@tonic-gate	/*
5727c478bd9Sstevel@tonic-gate	 * We may have arrived from userland.  We need to be in kernel context
5737c478bd9Sstevel@tonic-gate	 * before we can save state, so we'll stash the current value in %g4
5747c478bd9Sstevel@tonic-gate	 * until we've calculated the save address and have decided that we're
5757c478bd9Sstevel@tonic-gate	 * heading into the debugger.
5767c478bd9Sstevel@tonic-gate	 *
5777c478bd9Sstevel@tonic-gate	 * %g4 is used to hold the entry MMU context until we decide whether to
5787c478bd9Sstevel@tonic-gate	 * return or re-enter the debugger.
5797c478bd9Sstevel@tonic-gate	 */
5807c478bd9Sstevel@tonic-gate	mov	MMU_PCONTEXT, %g3
5817c478bd9Sstevel@tonic-gate	ldxa	[%g3]ASI_MMU_CTX, %g4
583febcc4a5Sjimand#ifndef sun4v
584febcc4a5Sjimand	/*
585febcc4a5Sjimand	 * If OBP supports preserving the Solaris kernel context register,
586febcc4a5Sjimand	 * then shift the nucleus bits into the primary and set context to 0,
587febcc4a5Sjimand	 * Otherwise, flush TLBs and clear the entire context register since
588febcc4a5Sjimand	 * OBP will clear it without flushing on entry to OBP.
589febcc4a5Sjimand	 */
590febcc4a5Sjimand	sethi	%hi(kmdb_prom_preserve_kctx), %g1
591febcc4a5Sjimand	ld	[%g1 + %lo(kmdb_prom_preserve_kctx)], %g1
592febcc4a5Sjimand	brz	%g1, 1f
593febcc4a5Sjimand	  nop
594febcc4a5Sjimand	/*
595febcc4a5Sjimand	 * Move nucleus context page size bits into primary context page size
596febcc4a5Sjimand	 * and set context to 0.  Use %g2 as a temporary.
597febcc4a5Sjimand	 */
598febcc4a5Sjimand	mov	%g4, %g2
599febcc4a5Sjimand	KAIF_MAKE_NEW_CTXREG(%g2, %g1)		! new context reg in %g2
601febcc4a5Sjimand	stxa	%g2, [%g3]ASI_MMU_CTX
602febcc4a5Sjimand	membar	#Sync
603febcc4a5Sjimand	ba	2f
604febcc4a5Sjimand	  nop
606febcc4a5Sjimand#endif /* sun4v */
607febcc4a5Sjimand	/*
608febcc4a5Sjimand	 * Flush TLBs and clear primary context register.
609febcc4a5Sjimand	 */
6107c478bd9Sstevel@tonic-gate	KAIF_DEMAP_TLB_ALL(%g1)
6117c478bd9Sstevel@tonic-gate	stxa	%g0, [%g3]ASI_MMU_CTX
6127c478bd9Sstevel@tonic-gate	membar	#Sync
6157c478bd9Sstevel@tonic-gate	set	1f, %g7
6167c478bd9Sstevel@tonic-gate	set	kaif_cpusave_getaddr, %g6
6177c478bd9Sstevel@tonic-gate	jmp	%g6		! is not to alter %g4
6187c478bd9Sstevel@tonic-gate	nop
6197c478bd9Sstevel@tonic-gate1:	/* CPU save area address is now in %g6 */
6217c478bd9Sstevel@tonic-gate	ADVANCE_CRUMB_POINTER(%g6, %g1, %g2)
6227c478bd9Sstevel@tonic-gate	ADD_CRUMB_CONST(%g6, KRM_SRC, KAIF_CRUMB_SRC_IVEC, %g1, %g2)
6247c478bd9Sstevel@tonic-gate	ld	[%g6 + KRS_CPU_STATE], %g5
6257c478bd9Sstevel@tonic-gate	cmp	%g5, KAIF_CPU_STATE_NONE
6267c478bd9Sstevel@tonic-gate	be,a	ivec_not_already_in_debugger
6287c478bd9Sstevel@tonic-gate	/* Case 2 - CPU was already stopped, so ignore this cross call */
6297c478bd9Sstevel@tonic-gate	ADD_CRUMB_FLAG(%g6, KAIF_CRUMB_F_IVEC_REENTER, %g1, %g2, %g3)
6317c478bd9Sstevel@tonic-gate	/* Restore MMU_PCONTEXT, which we set on the way in */
6327c478bd9Sstevel@tonic-gate	mov	MMU_PCONTEXT, %g3
6337c478bd9Sstevel@tonic-gate	KAIF_DEMAP_TLB_ALL(%g2)
6347c478bd9Sstevel@tonic-gate	stxa	%g4, [%g3]ASI_MMU_CTX
6357c478bd9Sstevel@tonic-gate	membar	#Sync
6377c478bd9Sstevel@tonic-gate	retry
6407c478bd9Sstevel@tonic-gate	brnz	%g4, ivec_not_in_obp	/* OBP runs in kernel context */
6417c478bd9Sstevel@tonic-gate	nop
6437c478bd9Sstevel@tonic-gate	/* Were we in OBP's memory range? */
6447c478bd9Sstevel@tonic-gate	rdpr	%tpc, %g2
6457c478bd9Sstevel@tonic-gate	set	OFW_START_ADDR, %g1
6467c478bd9Sstevel@tonic-gate	cmp	%g2, %g1
6477c478bd9Sstevel@tonic-gate	bl	ivec_not_in_obp
6487c478bd9Sstevel@tonic-gate	nop
6507c478bd9Sstevel@tonic-gate	set	OFW_END_ADDR, %g1
6517c478bd9Sstevel@tonic-gate	cmp	%g2, %g1
6527c478bd9Sstevel@tonic-gate	bg	ivec_not_in_obp
6537c478bd9Sstevel@tonic-gate	nop
6557c478bd9Sstevel@tonic-gate	/* Case 3 - CPU in OBP - arm return trap, release the CPU */
6567c478bd9Sstevel@tonic-gate	ADD_CRUMB_FLAG(%g6, KAIF_CRUMB_F_IVEC_INOBP, %g1, %g2, %g3)
6587c478bd9Sstevel@tonic-gate	set	kaif_promexitarmp, %g1
6597c478bd9Sstevel@tonic-gate	ldx	[%g1], %g1
6607c478bd9Sstevel@tonic-gate	mov	1, %g2
6617c478bd9Sstevel@tonic-gate	st	%g2, [%g1]
6637c478bd9Sstevel@tonic-gate	/* We were already in kernel context, so no need to restore it */
6657c478bd9Sstevel@tonic-gate	retry
6677c478bd9Sstevel@tonic-gate	/* Case 1 - head into debugger, via the state-saver */
6697c478bd9Sstevel@tonic-gate	ADD_CRUMB_FLAG(%g6, KAIF_CRUMB_F_IVEC_NORMAL, %g1, %g2, %g3)
6717c478bd9Sstevel@tonic-gate	stx	%g4, [%g6 + KRS_MMU_PCONTEXT]
6737c478bd9Sstevel@tonic-gate	set	kaif_trap_common, %g7
6757c478bd9Sstevel@tonic-gate	KAIF_SAVE_TL1_STATE_SLAVE();
6777c478bd9Sstevel@tonic-gate	/*NOTREACHED*/
6797c478bd9Sstevel@tonic-gate	SET_SIZE(kaif_slave_entry)
6837c478bd9Sstevel@tonic-gate	/*
6847c478bd9Sstevel@tonic-gate	 * The trap handler used when we're on OBP's trap table, which is used
6857c478bd9Sstevel@tonic-gate	 * during initial system startup, while the debugger itself is
6867c478bd9Sstevel@tonic-gate	 * executing, and when we're single-stepping.  When a trap occurs that
6877c478bd9Sstevel@tonic-gate	 * it can't handle, OBP will execute our Forth word (kmdb_callback).
6887c478bd9Sstevel@tonic-gate	 * Our word saves TL1 state, much as kaif_save_tl1_state does for the
6897c478bd9Sstevel@tonic-gate	 * other handlers.  kmdb_callback will then cause control to be
6907c478bd9Sstevel@tonic-gate	 * transferred to this routine.
6917c478bd9Sstevel@tonic-gate	 *
6927c478bd9Sstevel@tonic-gate	 * CPUs entering this routine will fall into the following categories:
6937c478bd9Sstevel@tonic-gate	 *
6947c478bd9Sstevel@tonic-gate	 * 1. The system is booting, and we encountered a trap that OBP couldn't
6957c478bd9Sstevel@tonic-gate	 *    handle.  We save the CPU's state, and let it into the debugger.
6967c478bd9Sstevel@tonic-gate	 *
6977c478bd9Sstevel@tonic-gate	 * 2. We were single-stepping this CPU, causing it to encounter one of
6987c478bd9Sstevel@tonic-gate	 *    the breakpoint traps we installed for stepping.  We save the CPU's
6997c478bd9Sstevel@tonic-gate	 *    state, and let it back into the debugger.
7007c478bd9Sstevel@tonic-gate	 *
7017c478bd9Sstevel@tonic-gate	 * 3. We took a trap while executing in the debugger.  Before saving
7027c478bd9Sstevel@tonic-gate	 *    this CPU's state in the CPU-specific save area, we will let the
7037c478bd9Sstevel@tonic-gate	 *    debugger handle the trap.  If the trap resulted from a debugger
7047c478bd9Sstevel@tonic-gate	 *    problem, and if the user decides to use the debugger to debug
7057c478bd9Sstevel@tonic-gate	 *    itself, we'll overwrite the existing state with the state saved
7067c478bd9Sstevel@tonic-gate	 *    by the Forth word, after which we'll let the CPU enter the
7077c478bd9Sstevel@tonic-gate	 *    debugger.
7087c478bd9Sstevel@tonic-gate	 *
7097c478bd9Sstevel@tonic-gate	 * NOTE: The Forth word and the copying code here *must* be kept
7107c478bd9Sstevel@tonic-gate	 * in sync with kaif_save_tl1_state.
7117c478bd9Sstevel@tonic-gate	 */
7137c478bd9Sstevel@tonic-gate#if defined(__lint)
7187c478bd9Sstevel@tonic-gate#else	/* __lint */
7207c478bd9Sstevel@tonic-gate	ENTRY_NP(kaif_trap_obp)
7227c478bd9Sstevel@tonic-gate	set	1f, %g7
7237c478bd9Sstevel@tonic-gate	set	kaif_cpusave_getaddr, %g6
7247c478bd9Sstevel@tonic-gate	jmp	%g6
7257c478bd9Sstevel@tonic-gate	nop
7267c478bd9Sstevel@tonic-gate1:	/* CPU save area address is now in %g6 */
7277c478bd9Sstevel@tonic-gate	add	%g6, KRS_GREGS + GREG_KREGS, %g5
7297c478bd9Sstevel@tonic-gate	ADVANCE_CRUMB_POINTER(%g6, %g1, %g2)
7307c478bd9Sstevel@tonic-gate	ADD_CRUMB_CONST(%g6, KRM_SRC, KAIF_CRUMB_SRC_OBP, %g1, %g2)
7317c478bd9Sstevel@tonic-gate	ADD_CRUMB_FLAG(%g6, KAIF_CRUMB_F_OBP_NORMAL, %g1, %g2, %g3)
7337c478bd9Sstevel@tonic-gate	set	kaif_cb_save, %g4
7347c478bd9Sstevel@tonic-gate	add	%g4, KRS_GREGS + GREG_KREGS, %g4
7357c478bd9Sstevel@tonic-gate	ldx	[%g4 + KREG_OFF(KREG_PC)], %g1
7367c478bd9Sstevel@tonic-gate	ADD_CRUMB(%g6, KRM_PC, %g1, %g2)
7377c478bd9Sstevel@tonic-gate	ldx	[%g4 + KREG_OFF(KREG_TT)], %g1
7387c478bd9Sstevel@tonic-gate	ADD_CRUMB(%g6, KRM_TT, %g1, %g2)
7407c478bd9Sstevel@tonic-gate	ALTENTRY(kaif_trap_obp_saved)
7427c478bd9Sstevel@tonic-gate	/*
7437c478bd9Sstevel@tonic-gate	 * Are we here because of a trap we took while running the debugger, or
7447c478bd9Sstevel@tonic-gate	 * because of one we took while executing kernel code?
7457c478bd9Sstevel@tonic-gate	 */
7467c478bd9Sstevel@tonic-gate	set	kaif_dseg, %g1
7477c478bd9Sstevel@tonic-gate	ldx	[%g1], %g1
7487c478bd9Sstevel@tonic-gate	cmp	%sp, %g1
7497c478bd9Sstevel@tonic-gate	bl	obp_normal_entry
7507c478bd9Sstevel@tonic-gate	nop
7527c478bd9Sstevel@tonic-gate	set	kaif_dseg_lim, %g1
7537c478bd9Sstevel@tonic-gate	ldx	[%g1], %g1
7547c478bd9Sstevel@tonic-gate	cmp	%sp, %g1
7557c478bd9Sstevel@tonic-gate	bg	obp_normal_entry
7567c478bd9Sstevel@tonic-gate	nop
7587c478bd9Sstevel@tonic-gate	/*
7597c478bd9Sstevel@tonic-gate	 * The debugger fault code will need access to saved copies of the outs
7607c478bd9Sstevel@tonic-gate	 * and %y if the user elects to panic.  We'll also need the saved outs if
7617c478bd9Sstevel@tonic-gate	 * they decide to debug the fault with the debugger, as we'll have
7627c478bd9Sstevel@tonic-gate	 * trashed the outs while asking the user how to handle the fault.
7637c478bd9Sstevel@tonic-gate	 */
7647c478bd9Sstevel@tonic-gate	set	kaif_cb_save, %g4
7657c478bd9Sstevel@tonic-gate	add	%g4, KRS_GREGS + GREG_KREGS, %g4
7667c478bd9Sstevel@tonic-gate	rd	%y, %g2
7677c478bd9Sstevel@tonic-gate	stx	%g2, [%g4 + KREG_OFF(KREG_Y)]
7687c478bd9Sstevel@tonic-gate	stx	%o0, [%g4 + KREG_OFF(KREG_O0)]
7697c478bd9Sstevel@tonic-gate	stx	%o1, [%g4 + KREG_OFF(KREG_O1)]
7707c478bd9Sstevel@tonic-gate	stx	%o2, [%g4 + KREG_OFF(KREG_O2)]
7717c478bd9Sstevel@tonic-gate	stx	%o3, [%g4 + KREG_OFF(KREG_O3)]
7727c478bd9Sstevel@tonic-gate	stx	%o4, [%g4 + KREG_OFF(KREG_O4)]
7737c478bd9Sstevel@tonic-gate	stx	%o5, [%g4 + KREG_OFF(KREG_O5)]
7747c478bd9Sstevel@tonic-gate	stx	%o6, [%g4 + KREG_OFF(KREG_O6)]
7757c478bd9Sstevel@tonic-gate	stx	%o7, [%g4 + KREG_OFF(KREG_O7)]
7777c478bd9Sstevel@tonic-gate	/*
7787c478bd9Sstevel@tonic-gate	 * Receipt of an XIR while on the debugger's stack is likely to mean
7797c478bd9Sstevel@tonic-gate	 * that something has gone very wrong in the debugger.  Our safest
7807c478bd9Sstevel@tonic-gate	 * course of action is to bail out to OBP, thus preserving as much state
7817c478bd9Sstevel@tonic-gate	 * as we can.
7827c478bd9Sstevel@tonic-gate	 */
7837c478bd9Sstevel@tonic-gate	ldx	[%g4 + KREG_OFF(KREG_TT)], %g1
7847c478bd9Sstevel@tonic-gate	cmp	%g1, T_XIR
7857c478bd9Sstevel@tonic-gate	bne	1f
7867c478bd9Sstevel@tonic-gate	nop
7887c478bd9Sstevel@tonic-gate	call	prom_enter_mon
7897c478bd9Sstevel@tonic-gate	nop
7927c478bd9Sstevel@tonic-gate	/*
7937c478bd9Sstevel@tonic-gate	 * We're still on the debugger's stack, as we were when we took the
7947c478bd9Sstevel@tonic-gate	 * fault.  Re-arm the Forth word and transfer control to the debugger.
7957c478bd9Sstevel@tonic-gate	 */
7967c478bd9Sstevel@tonic-gate	call	kaif_prom_rearm
7977c478bd9Sstevel@tonic-gate	nop
7997c478bd9Sstevel@tonic-gate	KAIF_CPU_INDEX		! index returned in %g1, clobbers %g2, %g7
8007c478bd9Sstevel@tonic-gate	mov	%g1, %o4
8027c478bd9Sstevel@tonic-gate	set	kaif_cb_save, %g5
8037c478bd9Sstevel@tonic-gate	ldx	[%g5 + KREG_OFF(KREG_TT)], %o0
8047c478bd9Sstevel@tonic-gate	ldx	[%g5 + KREG_OFF(KREG_PC)], %o1
8057c478bd9Sstevel@tonic-gate	ldx	[%g5 + KREG_OFF(KREG_NPC)], %o2
8067c478bd9Sstevel@tonic-gate	call	kmdb_dpi_handle_fault
8077c478bd9Sstevel@tonic-gate	mov	%sp, %o3
8097c478bd9Sstevel@tonic-gate	/*
8107c478bd9Sstevel@tonic-gate	 * If we return from kmdb_dpi_handle_fault, the trap was due to a
8117c478bd9Sstevel@tonic-gate	 * problem in the debugger, and the user has elected to diagnose it
8127c478bd9Sstevel@tonic-gate	 * using the debugger.  When we pass back into the normal kaif_trap_obp
8137c478bd9Sstevel@tonic-gate	 * flow, we'll save the debugger fault state over the state saved when
8147c478bd9Sstevel@tonic-gate	 * we initially entered the debugger.  Debugger fault handling trashed
8157c478bd9Sstevel@tonic-gate	 * the out registers, so we'll need to restore them before returning
8167c478bd9Sstevel@tonic-gate	 * to the normal flow.
8177c478bd9Sstevel@tonic-gate	 */
8197c478bd9Sstevel@tonic-gate	set	kaif_cb_save, %g4
8207c478bd9Sstevel@tonic-gate	ldx	[%g4 + KREG_OFF(KREG_O0)], %o0
8217c478bd9Sstevel@tonic-gate	ldx	[%g4 + KREG_OFF(KREG_O1)], %o1
8227c478bd9Sstevel@tonic-gate	ldx	[%g4 + KREG_OFF(KREG_O2)], %o2
8237c478bd9Sstevel@tonic-gate	ldx	[%g4 + KREG_OFF(KREG_O3)], %o3
8247c478bd9Sstevel@tonic-gate	ldx	[%g4 + KREG_OFF(KREG_O4)], %o4
8257c478bd9Sstevel@tonic-gate	ldx	[%g4 + KREG_OFF(KREG_O5)], %o5
8267c478bd9Sstevel@tonic-gate	ldx	[%g4 + KREG_OFF(KREG_O6)], %o6
8277c478bd9Sstevel@tonic-gate	ldx	[%g4 + KREG_OFF(KREG_O7)], %o7
8317c478bd9Sstevel@tonic-gate	set	1f, %g7
8327c478bd9Sstevel@tonic-gate	set	kaif_cpusave_getaddr, %g6
8337c478bd9Sstevel@tonic-gate	jmp	%g6
8347c478bd9Sstevel@tonic-gate	nop
8357c478bd9Sstevel@tonic-gate1:	/* CPU save area address is now in %g6 */
8367c478bd9Sstevel@tonic-gate	add	%g6, KRS_GREGS + GREG_KREGS, %g5
8387c478bd9Sstevel@tonic-gate	/*
8397c478bd9Sstevel@tonic-gate	 * Register state has been saved in kaif_cb_save.  Now that we're sure
8407c478bd9Sstevel@tonic-gate	 * we're going into the debugger using this state, copy it to the CPU-
8417c478bd9Sstevel@tonic-gate	 * specific save area.
8427c478bd9Sstevel@tonic-gate	 */
8447c478bd9Sstevel@tonic-gate	set	kaif_cb_save, %g4
8457c478bd9Sstevel@tonic-gate	add	%g4, KRS_GREGS + GREG_KREGS, %g3
8477c478bd9Sstevel@tonic-gate	KAIF_COPY_KREG(%g3, %g5, KREG_PC, %g1)
8487c478bd9Sstevel@tonic-gate	KAIF_COPY_KREG(%g3, %g5, KREG_NPC, %g1)
8497c478bd9Sstevel@tonic-gate	KAIF_COPY_KREG(%g3, %g5, KREG_G1, %g1)
8507c478bd9Sstevel@tonic-gate	KAIF_COPY_KREG(%g3, %g5, KREG_G2, %g1)
8517c478bd9Sstevel@tonic-gate	KAIF_COPY_KREG(%g3, %g5, KREG_G3, %g1)
8527c478bd9Sstevel@tonic-gate	KAIF_COPY_KREG(%g3, %g5, KREG_G4, %g1)
8537c478bd9Sstevel@tonic-gate	KAIF_COPY_KREG(%g3, %g5, KREG_G5, %g1)
8547c478bd9Sstevel@tonic-gate	KAIF_COPY_KREG(%g3, %g5, KREG_G6, %g1)
8557c478bd9Sstevel@tonic-gate	KAIF_COPY_KREG(%g3, %g5, KREG_G7, %g1)
8567c478bd9Sstevel@tonic-gate	KAIF_COPY_KREG(%g3, %g5, KREG_TT, %g1)
8587c478bd9Sstevel@tonic-gate	ldx	[%g4 + KRS_TSTATE], %g1
8597c478bd9Sstevel@tonic-gate	stx	%g1, [%g6 + KRS_TSTATE]
8617c478bd9Sstevel@tonic-gate	/* A formality */
8627c478bd9Sstevel@tonic-gate	mov	MMU_PCONTEXT, %g3
8637c478bd9Sstevel@tonic-gate	ldxa	[%g3]ASI_MMU_CTX, %g2
8647c478bd9Sstevel@tonic-gate	stx	%g2, [%g6 + KRS_MMU_PCONTEXT]
866febcc4a5Sjimand#ifndef sun4v
867febcc4a5Sjimand	/*
868febcc4a5Sjimand	 * If OBP supports preserving the Solaris kernel context register,
869febcc4a5Sjimand	 * then shift the nucleus bits into the primary and set context to 0,
870febcc4a5Sjimand	 * Otherwise, flush TLBs and clear the entire context register since
871febcc4a5Sjimand	 * OBP will clear it without flushing on entry to OBP.
872febcc4a5Sjimand	 */
873febcc4a5Sjimand	sethi	%hi(kmdb_prom_preserve_kctx), %g4
874febcc4a5Sjimand	ld	[%g4 + %lo(kmdb_prom_preserve_kctx)], %g4
875febcc4a5Sjimand	brz	%g4, 1f
876febcc4a5Sjimand	  nop
877febcc4a5Sjimand	/*
878febcc4a5Sjimand	 * Move nucleus context page size bits into primary context page size
879febcc4a5Sjimand	 * and set context to 0.  Use %g4 as a temporary.
880febcc4a5Sjimand	 */
881febcc4a5Sjimand	KAIF_MAKE_NEW_CTXREG(%g2, %g4)		! new context reg in %g2
883febcc4a5Sjimand	stxa	%g2, [%g3]ASI_MMU_CTX
884febcc4a5Sjimand	membar	#Sync
885febcc4a5Sjimand	ba	2f
886febcc4a5Sjimand	  nop
888febcc4a5Sjimand#endif /* sun4v */
889febcc4a5Sjimand	/*
890febcc4a5Sjimand	 * Flush TLBs and clear primary context register.
891febcc4a5Sjimand	 */
8927c478bd9Sstevel@tonic-gate	KAIF_DEMAP_TLB_ALL(%g4)
893febcc4a5Sjimand	stxa	%g0, [%g3]ASI_MMU_CTX	! ASI_MMU_CTX == ASI_DMMU for sun4u
8947c478bd9Sstevel@tonic-gate	membar	#Sync
8977c478bd9Sstevel@tonic-gate	ba,a	kaif_trap_common
8997c478bd9Sstevel@tonic-gate	SET_SIZE(kaif_trap_obp_saved)
9007c478bd9Sstevel@tonic-gate	SET_SIZE(kaif_trap_obp)
9027c478bd9Sstevel@tonic-gate#endif	/* __lint */
9047c478bd9Sstevel@tonic-gate#if defined(lint)
9097c478bd9Sstevel@tonic-gate#else   /* lint */
9117c478bd9Sstevel@tonic-gate	/*
9127c478bd9Sstevel@tonic-gate	 * This routine is used to handle all "failed" traps.  A trap is
9137c478bd9Sstevel@tonic-gate	 * considered to have failed if it was not able to return to the code
9147c478bd9Sstevel@tonic-gate	 * that caused the trap.  A DTLB miss handler, for example, fails if
9157c478bd9Sstevel@tonic-gate	 * it can't find a translation for a given address.  Some traps always
9167c478bd9Sstevel@tonic-gate	 * fail, because the thing that caused the trap is an actual problem
9177c478bd9Sstevel@tonic-gate	 * that can't be resolved by the handler.  Examples of these include
9187c478bd9Sstevel@tonic-gate	 * alignment and DTLB protection faults.
9197c478bd9Sstevel@tonic-gate	 */
9217c478bd9Sstevel@tonic-gate	ENTRY_NP(kaif_dtrap)
9237c478bd9Sstevel@tonic-gate	SET_PSTATE_COMMON_AG(%g1);
9247c478bd9Sstevel@tonic-gate	SET_GL(1);		/* set %gl = 1 */
9267c478bd9Sstevel@tonic-gate	KAIF_CPU_GETADDR_TL1	/* uses label 1, %g1, %g2, %g7, ret in %g6 */
9287c478bd9Sstevel@tonic-gate	ADVANCE_CRUMB_POINTER(%g6, %g1, %g2)
9297c478bd9Sstevel@tonic-gate	ADD_CRUMB_CONST(%g6, KRM_SRC, KAIF_CRUMB_SRC_OBP, %g1, %g2)
9307c478bd9Sstevel@tonic-gate	ADD_CRUMB_FLAG(%g6, KAIF_CRUMB_F_OBP_REVECT, %g1, %g2, %g3)
9327c478bd9Sstevel@tonic-gate	rdpr	%tt, %g1
9337c478bd9Sstevel@tonic-gate	ADD_CRUMB(%g6, KRM_TT, %g1, %g2)
9347c478bd9Sstevel@tonic-gate	rdpr	%tpc, %g1
9357c478bd9Sstevel@tonic-gate	ADD_CRUMB(%g6, KRM_PC, %g1, %g2)
9377c478bd9Sstevel@tonic-gate	set	kaif_cb_save, %g6
9397c478bd9Sstevel@tonic-gate	set	1f, %g7
9407c478bd9Sstevel@tonic-gate	ba	kaif_save_tl1_state
9417c478bd9Sstevel@tonic-gate	rdpr	%pstate, %g4
9437c478bd9Sstevel@tonic-gate1:	wrpr	%g0, PTSTATE_KERN_COMMON, %pstate
9447c478bd9Sstevel@tonic-gate	wrpr	%g0, %tl
9457c478bd9Sstevel@tonic-gate	SET_GL(0);
9477c478bd9Sstevel@tonic-gate	ba	kaif_trap_obp_saved
9487c478bd9Sstevel@tonic-gate	nop
9507c478bd9Sstevel@tonic-gate	SET_SIZE(kaif_dtrap)
9527c478bd9Sstevel@tonic-gate#endif	/* lint */