xref: /titanic_41/usr/src/cmd/mdb/sparc/kmdb/kaif_activate.c (revision 29949e866e40b95795203f3ee46f44a197c946e4)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * The debugger/PROM interface layer - debugger activation
31  */
32 
33 #include <kmdb/kmdb_promif_isadep.h>
34 #include <kmdb/kmdb_start.h>
35 #include <kmdb/kmdb_kdi.h>
36 #include <kmdb/kmdb_asmutil.h>
37 #include <kmdb/kaif.h>
38 #include <mdb/mdb_debug.h>
39 #include <mdb/mdb_kreg.h>
40 
41 #include <sys/cpuvar.h>
42 #include <sys/kdi_impl.h>
43 #include <sys/machtrap.h>
44 
45 kaif_cpusave_t kaif_cb_save;
46 
47 static const char kaif_defer_word_tmpl[] =
48 	/*  1 */ ": kmdb_callback "
49 
50 	/*
51 	 * Don't hand control to the debugger if we're coming from OBP's text.
52 	 */
53 
54 	/*  2 */ "  %%pc f000.0000 ffff.ffff between if exit then "
55 
56 	/*
57 	 * Save registers
58 	 */
59 
60 	/*  3 */ "  %%pc h# %x x! "
61 	/*  4 */ "  %%npc h# %x x! "
62 	/*  5 */ "  %%g1 h# %x x! "
63 	/*  6 */ "  %%g2 h# %x x! "
64 	/*  7 */ "  %%g3 h# %x x! "
65 	/*  8 */ "  %%g4 h# %x x! "
66 	/*  9 */ "  %%g5 h# %x x! "
67 	/* 10 */ "  %%g6 h# %x x! "
68 	/* 11 */ "  %%g7 h# %x x! "
69 	/* 12 */ "  1 %%tstate h# %x x! "
70 	/* 13 */ "  1 %%tt h# %x x! "
71 	/* 14 */ "  %%tba h# %x x! "
72 	/* 15 */ "  h# %x set-pc "
73 	/* 16 */ "    go "
74 	/* 17 */ "; ";
75 
76 /*
77  * Format the Forth word which tells the prom how to save state for
78  * giving control to us.
79  */
80 static char *
81 kaif_format_word(void)
82 {
83 	static char prom_str[550];
84 	kreg_t *kregs = kaif_cb_save.krs_gregs.kregs;
85 	int len;
86 
87 	len = mdb_snprintf(prom_str, sizeof (prom_str), kaif_defer_word_tmpl,
88 	    &kregs[KREG_PC],			/*  3 */
89 	    &kregs[KREG_NPC],			/*  4 */
90 	    &kregs[KREG_G1],			/*  5 */
91 	    &kregs[KREG_G2],			/*  6 */
92 	    &kregs[KREG_G3],			/*  7 */
93 	    &kregs[KREG_G4],			/*  8 */
94 	    &kregs[KREG_G5],			/*  9 */
95 	    &kregs[KREG_G6],			/* 10 */
96 	    &kregs[KREG_G7],			/* 11 */
97 	    &kaif_cb_save.krs_tstate,		/* 12 */
98 	    &kregs[KREG_TT],			/* 13 */
99 	    &kregs[KREG_TBA],			/* 14 */
100 	    kaif_trap_obp);			/* 15 */
101 
102 	ASSERT(len <= sizeof (prom_str));
103 
104 	return (prom_str);
105 }
106 
107 static void
108 kaif_prom_install(void)
109 {
110 	kmdb_prom_interpret(kaif_format_word());
111 	kmdb_prom_interpret(" ['] kmdb_callback init-debugger-hook ");
112 }
113 
114 void
115 kaif_prom_rearm(void)
116 {
117 	kmdb_prom_interpret(" ['] kmdb_callback is debugger-hook ");
118 }
119 
120 /*ARGSUSED*/
121 static void
122 kaif_cpu_init(cpu_t *cp)
123 {
124 	kaif_wapt_set_regs();
125 }
126 
127 /*ARGSUSED*/
128 static void
129 kaif_install_generic(caddr_t tgt, caddr_t arg)
130 {
131 	bcopy((caddr_t)kaif_hdlr_generic, tgt, 32);
132 }
133 
134 #ifndef sun4v
135 static void
136 kaif_install_dmmumiss(caddr_t tgt, caddr_t vatotte)
137 {
138 	uint32_t *patch;
139 
140 	bcopy((caddr_t)kaif_hdlr_dmiss, tgt, 128);
141 
142 	/* LINTED - pointer alignment */
143 	patch = (uint32_t *)(tgt + ((uintptr_t)&kaif_hdlr_dmiss_patch -
144 	    (uintptr_t)kaif_hdlr_dmiss));
145 	*patch++ |= (uintptr_t)vatotte >> 10;
146 	*patch |= ((uintptr_t)vatotte) & 0x3ff;
147 }
148 
149 static void
150 kaif_install_immumiss(caddr_t tgt, caddr_t vatotte)
151 {
152 	uint32_t *patch;
153 
154 	bcopy((caddr_t)kaif_hdlr_imiss, tgt, 128);
155 
156 	/* LINTED - pointer alignment */
157 	patch = (uint32_t *)(tgt + ((uintptr_t)&kaif_hdlr_imiss_patch -
158 	    (uintptr_t)kaif_hdlr_imiss));
159 	*patch++ |= (uintptr_t)vatotte >> 10;
160 	*patch |= ((uintptr_t)vatotte) & 0x3ff;
161 }
162 #endif /* sun4v */
163 
164 static struct kaif_trap_handlers {
165 	uint_t th_tt;
166 	void (*th_install)(caddr_t, caddr_t);
167 } kaif_trap_handlers[] = {
168 	{ T_INSTR_EXCEPTION,			kaif_install_generic },
169 	{ T_IDIV0,				kaif_install_generic },
170 	{ T_DATA_EXCEPTION,			kaif_install_generic },
171 	{ T_DATA_ERROR,				kaif_install_generic },
172 	{ T_ALIGNMENT,				kaif_install_generic },
173 #ifdef sun4v
174 #else /* sun4v */
175 	{ T_FAST_INSTR_MMU_MISS,		kaif_install_immumiss },
176 	{ T_FAST_DATA_MMU_MISS,			kaif_install_dmmumiss },
177 	{ T_FAST_DATA_MMU_PROT,			kaif_install_generic },
178 	{ T_FAST_INSTR_MMU_MISS + T_TL1,	kaif_install_immumiss },
179 	{ T_FAST_DATA_MMU_MISS + T_TL1,		kaif_install_dmmumiss },
180 #endif /* sun4v */
181 	{ 0 }
182 };
183 
184 static void
185 kaif_trap_init(void)
186 {
187 	caddr_t vatotte = kmdb_kdi_get_trap_vatotte();
188 	uintptr_t brtgt;
189 	int i;
190 
191 	/*
192 	 * We rely upon OBP for the handling of a great many traps.  As such,
193 	 * we begin by populating our table with pointers to OBP's handlers.
194 	 * We then copy in our own handlers where appropriate.  At some point,
195 	 * when we provide the bulk of the handlers, this process will be
196 	 * reversed.
197 	 */
198 	for (i = 0; i < kaif_tba_native_sz; i += 0x20) {
199 		/* LINTED - pointer alignment */
200 		uint32_t *hdlr = (uint32_t *)(kaif_tba_native + i);
201 #ifdef	sun4v
202 		uint32_t tt = i/0x20;
203 
204 		/*
205 		 * We use obp's tl0 handlers. Sine kmdb installs itsdebug
206 		 * hook in obp, if obp cannot handle any traps, such as
207 		 * user enter an invalid address in kmdb, obp will call
208 		 * kmdb's callback and the control goes back to kmdb.
209 		 * For tl>0 traps, kernel's trap handlers are good at
210 		 * handling these on sun4v.
211 		 */
212 		if (tt >= T_TL1)
213 			brtgt = (uintptr_t)(kaif_tba_kernel + i);
214 		else
215 			brtgt = (uintptr_t)(kaif_tba_obp + i);
216 #else /* !sun4v */
217 		brtgt = (uintptr_t)(kaif_tba_obp + i);
218 #endif /* sun4v */
219 
220 		*hdlr++ = 0x03000000 | (brtgt >> 10);	/* sethi brtgt, %g1 */
221 		*hdlr++ = 0x81c06000 | (brtgt & 0x3ff);	/* jmp %g1 + brtgt */
222 		*hdlr++ = 0x01000000;			/* nop */
223 	}
224 
225 	for (i = 0; kaif_trap_handlers[i].th_tt != 0; i++) {
226 		struct kaif_trap_handlers *th = &kaif_trap_handlers[i];
227 		th->th_install(kaif_tba_native + th->th_tt * 0x20, vatotte);
228 	}
229 	membar_producer();
230 }
231 
232 /*
233  * The kernel is ready for us to switch to our table (the HAT has been
234  * initialized, the hments are walkable, and the trap table's pages
235  * have been locked into the TLBs.
236  */
237 static void
238 kaif_vmready(void)
239 {
240 	kaif_tba = kaif_tba_native;
241 }
242 
243 /*
244  * Called on the CPR master CPU.  The driver has taken care of locking the
245  * TLB entries.  CPR restored the OBP image which contains kmdb_callback,
246  * so there's nothing we need to do.  This function should be removed entirely
247  * in a future release.
248  */
249 static void
250 kaif_cpr_restart(void)
251 {
252 }
253 
254 static kdi_debugvec_t kaif_dvec = {
255 	kaif_enter,
256 	kaif_cpu_init,
257 	NULL,			/* dv_kctl_cpu_init */
258 	kaif_vmready,
259 	NULL,			/* dv_kctl_vmready */
260 	NULL,			/* dv_kctl_memavail */
261 	kaif_memrange_add,
262 	kaif_cpr_restart,
263 	NULL,			/* dv_kctl_modavail */
264 	NULL,			/* dv_kctl_thravail */
265 	kaif_mod_loaded,
266 	kaif_mod_unloading
267 };
268 
269 /*ARGSUSED1*/
270 void
271 kaif_activate(kdi_debugvec_t **dvecp, uint_t flags)
272 {
273 	kaif_prom_install();
274 
275 	kaif_ktrap_install(0, kaif_ktrap);
276 	kaif_trap_init();
277 
278 	*dvecp = &kaif_dvec;
279 }
280 
281 void
282 kaif_deactivate(void)
283 {
284 	kmdb_prom_interpret(" ['] noop is debugger-hook ");
285 
286 	kaif_ktrap_restore();
287 }
288