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