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 void 140 kobj_kdi_mod_notify(uint_t why, struct modctl *what) 141 { 142 switch (why) { 143 case KOBJ_NOTIFY_MODLOADING: 144 kobj_kdi_mod_state = KOBJ_KDI_MOD_CHANGING; 145 break; 146 case KOBJ_NOTIFY_MODLOADED: 147 kobj_kdi_mod_state = KOBJ_KDI_MOD_CHANGED; 148 if (boothowto & RB_DEBUG) 149 kdi_dvec_mod_loaded(what); 150 break; 151 case KOBJ_NOTIFY_MODUNLOADING: 152 kobj_kdi_mod_state = KOBJ_KDI_MOD_CHANGING; 153 if (boothowto & RB_DEBUG) 154 kdi_dvec_mod_unloading(what); 155 break; 156 case KOBJ_NOTIFY_MODUNLOADED: 157 kobj_kdi_mod_state = KOBJ_KDI_MOD_CHANGED; 158 break; 159 } 160 } 161 162 /* 163 * Compare two modctl and module snapshots, attempting to determine whether 164 * the module to which they both refer has changed between the time of the first 165 * and the time of the second. We can't do a straight bcmp, because there are 166 * fields that change in the normal course of operations. False positives 167 * aren't the end of the world, but it'd be nice to avoid flagging a module 168 * as changed every time someone holds or releases it. 169 */ 170 int 171 kobj_kdi_mod_haschanged(struct modctl *mc1, struct module *mp1, 172 struct modctl *mc2, struct module *mp2) 173 { 174 if (mc1->mod_loadcnt != mc2->mod_loadcnt || mc1->mod_mp != mc2->mod_mp) 175 return (1); 176 177 if (mc1->mod_mp == NULL) 178 return (0); 179 180 /* Take breath here. */ 181 return (bcmp(&mp1->hdr, &mp2->hdr, sizeof (mp1->hdr)) != 0 || 182 mp1->symhdr != mp2->symhdr || mp1->strhdr != mp2->strhdr || 183 mp1->text != mp2->text || mp1->bss != mp2->bss || 184 mp1->ctfdata != mp2->ctfdata || mp1->ctfsize != mp2->ctfsize); 185 } 186 187 void 188 kobj_kdi_system_claim(void) 189 { 190 kobj_kdi.kdi_plat_call(kobj_kdi.pkdi_system_claim); 191 kobj_kdi.kdi_plat_call(kobj_kdi.pkdi_console_claim); 192 } 193 194 void 195 kobj_kdi_system_release(void) 196 { 197 kobj_kdi.kdi_plat_call(kobj_kdi.pkdi_console_release); 198 kobj_kdi.kdi_plat_call(kobj_kdi.pkdi_system_release); 199 } 200 201 void 202 kobj_kdi_init(void) 203 { 204 static const char *const initializers[] = { 205 "cpu_kdi_init", "mach_kdi_init", "plat_kdi_init", NULL 206 }; 207 208 Sym *sym; 209 int i; 210 211 for (i = 0; initializers[i] != NULL; i++) { 212 if ((sym = kobj_lookup_kernel(initializers[i])) != NULL) 213 ((void (*)(kdi_t *))sym->st_value)(&kobj_kdi); 214 } 215 } 216 217 kdi_t kobj_kdi = { 218 KDI_VERSION, 219 kobj_kdi_mods_changed, 220 kobj_kdi_mod_iter, 221 kobj_kdi_mod_isloaded, 222 kobj_kdi_mod_haschanged, 223 kobj_kdi_system_claim, 224 kobj_kdi_system_release, 225 kdi_pread, 226 kdi_pwrite, 227 kdi_flush_caches, 228 kdi_range_is_nontoxic, 229 kobj_kdi_get_polled_io, 230 kdi_vtop, 231 kdi_dtrace_get_state, 232 kdi_dtrace_set, 233 /* 234 * The rest are filled in by cpu_kdi_init, mach_kdi_init, and/or 235 * plat_kdi_init. 236 */ 237 NULL, /* kdi_plat_call */ 238 NULL, /* kdi_kmdb_enter */ 239 { NULL }, /* kdi_arch */ 240 { NULL } /* kdi_plat */ 241 }; 242