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