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 2006 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 #ifdef sun4v 135 136 /*ARGSUSED*/ 137 static void 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 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 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 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 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 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 276 kaif_cpr_restart(void) 277 { 278 } 279 280 static kdi_debugvec_t kaif_dvec = { 281 kaif_enter, 282 kaif_cpu_init, 283 NULL, /* dv_kctl_cpu_init */ 284 kaif_vmready, 285 NULL, /* dv_kctl_vmready */ 286 NULL, /* dv_kctl_memavail */ 287 kaif_memrange_add, 288 kaif_cpr_restart, 289 NULL, /* dv_kctl_modavail */ 290 NULL, /* dv_kctl_thravail */ 291 kaif_mod_loaded, 292 kaif_mod_unloading 293 }; 294 295 /*ARGSUSED1*/ 296 void 297 kaif_activate(kdi_debugvec_t **dvecp, uint_t flags) 298 { 299 kaif_prom_install(); 300 301 kaif_ktrap_install(0, kaif_ktrap); 302 kaif_trap_init(); 303 304 *dvecp = &kaif_dvec; 305 } 306 307 void 308 kaif_deactivate(void) 309 { 310 kmdb_prom_interpret(" ['] noop is debugger-hook "); 311 312 kaif_ktrap_restore(); 313 } 314