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 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * The KDI, or kernel/debugger interface, is used to allow the kernel and the 30 * debugger to communicate. These communications take two forms: 31 * 32 * 1. kernel to debugger. Interfaces of this type are used by the kernel to 33 * inform the debugger of changes in the state of the system that need to 34 * be noted by the debugger. For example, the kernel uses one of these 35 * interfaces to tell debugger that the set of currently-loaded modules 36 * has changed. 37 * 38 * 2. debugger to kernel. Interfaces of this type are used by the debugger 39 * to extract information from the kernel that would otherwise be difficult 40 * to get, or to perform services that are specific to the machine being 41 * used. An example of the former is the module iterator, which is needed 42 * to allow symbol resolution, but which needs to resolve symbols prior 43 * to the iteration. The latter class include machine-specific or 44 * cpu-type-specific functions, such as the I-cache flusher. By directly 45 * using the kernel versions of these functions, we avoid the need to 46 * include multiple versions of each function - one per cpu and/or machine - 47 * in kmdb. 48 */ 49 50 #include <sys/kdi_impl.h> 51 52 #include <kmdb/kmdb_kdi.h> 53 #include <kmdb/kmdb_dpi.h> 54 #include <kmdb/kmdb_kvm.h> 55 #include <kmdb/kmdb_promif.h> 56 #include <mdb/mdb_debug.h> 57 #include <mdb/mdb_err.h> 58 #include <mdb/mdb.h> 59 60 static int kdi_unload_request; 61 62 typedef struct mod_interp_data { 63 int (*mid_usercb)(struct modctl *, void *); 64 void *mid_userarg; 65 jmp_buf mid_pcb; 66 jmp_buf *mid_oldpcb; 67 } mod_interp_data_t; 68 69 static kmdb_auxv_t *kdi_auxv; 70 71 int 72 kmdb_kdi_mods_changed(void) 73 { 74 return (mdb.m_kdi->kdi_mods_changed()); 75 } 76 77 static int 78 kmdb_kdi_mod_interp(struct modctl *mp, void *arg) 79 { 80 mod_interp_data_t *mid = arg; 81 int rc; 82 83 kmdb_dpi_restore_fault_hdlr(mid->mid_oldpcb); 84 rc = mid->mid_usercb(mp, mid->mid_userarg); 85 mid->mid_oldpcb = kmdb_dpi_set_fault_hdlr(&mid->mid_pcb); 86 87 return (rc); 88 } 89 90 /* 91 * We need to protect ourselves against any problems that may occur while 92 * executing the module iterator, currently located in krtld. If, for 93 * example, one of the next pointers in the module list points to an invalid 94 * address, we don't want kmdb to explode. As such, we protect ourselves 95 * with the DPI fault-protection routines. We don't want our fault-protection 96 * callback to protect the callback that the kmdb consumer provided, so we 97 * provide our own interposition callback that removes our fault-protector 98 * before invoking the user's callback. 99 */ 100 int 101 kmdb_kdi_mod_iter(int (*cb)(struct modctl *, void *), void *arg) 102 { 103 mod_interp_data_t mid; 104 int rc; 105 106 if (setjmp(mid.mid_pcb) != 0) { 107 /* We took a fault while iterating through the modules */ 108 kmdb_dpi_restore_fault_hdlr(mid.mid_oldpcb); 109 return (-1); 110 } 111 112 mid.mid_usercb = cb; 113 mid.mid_userarg = arg; 114 mid.mid_oldpcb = kmdb_dpi_set_fault_hdlr(&mid.mid_pcb); 115 116 rc = mdb.m_kdi->kdi_mod_iter(kmdb_kdi_mod_interp, &mid); 117 118 kmdb_dpi_restore_fault_hdlr(mid.mid_oldpcb); 119 120 return (rc); 121 } 122 123 int 124 kmdb_kdi_mod_isloaded(struct modctl *modp) 125 { 126 return (mdb.m_kdi->kdi_mod_isloaded(modp)); 127 } 128 129 int 130 kmdb_kdi_mod_haschanged(struct modctl *mc1, struct module *mp1, 131 struct modctl *mc2, struct module *mp2) 132 { 133 return (mdb.m_kdi->kdi_mod_haschanged(mc1, mp1, mc2, mp2)); 134 } 135 136 static ssize_t 137 kdi_prw(void *buf, size_t nbytes, physaddr_t addr, int (*rw)(caddr_t, size_t, 138 physaddr_t, size_t *)) 139 { 140 size_t sz; 141 int rc; 142 143 kmdb_dpi_flush_slave_caches(); 144 if ((rc = rw(buf, nbytes, addr, &sz)) != 0) 145 return (set_errno(rc)); 146 147 return (sz); 148 } 149 150 ssize_t 151 kmdb_kdi_pread(void *buf, size_t nbytes, physaddr_t addr) 152 { 153 return (kdi_prw(buf, nbytes, addr, mdb.m_kdi->kdi_pread)); 154 } 155 156 ssize_t 157 kmdb_kdi_pwrite(void *buf, size_t nbytes, physaddr_t addr) 158 { 159 return (kdi_prw(buf, nbytes, addr, mdb.m_kdi->kdi_pwrite)); 160 } 161 162 void 163 kmdb_kdi_flush_caches(void) 164 { 165 mdb.m_kdi->kdi_flush_caches(); 166 } 167 168 int 169 kmdb_kdi_get_unload_request(void) 170 { 171 return (kdi_unload_request); 172 } 173 174 void 175 kmdb_kdi_set_unload_request(void) 176 { 177 kdi_unload_request = 1; 178 } 179 180 int 181 kmdb_kdi_get_flags(void) 182 { 183 uint_t flags = 0; 184 185 if (mdb.m_flags & MDB_FL_NOCTF) 186 flags |= KMDB_KDI_FL_NOCTF; 187 if (mdb.m_flags & MDB_FL_NOMODS) 188 flags |= KMDB_KDI_FL_NOMODS; 189 190 return (flags); 191 } 192 193 size_t 194 kmdb_kdi_range_is_nontoxic(uintptr_t va, size_t sz, int write) 195 { 196 return (mdb.m_kdi->kdi_range_is_nontoxic(va, sz, write)); 197 } 198 199 void 200 kmdb_kdi_system_claim(void) 201 { 202 (void) kmdb_dpi_call((uintptr_t)mdb.m_kdi->kdi_system_claim, 0, NULL); 203 kmdb_prom_debugger_entry(); 204 } 205 206 void 207 kmdb_kdi_system_release(void) 208 { 209 kmdb_prom_debugger_exit(); 210 211 if (mdb.m_kdi->kdi_system_release != NULL) { 212 (void) kmdb_dpi_call((uintptr_t)mdb.m_kdi->kdi_system_release, 213 0, NULL); 214 } 215 } 216 217 struct cons_polledio * 218 kmdb_kdi_get_polled_io(void) 219 { 220 return (mdb.m_kdi->kdi_get_polled_io()); 221 } 222 223 void 224 kmdb_kdi_kmdb_enter(void) 225 { 226 mdb.m_kdi->kdi_kmdb_enter(); 227 } 228 229 int 230 kmdb_kdi_vtop(uintptr_t va, physaddr_t *pap) 231 { 232 jmp_buf pcb, *oldpcb; 233 int rc = 0; 234 235 if (setjmp(pcb) == 0) { 236 int err; 237 238 oldpcb = kmdb_dpi_set_fault_hdlr(&pcb); 239 240 if ((err = mdb.m_kdi->kdi_vtop(va, pap)) != 0) 241 rc = set_errno(err == ENOENT ? EMDB_NOMAP : err); 242 } else { 243 /* We faulted during the translation */ 244 rc = set_errno(EMDB_NOMAP); 245 } 246 247 kmdb_dpi_restore_fault_hdlr(oldpcb); 248 249 return (rc); 250 } 251 252 kdi_dtrace_state_t 253 kmdb_kdi_dtrace_get_state(void) 254 { 255 return (mdb.m_kdi->kdi_dtrace_get_state()); 256 } 257 258 int 259 kmdb_kdi_dtrace_set(int state) 260 { 261 int err; 262 263 if ((err = mdb.m_kdi->kdi_dtrace_set(state)) != 0) 264 return (set_errno(err)); 265 266 return (0); 267 } 268 269 /* 270 * This function is to be called only during kmdb initialization, as it 271 * uses the running kernel for symbol translation facilities. 272 */ 273 uintptr_t 274 kmdb_kdi_lookup_by_name(char *modname, char *symname) 275 { 276 ASSERT(kmdb_dpi_get_state(NULL) == DPI_STATE_INIT); 277 278 return (kdi_auxv->kav_lookup_by_name(modname, symname)); 279 } 280 281 void 282 kmdb_kdi_init(kdi_t *kdi, kmdb_auxv_t *kav) 283 { 284 mdb.m_kdi = kdi; 285 mdb.m_pagesize = kav->kav_pagesize; 286 287 kdi_unload_request = 0; 288 289 kdi_auxv = kav; 290 291 kmdb_kdi_init_isadep(kdi, kav); 292 } 293 294 void 295 kmdb_kdi_end_init(void) 296 { 297 kdi_auxv = NULL; 298 } 299