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