xref: /onnv-gate/usr/src/cmd/mdb/sparc/kmdb/kaif_activate.c (revision 3446:5903aece022d)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51991Sheppo  * Common Development and Distribution License (the "License").
61991Sheppo  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
211991Sheppo 
220Sstevel@tonic-gate /*
23*3446Smrj  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * The debugger/PROM interface layer - debugger activation
310Sstevel@tonic-gate  */
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <kmdb/kmdb_promif_isadep.h>
340Sstevel@tonic-gate #include <kmdb/kmdb_start.h>
350Sstevel@tonic-gate #include <kmdb/kmdb_kdi.h>
360Sstevel@tonic-gate #include <kmdb/kmdb_asmutil.h>
370Sstevel@tonic-gate #include <kmdb/kaif.h>
380Sstevel@tonic-gate #include <mdb/mdb_debug.h>
390Sstevel@tonic-gate #include <mdb/mdb_kreg.h>
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #include <sys/cpuvar.h>
420Sstevel@tonic-gate #include <sys/kdi_impl.h>
430Sstevel@tonic-gate #include <sys/machtrap.h>
440Sstevel@tonic-gate 
450Sstevel@tonic-gate kaif_cpusave_t kaif_cb_save;
460Sstevel@tonic-gate 
470Sstevel@tonic-gate static const char kaif_defer_word_tmpl[] =
480Sstevel@tonic-gate 	/*  1 */ ": kmdb_callback "
490Sstevel@tonic-gate 
500Sstevel@tonic-gate 	/*
510Sstevel@tonic-gate 	 * Don't hand control to the debugger if we're coming from OBP's text.
520Sstevel@tonic-gate 	 */
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	/*  2 */ "  %%pc f000.0000 ffff.ffff between if exit then "
550Sstevel@tonic-gate 
560Sstevel@tonic-gate 	/*
570Sstevel@tonic-gate 	 * Save registers
580Sstevel@tonic-gate 	 */
590Sstevel@tonic-gate 
600Sstevel@tonic-gate 	/*  3 */ "  %%pc h# %x x! "
610Sstevel@tonic-gate 	/*  4 */ "  %%npc h# %x x! "
620Sstevel@tonic-gate 	/*  5 */ "  %%g1 h# %x x! "
630Sstevel@tonic-gate 	/*  6 */ "  %%g2 h# %x x! "
640Sstevel@tonic-gate 	/*  7 */ "  %%g3 h# %x x! "
650Sstevel@tonic-gate 	/*  8 */ "  %%g4 h# %x x! "
660Sstevel@tonic-gate 	/*  9 */ "  %%g5 h# %x x! "
670Sstevel@tonic-gate 	/* 10 */ "  %%g6 h# %x x! "
680Sstevel@tonic-gate 	/* 11 */ "  %%g7 h# %x x! "
690Sstevel@tonic-gate 	/* 12 */ "  1 %%tstate h# %x x! "
700Sstevel@tonic-gate 	/* 13 */ "  1 %%tt h# %x x! "
710Sstevel@tonic-gate 	/* 14 */ "  %%tba h# %x x! "
720Sstevel@tonic-gate 	/* 15 */ "  h# %x set-pc "
730Sstevel@tonic-gate 	/* 16 */ "    go "
740Sstevel@tonic-gate 	/* 17 */ "; ";
750Sstevel@tonic-gate 
760Sstevel@tonic-gate /*
770Sstevel@tonic-gate  * Format the Forth word which tells the prom how to save state for
780Sstevel@tonic-gate  * giving control to us.
790Sstevel@tonic-gate  */
800Sstevel@tonic-gate static char *
kaif_format_word(void)810Sstevel@tonic-gate kaif_format_word(void)
820Sstevel@tonic-gate {
830Sstevel@tonic-gate 	static char prom_str[550];
840Sstevel@tonic-gate 	kreg_t *kregs = kaif_cb_save.krs_gregs.kregs;
850Sstevel@tonic-gate 	int len;
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	len = mdb_snprintf(prom_str, sizeof (prom_str), kaif_defer_word_tmpl,
880Sstevel@tonic-gate 	    &kregs[KREG_PC],			/*  3 */
890Sstevel@tonic-gate 	    &kregs[KREG_NPC],			/*  4 */
900Sstevel@tonic-gate 	    &kregs[KREG_G1],			/*  5 */
910Sstevel@tonic-gate 	    &kregs[KREG_G2],			/*  6 */
920Sstevel@tonic-gate 	    &kregs[KREG_G3],			/*  7 */
930Sstevel@tonic-gate 	    &kregs[KREG_G4],			/*  8 */
940Sstevel@tonic-gate 	    &kregs[KREG_G5],			/*  9 */
950Sstevel@tonic-gate 	    &kregs[KREG_G6],			/* 10 */
960Sstevel@tonic-gate 	    &kregs[KREG_G7],			/* 11 */
970Sstevel@tonic-gate 	    &kaif_cb_save.krs_tstate,		/* 12 */
980Sstevel@tonic-gate 	    &kregs[KREG_TT],			/* 13 */
990Sstevel@tonic-gate 	    &kregs[KREG_TBA],			/* 14 */
1000Sstevel@tonic-gate 	    kaif_trap_obp);			/* 15 */
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 	ASSERT(len <= sizeof (prom_str));
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 	return (prom_str);
1050Sstevel@tonic-gate }
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate static void
kaif_prom_install(void)1080Sstevel@tonic-gate kaif_prom_install(void)
1090Sstevel@tonic-gate {
1100Sstevel@tonic-gate 	kmdb_prom_interpret(kaif_format_word());
1110Sstevel@tonic-gate 	kmdb_prom_interpret(" ['] kmdb_callback init-debugger-hook ");
1120Sstevel@tonic-gate }
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate void
kaif_prom_rearm(void)1150Sstevel@tonic-gate kaif_prom_rearm(void)
1160Sstevel@tonic-gate {
1170Sstevel@tonic-gate 	kmdb_prom_interpret(" ['] kmdb_callback is debugger-hook ");
1180Sstevel@tonic-gate }
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate /*ARGSUSED*/
1210Sstevel@tonic-gate static void
kaif_cpu_init(cpu_t * cp)1220Sstevel@tonic-gate kaif_cpu_init(cpu_t *cp)
1230Sstevel@tonic-gate {
1240Sstevel@tonic-gate 	kaif_wapt_set_regs();
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate /*ARGSUSED*/
1280Sstevel@tonic-gate static void
kaif_install_generic(caddr_t tgt,caddr_t arg)1290Sstevel@tonic-gate kaif_install_generic(caddr_t tgt, caddr_t arg)
1300Sstevel@tonic-gate {
1310Sstevel@tonic-gate 	bcopy((caddr_t)kaif_hdlr_generic, tgt, 32);
1320Sstevel@tonic-gate }
1330Sstevel@tonic-gate 
1341991Sheppo #ifdef	sun4v
1351991Sheppo 
1361991Sheppo /*ARGSUSED*/
1371991Sheppo static void
kaif_install_goto_tt64(caddr_t tgt,caddr_t arg)1381991Sheppo kaif_install_goto_tt64(caddr_t tgt, caddr_t arg)
1391991Sheppo {
1401991Sheppo 	/* LINTED - pointer alignment */
1411991Sheppo 	uint32_t *hdlr = (uint32_t *)tgt;
1421991Sheppo 	uint32_t disp = (T_FAST_INSTR_MMU_MISS - T_INSTR_MMU_MISS) * 0x20;
1431991Sheppo 
1441991Sheppo 	*hdlr++ = 0x10480000 | (disp >> 2);	/* ba,pt (to tt64) */
1451991Sheppo 	*hdlr++ = 0x01000000;			/* nop */
1461991Sheppo }
1471991Sheppo 
1481991Sheppo /*ARGSUSED*/
1491991Sheppo static void
kaif_install_goto_tt68(caddr_t tgt,caddr_t arg)1501991Sheppo kaif_install_goto_tt68(caddr_t tgt, caddr_t arg)
1511991Sheppo {
1521991Sheppo 	/* LINTED - pointer alignment */
1531991Sheppo 	uint32_t *hdlr = (uint32_t *)tgt;
1541991Sheppo 	uint32_t disp = (T_FAST_DATA_MMU_MISS - T_DATA_MMU_MISS) * 0x20;
1551991Sheppo 
1561991Sheppo 	*hdlr++ = 0x10480000 | (disp >> 2);	/* ba,pt (to tt68) */
1571991Sheppo 	*hdlr++ = 0x01000000;			/* nop */
1581991Sheppo }
1591991Sheppo 
1601991Sheppo #endif	/* sun4v */
1611991Sheppo 
1620Sstevel@tonic-gate static void
kaif_install_dmmumiss(caddr_t tgt,caddr_t vatotte)1630Sstevel@tonic-gate kaif_install_dmmumiss(caddr_t tgt, caddr_t vatotte)
1640Sstevel@tonic-gate {
1650Sstevel@tonic-gate 	uint32_t *patch;
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 	bcopy((caddr_t)kaif_hdlr_dmiss, tgt, 128);
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	/* LINTED - pointer alignment */
1700Sstevel@tonic-gate 	patch = (uint32_t *)(tgt + ((uintptr_t)&kaif_hdlr_dmiss_patch -
1710Sstevel@tonic-gate 	    (uintptr_t)kaif_hdlr_dmiss));
1720Sstevel@tonic-gate 	*patch++ |= (uintptr_t)vatotte >> 10;
1730Sstevel@tonic-gate 	*patch |= ((uintptr_t)vatotte) & 0x3ff;
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate static void
kaif_install_immumiss(caddr_t tgt,caddr_t vatotte)1770Sstevel@tonic-gate kaif_install_immumiss(caddr_t tgt, caddr_t vatotte)
1780Sstevel@tonic-gate {
1790Sstevel@tonic-gate 	uint32_t *patch;
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	bcopy((caddr_t)kaif_hdlr_imiss, tgt, 128);
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate 	/* LINTED - pointer alignment */
1840Sstevel@tonic-gate 	patch = (uint32_t *)(tgt + ((uintptr_t)&kaif_hdlr_imiss_patch -
1850Sstevel@tonic-gate 	    (uintptr_t)kaif_hdlr_imiss));
1860Sstevel@tonic-gate 	*patch++ |= (uintptr_t)vatotte >> 10;
1870Sstevel@tonic-gate 	*patch |= ((uintptr_t)vatotte) & 0x3ff;
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate static struct kaif_trap_handlers {
1910Sstevel@tonic-gate 	uint_t th_tt;
1920Sstevel@tonic-gate 	void (*th_install)(caddr_t, caddr_t);
1930Sstevel@tonic-gate } kaif_trap_handlers[] = {
1940Sstevel@tonic-gate 	{ T_INSTR_EXCEPTION,			kaif_install_generic },
1951991Sheppo #ifdef sun4v
1961991Sheppo 	{ T_INSTR_MMU_MISS,			kaif_install_goto_tt64 },
1971991Sheppo #endif
1980Sstevel@tonic-gate 	{ T_IDIV0,				kaif_install_generic },
1990Sstevel@tonic-gate 	{ T_DATA_EXCEPTION,			kaif_install_generic },
2001991Sheppo #ifdef sun4v
2011991Sheppo 	{ T_DATA_MMU_MISS,			kaif_install_goto_tt68 },
2021991Sheppo #endif
2030Sstevel@tonic-gate 	{ T_DATA_ERROR,				kaif_install_generic },
2040Sstevel@tonic-gate 	{ T_ALIGNMENT,				kaif_install_generic },
2050Sstevel@tonic-gate 	{ T_FAST_INSTR_MMU_MISS,		kaif_install_immumiss },
2060Sstevel@tonic-gate 	{ T_FAST_DATA_MMU_MISS,			kaif_install_dmmumiss },
2070Sstevel@tonic-gate 	{ T_FAST_DATA_MMU_PROT,			kaif_install_generic },
2081991Sheppo #ifdef sun4v
2091991Sheppo 	{ T_INSTR_MMU_MISS + T_TL1,		kaif_install_goto_tt64 },
2101991Sheppo 	{ T_DATA_MMU_MISS + T_TL1,		kaif_install_goto_tt68 },
2111991Sheppo #endif
2120Sstevel@tonic-gate 	{ T_FAST_INSTR_MMU_MISS + T_TL1,	kaif_install_immumiss },
2130Sstevel@tonic-gate 	{ T_FAST_DATA_MMU_MISS + T_TL1,		kaif_install_dmmumiss },
2140Sstevel@tonic-gate 	{ 0 }
2150Sstevel@tonic-gate };
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate static void
kaif_trap_init(void)2180Sstevel@tonic-gate kaif_trap_init(void)
2190Sstevel@tonic-gate {
2200Sstevel@tonic-gate 	caddr_t vatotte = kmdb_kdi_get_trap_vatotte();
2210Sstevel@tonic-gate 	uintptr_t brtgt;
2220Sstevel@tonic-gate 	int i;
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 	/*
2251991Sheppo 	 * sun4u:
2260Sstevel@tonic-gate 	 * We rely upon OBP for the handling of a great many traps.  As such,
2270Sstevel@tonic-gate 	 * we begin by populating our table with pointers to OBP's handlers.
2280Sstevel@tonic-gate 	 * We then copy in our own handlers where appropriate.  At some point,
2290Sstevel@tonic-gate 	 * when we provide the bulk of the handlers, this process will be
2300Sstevel@tonic-gate 	 * reversed.
2311991Sheppo 	 *
2321991Sheppo 	 * sun4v:
2331991Sheppo 	 * The sun4v kernel dismisses OBP at boot. Both fast and slow TLB
2341991Sheppo 	 * misses are handled by KMDB. Breakpoint traps go directly KMDB.
2351991Sheppo 	 * All other trap entries are redirected to their respective
2361991Sheppo 	 * trap implemenation within the Solaris trap table.
2370Sstevel@tonic-gate 	 */
2380Sstevel@tonic-gate 	for (i = 0; i < kaif_tba_native_sz; i += 0x20) {
2390Sstevel@tonic-gate 		/* LINTED - pointer alignment */
2400Sstevel@tonic-gate 		uint32_t *hdlr = (uint32_t *)(kaif_tba_native + i);
2410Sstevel@tonic-gate #ifdef	sun4v
2421991Sheppo 		brtgt = (uintptr_t)(kaif_tba_kernel + i);
2431991Sheppo #else
2440Sstevel@tonic-gate 		brtgt = (uintptr_t)(kaif_tba_obp + i);
2451991Sheppo #endif
2460Sstevel@tonic-gate 		*hdlr++ = 0x03000000 | (brtgt >> 10);	/* sethi brtgt, %g1 */
2470Sstevel@tonic-gate 		*hdlr++ = 0x81c06000 | (brtgt & 0x3ff);	/* jmp %g1 + brtgt */
2480Sstevel@tonic-gate 		*hdlr++ = 0x01000000;			/* nop */
2490Sstevel@tonic-gate 	}
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 	for (i = 0; kaif_trap_handlers[i].th_tt != 0; i++) {
2520Sstevel@tonic-gate 		struct kaif_trap_handlers *th = &kaif_trap_handlers[i];
2530Sstevel@tonic-gate 		th->th_install(kaif_tba_native + th->th_tt * 0x20, vatotte);
2540Sstevel@tonic-gate 	}
2550Sstevel@tonic-gate 	membar_producer();
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate /*
2590Sstevel@tonic-gate  * The kernel is ready for us to switch to our table (the HAT has been
2600Sstevel@tonic-gate  * initialized, the hments are walkable, and the trap table's pages
2610Sstevel@tonic-gate  * have been locked into the TLBs.
2620Sstevel@tonic-gate  */
2630Sstevel@tonic-gate static void
kaif_vmready(void)2640Sstevel@tonic-gate kaif_vmready(void)
2650Sstevel@tonic-gate {
2660Sstevel@tonic-gate 	kaif_tba = kaif_tba_native;
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate /*
2700Sstevel@tonic-gate  * Called on the CPR master CPU.  The driver has taken care of locking the
2710Sstevel@tonic-gate  * TLB entries.  CPR restored the OBP image which contains kmdb_callback,
2720Sstevel@tonic-gate  * so there's nothing we need to do.  This function should be removed entirely
2730Sstevel@tonic-gate  * in a future release.
2740Sstevel@tonic-gate  */
2750Sstevel@tonic-gate static void
kaif_cpr_restart(void)2760Sstevel@tonic-gate kaif_cpr_restart(void)
2770Sstevel@tonic-gate {
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate static kdi_debugvec_t kaif_dvec = {
2810Sstevel@tonic-gate 	NULL,			/* dv_kctl_vmready */
2820Sstevel@tonic-gate 	NULL,			/* dv_kctl_memavail */
2830Sstevel@tonic-gate 	NULL,			/* dv_kctl_modavail */
2840Sstevel@tonic-gate 	NULL,			/* dv_kctl_thravail */
285*3446Smrj 	kaif_vmready,
286*3446Smrj 	NULL,			/* dv_memavail */
2870Sstevel@tonic-gate 	kaif_mod_loaded,
288*3446Smrj 	kaif_mod_unloading,
289*3446Smrj 	NULL,			/* dv_kctl_cpu_init */
290*3446Smrj 	kaif_cpu_init,
291*3446Smrj 	kaif_cpr_restart
2920Sstevel@tonic-gate };
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate /*ARGSUSED1*/
2950Sstevel@tonic-gate void
kaif_activate(kdi_debugvec_t ** dvecp,uint_t flags)2960Sstevel@tonic-gate kaif_activate(kdi_debugvec_t **dvecp, uint_t flags)
2970Sstevel@tonic-gate {
2980Sstevel@tonic-gate 	kaif_prom_install();
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	kaif_ktrap_install(0, kaif_ktrap);
3010Sstevel@tonic-gate 	kaif_trap_init();
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	*dvecp = &kaif_dvec;
3040Sstevel@tonic-gate }
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate void
kaif_deactivate(void)3070Sstevel@tonic-gate kaif_deactivate(void)
3080Sstevel@tonic-gate {
3090Sstevel@tonic-gate 	kmdb_prom_interpret(" ['] noop is debugger-hook ");
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 	kaif_ktrap_restore();
3120Sstevel@tonic-gate }
313