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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2007 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 *
kaif_format_word(void)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
kaif_prom_install(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
kaif_prom_rearm(void)115 kaif_prom_rearm(void)
116 {
117 kmdb_prom_interpret(" ['] kmdb_callback is debugger-hook ");
118 }
119
120 /*ARGSUSED*/
121 static void
kaif_cpu_init(cpu_t * cp)122 kaif_cpu_init(cpu_t *cp)
123 {
124 kaif_wapt_set_regs();
125 }
126
127 /*ARGSUSED*/
128 static void
kaif_install_generic(caddr_t tgt,caddr_t arg)129 kaif_install_generic(caddr_t tgt, caddr_t arg)
130 {
131 bcopy((caddr_t)kaif_hdlr_generic, tgt, 32);
132 }
133
134 #ifdef sun4v
135
136 /*ARGSUSED*/
137 static void
kaif_install_goto_tt64(caddr_t tgt,caddr_t arg)138 kaif_install_goto_tt64(caddr_t tgt, caddr_t arg)
139 {
140 /* LINTED - pointer alignment */
141 uint32_t *hdlr = (uint32_t *)tgt;
142 uint32_t disp = (T_FAST_INSTR_MMU_MISS - T_INSTR_MMU_MISS) * 0x20;
143
144 *hdlr++ = 0x10480000 | (disp >> 2); /* ba,pt (to tt64) */
145 *hdlr++ = 0x01000000; /* nop */
146 }
147
148 /*ARGSUSED*/
149 static void
kaif_install_goto_tt68(caddr_t tgt,caddr_t arg)150 kaif_install_goto_tt68(caddr_t tgt, caddr_t arg)
151 {
152 /* LINTED - pointer alignment */
153 uint32_t *hdlr = (uint32_t *)tgt;
154 uint32_t disp = (T_FAST_DATA_MMU_MISS - T_DATA_MMU_MISS) * 0x20;
155
156 *hdlr++ = 0x10480000 | (disp >> 2); /* ba,pt (to tt68) */
157 *hdlr++ = 0x01000000; /* nop */
158 }
159
160 #endif /* sun4v */
161
162 static void
kaif_install_dmmumiss(caddr_t tgt,caddr_t vatotte)163 kaif_install_dmmumiss(caddr_t tgt, caddr_t vatotte)
164 {
165 uint32_t *patch;
166
167 bcopy((caddr_t)kaif_hdlr_dmiss, tgt, 128);
168
169 /* LINTED - pointer alignment */
170 patch = (uint32_t *)(tgt + ((uintptr_t)&kaif_hdlr_dmiss_patch -
171 (uintptr_t)kaif_hdlr_dmiss));
172 *patch++ |= (uintptr_t)vatotte >> 10;
173 *patch |= ((uintptr_t)vatotte) & 0x3ff;
174 }
175
176 static void
kaif_install_immumiss(caddr_t tgt,caddr_t vatotte)177 kaif_install_immumiss(caddr_t tgt, caddr_t vatotte)
178 {
179 uint32_t *patch;
180
181 bcopy((caddr_t)kaif_hdlr_imiss, tgt, 128);
182
183 /* LINTED - pointer alignment */
184 patch = (uint32_t *)(tgt + ((uintptr_t)&kaif_hdlr_imiss_patch -
185 (uintptr_t)kaif_hdlr_imiss));
186 *patch++ |= (uintptr_t)vatotte >> 10;
187 *patch |= ((uintptr_t)vatotte) & 0x3ff;
188 }
189
190 static struct kaif_trap_handlers {
191 uint_t th_tt;
192 void (*th_install)(caddr_t, caddr_t);
193 } kaif_trap_handlers[] = {
194 { T_INSTR_EXCEPTION, kaif_install_generic },
195 #ifdef sun4v
196 { T_INSTR_MMU_MISS, kaif_install_goto_tt64 },
197 #endif
198 { T_IDIV0, kaif_install_generic },
199 { T_DATA_EXCEPTION, kaif_install_generic },
200 #ifdef sun4v
201 { T_DATA_MMU_MISS, kaif_install_goto_tt68 },
202 #endif
203 { T_DATA_ERROR, kaif_install_generic },
204 { T_ALIGNMENT, kaif_install_generic },
205 { T_FAST_INSTR_MMU_MISS, kaif_install_immumiss },
206 { T_FAST_DATA_MMU_MISS, kaif_install_dmmumiss },
207 { T_FAST_DATA_MMU_PROT, kaif_install_generic },
208 #ifdef sun4v
209 { T_INSTR_MMU_MISS + T_TL1, kaif_install_goto_tt64 },
210 { T_DATA_MMU_MISS + T_TL1, kaif_install_goto_tt68 },
211 #endif
212 { T_FAST_INSTR_MMU_MISS + T_TL1, kaif_install_immumiss },
213 { T_FAST_DATA_MMU_MISS + T_TL1, kaif_install_dmmumiss },
214 { 0 }
215 };
216
217 static void
kaif_trap_init(void)218 kaif_trap_init(void)
219 {
220 caddr_t vatotte = kmdb_kdi_get_trap_vatotte();
221 uintptr_t brtgt;
222 int i;
223
224 /*
225 * sun4u:
226 * We rely upon OBP for the handling of a great many traps. As such,
227 * we begin by populating our table with pointers to OBP's handlers.
228 * We then copy in our own handlers where appropriate. At some point,
229 * when we provide the bulk of the handlers, this process will be
230 * reversed.
231 *
232 * sun4v:
233 * The sun4v kernel dismisses OBP at boot. Both fast and slow TLB
234 * misses are handled by KMDB. Breakpoint traps go directly KMDB.
235 * All other trap entries are redirected to their respective
236 * trap implemenation within the Solaris trap table.
237 */
238 for (i = 0; i < kaif_tba_native_sz; i += 0x20) {
239 /* LINTED - pointer alignment */
240 uint32_t *hdlr = (uint32_t *)(kaif_tba_native + i);
241 #ifdef sun4v
242 brtgt = (uintptr_t)(kaif_tba_kernel + i);
243 #else
244 brtgt = (uintptr_t)(kaif_tba_obp + i);
245 #endif
246 *hdlr++ = 0x03000000 | (brtgt >> 10); /* sethi brtgt, %g1 */
247 *hdlr++ = 0x81c06000 | (brtgt & 0x3ff); /* jmp %g1 + brtgt */
248 *hdlr++ = 0x01000000; /* nop */
249 }
250
251 for (i = 0; kaif_trap_handlers[i].th_tt != 0; i++) {
252 struct kaif_trap_handlers *th = &kaif_trap_handlers[i];
253 th->th_install(kaif_tba_native + th->th_tt * 0x20, vatotte);
254 }
255 membar_producer();
256 }
257
258 /*
259 * The kernel is ready for us to switch to our table (the HAT has been
260 * initialized, the hments are walkable, and the trap table's pages
261 * have been locked into the TLBs.
262 */
263 static void
kaif_vmready(void)264 kaif_vmready(void)
265 {
266 kaif_tba = kaif_tba_native;
267 }
268
269 /*
270 * Called on the CPR master CPU. The driver has taken care of locking the
271 * TLB entries. CPR restored the OBP image which contains kmdb_callback,
272 * so there's nothing we need to do. This function should be removed entirely
273 * in a future release.
274 */
275 static void
kaif_cpr_restart(void)276 kaif_cpr_restart(void)
277 {
278 }
279
280 static kdi_debugvec_t kaif_dvec = {
281 NULL, /* dv_kctl_vmready */
282 NULL, /* dv_kctl_memavail */
283 NULL, /* dv_kctl_modavail */
284 NULL, /* dv_kctl_thravail */
285 kaif_vmready,
286 NULL, /* dv_memavail */
287 kaif_mod_loaded,
288 kaif_mod_unloading,
289 NULL, /* dv_kctl_cpu_init */
290 kaif_cpu_init,
291 kaif_cpr_restart
292 };
293
294 /*ARGSUSED1*/
295 void
kaif_activate(kdi_debugvec_t ** dvecp,uint_t flags)296 kaif_activate(kdi_debugvec_t **dvecp, uint_t flags)
297 {
298 kaif_prom_install();
299
300 kaif_ktrap_install(0, kaif_ktrap);
301 kaif_trap_init();
302
303 *dvecp = &kaif_dvec;
304 }
305
306 void
kaif_deactivate(void)307 kaif_deactivate(void)
308 {
309 kmdb_prom_interpret(" ['] noop is debugger-hook ");
310
311 kaif_ktrap_restore();
312 }
313