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.
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.
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]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
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
38 * There are three classes of KDI function:
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.
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.
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).
74 #include <sys/types.h>
75 #include <sys/systm.h>
76 #include <sys/reboot.h>
77 #include <sys/kdi_impl.h>
79 #include <krtld/kobj_kdi.h>
81 #define KOBJ_KDI_MOD_IDLE 0
82 #define KOBJ_KDI_MOD_CHANGING 1
83 #define KOBJ_KDI_MOD_CHANGED 2
85 static int kobj_kdi_mod_state
= KOBJ_KDI_MOD_IDLE
;
87 extern int standalone
;
90 kobj_kdi_get_polled_io(void)
92 cons_polledio_t
**polled_io
= &cons_polledio
;
94 return (polled_io
== NULL
? NULL
: *polled_io
);
98 kobj_kdi_mod_iter(int (*func
)(struct modctl
*, void *), void *arg
)
103 struct modctl_list
*lp
, **lpp
;
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)
113 struct modctl
*modp
= &modules
;
116 if ((rc
= func(modp
, arg
)) != 0)
118 } while ((modp
= modp
->mod_next
) != &modules
);
125 kobj_kdi_mod_isloaded(struct modctl
*modp
)
127 return (modp
->mod_mp
!= NULL
);
131 kobj_kdi_mods_changed(void)
135 if ((state
= kobj_kdi_mod_state
) == KOBJ_KDI_MOD_CHANGED
)
136 kobj_kdi_mod_state
= KOBJ_KDI_MOD_IDLE
;
138 return (state
!= KOBJ_KDI_MOD_IDLE
);
143 kobj_kdi_mod_notify(uint_t why
, struct modctl
*what
)
146 case KOBJ_NOTIFY_MODLOADING
:
147 kobj_kdi_mod_state
= KOBJ_KDI_MOD_CHANGING
;
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
);
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
);
159 case KOBJ_NOTIFY_MODUNLOADED
:
160 kobj_kdi_mod_state
= KOBJ_KDI_MOD_CHANGED
;
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.
174 kobj_kdi_mod_haschanged(struct modctl
*mc1
, struct module
*mp1
,
175 struct modctl
*mc2
, struct module
*mp2
)
177 if (mc1
->mod_loadcnt
!= mc2
->mod_loadcnt
|| mc1
->mod_mp
!= mc2
->mod_mp
)
180 if (mc1
->mod_mp
== NULL
)
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
);
191 kobj_kdi_system_claim(void)
193 kobj_kdi
.kdi_plat_call(kobj_kdi
.pkdi_system_claim
);
194 kobj_kdi
.kdi_plat_call(kobj_kdi
.pkdi_console_claim
);
198 kobj_kdi_system_release(void)
200 kobj_kdi
.kdi_plat_call(kobj_kdi
.pkdi_console_release
);
201 kobj_kdi
.kdi_plat_call(kobj_kdi
.pkdi_system_release
);
207 static const char *const initializers
[] = {
208 "cpu_kdi_init", "mach_kdi_init", "plat_kdi_init", NULL
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
);
222 kobj_kdi_mods_changed
,
224 kobj_kdi_mod_isloaded
,
225 kobj_kdi_mod_haschanged
,
226 kobj_kdi_system_claim
,
227 kobj_kdi_system_release
,
231 kdi_range_is_nontoxic
,
232 kobj_kdi_get_polled_io
,
234 kdi_dtrace_get_state
,
237 * The rest are filled in by cpu_kdi_init, mach_kdi_init, and/or
240 NULL
, /* kdi_plat_call */
241 NULL
, /* kdi_kmdb_enter */
242 { NULL
}, /* kdi_arch */
243 { NULL
} /* kdi_plat */