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 is used to allow the kernel debugger to directly invoke various 30 * kernel functions. In some cases, such as with kdi_mod_iter(), the 31 * debugger needs to execute functions that use the kernel's linker bindings. 32 * In other cases, the implementation of the KDI functions vary by platform 33 * and/or by CPU. By embedding the implementation of these functions in 34 * the platmod/cpumod, we can avoid the need for platform-specific knowledge 35 * in the debugger, and can thus have a single debugger binary for all 36 * platforms. 37 * 38 * There are three classes of KDI function: 39 * 40 * 1. Normal - These are functions whose implementations are in the kernel for 41 * convenience. An example is the modctl iterator, kdi_mod_iter. Using the 42 * modules symbol, this function iterates through the kernel's modctl list, 43 * invoking a debugger-provided callback for each one. This function is in 44 * the KDI because the debugger needs to be able to execute it in order to 45 * enable symbol resolution. Without symbol resolution, the debugger can't 46 * locate the modules symbol. A chicken-and-egg problem results. We solve 47 * this problem by locating the module iterator in the kernel, where run-time 48 * linking solves the problem for us. 49 * 50 * 2. CPU-specific - Functions in this class have implementations that differ 51 * by CPU. For example, the crosscall delivery notification method differs 52 * between Cheetah and Jalapeno, necessitating a different implementation for 53 * each. By locating the KDI implementation of these functions in the 54 * cpumods, we automatically get the correct implementation, as krtld 55 * automatically loads the correct cpumod when it starts. The cpumods 56 * directly fill in their portion of the kdi_t, using the mandatory 57 * cpu_kdi_init cpumod entry point. 58 * 59 * 3. Platform-specific - Similar to the CPU-specific class, platform-specific 60 * KDI functions have implementations that differ from platform to platform. 61 * As such, the implementations live in the platmods. Further 62 * differentiating the platform-specific KDI functions from their 63 * CPU-dependent brethren, many directly invoke PROM functions. This poses 64 * a problem, as the platmods use the kernel's promif functions, rather than 65 * the lock-free kmdb versions. We provide an interposition layer for these 66 * platform-specific calls that disables the pre- and post-processing 67 * functions used by the kernel to implement kernel-specific functionality 68 * that must not be executed when kmdb has control of the machine. Platmods 69 * fill in a kdi_plat_t using their optional plat_kdi_init entry point. 70 * krtld provides wrapper functions which suspend the necessary functions in 71 * the promif layer before invoking the kdi_plat_t functions (if any). 72 */ 73 74 #include <sys/types.h> 75 #include <sys/systm.h> 76 #include <sys/reboot.h> 77 #include <sys/kdi_impl.h> 78 79 #include <kobj_kdi.h> 80 81 #define KOBJ_KDI_MOD_IDLE 0 82 #define KOBJ_KDI_MOD_CHANGING 1 83 #define KOBJ_KDI_MOD_CHANGED 2 84 85 static int kobj_kdi_mod_state = KOBJ_KDI_MOD_IDLE; 86 87 extern int standalone; 88 89 cons_polledio_t * 90 kobj_kdi_get_polled_io(void) 91 { 92 cons_polledio_t **polled_io = &cons_polledio; 93 94 return (polled_io == NULL ? NULL : *polled_io); 95 } 96 97 int 98 kobj_kdi_mod_iter(int (*func)(struct modctl *, void *), void *arg) 99 { 100 int rc; 101 102 if (standalone) { 103 struct modctl_list *lp, **lpp; 104 105 for (lpp = kobj_linkmaps; *lpp != NULL; lpp++) { 106 for (lp = *lpp; lp != NULL; lp = lp->modl_next) { 107 if ((rc = func(lp->modl_modp, arg)) != 0) 108 return (rc); 109 } 110 } 111 112 } else { 113 struct modctl *modp = &modules; 114 115 do { 116 if ((rc = func(modp, arg)) != 0) 117 return (rc); 118 } while ((modp = modp->mod_next) != &modules); 119 } 120 121 return (0); 122 } 123 124 int 125 kobj_kdi_mod_isloaded(struct modctl *modp) 126 { 127 return (modp->mod_mp != NULL); 128 } 129 130 int 131 kobj_kdi_mods_changed(void) 132 { 133 int state; 134 135 if ((state = kobj_kdi_mod_state) == KOBJ_KDI_MOD_CHANGED) 136 kobj_kdi_mod_state = KOBJ_KDI_MOD_IDLE; 137 138 return (state != KOBJ_KDI_MOD_IDLE); 139 } 140 141 /*ARGSUSED1*/ 142 void 143 kobj_kdi_mod_notify(uint_t why, struct modctl *what) 144 { 145 switch (why) { 146 case KOBJ_NOTIFY_MODLOADING: 147 kobj_kdi_mod_state = KOBJ_KDI_MOD_CHANGING; 148 break; 149 case KOBJ_NOTIFY_MODLOADED: 150 kobj_kdi_mod_state = KOBJ_KDI_MOD_CHANGED; 151 if (boothowto & RB_DEBUG) 152 kdi_dvec_mod_loaded(what); 153 break; 154 case KOBJ_NOTIFY_MODUNLOADING: 155 kobj_kdi_mod_state = KOBJ_KDI_MOD_CHANGING; 156 if (boothowto & RB_DEBUG) 157 kdi_dvec_mod_unloading(what); 158 break; 159 case KOBJ_NOTIFY_MODUNLOADED: 160 kobj_kdi_mod_state = KOBJ_KDI_MOD_CHANGED; 161 break; 162 } 163 } 164 165 /* 166 * Compare two modctl and module snapshots, attempting to determine whether 167 * the module to which they both refer has changed between the time of the first 168 * and the time of the second. We can't do a straight bcmp, because there are 169 * fields that change in the normal course of operations. False positives 170 * aren't the end of the world, but it'd be nice to avoid flagging a module 171 * as changed every time someone holds or releases it. 172 */ 173 int 174 kobj_kdi_mod_haschanged(struct modctl *mc1, struct module *mp1, 175 struct modctl *mc2, struct module *mp2) 176 { 177 if (mc1->mod_loadcnt != mc2->mod_loadcnt || mc1->mod_mp != mc2->mod_mp) 178 return (1); 179 180 if (mc1->mod_mp == NULL) 181 return (0); 182 183 /* Take breath here. */ 184 return (bcmp(&mp1->hdr, &mp2->hdr, sizeof (mp1->hdr)) != 0 || 185 mp1->symhdr != mp2->symhdr || mp1->strhdr != mp2->strhdr || 186 mp1->text != mp2->text || mp1->bss != mp2->bss || 187 mp1->ctfdata != mp2->ctfdata || mp1->ctfsize != mp2->ctfsize); 188 } 189 190 void 191 kobj_kdi_system_claim(void) 192 { 193 kobj_kdi.kdi_plat_call(kobj_kdi.pkdi_system_claim); 194 kobj_kdi.kdi_plat_call(kobj_kdi.pkdi_console_claim); 195 } 196 197 void 198 kobj_kdi_system_release(void) 199 { 200 kobj_kdi.kdi_plat_call(kobj_kdi.pkdi_console_release); 201 kobj_kdi.kdi_plat_call(kobj_kdi.pkdi_system_release); 202 } 203 204 void 205 kobj_kdi_init(void) 206 { 207 static const char *const initializers[] = { 208 "cpu_kdi_init", "mach_kdi_init", "plat_kdi_init", NULL 209 }; 210 211 Sym *sym; 212 int i; 213 214 for (i = 0; initializers[i] != NULL; i++) { 215 if ((sym = kobj_lookup_kernel(initializers[i])) != NULL) 216 ((void (*)(kdi_t *))sym->st_value)(&kobj_kdi); 217 } 218 } 219 220 kdi_t kobj_kdi = { 221 KDI_VERSION, 222 kobj_kdi_mods_changed, 223 kobj_kdi_mod_iter, 224 kobj_kdi_mod_isloaded, 225 kobj_kdi_mod_haschanged, 226 kobj_kdi_system_claim, 227 kobj_kdi_system_release, 228 kdi_pread, 229 kdi_pwrite, 230 kdi_flush_caches, 231 kdi_range_is_nontoxic, 232 kobj_kdi_get_polled_io, 233 kdi_vtop, 234 kdi_dtrace_get_state, 235 kdi_dtrace_set, 236 /* 237 * The rest are filled in by cpu_kdi_init, mach_kdi_init, and/or 238 * plat_kdi_init. 239 */ 240 NULL, /* kdi_plat_call */ 241 NULL, /* kdi_kmdb_enter */ 242 { NULL }, /* kdi_arch */ 243 { NULL } /* kdi_plat */ 244 }; 245