dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / mdb / common / modules / mdb_ks / mdb_ks.c
blob024def25f942f67608440452d3f1c28fff287f8c
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 (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
26 * Mdb kernel support module. This module is loaded automatically when the
27 * kvm target is initialized. Any global functions declared here are exported
28 * for the resolution of symbols in subsequently loaded modules.
30 * WARNING: Do not assume that static variables in mdb_ks will be initialized
31 * to zero.
34 #include <mdb/mdb_target.h>
35 #include <mdb/mdb_param.h>
36 #include <mdb/mdb_modapi.h>
37 #include <mdb/mdb_ks.h>
39 #include <sys/types.h>
40 #include <sys/procfs.h>
41 #include <sys/proc.h>
42 #include <sys/dnlc.h>
43 #include <sys/autoconf.h>
44 #include <sys/machelf.h>
45 #include <sys/modctl.h>
46 #include <sys/hwconf.h>
47 #include <sys/kobj.h>
48 #include <sys/fs/autofs.h>
49 #include <sys/ddi_impldefs.h>
50 #include <sys/refstr_impl.h>
51 #include <sys/cpuvar.h>
52 #include <sys/dlpi.h>
53 #include <sys/clock_impl.h>
54 #include <sys/swap.h>
55 #include <errno.h>
57 #include <vm/seg_vn.h>
58 #include <vm/page.h>
60 #define MDB_PATH_NELEM 256 /* Maximum path components */
62 typedef struct mdb_path {
63 size_t mdp_nelem; /* Number of components */
64 uint_t mdp_complete; /* Path completely resolved? */
65 uintptr_t mdp_vnode[MDB_PATH_NELEM]; /* Array of vnode_t addresses */
66 char *mdp_name[MDB_PATH_NELEM]; /* Array of name components */
67 } mdb_path_t;
69 static int mdb_autonode2path(uintptr_t, mdb_path_t *);
70 static int mdb_sprintpath(char *, size_t, mdb_path_t *);
73 * Kernel parameters from <sys/param.h> which we keep in-core:
75 unsigned long _mdb_ks_pagesize;
76 unsigned int _mdb_ks_pageshift;
77 unsigned long _mdb_ks_pageoffset;
78 unsigned long long _mdb_ks_pagemask;
79 unsigned long _mdb_ks_mmu_pagesize;
80 unsigned int _mdb_ks_mmu_pageshift;
81 unsigned long _mdb_ks_mmu_pageoffset;
82 unsigned long _mdb_ks_mmu_pagemask;
83 uintptr_t _mdb_ks_kernelbase;
84 uintptr_t _mdb_ks_userlimit;
85 uintptr_t _mdb_ks_userlimit32;
86 uintptr_t _mdb_ks_argsbase;
87 unsigned long _mdb_ks_msg_bsize;
88 unsigned long _mdb_ks_defaultstksz;
89 int _mdb_ks_ncpu;
90 int _mdb_ks_ncpu_log2;
91 int _mdb_ks_ncpu_p2;
94 * In-core copy of DNLC information:
96 #define MDB_DNLC_HSIZE 1024
97 #define MDB_DNLC_HASH(vp) (((uintptr_t)(vp) >> 3) & (MDB_DNLC_HSIZE - 1))
98 #define MDB_DNLC_NCACHE_SZ(ncp) (sizeof (ncache_t) + (ncp)->namlen)
99 #define MDB_DNLC_MAX_RETRY 4
101 static ncache_t **dnlc_hash; /* mdbs hash array of dnlc entries */
104 * STREAMS queue registrations:
106 typedef struct mdb_qinfo {
107 const mdb_qops_t *qi_ops; /* Address of ops vector */
108 uintptr_t qi_addr; /* Address of qinit structure (key) */
109 struct mdb_qinfo *qi_next; /* Next qinfo in list */
110 } mdb_qinfo_t;
112 static mdb_qinfo_t *qi_head; /* Head of qinfo chain */
115 * Device naming callback structure:
117 typedef struct nm_query {
118 const char *nm_name; /* Device driver name [in/out] */
119 major_t nm_major; /* Device major number [in/out] */
120 ushort_t nm_found; /* Did we find a match? [out] */
121 } nm_query_t;
124 * Address-to-modctl callback structure:
126 typedef struct a2m_query {
127 uintptr_t a2m_addr; /* Virtual address [in] */
128 uintptr_t a2m_where; /* Modctl address [out] */
129 } a2m_query_t;
132 * Segment-to-mdb_map callback structure:
134 typedef struct {
135 struct seg_ops *asm_segvn_ops; /* Address of segvn ops [in] */
136 void (*asm_callback)(const struct mdb_map *, void *); /* Callb [in] */
137 void *asm_cbdata; /* Callback data [in] */
138 } asmap_arg_t;
140 static void
141 dnlc_free(void)
143 ncache_t *ncp, *next;
144 int i;
146 if (dnlc_hash == NULL) {
147 return;
151 * Free up current dnlc entries
153 for (i = 0; i < MDB_DNLC_HSIZE; i++) {
154 for (ncp = dnlc_hash[i]; ncp; ncp = next) {
155 next = ncp->hash_next;
156 mdb_free(ncp, MDB_DNLC_NCACHE_SZ(ncp));
159 mdb_free(dnlc_hash, MDB_DNLC_HSIZE * sizeof (ncache_t *));
160 dnlc_hash = NULL;
163 char bad_dnlc[] = "inconsistent dnlc chain: %d, ncache va: %p"
164 " - continuing with the rest\n";
166 static int
167 dnlc_load(void)
169 int i; /* hash index */
170 int retry_cnt = 0;
171 int skip_bad_chains = 0;
172 int nc_hashsz; /* kernel hash array size */
173 uintptr_t nc_hash_addr; /* kernel va of ncache hash array */
174 uintptr_t head; /* kernel va of head of hash chain */
177 * If we've already cached the DNLC and we're looking at a dump,
178 * our cache is good forever, so don't bother re-loading.
180 if (dnlc_hash && mdb_prop_postmortem) {
181 return (0);
185 * For a core dump, retries wont help.
186 * Just print and skip any bad chains.
188 if (mdb_prop_postmortem) {
189 skip_bad_chains = 1;
191 retry:
192 if (retry_cnt++ >= MDB_DNLC_MAX_RETRY) {
194 * Give up retrying the rapidly changing dnlc.
195 * Just print and skip any bad chains
197 skip_bad_chains = 1;
200 dnlc_free(); /* Free up the mdb hashed dnlc - if any */
203 * Although nc_hashsz and the location of nc_hash doesn't currently
204 * change, it may do in the future with a more dynamic dnlc.
205 * So always read these values afresh.
207 if (mdb_readvar(&nc_hashsz, "nc_hashsz") == -1) {
208 mdb_warn("failed to read nc_hashsz");
209 return (-1);
211 if (mdb_readvar(&nc_hash_addr, "nc_hash") == -1) {
212 mdb_warn("failed to read nc_hash");
213 return (-1);
217 * Allocate the mdb dnlc hash array
219 dnlc_hash = mdb_zalloc(MDB_DNLC_HSIZE * sizeof (ncache_t *), UM_SLEEP);
221 /* for each kernel hash chain */
222 for (i = 0, head = nc_hash_addr; i < nc_hashsz;
223 i++, head += sizeof (nc_hash_t)) {
224 nc_hash_t nch; /* kernel hash chain header */
225 ncache_t *ncp; /* name cache pointer */
226 int hash; /* mdb hash value */
227 uintptr_t nc_va; /* kernel va of next ncache */
228 uintptr_t ncprev_va; /* kernel va of previous ncache */
229 int khash; /* kernel dnlc hash value */
230 uchar_t namelen; /* name length */
231 ncache_t nc; /* name cache entry */
232 int nc_size; /* size of a name cache entry */
235 * We read each element of the nc_hash array individually
236 * just before we process the entries in its chain. This is
237 * because the chain can change so rapidly on a running system.
239 if (mdb_vread(&nch, sizeof (nc_hash_t), head) == -1) {
240 mdb_warn("failed to read nc_hash chain header %d", i);
241 dnlc_free();
242 return (-1);
245 ncprev_va = head;
246 nc_va = (uintptr_t)(nch.hash_next);
247 /* for each entry in the chain */
248 while (nc_va != head) {
250 * The size of the ncache entries varies
251 * because the name is appended to the structure.
252 * So we read in the structure then re-read
253 * for the structure plus name.
255 if (mdb_vread(&nc, sizeof (ncache_t), nc_va) == -1) {
256 if (skip_bad_chains) {
257 mdb_warn(bad_dnlc, i, nc_va);
258 break;
260 goto retry;
262 nc_size = MDB_DNLC_NCACHE_SZ(&nc);
263 ncp = mdb_alloc(nc_size, UM_SLEEP);
264 if (mdb_vread(ncp, nc_size - 1, nc_va) == -1) {
265 mdb_free(ncp, nc_size);
266 if (skip_bad_chains) {
267 mdb_warn(bad_dnlc, i, nc_va);
268 break;
270 goto retry;
274 * Check for chain consistency
276 if ((uintptr_t)ncp->hash_prev != ncprev_va) {
277 mdb_free(ncp, nc_size);
278 if (skip_bad_chains) {
279 mdb_warn(bad_dnlc, i, nc_va);
280 break;
282 goto retry;
285 * Terminate the new name with a null.
286 * Note, we allowed space for this null when
287 * allocating space for the entry.
289 ncp->name[ncp->namlen] = '\0';
292 * Validate new entry by re-hashing using the
293 * kernel dnlc hash function and comparing the hash
295 DNLCHASH(ncp->name, ncp->dp, khash, namelen);
296 if ((namelen != ncp->namlen) ||
297 (khash != ncp->hash)) {
298 mdb_free(ncp, nc_size);
299 if (skip_bad_chains) {
300 mdb_warn(bad_dnlc, i, nc_va);
301 break;
303 goto retry;
307 * Finally put the validated entry into the mdb
308 * hash chains. Reuse the kernel next hash field
309 * for the mdb hash chain pointer.
311 hash = MDB_DNLC_HASH(ncp->vp);
312 ncprev_va = nc_va;
313 nc_va = (uintptr_t)(ncp->hash_next);
314 ncp->hash_next = dnlc_hash[hash];
315 dnlc_hash[hash] = ncp;
318 return (0);
321 /*ARGSUSED*/
323 dnlcdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
325 ncache_t *ent;
326 int i;
328 if ((flags & DCMD_ADDRSPEC) || argc != 0)
329 return (DCMD_USAGE);
331 if (dnlc_load() == -1)
332 return (DCMD_ERR);
334 mdb_printf("%<u>%-?s %-?s %-32s%</u>\n", "VP", "DVP", "NAME");
336 for (i = 0; i < MDB_DNLC_HSIZE; i++) {
337 for (ent = dnlc_hash[i]; ent != NULL; ent = ent->hash_next) {
338 mdb_printf("%0?p %0?p %s\n",
339 ent->vp, ent->dp, ent->name);
343 return (DCMD_OK);
346 static int
347 mdb_sprintpath(char *buf, size_t len, mdb_path_t *path)
349 char *s = buf;
350 int i;
352 if (len < sizeof ("/..."))
353 return (-1);
355 if (!path->mdp_complete) {
356 (void) strcpy(s, "??");
357 s += 2;
359 if (path->mdp_nelem == 0)
360 return (-1);
363 if (path->mdp_nelem == 0) {
364 (void) strcpy(s, "/");
365 return (0);
368 for (i = path->mdp_nelem - 1; i >= 0; i--) {
370 * Number of bytes left is the distance from where we
371 * are to the end, minus 2 for '/' and '\0'
373 ssize_t left = (ssize_t)(&buf[len] - s) - 2;
375 if (left <= 0)
376 break;
378 *s++ = '/';
379 (void) strncpy(s, path->mdp_name[i], left);
380 s[left - 1] = '\0';
381 s += strlen(s);
383 if (left < strlen(path->mdp_name[i]))
384 break;
387 if (i >= 0)
388 (void) strcpy(&buf[len - 4], "...");
390 return (0);
393 static int
394 mdb_autonode2path(uintptr_t addr, mdb_path_t *path)
396 GElf_Sym sym;
397 fninfo_t fni;
398 fnnode_t fn;
400 vnode_t vn;
401 vfs_t vfs;
404 * We want to look it up each time we access it since autofs could
405 * (in theory) be unloaded and reloaded.
407 if (mdb_lookup_by_name("auto_vnodeops", &sym) != 0)
408 return (-1);
410 if (vn.v_op != (struct vnodeops *)(uintptr_t)sym.st_value)
411 return (-1);
413 addr = (uintptr_t)vn.v_data;
415 if (mdb_vread(&vfs, sizeof (vfs), (uintptr_t)vn.v_vfsp) == -1 ||
416 mdb_vread(&fni, sizeof (fni), (uintptr_t)vfs.vfs_data) == -1 ||
417 mdb_vread(&vn, sizeof (vn), (uintptr_t)fni.fi_rootvp) == -1)
418 return (-1);
420 for (;;) {
421 size_t elem = path->mdp_nelem++;
422 char elemstr[MAXNAMELEN];
423 char *c, *p;
425 if (elem == MDB_PATH_NELEM) {
426 path->mdp_nelem--;
427 return (-1);
430 if (mdb_vread(&fn, sizeof (fn), addr) != sizeof (fn)) {
431 path->mdp_nelem--;
432 return (-1);
435 if (mdb_readstr(elemstr, sizeof (elemstr),
436 (uintptr_t)fn.fn_name) <= 0) {
437 (void) strcpy(elemstr, "?");
440 c = mdb_alloc(strlen(elemstr) + 1, UM_SLEEP | UM_GC);
441 (void) strcpy(c, elemstr);
443 path->mdp_vnode[elem] = (uintptr_t)fn.fn_vnode;
445 if (addr == (uintptr_t)fn.fn_parent) {
446 path->mdp_name[elem] = &c[1];
447 path->mdp_complete = TRUE;
448 break;
451 if ((p = strrchr(c, '/')) != NULL)
452 path->mdp_name[elem] = p + 1;
453 else
454 path->mdp_name[elem] = c;
456 addr = (uintptr_t)fn.fn_parent;
459 return (0);
463 mdb_vnode2path(uintptr_t addr, char *buf, size_t buflen)
465 uintptr_t rootdir;
466 ncache_t *ent;
467 vnode_t vp;
468 mdb_path_t path;
471 * Check to see if we have a cached value for this vnode
473 if (mdb_vread(&vp, sizeof (vp), addr) != -1 &&
474 vp.v_path != NULL &&
475 mdb_readstr(buf, buflen, (uintptr_t)vp.v_path) != -1)
476 return (0);
478 if (dnlc_load() == -1)
479 return (-1);
481 if (mdb_readvar(&rootdir, "rootdir") == -1) {
482 mdb_warn("failed to read 'rootdir'");
483 return (-1);
486 bzero(&path, sizeof (mdb_path_t));
487 again:
488 if ((addr == (uintptr_t)NULL) && (path.mdp_nelem == 0)) {
490 * 0 elems && complete tells sprintpath to just print "/"
492 path.mdp_complete = TRUE;
493 goto out;
496 if (addr == rootdir) {
497 path.mdp_complete = TRUE;
498 goto out;
501 for (ent = dnlc_hash[MDB_DNLC_HASH(addr)]; ent; ent = ent->hash_next) {
502 if ((uintptr_t)ent->vp == addr) {
503 if (strcmp(ent->name, "..") == 0 ||
504 strcmp(ent->name, ".") == 0)
505 continue;
507 path.mdp_vnode[path.mdp_nelem] = (uintptr_t)ent->vp;
508 path.mdp_name[path.mdp_nelem] = ent->name;
509 path.mdp_nelem++;
511 if (path.mdp_nelem == MDB_PATH_NELEM) {
512 path.mdp_nelem--;
513 mdb_warn("path exceeded maximum expected "
514 "elements\n");
515 return (-1);
518 addr = (uintptr_t)ent->dp;
519 goto again;
523 (void) mdb_autonode2path(addr, &path);
525 out:
526 return (mdb_sprintpath(buf, buflen, &path));
530 uintptr_t
531 mdb_pid2proc(pid_t pid, proc_t *proc)
533 int pid_hashsz, hash;
534 uintptr_t paddr, pidhash, procdir;
535 struct pid pidp;
537 if (mdb_readvar(&pidhash, "pidhash") == -1)
538 return ((uintptr_t)NULL);
540 if (mdb_readvar(&pid_hashsz, "pid_hashsz") == -1)
541 return ((uintptr_t)NULL);
543 if (mdb_readvar(&procdir, "procdir") == -1)
544 return ((uintptr_t)NULL);
546 hash = pid & (pid_hashsz - 1);
548 if (mdb_vread(&paddr, sizeof (paddr),
549 pidhash + (hash * sizeof (paddr))) == -1)
550 return ((uintptr_t)NULL);
552 while (paddr != (uintptr_t)NULL) {
553 if (mdb_vread(&pidp, sizeof (pidp), paddr) == -1)
554 return ((uintptr_t)NULL);
556 if (pidp.pid_id == pid) {
557 uintptr_t procp;
559 if (mdb_vread(&procp, sizeof (procp), procdir +
560 (pidp.pid_prslot * sizeof (procp))) == -1)
561 return ((uintptr_t)NULL);
563 if (proc != NULL)
564 (void) mdb_vread(proc, sizeof (proc_t), procp);
566 return (procp);
568 paddr = (uintptr_t)pidp.pid_link;
570 return ((uintptr_t)NULL);
574 mdb_cpu2cpuid(uintptr_t cpup)
576 cpu_t cpu;
578 if (mdb_vread(&cpu, sizeof (cpu_t), cpup) != sizeof (cpu_t))
579 return (-1);
581 return (cpu.cpu_id);
585 mdb_cpuset_find(uintptr_t cpusetp)
587 ulong_t *cpuset;
588 size_t nr_words = BT_BITOUL(NCPU);
589 size_t sz = nr_words * sizeof (ulong_t);
590 size_t i;
591 int cpu = -1;
593 cpuset = mdb_alloc(sz, UM_SLEEP);
595 if (mdb_vread((void *)cpuset, sz, cpusetp) != sz)
596 goto out;
598 for (i = 0; i < nr_words; i++) {
599 size_t j;
600 ulong_t m;
602 for (j = 0, m = 1; j < BT_NBIPUL; j++, m <<= 1) {
603 if (cpuset[i] & m) {
604 cpu = i * BT_NBIPUL + j;
605 goto out;
610 out:
611 mdb_free(cpuset, sz);
612 return (cpu);
615 struct page_lookup_state {
616 /* input */
617 uintptr_t vnode;
618 uoff_t offset;
620 /* output */
621 uintptr_t page;
624 static int
625 __page_lookup(uintptr_t addr, const void *data, void *private)
627 struct page_lookup_state *state = private;
628 const page_t *page = data;
630 if ((uintptr_t)page->p_vnode != state->vnode) {
631 mdb_warn("unexpected vnode pointer (got: %p, expected: %p)",
632 page->p_vnode, state->vnode);
633 return (WALK_ERR);
636 if (page->p_offset != state->offset)
637 return (WALK_NEXT);
639 state->page = addr;
640 return (WALK_DONE);
643 uintptr_t
644 mdb_page_lookup(uintptr_t vp, uoff_t offset)
646 uintptr_t addr = vp + OFFSETOF(vnode_t, v_object.tree);
647 struct page_lookup_state state = {
648 .vnode = vp,
649 .offset = offset,
652 if (mdb_pwalk("avl", __page_lookup, &state, addr) != 0)
653 return 0;
655 return state.page;
658 char
659 mdb_vtype2chr(vtype_t type, mode_t mode)
661 static const char vttab[] = {
662 ' ', /* VNON */
663 ' ', /* VREG */
664 '/', /* VDIR */
665 ' ', /* VBLK */
666 ' ', /* VCHR */
667 '@', /* VLNK */
668 '|', /* VFIFO */
669 '>', /* VDOOR */
670 ' ', /* VPROC */
671 '=', /* VSOCK */
672 ' ', /* VBAD */
675 if (type < 0 || type >= sizeof (vttab) / sizeof (vttab[0]))
676 return ('?');
678 if (type == VREG && (mode & 0111) != 0)
679 return ('*');
681 return (vttab[type]);
684 struct pfn2page {
685 pfn_t pfn;
686 page_t *pp;
689 /*ARGSUSED*/
690 static int
691 pfn2page_cb(uintptr_t addr, const struct memseg *msp, void *data)
693 struct pfn2page *p = data;
695 if (p->pfn >= msp->pages_base && p->pfn < msp->pages_end) {
696 p->pp = msp->pages + (p->pfn - msp->pages_base);
697 return (WALK_DONE);
700 return (WALK_NEXT);
703 uintptr_t
704 mdb_pfn2page(pfn_t pfn)
706 struct pfn2page arg;
707 struct page page;
709 arg.pfn = pfn;
710 arg.pp = NULL;
712 if (mdb_walk("memseg", (mdb_walk_cb_t)pfn2page_cb, &arg) == -1) {
713 mdb_warn("pfn2page: can't walk memsegs");
714 return (0);
716 if (arg.pp == NULL) {
717 mdb_warn("pfn2page: unable to find page_t for pfn %lx\n",
718 pfn);
719 return (0);
722 if (mdb_vread(&page, sizeof (page_t), (uintptr_t)arg.pp) == -1) {
723 mdb_warn("pfn2page: can't read page 0x%lx at %p", pfn, arg.pp);
724 return (0);
726 if (page.p_pagenum != pfn) {
727 mdb_warn("pfn2page: page_t 0x%p should have PFN 0x%lx, "
728 "but actually has 0x%lx\n", arg.pp, pfn, page.p_pagenum);
729 return (0);
732 return ((uintptr_t)arg.pp);
735 pfn_t
736 mdb_page2pfn(uintptr_t addr)
738 struct page page;
740 if (mdb_vread(&page, sizeof (page_t), addr) == -1) {
741 mdb_warn("pp2pfn: can't read page at %p", addr);
742 return ((pfn_t)(-1));
745 return (page.p_pagenum);
748 static int
749 a2m_walk_modctl(uintptr_t addr, const struct modctl *m, a2m_query_t *a2m)
751 struct module mod;
753 if (m->mod_mp == NULL)
754 return (0);
756 if (mdb_vread(&mod, sizeof (mod), (uintptr_t)m->mod_mp) == -1) {
757 mdb_warn("couldn't read modctl %p's module", addr);
758 return (0);
761 if (a2m->a2m_addr >= (uintptr_t)mod.text &&
762 a2m->a2m_addr < (uintptr_t)mod.text + mod.text_size)
763 goto found;
765 if (a2m->a2m_addr >= (uintptr_t)mod.data &&
766 a2m->a2m_addr < (uintptr_t)mod.data + mod.data_size)
767 goto found;
769 return (0);
771 found:
772 a2m->a2m_where = addr;
773 return (-1);
776 uintptr_t
777 mdb_addr2modctl(uintptr_t addr)
779 a2m_query_t a2m;
781 a2m.a2m_addr = addr;
782 a2m.a2m_where = (uintptr_t)NULL;
784 (void) mdb_walk("modctl", (mdb_walk_cb_t)a2m_walk_modctl, &a2m);
785 return (a2m.a2m_where);
788 static mdb_qinfo_t *
789 qi_lookup(uintptr_t qinit_addr)
791 mdb_qinfo_t *qip;
793 for (qip = qi_head; qip != NULL; qip = qip->qi_next) {
794 if (qip->qi_addr == qinit_addr)
795 return (qip);
798 return (NULL);
801 void
802 mdb_qops_install(const mdb_qops_t *qops, uintptr_t qinit_addr)
804 mdb_qinfo_t *qip = qi_lookup(qinit_addr);
806 if (qip != NULL) {
807 qip->qi_ops = qops;
808 return;
811 qip = mdb_alloc(sizeof (mdb_qinfo_t), UM_SLEEP);
813 qip->qi_ops = qops;
814 qip->qi_addr = qinit_addr;
815 qip->qi_next = qi_head;
817 qi_head = qip;
820 void
821 mdb_qops_remove(const mdb_qops_t *qops, uintptr_t qinit_addr)
823 mdb_qinfo_t *qip, *p = NULL;
825 for (qip = qi_head; qip != NULL; p = qip, qip = qip->qi_next) {
826 if (qip->qi_addr == qinit_addr && qip->qi_ops == qops) {
827 if (qi_head == qip)
828 qi_head = qip->qi_next;
829 else
830 p->qi_next = qip->qi_next;
831 mdb_free(qip, sizeof (mdb_qinfo_t));
832 return;
837 char *
838 mdb_qname(const queue_t *q, char *buf, size_t nbytes)
840 struct module_info mi;
841 struct qinit qi;
843 if (mdb_vread(&qi, sizeof (qi), (uintptr_t)q->q_qinfo) == -1) {
844 mdb_warn("failed to read qinit at %p", q->q_qinfo);
845 goto err;
848 if (mdb_vread(&mi, sizeof (mi), (uintptr_t)qi.qi_minfo) == -1) {
849 mdb_warn("failed to read module_info at %p", qi.qi_minfo);
850 goto err;
853 if (mdb_readstr(buf, nbytes, (uintptr_t)mi.mi_idname) <= 0) {
854 mdb_warn("failed to read mi_idname at %p", mi.mi_idname);
855 goto err;
858 return (buf);
860 err:
861 (void) mdb_snprintf(buf, nbytes, "???");
862 return (buf);
865 void
866 mdb_qinfo(const queue_t *q, char *buf, size_t nbytes)
868 mdb_qinfo_t *qip = qi_lookup((uintptr_t)q->q_qinfo);
869 buf[0] = '\0';
871 if (qip != NULL)
872 qip->qi_ops->q_info(q, buf, nbytes);
875 uintptr_t
876 mdb_qrnext(const queue_t *q)
878 mdb_qinfo_t *qip = qi_lookup((uintptr_t)q->q_qinfo);
880 if (qip != NULL)
881 return (qip->qi_ops->q_rnext(q));
883 return ((uintptr_t)NULL);
886 uintptr_t
887 mdb_qwnext(const queue_t *q)
889 mdb_qinfo_t *qip = qi_lookup((uintptr_t)q->q_qinfo);
891 if (qip != NULL)
892 return (qip->qi_ops->q_wnext(q));
894 return ((uintptr_t)NULL);
897 uintptr_t
898 mdb_qrnext_default(const queue_t *q)
900 return ((uintptr_t)q->q_next);
903 uintptr_t
904 mdb_qwnext_default(const queue_t *q)
906 return ((uintptr_t)q->q_next);
910 * The following three routines borrowed from modsubr.c
912 static int
913 nm_hash(const char *name)
915 char c;
916 int hash = 0;
918 for (c = *name++; c; c = *name++)
919 hash ^= c;
921 return (hash & MOD_BIND_HASHMASK);
924 static uintptr_t
925 find_mbind(const char *name, uintptr_t *hashtab)
927 int hashndx;
928 uintptr_t mb;
929 struct bind mb_local;
930 char node_name[MAXPATHLEN + 1];
932 hashndx = nm_hash(name);
933 mb = hashtab[hashndx];
934 while (mb) {
935 if (mdb_vread(&mb_local, sizeof (mb_local), mb) == -1) {
936 mdb_warn("failed to read struct bind at %p", mb);
937 return ((uintptr_t)NULL);
939 if (mdb_readstr(node_name, sizeof (node_name),
940 (uintptr_t)mb_local.b_name) == -1) {
941 mdb_warn("failed to read node name string at %p",
942 mb_local.b_name);
943 return ((uintptr_t)NULL);
946 if (strcmp(name, node_name) == 0)
947 break;
949 mb = (uintptr_t)mb_local.b_next;
951 return (mb);
955 mdb_name_to_major(const char *name, major_t *major)
957 uintptr_t mbind;
958 uintptr_t mb_hashtab[MOD_BIND_HASHSIZE];
959 struct bind mbind_local;
962 if (mdb_readsym(mb_hashtab, sizeof (mb_hashtab), "mb_hashtab") == -1) {
963 mdb_warn("failed to read symbol 'mb_hashtab'");
964 return (-1);
967 if ((mbind = find_mbind(name, mb_hashtab)) != (uintptr_t)NULL) {
968 if (mdb_vread(&mbind_local, sizeof (mbind_local), mbind) ==
969 -1) {
970 mdb_warn("failed to read mbind struct at %p", mbind);
971 return (-1);
974 *major = (major_t)mbind_local.b_num;
975 return (0);
977 return (-1);
980 const char *
981 mdb_major_to_name(major_t major)
983 static char name[MODMAXNAMELEN + 1];
985 uintptr_t devnamesp;
986 struct devnames dn;
987 uint_t devcnt;
989 if (mdb_readvar(&devcnt, "devcnt") == -1 || major >= devcnt ||
990 mdb_readvar(&devnamesp, "devnamesp") == -1)
991 return (NULL);
993 if (mdb_vread(&dn, sizeof (struct devnames), devnamesp +
994 major * sizeof (struct devnames)) != sizeof (struct devnames))
995 return (NULL);
997 if (mdb_readstr(name, MODMAXNAMELEN + 1, (uintptr_t)dn.dn_name) == -1)
998 return (NULL);
1000 return ((const char *)name);
1004 * Return the name of the driver attached to the dip in drivername.
1007 mdb_devinfo2driver(uintptr_t dip_addr, char *drivername, size_t namebufsize)
1009 struct dev_info devinfo;
1010 char bind_name[MAXPATHLEN + 1];
1011 major_t major;
1012 const char *namestr;
1015 if (mdb_vread(&devinfo, sizeof (devinfo), dip_addr) == -1) {
1016 mdb_warn("failed to read devinfo at %p", dip_addr);
1017 return (-1);
1020 if (mdb_readstr(bind_name, sizeof (bind_name),
1021 (uintptr_t)devinfo.devi_binding_name) == -1) {
1022 mdb_warn("failed to read binding name at %p",
1023 devinfo.devi_binding_name);
1024 return (-1);
1028 * Many->one relation: various names to one major number
1030 if (mdb_name_to_major(bind_name, &major) == -1) {
1031 mdb_warn("failed to translate bind name to major number\n");
1032 return (-1);
1036 * One->one relation: one major number corresponds to one driver
1038 if ((namestr = mdb_major_to_name(major)) == NULL) {
1039 (void) strncpy(drivername, "???", namebufsize);
1040 return (-1);
1043 (void) strncpy(drivername, namestr, namebufsize);
1044 return (0);
1048 * Find the name of the driver attached to this dip (if any), given:
1049 * - the address of a dip (in core)
1050 * - the NAME of the global pointer to the driver's i_ddi_soft_state struct
1051 * - pointer to a pointer to receive the address
1054 mdb_devinfo2statep(uintptr_t dip_addr, char *soft_statep_name,
1055 uintptr_t *statep)
1057 struct dev_info dev_info;
1060 if (mdb_vread(&dev_info, sizeof (dev_info), dip_addr) == -1) {
1061 mdb_warn("failed to read devinfo at %p", dip_addr);
1062 return (-1);
1065 return (mdb_get_soft_state_byname(soft_statep_name,
1066 dev_info.devi_instance, statep, NULL, 0));
1070 * Returns a pointer to the top of the soft state struct for the instance
1071 * specified (in state_addr), given the address of the global soft state
1072 * pointer and size of the struct. Also fills in the buffer pointed to by
1073 * state_buf_p (if non-NULL) with the contents of the state struct.
1076 mdb_get_soft_state_byaddr(uintptr_t ssaddr, uint_t instance,
1077 uintptr_t *state_addr, void *state_buf_p, size_t sizeof_state)
1079 struct i_ddi_soft_state ss;
1080 void *statep;
1083 if (mdb_vread(&ss, sizeof (ss), ssaddr) == -1)
1084 return (-1);
1086 if (instance >= ss.n_items)
1087 return (-1);
1089 if (mdb_vread(&statep, sizeof (statep), (uintptr_t)ss.array +
1090 (sizeof (statep) * instance)) == -1)
1091 return (-1);
1093 if (state_addr != NULL)
1094 *state_addr = (uintptr_t)statep;
1096 if (statep == NULL) {
1097 errno = ENOENT;
1098 return (-1);
1101 if (state_buf_p != NULL) {
1103 /* Read the state struct into the buffer in local space. */
1104 if (mdb_vread(state_buf_p, sizeof_state,
1105 (uintptr_t)statep) == -1)
1106 return (-1);
1109 return (0);
1114 * Returns a pointer to the top of the soft state struct for the instance
1115 * specified (in state_addr), given the name of the global soft state pointer
1116 * and size of the struct. Also fills in the buffer pointed to by
1117 * state_buf_p (if non-NULL) with the contents of the state struct.
1120 mdb_get_soft_state_byname(char *softstatep_name, uint_t instance,
1121 uintptr_t *state_addr, void *state_buf_p, size_t sizeof_state)
1123 uintptr_t ssaddr;
1125 if (mdb_readvar((void *)&ssaddr, softstatep_name) == -1)
1126 return (-1);
1128 return (mdb_get_soft_state_byaddr(ssaddr, instance, state_addr,
1129 state_buf_p, sizeof_state));
1132 static const mdb_dcmd_t dcmds[] = {
1133 { "dnlc", NULL, "print DNLC contents", dnlcdump },
1134 { NULL }
1137 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds };
1139 /*ARGSUSED*/
1140 static void
1141 update_vars(void *arg)
1143 (void) mdb_readvar(&_mdb_ks_pagesize, "_pagesize");
1144 (void) mdb_readvar(&_mdb_ks_pageshift, "_pageshift");
1145 (void) mdb_readvar(&_mdb_ks_pageoffset, "_pageoffset");
1146 (void) mdb_readvar(&_mdb_ks_pagemask, "_pagemask");
1147 (void) mdb_readvar(&_mdb_ks_mmu_pagesize, "_mmu_pagesize");
1148 (void) mdb_readvar(&_mdb_ks_mmu_pageshift, "_mmu_pageshift");
1149 (void) mdb_readvar(&_mdb_ks_mmu_pageoffset, "_mmu_pageoffset");
1150 (void) mdb_readvar(&_mdb_ks_mmu_pagemask, "_mmu_pagemask");
1151 (void) mdb_readvar(&_mdb_ks_kernelbase, "_kernelbase");
1153 (void) mdb_readvar(&_mdb_ks_userlimit, "_userlimit");
1154 (void) mdb_readvar(&_mdb_ks_userlimit32, "_userlimit32");
1155 (void) mdb_readvar(&_mdb_ks_argsbase, "_argsbase");
1156 (void) mdb_readvar(&_mdb_ks_msg_bsize, "_msg_bsize");
1157 (void) mdb_readvar(&_mdb_ks_defaultstksz, "_defaultstksz");
1158 (void) mdb_readvar(&_mdb_ks_ncpu, "_ncpu");
1159 (void) mdb_readvar(&_mdb_ks_ncpu_log2, "_ncpu_log2");
1160 (void) mdb_readvar(&_mdb_ks_ncpu_p2, "_ncpu_p2");
1163 const mdb_modinfo_t *
1164 _mdb_init(void)
1167 * When used with mdb, mdb_ks is a separate dmod. With kmdb, however,
1168 * mdb_ks is compiled into the debugger module. kmdb cannot
1169 * automatically modunload itself when it exits. If it restarts after
1170 * debugger fault, static variables may not be initialized to zero.
1171 * They must be manually reinitialized here.
1173 dnlc_hash = NULL;
1174 qi_head = NULL;
1176 mdb_callback_add(MDB_CALLBACK_STCHG, update_vars, NULL);
1178 update_vars(NULL);
1180 return (&modinfo);
1183 void
1184 _mdb_fini(void)
1186 dnlc_free();
1187 while (qi_head != NULL) {
1188 mdb_qinfo_t *qip = qi_head;
1189 qi_head = qip->qi_next;
1190 mdb_free(qip, sizeof (mdb_qinfo_t));
1195 * Interface between MDB kproc target and mdb_ks. The kproc target relies
1196 * on looking up and invoking these functions in mdb_ks so that dependencies
1197 * on the current kernel implementation are isolated in mdb_ks.
1201 * Given the address of a proc_t, return the p.p_as pointer; return NULL
1202 * if we were unable to read a proc structure from the given address.
1204 uintptr_t
1205 mdb_kproc_as(uintptr_t proc_addr)
1207 proc_t p;
1209 if (mdb_vread(&p, sizeof (p), proc_addr) == sizeof (p))
1210 return ((uintptr_t)p.p_as);
1212 return ((uintptr_t)NULL);
1216 * Given the address of a proc_t, return the p.p_model value; return
1217 * PR_MODEL_UNKNOWN if we were unable to read a proc structure or if
1218 * the model value does not match one of the two known values.
1220 uint_t
1221 mdb_kproc_model(uintptr_t proc_addr)
1223 proc_t p;
1225 if (mdb_vread(&p, sizeof (p), proc_addr) == sizeof (p)) {
1226 switch (p.p_model) {
1227 case DATAMODEL_ILP32:
1228 return (PR_MODEL_ILP32);
1229 case DATAMODEL_LP64:
1230 return (PR_MODEL_LP64);
1234 return (PR_MODEL_UNKNOWN);
1238 * Callback function for walking process's segment list. For each segment,
1239 * we fill in an mdb_map_t describing its properties, and then invoke
1240 * the callback function provided by the kproc target.
1242 static int
1243 asmap_step(uintptr_t addr, const struct seg *seg, asmap_arg_t *asmp)
1245 struct segvn_data svd;
1246 mdb_map_t map;
1248 if (seg->s_ops == asmp->asm_segvn_ops && mdb_vread(&svd,
1249 sizeof (svd), (uintptr_t)seg->s_data) == sizeof (svd)) {
1251 if (svd.vp != NULL) {
1252 if (mdb_vnode2path((uintptr_t)svd.vp, map.map_name,
1253 MDB_TGT_MAPSZ) != 0) {
1254 (void) mdb_snprintf(map.map_name,
1255 MDB_TGT_MAPSZ, "[ vnode %p ]", svd.vp);
1257 } else
1258 (void) strcpy(map.map_name, "[ anon ]");
1260 } else {
1261 (void) mdb_snprintf(map.map_name, MDB_TGT_MAPSZ,
1262 "[ seg %p ]", addr);
1265 map.map_base = (uintptr_t)seg->s_base;
1266 map.map_size = seg->s_size;
1267 map.map_flags = 0;
1269 asmp->asm_callback((const struct mdb_map *)&map, asmp->asm_cbdata);
1270 return (WALK_NEXT);
1274 * Given a process address space, walk its segment list using the seg walker,
1275 * convert the segment data to an mdb_map_t, and pass this information
1276 * back to the kproc target via the given callback function.
1279 mdb_kproc_asiter(uintptr_t as,
1280 void (*func)(const struct mdb_map *, void *), void *p)
1282 asmap_arg_t arg;
1283 GElf_Sym sym;
1285 arg.asm_segvn_ops = NULL;
1286 arg.asm_callback = func;
1287 arg.asm_cbdata = p;
1289 if (mdb_lookup_by_name("segvn_ops", &sym) == 0)
1290 arg.asm_segvn_ops = (struct seg_ops *)(uintptr_t)sym.st_value;
1292 return (mdb_pwalk("seg", (mdb_walk_cb_t)asmap_step, &arg, as));
1296 * Copy the auxv array from the given process's u-area into the provided
1297 * buffer. If the buffer is NULL, only return the size of the auxv array
1298 * so the caller knows how much space will be required.
1301 mdb_kproc_auxv(uintptr_t proc, auxv_t *auxv)
1303 if (auxv != NULL) {
1304 proc_t p;
1306 if (mdb_vread(&p, sizeof (p), proc) != sizeof (p))
1307 return (-1);
1309 bcopy(p.p_user.u_auxv, auxv,
1310 sizeof (auxv_t) * __KERN_NAUXV_IMPL);
1313 return (__KERN_NAUXV_IMPL);
1317 * Given a process address, return the PID.
1319 pid_t
1320 mdb_kproc_pid(uintptr_t proc_addr)
1322 struct pid pid;
1323 proc_t p;
1325 if (mdb_vread(&p, sizeof (p), proc_addr) == sizeof (p) &&
1326 mdb_vread(&pid, sizeof (pid), (uintptr_t)p.p_pidp) == sizeof (pid))
1327 return (pid.pid_id);
1329 return (-1);
1333 * Interface between the MDB kvm target and mdb_ks. The kvm target relies
1334 * on looking up and invoking these functions in mdb_ks so that dependencies
1335 * on the current kernel implementation are isolated in mdb_ks.
1339 * Determine whether or not the thread that panicked the given kernel was a
1340 * kernel thread (panic_thread->t_procp == &p0).
1342 void
1343 mdb_dump_print_content(dumphdr_t *dh, pid_t content)
1345 GElf_Sym sym;
1346 uintptr_t pt;
1347 uintptr_t procp;
1348 int expcont = 0;
1349 int actcont;
1351 (void) mdb_readvar(&expcont, "dump_conflags");
1352 actcont = dh->dump_flags & DF_CONTENT;
1354 if (actcont == DF_ALL) {
1355 mdb_printf("dump content: all kernel and user pages\n");
1356 return;
1357 } else if (actcont == DF_CURPROC) {
1358 mdb_printf("dump content: kernel pages and pages from "
1359 "PID %d", content);
1360 return;
1363 mdb_printf("dump content: kernel pages only\n");
1364 if (!(expcont & DF_CURPROC))
1365 return;
1367 if (mdb_readvar(&pt, "panic_thread") != sizeof (pt) ||
1368 pt == (uintptr_t)NULL)
1369 goto kthreadpanic_err;
1371 if (mdb_vread(&procp, sizeof (procp), pt + OFFSETOF(kthread_t,
1372 t_procp)) == -1 || procp == (uintptr_t)NULL)
1373 goto kthreadpanic_err;
1375 if (mdb_lookup_by_name("p0", &sym) != 0)
1376 goto kthreadpanic_err;
1378 if (procp == (uintptr_t)sym.st_value) {
1379 mdb_printf(" (curproc requested, but a kernel thread "
1380 "panicked)\n");
1381 } else {
1382 mdb_printf(" (curproc requested, but the process that "
1383 "panicked could not be dumped)\n");
1386 return;
1388 kthreadpanic_err:
1389 mdb_printf(" (curproc requested, but the process that panicked could "
1390 "not be found)\n");
1394 * Determine the process that was saved in a `curproc' dump. This process will
1395 * be recorded as the first element in dump_pids[].
1398 mdb_dump_find_curproc(void)
1400 uintptr_t pidp;
1401 pid_t pid = -1;
1403 if (mdb_readvar(&pidp, "dump_pids") == sizeof (pidp) &&
1404 mdb_vread(&pid, sizeof (pid), pidp) == sizeof (pid) &&
1405 pid > 0)
1406 return (pid);
1407 else
1408 return (-1);
1413 * Following three funcs extracted from sunddi.c
1417 * Return core address of root node of devinfo tree
1419 static uintptr_t
1420 mdb_ddi_root_node(void)
1422 uintptr_t top_devinfo_addr;
1424 /* return (top_devinfo); */
1425 if (mdb_readvar(&top_devinfo_addr, "top_devinfo") == -1) {
1426 mdb_warn("failed to read top_devinfo");
1427 return ((uintptr_t)NULL);
1429 return (top_devinfo_addr);
1433 * Return the name of the devinfo node pointed at by 'dip_addr' in the buffer
1434 * pointed at by 'name.'
1436 * - dip_addr is a pointer to a dev_info struct in core.
1438 static char *
1439 mdb_ddi_deviname(uintptr_t dip_addr, char *name, size_t name_size)
1441 uintptr_t addrname;
1442 ssize_t length;
1443 char *local_namep = name;
1444 size_t local_name_size = name_size;
1445 struct dev_info local_dip;
1448 if (dip_addr == mdb_ddi_root_node()) {
1449 if (name_size < 1) {
1450 mdb_warn("failed to get node name: buf too small\n");
1451 return (NULL);
1454 *name = '\0';
1455 return (name);
1458 if (name_size < 2) {
1459 mdb_warn("failed to get node name: buf too small\n");
1460 return (NULL);
1463 local_namep = name;
1464 *local_namep++ = '/';
1465 *local_namep = '\0';
1466 local_name_size--;
1468 if (mdb_vread(&local_dip, sizeof (struct dev_info), dip_addr) == -1) {
1469 mdb_warn("failed to read devinfo struct");
1472 length = mdb_readstr(local_namep, local_name_size,
1473 (uintptr_t)local_dip.devi_node_name);
1474 if (length == -1) {
1475 mdb_warn("failed to read node name");
1476 return (NULL);
1478 local_namep += length;
1479 local_name_size -= length;
1480 addrname = (uintptr_t)local_dip.devi_addr;
1482 if (addrname != (uintptr_t)NULL) {
1484 if (local_name_size < 2) {
1485 mdb_warn("not enough room for node address string");
1486 return (name);
1488 *local_namep++ = '@';
1489 *local_namep = '\0';
1490 local_name_size--;
1492 length = mdb_readstr(local_namep, local_name_size, addrname);
1493 if (length == -1) {
1494 mdb_warn("failed to read name");
1495 return (NULL);
1499 return (name);
1503 * Generate the full path under the /devices dir to the device entry.
1505 * dip is a pointer to a devinfo struct in core (not in local memory).
1507 char *
1508 mdb_ddi_pathname(uintptr_t dip_addr, char *path, size_t pathlen)
1510 struct dev_info local_dip;
1511 uintptr_t parent_dip;
1512 char *bp;
1513 size_t buf_left;
1516 if (dip_addr == mdb_ddi_root_node()) {
1517 *path = '\0';
1518 return (path);
1522 if (mdb_vread(&local_dip, sizeof (struct dev_info), dip_addr) == -1) {
1523 mdb_warn("failed to read devinfo struct");
1526 parent_dip = (uintptr_t)local_dip.devi_parent;
1527 (void) mdb_ddi_pathname(parent_dip, path, pathlen);
1529 bp = path + strlen(path);
1530 buf_left = pathlen - strlen(path);
1531 (void) mdb_ddi_deviname(dip_addr, bp, buf_left);
1532 return (path);
1537 * Read in the string value of a refstr, which is appended to the end of
1538 * the structure.
1540 ssize_t
1541 mdb_read_refstr(uintptr_t refstr_addr, char *str, size_t nbytes)
1543 struct refstr *r = (struct refstr *)refstr_addr;
1545 return (mdb_readstr(str, nbytes, (uintptr_t)r->rs_string));
1549 * Chase an mblk list by b_next and return the length.
1552 mdb_mblk_count(const mblk_t *mb)
1554 int count;
1555 mblk_t mblk;
1557 if (mb == NULL)
1558 return (0);
1560 count = 1;
1561 while (mb->b_next != NULL) {
1562 count++;
1563 if (mdb_vread(&mblk, sizeof (mblk), (uintptr_t)mb->b_next) ==
1565 break;
1566 mb = &mblk;
1568 return (count);
1572 * Write the given MAC address as a printable string in the usual colon-
1573 * separated format. Assumes that buflen is at least 2.
1575 void
1576 mdb_mac_addr(const uint8_t *addr, size_t alen, char *buf, size_t buflen)
1578 int slen;
1580 if (alen == 0 || buflen < 4) {
1581 (void) strcpy(buf, "?");
1582 return;
1584 for (;;) {
1586 * If there are more MAC address bytes available, but we won't
1587 * have any room to print them, then add "..." to the string
1588 * instead. See below for the 'magic number' explanation.
1590 if ((alen == 2 && buflen < 6) || (alen > 2 && buflen < 7)) {
1591 (void) strcpy(buf, "...");
1592 break;
1594 slen = mdb_snprintf(buf, buflen, "%02x", *addr++);
1595 buf += slen;
1596 if (--alen == 0)
1597 break;
1598 *buf++ = ':';
1599 buflen -= slen + 1;
1601 * At this point, based on the first 'if' statement above,
1602 * either alen == 1 and buflen >= 3, or alen > 1 and
1603 * buflen >= 4. The first case leaves room for the final "xx"
1604 * number and trailing NUL byte. The second leaves room for at
1605 * least "...". Thus the apparently 'magic' numbers chosen for
1606 * that statement.
1612 * Produce a string that represents a DLPI primitive, or NULL if no such string
1613 * is possible.
1615 const char *
1616 mdb_dlpi_prim(int prim)
1618 switch (prim) {
1619 case DL_INFO_REQ: return ("DL_INFO_REQ");
1620 case DL_INFO_ACK: return ("DL_INFO_ACK");
1621 case DL_ATTACH_REQ: return ("DL_ATTACH_REQ");
1622 case DL_DETACH_REQ: return ("DL_DETACH_REQ");
1623 case DL_BIND_REQ: return ("DL_BIND_REQ");
1624 case DL_BIND_ACK: return ("DL_BIND_ACK");
1625 case DL_UNBIND_REQ: return ("DL_UNBIND_REQ");
1626 case DL_OK_ACK: return ("DL_OK_ACK");
1627 case DL_ERROR_ACK: return ("DL_ERROR_ACK");
1628 case DL_ENABMULTI_REQ: return ("DL_ENABMULTI_REQ");
1629 case DL_DISABMULTI_REQ: return ("DL_DISABMULTI_REQ");
1630 case DL_PROMISCON_REQ: return ("DL_PROMISCON_REQ");
1631 case DL_PROMISCOFF_REQ: return ("DL_PROMISCOFF_REQ");
1632 case DL_UNITDATA_REQ: return ("DL_UNITDATA_REQ");
1633 case DL_UNITDATA_IND: return ("DL_UNITDATA_IND");
1634 case DL_UDERROR_IND: return ("DL_UDERROR_IND");
1635 case DL_PHYS_ADDR_REQ: return ("DL_PHYS_ADDR_REQ");
1636 case DL_PHYS_ADDR_ACK: return ("DL_PHYS_ADDR_ACK");
1637 case DL_SET_PHYS_ADDR_REQ: return ("DL_SET_PHYS_ADDR_REQ");
1638 case DL_NOTIFY_REQ: return ("DL_NOTIFY_REQ");
1639 case DL_NOTIFY_ACK: return ("DL_NOTIFY_ACK");
1640 case DL_NOTIFY_IND: return ("DL_NOTIFY_IND");
1641 case DL_NOTIFY_CONF: return ("DL_NOTIFY_CONF");
1642 case DL_CAPABILITY_REQ: return ("DL_CAPABILITY_REQ");
1643 case DL_CAPABILITY_ACK: return ("DL_CAPABILITY_ACK");
1644 case DL_CONTROL_REQ: return ("DL_CONTROL_REQ");
1645 case DL_CONTROL_ACK: return ("DL_CONTROL_ACK");
1646 case DL_PASSIVE_REQ: return ("DL_PASSIVE_REQ");
1647 default: return (NULL);
1652 * mdb_gethrtime() returns the hires system time. This will be the timestamp at
1653 * which we dropped into, if called from, kmdb(1); the core dump's hires time
1654 * if inspecting one; or the running system's hires time if we're inspecting
1655 * a live kernel.
1657 hrtime_t
1658 mdb_gethrtime(void)
1660 uintptr_t ptr;
1661 GElf_Sym sym;
1662 lbolt_info_t lbi;
1663 hrtime_t ts;
1666 * We first check whether the lbolt info structure has been allocated
1667 * and initialized. If not, lbolt_hybrid will be pointing at
1668 * lbolt_bootstrap.
1670 if (mdb_lookup_by_name("lbolt_bootstrap", &sym) == -1)
1671 return (0);
1673 if (mdb_readvar(&ptr, "lbolt_hybrid") == -1)
1674 return (0);
1676 if (ptr == (uintptr_t)sym.st_value)
1677 return (0);
1679 #ifdef _KMDB
1680 if (mdb_readvar(&ptr, "lb_info") == -1)
1681 return (0);
1683 if (mdb_vread(&lbi, sizeof (lbolt_info_t), ptr) !=
1684 sizeof (lbolt_info_t))
1685 return (0);
1687 ts = lbi.lbi_debug_ts;
1688 #else
1689 if (mdb_prop_postmortem) {
1690 if (mdb_readvar(&ptr, "lb_info") == -1)
1691 return (0);
1693 if (mdb_vread(&lbi, sizeof (lbolt_info_t), ptr) !=
1694 sizeof (lbolt_info_t))
1695 return (0);
1697 ts = lbi.lbi_debug_ts;
1698 } else {
1699 ts = gethrtime();
1701 #endif
1702 return (ts);
1706 * mdb_get_lbolt() returns the number of clock ticks since system boot.
1707 * Depending on the context in which it's called, the value will be derived
1708 * from different sources per mdb_gethrtime(). If inspecting a panicked
1709 * system, the routine returns the 'panic_lbolt64' variable from the core file.
1711 int64_t
1712 mdb_get_lbolt(void)
1714 lbolt_info_t lbi;
1715 uintptr_t ptr;
1716 int64_t pl;
1717 hrtime_t ts;
1718 int nsec;
1720 if (mdb_readvar(&pl, "panic_lbolt64") != -1 && pl > 0)
1721 return (pl);
1724 * mdb_gethrtime() will return zero if the lbolt info structure hasn't
1725 * been allocated and initialized yet, or if it fails to read it.
1727 if ((ts = mdb_gethrtime()) <= 0)
1728 return (0);
1731 * Load the time spent in kmdb, if any.
1733 if (mdb_readvar(&ptr, "lb_info") == -1)
1734 return (0);
1736 if (mdb_vread(&lbi, sizeof (lbolt_info_t), ptr) !=
1737 sizeof (lbolt_info_t))
1738 return (0);
1740 if (mdb_readvar(&nsec, "nsec_per_tick") == -1 || nsec == 0) {
1741 mdb_warn("failed to read 'nsec_per_tick'");
1742 return (-1);
1745 return ((ts/nsec) - lbi.lbi_debug_time);