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