dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / mdb / common / kmdb / kmdb_kdi.c
blobc9e3358af996269336791df750f7ed4ea3fa919a
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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, or kernel/debugger interface, is used to allow the kernel and the
30 * debugger to communicate. These communications take two forms:
32 * 1. kernel to debugger. Interfaces of this type are used by the kernel to
33 * inform the debugger of changes in the state of the system that need to
34 * be noted by the debugger. For example, the kernel uses one of these
35 * interfaces to tell debugger that the set of currently-loaded modules
36 * has changed.
38 * 2. debugger to kernel. Interfaces of this type are used by the debugger
39 * to extract information from the kernel that would otherwise be difficult
40 * to get, or to perform services that are specific to the machine being
41 * used. An example of the former is the module iterator, which is needed
42 * to allow symbol resolution, but which needs to resolve symbols prior
43 * to the iteration. The latter class include machine-specific or
44 * cpu-type-specific functions, such as the I-cache flusher. By directly
45 * using the kernel versions of these functions, we avoid the need to
46 * include multiple versions of each function - one per cpu and/or machine -
47 * in kmdb.
50 #include <sys/kdi_impl.h>
52 #include <kmdb/kmdb_kdi.h>
53 #include <kmdb/kmdb_dpi.h>
54 #include <kmdb/kmdb_kvm.h>
55 #include <kmdb/kmdb_promif.h>
56 #include <mdb/mdb_debug.h>
57 #include <mdb/mdb_err.h>
58 #include <mdb/mdb.h>
60 static int kdi_unload_request;
62 typedef struct mod_interp_data {
63 int (*mid_usercb)(struct modctl *, void *);
64 void *mid_userarg;
65 jmp_buf mid_pcb;
66 jmp_buf *mid_oldpcb;
67 } mod_interp_data_t;
69 static kmdb_auxv_t *kdi_auxv;
71 int
72 kmdb_kdi_mods_changed(void)
74 return (mdb.m_kdi->kdi_mods_changed());
77 static int
78 kmdb_kdi_mod_interp(struct modctl *mp, void *arg)
80 mod_interp_data_t *mid = arg;
81 int rc;
83 kmdb_dpi_restore_fault_hdlr(mid->mid_oldpcb);
84 rc = mid->mid_usercb(mp, mid->mid_userarg);
85 mid->mid_oldpcb = kmdb_dpi_set_fault_hdlr(&mid->mid_pcb);
87 return (rc);
91 * We need to protect ourselves against any problems that may occur while
92 * executing the module iterator, currently located in krtld. If, for
93 * example, one of the next pointers in the module list points to an invalid
94 * address, we don't want kmdb to explode. As such, we protect ourselves
95 * with the DPI fault-protection routines. We don't want our fault-protection
96 * callback to protect the callback that the kmdb consumer provided, so we
97 * provide our own interposition callback that removes our fault-protector
98 * before invoking the user's callback.
101 kmdb_kdi_mod_iter(int (*cb)(struct modctl *, void *), void *arg)
103 mod_interp_data_t mid;
104 int rc;
106 if (setjmp(mid.mid_pcb) != 0) {
107 /* We took a fault while iterating through the modules */
108 kmdb_dpi_restore_fault_hdlr(mid.mid_oldpcb);
109 return (-1);
112 mid.mid_usercb = cb;
113 mid.mid_userarg = arg;
114 mid.mid_oldpcb = kmdb_dpi_set_fault_hdlr(&mid.mid_pcb);
116 rc = mdb.m_kdi->kdi_mod_iter(kmdb_kdi_mod_interp, &mid);
118 kmdb_dpi_restore_fault_hdlr(mid.mid_oldpcb);
120 return (rc);
124 kmdb_kdi_mod_isloaded(struct modctl *modp)
126 return (mdb.m_kdi->kdi_mod_isloaded(modp));
130 kmdb_kdi_mod_haschanged(struct modctl *mc1, struct module *mp1,
131 struct modctl *mc2, struct module *mp2)
133 return (mdb.m_kdi->kdi_mod_haschanged(mc1, mp1, mc2, mp2));
136 static ssize_t
137 kdi_prw(void *buf, size_t nbytes, physaddr_t addr, int (*rw)(caddr_t, size_t,
138 physaddr_t, size_t *))
140 size_t sz;
141 int rc;
143 kmdb_dpi_flush_slave_caches();
144 if ((rc = rw(buf, nbytes, addr, &sz)) != 0)
145 return (set_errno(rc));
147 return (sz);
150 ssize_t
151 kmdb_kdi_pread(void *buf, size_t nbytes, physaddr_t addr)
153 return (kdi_prw(buf, nbytes, addr, mdb.m_kdi->kdi_pread));
156 ssize_t
157 kmdb_kdi_pwrite(void *buf, size_t nbytes, physaddr_t addr)
159 return (kdi_prw(buf, nbytes, addr, mdb.m_kdi->kdi_pwrite));
162 void
163 kmdb_kdi_flush_caches(void)
165 mdb.m_kdi->kdi_flush_caches();
169 kmdb_kdi_get_unload_request(void)
171 return (kdi_unload_request);
174 void
175 kmdb_kdi_set_unload_request(void)
177 kdi_unload_request = 1;
181 kmdb_kdi_get_flags(void)
183 uint_t flags = 0;
185 if (mdb.m_flags & MDB_FL_NOCTF)
186 flags |= KMDB_KDI_FL_NOCTF;
187 if (mdb.m_flags & MDB_FL_NOMODS)
188 flags |= KMDB_KDI_FL_NOMODS;
190 return (flags);
193 size_t
194 kmdb_kdi_range_is_nontoxic(uintptr_t va, size_t sz, int write)
196 return (mdb.m_kdi->kdi_range_is_nontoxic(va, sz, write));
199 void
200 kmdb_kdi_system_claim(void)
202 (void) kmdb_dpi_call((uintptr_t)mdb.m_kdi->kdi_system_claim, 0, NULL);
203 kmdb_prom_debugger_entry();
206 void
207 kmdb_kdi_system_release(void)
209 kmdb_prom_debugger_exit();
211 if (mdb.m_kdi->kdi_system_release != NULL) {
212 (void) kmdb_dpi_call((uintptr_t)mdb.m_kdi->kdi_system_release,
213 0, NULL);
217 struct cons_polledio *
218 kmdb_kdi_get_polled_io(void)
220 return (mdb.m_kdi->kdi_get_polled_io());
223 void
224 kmdb_kdi_kmdb_enter(void)
226 mdb.m_kdi->kdi_kmdb_enter();
230 kmdb_kdi_vtop(uintptr_t va, physaddr_t *pap)
232 jmp_buf pcb, *oldpcb;
233 int rc = 0;
235 if (setjmp(pcb) == 0) {
236 int err;
238 oldpcb = kmdb_dpi_set_fault_hdlr(&pcb);
240 if ((err = mdb.m_kdi->kdi_vtop(va, pap)) != 0)
241 rc = set_errno(err == ENOENT ? EMDB_NOMAP : err);
242 } else {
243 /* We faulted during the translation */
244 rc = set_errno(EMDB_NOMAP);
247 kmdb_dpi_restore_fault_hdlr(oldpcb);
249 return (rc);
252 kdi_dtrace_state_t
253 kmdb_kdi_dtrace_get_state(void)
255 return (mdb.m_kdi->kdi_dtrace_get_state());
259 kmdb_kdi_dtrace_set(int state)
261 int err;
263 if ((err = mdb.m_kdi->kdi_dtrace_set(state)) != 0)
264 return (set_errno(err));
266 return (0);
270 * This function is to be called only during kmdb initialization, as it
271 * uses the running kernel for symbol translation facilities.
273 uintptr_t
274 kmdb_kdi_lookup_by_name(char *modname, char *symname)
276 ASSERT(kmdb_dpi_get_state(NULL) == DPI_STATE_INIT);
278 return (kdi_auxv->kav_lookup_by_name(modname, symname));
281 void
282 kmdb_kdi_init(kdi_t *kdi, kmdb_auxv_t *kav)
284 mdb.m_kdi = kdi;
285 mdb.m_pagesize = kav->kav_pagesize;
287 kdi_unload_request = 0;
289 kdi_auxv = kav;
291 kmdb_kdi_init_isadep(kdi, kav);
294 void
295 kmdb_kdi_end_init(void)
297 kdi_auxv = NULL;