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