xref: /titanic_41/usr/src/cmd/mdb/common/modules/genunix/kmem.c (revision 685482d6dae8b0c167f468d6313a738ae17c592c)
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 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <mdb/mdb_param.h>
29 #include <mdb/mdb_modapi.h>
30 #include <mdb/mdb_ctf.h>
31 #include <sys/cpuvar.h>
32 #include <sys/kmem_impl.h>
33 #include <sys/vmem_impl.h>
34 #include <sys/machelf.h>
35 #include <sys/modctl.h>
36 #include <sys/kobj.h>
37 #include <sys/panic.h>
38 #include <sys/stack.h>
39 #include <sys/sysmacros.h>
40 #include <vm/page.h>
41 
42 #include "kmem.h"
43 #include "leaky.h"
44 
45 #define	dprintf(x) if (mdb_debug_level) { \
46 	mdb_printf("kmem debug: ");  \
47 	/*CSTYLED*/\
48 	mdb_printf x ;\
49 }
50 
51 #define	KM_ALLOCATED		0x01
52 #define	KM_FREE			0x02
53 #define	KM_BUFCTL		0x04
54 #define	KM_CONSTRUCTED		0x08	/* only constructed free buffers */
55 #define	KM_HASH			0x10
56 
57 static int mdb_debug_level = 0;
58 
59 /*ARGSUSED*/
60 static int
61 kmem_init_walkers(uintptr_t addr, const kmem_cache_t *c, void *ignored)
62 {
63 	mdb_walker_t w;
64 	char descr[64];
65 
66 	(void) mdb_snprintf(descr, sizeof (descr),
67 	    "walk the %s cache", c->cache_name);
68 
69 	w.walk_name = c->cache_name;
70 	w.walk_descr = descr;
71 	w.walk_init = kmem_walk_init;
72 	w.walk_step = kmem_walk_step;
73 	w.walk_fini = kmem_walk_fini;
74 	w.walk_init_arg = (void *)addr;
75 
76 	if (mdb_add_walker(&w) == -1)
77 		mdb_warn("failed to add %s walker", c->cache_name);
78 
79 	return (WALK_NEXT);
80 }
81 
82 /*ARGSUSED*/
83 int
84 kmem_debug(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
85 {
86 	mdb_debug_level ^= 1;
87 
88 	mdb_printf("kmem: debugging is now %s\n",
89 	    mdb_debug_level ? "on" : "off");
90 
91 	return (DCMD_OK);
92 }
93 
94 typedef struct {
95 	uintptr_t kcw_first;
96 	uintptr_t kcw_current;
97 } kmem_cache_walk_t;
98 
99 int
100 kmem_cache_walk_init(mdb_walk_state_t *wsp)
101 {
102 	kmem_cache_walk_t *kcw;
103 	kmem_cache_t c;
104 	uintptr_t cp;
105 	GElf_Sym sym;
106 
107 	if (mdb_lookup_by_name("kmem_null_cache", &sym) == -1) {
108 		mdb_warn("couldn't find kmem_null_cache");
109 		return (WALK_ERR);
110 	}
111 
112 	cp = (uintptr_t)sym.st_value;
113 
114 	if (mdb_vread(&c, sizeof (kmem_cache_t), cp) == -1) {
115 		mdb_warn("couldn't read cache at %p", cp);
116 		return (WALK_ERR);
117 	}
118 
119 	kcw = mdb_alloc(sizeof (kmem_cache_walk_t), UM_SLEEP);
120 
121 	kcw->kcw_first = cp;
122 	kcw->kcw_current = (uintptr_t)c.cache_next;
123 	wsp->walk_data = kcw;
124 
125 	return (WALK_NEXT);
126 }
127 
128 int
129 kmem_cache_walk_step(mdb_walk_state_t *wsp)
130 {
131 	kmem_cache_walk_t *kcw = wsp->walk_data;
132 	kmem_cache_t c;
133 	int status;
134 
135 	if (mdb_vread(&c, sizeof (kmem_cache_t), kcw->kcw_current) == -1) {
136 		mdb_warn("couldn't read cache at %p", kcw->kcw_current);
137 		return (WALK_DONE);
138 	}
139 
140 	status = wsp->walk_callback(kcw->kcw_current, &c, wsp->walk_cbdata);
141 
142 	if ((kcw->kcw_current = (uintptr_t)c.cache_next) == kcw->kcw_first)
143 		return (WALK_DONE);
144 
145 	return (status);
146 }
147 
148 void
149 kmem_cache_walk_fini(mdb_walk_state_t *wsp)
150 {
151 	kmem_cache_walk_t *kcw = wsp->walk_data;
152 	mdb_free(kcw, sizeof (kmem_cache_walk_t));
153 }
154 
155 int
156 kmem_cpu_cache_walk_init(mdb_walk_state_t *wsp)
157 {
158 	if (wsp->walk_addr == NULL) {
159 		mdb_warn("kmem_cpu_cache doesn't support global walks");
160 		return (WALK_ERR);
161 	}
162 
163 	if (mdb_layered_walk("cpu", wsp) == -1) {
164 		mdb_warn("couldn't walk 'cpu'");
165 		return (WALK_ERR);
166 	}
167 
168 	wsp->walk_data = (void *)wsp->walk_addr;
169 
170 	return (WALK_NEXT);
171 }
172 
173 int
174 kmem_cpu_cache_walk_step(mdb_walk_state_t *wsp)
175 {
176 	uintptr_t caddr = (uintptr_t)wsp->walk_data;
177 	const cpu_t *cpu = wsp->walk_layer;
178 	kmem_cpu_cache_t cc;
179 
180 	caddr += cpu->cpu_cache_offset;
181 
182 	if (mdb_vread(&cc, sizeof (kmem_cpu_cache_t), caddr) == -1) {
183 		mdb_warn("couldn't read kmem_cpu_cache at %p", caddr);
184 		return (WALK_ERR);
185 	}
186 
187 	return (wsp->walk_callback(caddr, &cc, wsp->walk_cbdata));
188 }
189 
190 int
191 kmem_slab_walk_init(mdb_walk_state_t *wsp)
192 {
193 	uintptr_t caddr = wsp->walk_addr;
194 	kmem_cache_t c;
195 
196 	if (caddr == NULL) {
197 		mdb_warn("kmem_slab doesn't support global walks\n");
198 		return (WALK_ERR);
199 	}
200 
201 	if (mdb_vread(&c, sizeof (c), caddr) == -1) {
202 		mdb_warn("couldn't read kmem_cache at %p", caddr);
203 		return (WALK_ERR);
204 	}
205 
206 	wsp->walk_data =
207 	    (void *)(caddr + offsetof(kmem_cache_t, cache_nullslab));
208 	wsp->walk_addr = (uintptr_t)c.cache_nullslab.slab_next;
209 
210 	return (WALK_NEXT);
211 }
212 
213 int
214 kmem_slab_walk_partial_init(mdb_walk_state_t *wsp)
215 {
216 	uintptr_t caddr = wsp->walk_addr;
217 	kmem_cache_t c;
218 
219 	if (caddr == NULL) {
220 		mdb_warn("kmem_slab_partial doesn't support global walks\n");
221 		return (WALK_ERR);
222 	}
223 
224 	if (mdb_vread(&c, sizeof (c), caddr) == -1) {
225 		mdb_warn("couldn't read kmem_cache at %p", caddr);
226 		return (WALK_ERR);
227 	}
228 
229 	wsp->walk_data =
230 	    (void *)(caddr + offsetof(kmem_cache_t, cache_nullslab));
231 	wsp->walk_addr = (uintptr_t)c.cache_freelist;
232 
233 	/*
234 	 * Some consumers (umem_walk_step(), in particular) require at
235 	 * least one callback if there are any buffers in the cache.  So
236 	 * if there are *no* partial slabs, report the last full slab, if
237 	 * any.
238 	 *
239 	 * Yes, this is ugly, but it's cleaner than the other possibilities.
240 	 */
241 	if ((uintptr_t)wsp->walk_data == wsp->walk_addr)
242 		wsp->walk_addr = (uintptr_t)c.cache_nullslab.slab_prev;
243 
244 	return (WALK_NEXT);
245 }
246 
247 int
248 kmem_slab_walk_step(mdb_walk_state_t *wsp)
249 {
250 	kmem_slab_t s;
251 	uintptr_t addr = wsp->walk_addr;
252 	uintptr_t saddr = (uintptr_t)wsp->walk_data;
253 	uintptr_t caddr = saddr - offsetof(kmem_cache_t, cache_nullslab);
254 
255 	if (addr == saddr)
256 		return (WALK_DONE);
257 
258 	if (mdb_vread(&s, sizeof (s), addr) == -1) {
259 		mdb_warn("failed to read slab at %p", wsp->walk_addr);
260 		return (WALK_ERR);
261 	}
262 
263 	if ((uintptr_t)s.slab_cache != caddr) {
264 		mdb_warn("slab %p isn't in cache %p (in cache %p)\n",
265 		    addr, caddr, s.slab_cache);
266 		return (WALK_ERR);
267 	}
268 
269 	wsp->walk_addr = (uintptr_t)s.slab_next;
270 
271 	return (wsp->walk_callback(addr, &s, wsp->walk_cbdata));
272 }
273 
274 int
275 kmem_cache(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *argv)
276 {
277 	kmem_cache_t c;
278 
279 	if (!(flags & DCMD_ADDRSPEC)) {
280 		if (mdb_walk_dcmd("kmem_cache", "kmem_cache", ac, argv) == -1) {
281 			mdb_warn("can't walk kmem_cache");
282 			return (DCMD_ERR);
283 		}
284 		return (DCMD_OK);
285 	}
286 
287 	if (DCMD_HDRSPEC(flags))
288 		mdb_printf("%-?s %-25s %4s %6s %8s %8s\n", "ADDR", "NAME",
289 		    "FLAG", "CFLAG", "BUFSIZE", "BUFTOTL");
290 
291 	if (mdb_vread(&c, sizeof (c), addr) == -1) {
292 		mdb_warn("couldn't read kmem_cache at %p", addr);
293 		return (DCMD_ERR);
294 	}
295 
296 	mdb_printf("%0?p %-25s %04x %06x %8ld %8lld\n", addr, c.cache_name,
297 	    c.cache_flags, c.cache_cflags, c.cache_bufsize, c.cache_buftotal);
298 
299 	return (DCMD_OK);
300 }
301 
302 static int
303 addrcmp(const void *lhs, const void *rhs)
304 {
305 	uintptr_t p1 = *((uintptr_t *)lhs);
306 	uintptr_t p2 = *((uintptr_t *)rhs);
307 
308 	if (p1 < p2)
309 		return (-1);
310 	if (p1 > p2)
311 		return (1);
312 	return (0);
313 }
314 
315 static int
316 bufctlcmp(const kmem_bufctl_audit_t **lhs, const kmem_bufctl_audit_t **rhs)
317 {
318 	const kmem_bufctl_audit_t *bcp1 = *lhs;
319 	const kmem_bufctl_audit_t *bcp2 = *rhs;
320 
321 	if (bcp1->bc_timestamp > bcp2->bc_timestamp)
322 		return (-1);
323 
324 	if (bcp1->bc_timestamp < bcp2->bc_timestamp)
325 		return (1);
326 
327 	return (0);
328 }
329 
330 typedef struct kmem_hash_walk {
331 	uintptr_t *kmhw_table;
332 	size_t kmhw_nelems;
333 	size_t kmhw_pos;
334 	kmem_bufctl_t kmhw_cur;
335 } kmem_hash_walk_t;
336 
337 int
338 kmem_hash_walk_init(mdb_walk_state_t *wsp)
339 {
340 	kmem_hash_walk_t *kmhw;
341 	uintptr_t *hash;
342 	kmem_cache_t c;
343 	uintptr_t haddr, addr = wsp->walk_addr;
344 	size_t nelems;
345 	size_t hsize;
346 
347 	if (addr == NULL) {
348 		mdb_warn("kmem_hash doesn't support global walks\n");
349 		return (WALK_ERR);
350 	}
351 
352 	if (mdb_vread(&c, sizeof (c), addr) == -1) {
353 		mdb_warn("couldn't read cache at addr %p", addr);
354 		return (WALK_ERR);
355 	}
356 
357 	if (!(c.cache_flags & KMF_HASH)) {
358 		mdb_warn("cache %p doesn't have a hash table\n", addr);
359 		return (WALK_DONE);		/* nothing to do */
360 	}
361 
362 	kmhw = mdb_zalloc(sizeof (kmem_hash_walk_t), UM_SLEEP);
363 	kmhw->kmhw_cur.bc_next = NULL;
364 	kmhw->kmhw_pos = 0;
365 
366 	kmhw->kmhw_nelems = nelems = c.cache_hash_mask + 1;
367 	hsize = nelems * sizeof (uintptr_t);
368 	haddr = (uintptr_t)c.cache_hash_table;
369 
370 	kmhw->kmhw_table = hash = mdb_alloc(hsize, UM_SLEEP);
371 	if (mdb_vread(hash, hsize, haddr) == -1) {
372 		mdb_warn("failed to read hash table at %p", haddr);
373 		mdb_free(hash, hsize);
374 		mdb_free(kmhw, sizeof (kmem_hash_walk_t));
375 		return (WALK_ERR);
376 	}
377 
378 	wsp->walk_data = kmhw;
379 
380 	return (WALK_NEXT);
381 }
382 
383 int
384 kmem_hash_walk_step(mdb_walk_state_t *wsp)
385 {
386 	kmem_hash_walk_t *kmhw = wsp->walk_data;
387 	uintptr_t addr = NULL;
388 
389 	if ((addr = (uintptr_t)kmhw->kmhw_cur.bc_next) == NULL) {
390 		while (kmhw->kmhw_pos < kmhw->kmhw_nelems) {
391 			if ((addr = kmhw->kmhw_table[kmhw->kmhw_pos++]) != NULL)
392 				break;
393 		}
394 	}
395 	if (addr == NULL)
396 		return (WALK_DONE);
397 
398 	if (mdb_vread(&kmhw->kmhw_cur, sizeof (kmem_bufctl_t), addr) == -1) {
399 		mdb_warn("couldn't read kmem_bufctl_t at addr %p", addr);
400 		return (WALK_ERR);
401 	}
402 
403 	return (wsp->walk_callback(addr, &kmhw->kmhw_cur, wsp->walk_cbdata));
404 }
405 
406 void
407 kmem_hash_walk_fini(mdb_walk_state_t *wsp)
408 {
409 	kmem_hash_walk_t *kmhw = wsp->walk_data;
410 
411 	if (kmhw == NULL)
412 		return;
413 
414 	mdb_free(kmhw->kmhw_table, kmhw->kmhw_nelems * sizeof (uintptr_t));
415 	mdb_free(kmhw, sizeof (kmem_hash_walk_t));
416 }
417 
418 /*
419  * Find the address of the bufctl structure for the address 'buf' in cache
420  * 'cp', which is at address caddr, and place it in *out.
421  */
422 static int
423 kmem_hash_lookup(kmem_cache_t *cp, uintptr_t caddr, void *buf, uintptr_t *out)
424 {
425 	uintptr_t bucket = (uintptr_t)KMEM_HASH(cp, buf);
426 	kmem_bufctl_t *bcp;
427 	kmem_bufctl_t bc;
428 
429 	if (mdb_vread(&bcp, sizeof (kmem_bufctl_t *), bucket) == -1) {
430 		mdb_warn("unable to read hash bucket for %p in cache %p",
431 		    buf, caddr);
432 		return (-1);
433 	}
434 
435 	while (bcp != NULL) {
436 		if (mdb_vread(&bc, sizeof (kmem_bufctl_t),
437 		    (uintptr_t)bcp) == -1) {
438 			mdb_warn("unable to read bufctl at %p", bcp);
439 			return (-1);
440 		}
441 		if (bc.bc_addr == buf) {
442 			*out = (uintptr_t)bcp;
443 			return (0);
444 		}
445 		bcp = bc.bc_next;
446 	}
447 
448 	mdb_warn("unable to find bufctl for %p in cache %p\n", buf, caddr);
449 	return (-1);
450 }
451 
452 int
453 kmem_get_magsize(const kmem_cache_t *cp)
454 {
455 	uintptr_t addr = (uintptr_t)cp->cache_magtype;
456 	GElf_Sym mt_sym;
457 	kmem_magtype_t mt;
458 	int res;
459 
460 	/*
461 	 * if cpu 0 has a non-zero magsize, it must be correct.  caches
462 	 * with KMF_NOMAGAZINE have disabled their magazine layers, so
463 	 * it is okay to return 0 for them.
464 	 */
465 	if ((res = cp->cache_cpu[0].cc_magsize) != 0 ||
466 	    (cp->cache_flags & KMF_NOMAGAZINE))
467 		return (res);
468 
469 	if (mdb_lookup_by_name("kmem_magtype", &mt_sym) == -1) {
470 		mdb_warn("unable to read 'kmem_magtype'");
471 	} else if (addr < mt_sym.st_value ||
472 	    addr + sizeof (mt) - 1 > mt_sym.st_value + mt_sym.st_size - 1 ||
473 	    ((addr - mt_sym.st_value) % sizeof (mt)) != 0) {
474 		mdb_warn("cache '%s' has invalid magtype pointer (%p)\n",
475 		    cp->cache_name, addr);
476 		return (0);
477 	}
478 	if (mdb_vread(&mt, sizeof (mt), addr) == -1) {
479 		mdb_warn("unable to read magtype at %a", addr);
480 		return (0);
481 	}
482 	return (mt.mt_magsize);
483 }
484 
485 /*ARGSUSED*/
486 static int
487 kmem_estimate_slab(uintptr_t addr, const kmem_slab_t *sp, size_t *est)
488 {
489 	*est -= (sp->slab_chunks - sp->slab_refcnt);
490 
491 	return (WALK_NEXT);
492 }
493 
494 /*
495  * Returns an upper bound on the number of allocated buffers in a given
496  * cache.
497  */
498 size_t
499 kmem_estimate_allocated(uintptr_t addr, const kmem_cache_t *cp)
500 {
501 	int magsize;
502 	size_t cache_est;
503 
504 	cache_est = cp->cache_buftotal;
505 
506 	(void) mdb_pwalk("kmem_slab_partial",
507 	    (mdb_walk_cb_t)kmem_estimate_slab, &cache_est, addr);
508 
509 	if ((magsize = kmem_get_magsize(cp)) != 0) {
510 		size_t mag_est = cp->cache_full.ml_total * magsize;
511 
512 		if (cache_est >= mag_est) {
513 			cache_est -= mag_est;
514 		} else {
515 			mdb_warn("cache %p's magazine layer holds more buffers "
516 			    "than the slab layer.\n", addr);
517 		}
518 	}
519 	return (cache_est);
520 }
521 
522 #define	READMAG_ROUNDS(rounds) { \
523 	if (mdb_vread(mp, magbsize, (uintptr_t)kmp) == -1) { \
524 		mdb_warn("couldn't read magazine at %p", kmp); \
525 		goto fail; \
526 	} \
527 	for (i = 0; i < rounds; i++) { \
528 		maglist[magcnt++] = mp->mag_round[i]; \
529 		if (magcnt == magmax) { \
530 			mdb_warn("%d magazines exceeds fudge factor\n", \
531 			    magcnt); \
532 			goto fail; \
533 		} \
534 	} \
535 }
536 
537 int
538 kmem_read_magazines(kmem_cache_t *cp, uintptr_t addr, int ncpus,
539     void ***maglistp, size_t *magcntp, size_t *magmaxp, int alloc_flags)
540 {
541 	kmem_magazine_t *kmp, *mp;
542 	void **maglist = NULL;
543 	int i, cpu;
544 	size_t magsize, magmax, magbsize;
545 	size_t magcnt = 0;
546 
547 	/*
548 	 * Read the magtype out of the cache, after verifying the pointer's
549 	 * correctness.
550 	 */
551 	magsize = kmem_get_magsize(cp);
552 	if (magsize == 0) {
553 		*maglistp = NULL;
554 		*magcntp = 0;
555 		*magmaxp = 0;
556 		return (WALK_NEXT);
557 	}
558 
559 	/*
560 	 * There are several places where we need to go buffer hunting:
561 	 * the per-CPU loaded magazine, the per-CPU spare full magazine,
562 	 * and the full magazine list in the depot.
563 	 *
564 	 * For an upper bound on the number of buffers in the magazine
565 	 * layer, we have the number of magazines on the cache_full
566 	 * list plus at most two magazines per CPU (the loaded and the
567 	 * spare).  Toss in 100 magazines as a fudge factor in case this
568 	 * is live (the number "100" comes from the same fudge factor in
569 	 * crash(1M)).
570 	 */
571 	magmax = (cp->cache_full.ml_total + 2 * ncpus + 100) * magsize;
572 	magbsize = offsetof(kmem_magazine_t, mag_round[magsize]);
573 
574 	if (magbsize >= PAGESIZE / 2) {
575 		mdb_warn("magazine size for cache %p unreasonable (%x)\n",
576 		    addr, magbsize);
577 		return (WALK_ERR);
578 	}
579 
580 	maglist = mdb_alloc(magmax * sizeof (void *), alloc_flags);
581 	mp = mdb_alloc(magbsize, alloc_flags);
582 	if (mp == NULL || maglist == NULL)
583 		goto fail;
584 
585 	/*
586 	 * First up: the magazines in the depot (i.e. on the cache_full list).
587 	 */
588 	for (kmp = cp->cache_full.ml_list; kmp != NULL; ) {
589 		READMAG_ROUNDS(magsize);
590 		kmp = mp->mag_next;
591 
592 		if (kmp == cp->cache_full.ml_list)
593 			break; /* cache_full list loop detected */
594 	}
595 
596 	dprintf(("cache_full list done\n"));
597 
598 	/*
599 	 * Now whip through the CPUs, snagging the loaded magazines
600 	 * and full spares.
601 	 */
602 	for (cpu = 0; cpu < ncpus; cpu++) {
603 		kmem_cpu_cache_t *ccp = &cp->cache_cpu[cpu];
604 
605 		dprintf(("reading cpu cache %p\n",
606 		    (uintptr_t)ccp - (uintptr_t)cp + addr));
607 
608 		if (ccp->cc_rounds > 0 &&
609 		    (kmp = ccp->cc_loaded) != NULL) {
610 			dprintf(("reading %d loaded rounds\n", ccp->cc_rounds));
611 			READMAG_ROUNDS(ccp->cc_rounds);
612 		}
613 
614 		if (ccp->cc_prounds > 0 &&
615 		    (kmp = ccp->cc_ploaded) != NULL) {
616 			dprintf(("reading %d previously loaded rounds\n",
617 			    ccp->cc_prounds));
618 			READMAG_ROUNDS(ccp->cc_prounds);
619 		}
620 	}
621 
622 	dprintf(("magazine layer: %d buffers\n", magcnt));
623 
624 	if (!(alloc_flags & UM_GC))
625 		mdb_free(mp, magbsize);
626 
627 	*maglistp = maglist;
628 	*magcntp = magcnt;
629 	*magmaxp = magmax;
630 
631 	return (WALK_NEXT);
632 
633 fail:
634 	if (!(alloc_flags & UM_GC)) {
635 		if (mp)
636 			mdb_free(mp, magbsize);
637 		if (maglist)
638 			mdb_free(maglist, magmax * sizeof (void *));
639 	}
640 	return (WALK_ERR);
641 }
642 
643 static int
644 kmem_walk_callback(mdb_walk_state_t *wsp, uintptr_t buf)
645 {
646 	return (wsp->walk_callback(buf, NULL, wsp->walk_cbdata));
647 }
648 
649 static int
650 bufctl_walk_callback(kmem_cache_t *cp, mdb_walk_state_t *wsp, uintptr_t buf)
651 {
652 	kmem_bufctl_audit_t b;
653 
654 	/*
655 	 * if KMF_AUDIT is not set, we know that we're looking at a
656 	 * kmem_bufctl_t.
657 	 */
658 	if (!(cp->cache_flags & KMF_AUDIT) ||
659 	    mdb_vread(&b, sizeof (kmem_bufctl_audit_t), buf) == -1) {
660 		(void) memset(&b, 0, sizeof (b));
661 		if (mdb_vread(&b, sizeof (kmem_bufctl_t), buf) == -1) {
662 			mdb_warn("unable to read bufctl at %p", buf);
663 			return (WALK_ERR);
664 		}
665 	}
666 
667 	return (wsp->walk_callback(buf, &b, wsp->walk_cbdata));
668 }
669 
670 typedef struct kmem_walk {
671 	int kmw_type;
672 
673 	int kmw_addr;			/* cache address */
674 	kmem_cache_t *kmw_cp;
675 	size_t kmw_csize;
676 
677 	/*
678 	 * magazine layer
679 	 */
680 	void **kmw_maglist;
681 	size_t kmw_max;
682 	size_t kmw_count;
683 	size_t kmw_pos;
684 
685 	/*
686 	 * slab layer
687 	 */
688 	char *kmw_valid;	/* to keep track of freed buffers */
689 	char *kmw_ubase;	/* buffer for slab data */
690 } kmem_walk_t;
691 
692 static int
693 kmem_walk_init_common(mdb_walk_state_t *wsp, int type)
694 {
695 	kmem_walk_t *kmw;
696 	int ncpus, csize;
697 	kmem_cache_t *cp;
698 	size_t vm_quantum;
699 
700 	size_t magmax, magcnt;
701 	void **maglist = NULL;
702 	uint_t chunksize, slabsize;
703 	int status = WALK_ERR;
704 	uintptr_t addr = wsp->walk_addr;
705 	const char *layered;
706 
707 	type &= ~KM_HASH;
708 
709 	if (addr == NULL) {
710 		mdb_warn("kmem walk doesn't support global walks\n");
711 		return (WALK_ERR);
712 	}
713 
714 	dprintf(("walking %p\n", addr));
715 
716 	/*
717 	 * First we need to figure out how many CPUs are configured in the
718 	 * system to know how much to slurp out.
719 	 */
720 	mdb_readvar(&ncpus, "max_ncpus");
721 
722 	csize = KMEM_CACHE_SIZE(ncpus);
723 	cp = mdb_alloc(csize, UM_SLEEP);
724 
725 	if (mdb_vread(cp, csize, addr) == -1) {
726 		mdb_warn("couldn't read cache at addr %p", addr);
727 		goto out2;
728 	}
729 
730 	/*
731 	 * It's easy for someone to hand us an invalid cache address.
732 	 * Unfortunately, it is hard for this walker to survive an
733 	 * invalid cache cleanly.  So we make sure that:
734 	 *
735 	 *	1. the vmem arena for the cache is readable,
736 	 *	2. the vmem arena's quantum is a power of 2,
737 	 *	3. our slabsize is a multiple of the quantum, and
738 	 *	4. our chunksize is >0 and less than our slabsize.
739 	 */
740 	if (mdb_vread(&vm_quantum, sizeof (vm_quantum),
741 	    (uintptr_t)&cp->cache_arena->vm_quantum) == -1 ||
742 	    vm_quantum == 0 ||
743 	    (vm_quantum & (vm_quantum - 1)) != 0 ||
744 	    cp->cache_slabsize < vm_quantum ||
745 	    P2PHASE(cp->cache_slabsize, vm_quantum) != 0 ||
746 	    cp->cache_chunksize == 0 ||
747 	    cp->cache_chunksize > cp->cache_slabsize) {
748 		mdb_warn("%p is not a valid kmem_cache_t\n", addr);
749 		goto out2;
750 	}
751 
752 	dprintf(("buf total is %d\n", cp->cache_buftotal));
753 
754 	if (cp->cache_buftotal == 0) {
755 		mdb_free(cp, csize);
756 		return (WALK_DONE);
757 	}
758 
759 	/*
760 	 * If they ask for bufctls, but it's a small-slab cache,
761 	 * there is nothing to report.
762 	 */
763 	if ((type & KM_BUFCTL) && !(cp->cache_flags & KMF_HASH)) {
764 		dprintf(("bufctl requested, not KMF_HASH (flags: %p)\n",
765 		    cp->cache_flags));
766 		mdb_free(cp, csize);
767 		return (WALK_DONE);
768 	}
769 
770 	/*
771 	 * If they want constructed buffers, but there's no constructor or
772 	 * the cache has DEADBEEF checking enabled, there is nothing to report.
773 	 */
774 	if ((type & KM_CONSTRUCTED) && (!(type & KM_FREE) ||
775 	    cp->cache_constructor == NULL ||
776 	    (cp->cache_flags & (KMF_DEADBEEF | KMF_LITE)) == KMF_DEADBEEF)) {
777 		mdb_free(cp, csize);
778 		return (WALK_DONE);
779 	}
780 
781 	/*
782 	 * Read in the contents of the magazine layer
783 	 */
784 	if (kmem_read_magazines(cp, addr, ncpus, &maglist, &magcnt,
785 	    &magmax, UM_SLEEP) == WALK_ERR)
786 		goto out2;
787 
788 	/*
789 	 * We have all of the buffers from the magazines;  if we are walking
790 	 * allocated buffers, sort them so we can bsearch them later.
791 	 */
792 	if (type & KM_ALLOCATED)
793 		qsort(maglist, magcnt, sizeof (void *), addrcmp);
794 
795 	wsp->walk_data = kmw = mdb_zalloc(sizeof (kmem_walk_t), UM_SLEEP);
796 
797 	kmw->kmw_type = type;
798 	kmw->kmw_addr = addr;
799 	kmw->kmw_cp = cp;
800 	kmw->kmw_csize = csize;
801 	kmw->kmw_maglist = maglist;
802 	kmw->kmw_max = magmax;
803 	kmw->kmw_count = magcnt;
804 	kmw->kmw_pos = 0;
805 
806 	/*
807 	 * When walking allocated buffers in a KMF_HASH cache, we walk the
808 	 * hash table instead of the slab layer.
809 	 */
810 	if ((cp->cache_flags & KMF_HASH) && (type & KM_ALLOCATED)) {
811 		layered = "kmem_hash";
812 
813 		kmw->kmw_type |= KM_HASH;
814 	} else {
815 		/*
816 		 * If we are walking freed buffers, we only need the
817 		 * magazine layer plus the partially allocated slabs.
818 		 * To walk allocated buffers, we need all of the slabs.
819 		 */
820 		if (type & KM_ALLOCATED)
821 			layered = "kmem_slab";
822 		else
823 			layered = "kmem_slab_partial";
824 
825 		/*
826 		 * for small-slab caches, we read in the entire slab.  For
827 		 * freed buffers, we can just walk the freelist.  For
828 		 * allocated buffers, we use a 'valid' array to track
829 		 * the freed buffers.
830 		 */
831 		if (!(cp->cache_flags & KMF_HASH)) {
832 			chunksize = cp->cache_chunksize;
833 			slabsize = cp->cache_slabsize;
834 
835 			kmw->kmw_ubase = mdb_alloc(slabsize +
836 			    sizeof (kmem_bufctl_t), UM_SLEEP);
837 
838 			if (type & KM_ALLOCATED)
839 				kmw->kmw_valid =
840 				    mdb_alloc(slabsize / chunksize, UM_SLEEP);
841 		}
842 	}
843 
844 	status = WALK_NEXT;
845 
846 	if (mdb_layered_walk(layered, wsp) == -1) {
847 		mdb_warn("unable to start layered '%s' walk", layered);
848 		status = WALK_ERR;
849 	}
850 
851 out1:
852 	if (status == WALK_ERR) {
853 		if (kmw->kmw_valid)
854 			mdb_free(kmw->kmw_valid, slabsize / chunksize);
855 
856 		if (kmw->kmw_ubase)
857 			mdb_free(kmw->kmw_ubase, slabsize +
858 			    sizeof (kmem_bufctl_t));
859 
860 		if (kmw->kmw_maglist)
861 			mdb_free(kmw->kmw_maglist,
862 			    kmw->kmw_max * sizeof (uintptr_t));
863 
864 		mdb_free(kmw, sizeof (kmem_walk_t));
865 		wsp->walk_data = NULL;
866 	}
867 
868 out2:
869 	if (status == WALK_ERR)
870 		mdb_free(cp, csize);
871 
872 	return (status);
873 }
874 
875 int
876 kmem_walk_step(mdb_walk_state_t *wsp)
877 {
878 	kmem_walk_t *kmw = wsp->walk_data;
879 	int type = kmw->kmw_type;
880 	kmem_cache_t *cp = kmw->kmw_cp;
881 
882 	void **maglist = kmw->kmw_maglist;
883 	int magcnt = kmw->kmw_count;
884 
885 	uintptr_t chunksize, slabsize;
886 	uintptr_t addr;
887 	const kmem_slab_t *sp;
888 	const kmem_bufctl_t *bcp;
889 	kmem_bufctl_t bc;
890 
891 	int chunks;
892 	char *kbase;
893 	void *buf;
894 	int i, ret;
895 
896 	char *valid, *ubase;
897 
898 	/*
899 	 * first, handle the 'kmem_hash' layered walk case
900 	 */
901 	if (type & KM_HASH) {
902 		/*
903 		 * We have a buffer which has been allocated out of the
904 		 * global layer. We need to make sure that it's not
905 		 * actually sitting in a magazine before we report it as
906 		 * an allocated buffer.
907 		 */
908 		buf = ((const kmem_bufctl_t *)wsp->walk_layer)->bc_addr;
909 
910 		if (magcnt > 0 &&
911 		    bsearch(&buf, maglist, magcnt, sizeof (void *),
912 		    addrcmp) != NULL)
913 			return (WALK_NEXT);
914 
915 		if (type & KM_BUFCTL)
916 			return (bufctl_walk_callback(cp, wsp, wsp->walk_addr));
917 
918 		return (kmem_walk_callback(wsp, (uintptr_t)buf));
919 	}
920 
921 	ret = WALK_NEXT;
922 
923 	addr = kmw->kmw_addr;
924 
925 	/*
926 	 * If we're walking freed buffers, report everything in the
927 	 * magazine layer before processing the first slab.
928 	 */
929 	if ((type & KM_FREE) && magcnt != 0) {
930 		kmw->kmw_count = 0;		/* only do this once */
931 		for (i = 0; i < magcnt; i++) {
932 			buf = maglist[i];
933 
934 			if (type & KM_BUFCTL) {
935 				uintptr_t out;
936 
937 				if (cp->cache_flags & KMF_BUFTAG) {
938 					kmem_buftag_t *btp;
939 					kmem_buftag_t tag;
940 
941 					/* LINTED - alignment */
942 					btp = KMEM_BUFTAG(cp, buf);
943 					if (mdb_vread(&tag, sizeof (tag),
944 					    (uintptr_t)btp) == -1) {
945 						mdb_warn("reading buftag for "
946 						    "%p at %p", buf, btp);
947 						continue;
948 					}
949 					out = (uintptr_t)tag.bt_bufctl;
950 				} else {
951 					if (kmem_hash_lookup(cp, addr, buf,
952 					    &out) == -1)
953 						continue;
954 				}
955 				ret = bufctl_walk_callback(cp, wsp, out);
956 			} else {
957 				ret = kmem_walk_callback(wsp, (uintptr_t)buf);
958 			}
959 
960 			if (ret != WALK_NEXT)
961 				return (ret);
962 		}
963 	}
964 
965 	/*
966 	 * If they want constructed buffers, we're finished, since the
967 	 * magazine layer holds them all.
968 	 */
969 	if (type & KM_CONSTRUCTED)
970 		return (WALK_DONE);
971 
972 	/*
973 	 * Handle the buffers in the current slab
974 	 */
975 	chunksize = cp->cache_chunksize;
976 	slabsize = cp->cache_slabsize;
977 
978 	sp = wsp->walk_layer;
979 	chunks = sp->slab_chunks;
980 	kbase = sp->slab_base;
981 
982 	dprintf(("kbase is %p\n", kbase));
983 
984 	if (!(cp->cache_flags & KMF_HASH)) {
985 		valid = kmw->kmw_valid;
986 		ubase = kmw->kmw_ubase;
987 
988 		if (mdb_vread(ubase, chunks * chunksize,
989 		    (uintptr_t)kbase) == -1) {
990 			mdb_warn("failed to read slab contents at %p", kbase);
991 			return (WALK_ERR);
992 		}
993 
994 		/*
995 		 * Set up the valid map as fully allocated -- we'll punch
996 		 * out the freelist.
997 		 */
998 		if (type & KM_ALLOCATED)
999 			(void) memset(valid, 1, chunks);
1000 	} else {
1001 		valid = NULL;
1002 		ubase = NULL;
1003 	}
1004 
1005 	/*
1006 	 * walk the slab's freelist
1007 	 */
1008 	bcp = sp->slab_head;
1009 
1010 	dprintf(("refcnt is %d; chunks is %d\n", sp->slab_refcnt, chunks));
1011 
1012 	/*
1013 	 * since we could be in the middle of allocating a buffer,
1014 	 * our refcnt could be one higher than it aught.  So we
1015 	 * check one further on the freelist than the count allows.
1016 	 */
1017 	for (i = sp->slab_refcnt; i <= chunks; i++) {
1018 		uint_t ndx;
1019 
1020 		dprintf(("bcp is %p\n", bcp));
1021 
1022 		if (bcp == NULL) {
1023 			if (i == chunks)
1024 				break;
1025 			mdb_warn(
1026 			    "slab %p in cache %p freelist too short by %d\n",
1027 			    sp, addr, chunks - i);
1028 			break;
1029 		}
1030 
1031 		if (cp->cache_flags & KMF_HASH) {
1032 			if (mdb_vread(&bc, sizeof (bc), (uintptr_t)bcp) == -1) {
1033 				mdb_warn("failed to read bufctl ptr at %p",
1034 				    bcp);
1035 				break;
1036 			}
1037 			buf = bc.bc_addr;
1038 		} else {
1039 			/*
1040 			 * Otherwise the buffer is in the slab which
1041 			 * we've read in;  we just need to determine
1042 			 * its offset in the slab to find the
1043 			 * kmem_bufctl_t.
1044 			 */
1045 			bc = *((kmem_bufctl_t *)
1046 			    ((uintptr_t)bcp - (uintptr_t)kbase +
1047 			    (uintptr_t)ubase));
1048 
1049 			buf = KMEM_BUF(cp, bcp);
1050 		}
1051 
1052 		ndx = ((uintptr_t)buf - (uintptr_t)kbase) / chunksize;
1053 
1054 		if (ndx > slabsize / cp->cache_bufsize) {
1055 			/*
1056 			 * This is very wrong; we have managed to find
1057 			 * a buffer in the slab which shouldn't
1058 			 * actually be here.  Emit a warning, and
1059 			 * try to continue.
1060 			 */
1061 			mdb_warn("buf %p is out of range for "
1062 			    "slab %p, cache %p\n", buf, sp, addr);
1063 		} else if (type & KM_ALLOCATED) {
1064 			/*
1065 			 * we have found a buffer on the slab's freelist;
1066 			 * clear its entry
1067 			 */
1068 			valid[ndx] = 0;
1069 		} else {
1070 			/*
1071 			 * Report this freed buffer
1072 			 */
1073 			if (type & KM_BUFCTL) {
1074 				ret = bufctl_walk_callback(cp, wsp,
1075 				    (uintptr_t)bcp);
1076 			} else {
1077 				ret = kmem_walk_callback(wsp, (uintptr_t)buf);
1078 			}
1079 			if (ret != WALK_NEXT)
1080 				return (ret);
1081 		}
1082 
1083 		bcp = bc.bc_next;
1084 	}
1085 
1086 	if (bcp != NULL) {
1087 		dprintf(("slab %p in cache %p freelist too long (%p)\n",
1088 		    sp, addr, bcp));
1089 	}
1090 
1091 	/*
1092 	 * If we are walking freed buffers, the loop above handled reporting
1093 	 * them.
1094 	 */
1095 	if (type & KM_FREE)
1096 		return (WALK_NEXT);
1097 
1098 	if (type & KM_BUFCTL) {
1099 		mdb_warn("impossible situation: small-slab KM_BUFCTL walk for "
1100 		    "cache %p\n", addr);
1101 		return (WALK_ERR);
1102 	}
1103 
1104 	/*
1105 	 * Report allocated buffers, skipping buffers in the magazine layer.
1106 	 * We only get this far for small-slab caches.
1107 	 */
1108 	for (i = 0; ret == WALK_NEXT && i < chunks; i++) {
1109 		buf = (char *)kbase + i * chunksize;
1110 
1111 		if (!valid[i])
1112 			continue;		/* on slab freelist */
1113 
1114 		if (magcnt > 0 &&
1115 		    bsearch(&buf, maglist, magcnt, sizeof (void *),
1116 		    addrcmp) != NULL)
1117 			continue;		/* in magazine layer */
1118 
1119 		ret = kmem_walk_callback(wsp, (uintptr_t)buf);
1120 	}
1121 	return (ret);
1122 }
1123 
1124 void
1125 kmem_walk_fini(mdb_walk_state_t *wsp)
1126 {
1127 	kmem_walk_t *kmw = wsp->walk_data;
1128 	uintptr_t chunksize;
1129 	uintptr_t slabsize;
1130 
1131 	if (kmw == NULL)
1132 		return;
1133 
1134 	if (kmw->kmw_maglist != NULL)
1135 		mdb_free(kmw->kmw_maglist, kmw->kmw_max * sizeof (void *));
1136 
1137 	chunksize = kmw->kmw_cp->cache_chunksize;
1138 	slabsize = kmw->kmw_cp->cache_slabsize;
1139 
1140 	if (kmw->kmw_valid != NULL)
1141 		mdb_free(kmw->kmw_valid, slabsize / chunksize);
1142 	if (kmw->kmw_ubase != NULL)
1143 		mdb_free(kmw->kmw_ubase, slabsize + sizeof (kmem_bufctl_t));
1144 
1145 	mdb_free(kmw->kmw_cp, kmw->kmw_csize);
1146 	mdb_free(kmw, sizeof (kmem_walk_t));
1147 }
1148 
1149 /*ARGSUSED*/
1150 static int
1151 kmem_walk_all(uintptr_t addr, const kmem_cache_t *c, mdb_walk_state_t *wsp)
1152 {
1153 	/*
1154 	 * Buffers allocated from NOTOUCH caches can also show up as freed
1155 	 * memory in other caches.  This can be a little confusing, so we
1156 	 * don't walk NOTOUCH caches when walking all caches (thereby assuring
1157 	 * that "::walk kmem" and "::walk freemem" yield disjoint output).
1158 	 */
1159 	if (c->cache_cflags & KMC_NOTOUCH)
1160 		return (WALK_NEXT);
1161 
1162 	if (mdb_pwalk(wsp->walk_data, wsp->walk_callback,
1163 	    wsp->walk_cbdata, addr) == -1)
1164 		return (WALK_DONE);
1165 
1166 	return (WALK_NEXT);
1167 }
1168 
1169 #define	KMEM_WALK_ALL(name, wsp) { \
1170 	wsp->walk_data = (name); \
1171 	if (mdb_walk("kmem_cache", (mdb_walk_cb_t)kmem_walk_all, wsp) == -1) \
1172 		return (WALK_ERR); \
1173 	return (WALK_DONE); \
1174 }
1175 
1176 int
1177 kmem_walk_init(mdb_walk_state_t *wsp)
1178 {
1179 	if (wsp->walk_arg != NULL)
1180 		wsp->walk_addr = (uintptr_t)wsp->walk_arg;
1181 
1182 	if (wsp->walk_addr == NULL)
1183 		KMEM_WALK_ALL("kmem", wsp);
1184 	return (kmem_walk_init_common(wsp, KM_ALLOCATED));
1185 }
1186 
1187 int
1188 bufctl_walk_init(mdb_walk_state_t *wsp)
1189 {
1190 	if (wsp->walk_addr == NULL)
1191 		KMEM_WALK_ALL("bufctl", wsp);
1192 	return (kmem_walk_init_common(wsp, KM_ALLOCATED | KM_BUFCTL));
1193 }
1194 
1195 int
1196 freemem_walk_init(mdb_walk_state_t *wsp)
1197 {
1198 	if (wsp->walk_addr == NULL)
1199 		KMEM_WALK_ALL("freemem", wsp);
1200 	return (kmem_walk_init_common(wsp, KM_FREE));
1201 }
1202 
1203 int
1204 freemem_constructed_walk_init(mdb_walk_state_t *wsp)
1205 {
1206 	if (wsp->walk_addr == NULL)
1207 		KMEM_WALK_ALL("freemem_constructed", wsp);
1208 	return (kmem_walk_init_common(wsp, KM_FREE | KM_CONSTRUCTED));
1209 }
1210 
1211 int
1212 freectl_walk_init(mdb_walk_state_t *wsp)
1213 {
1214 	if (wsp->walk_addr == NULL)
1215 		KMEM_WALK_ALL("freectl", wsp);
1216 	return (kmem_walk_init_common(wsp, KM_FREE | KM_BUFCTL));
1217 }
1218 
1219 int
1220 freectl_constructed_walk_init(mdb_walk_state_t *wsp)
1221 {
1222 	if (wsp->walk_addr == NULL)
1223 		KMEM_WALK_ALL("freectl_constructed", wsp);
1224 	return (kmem_walk_init_common(wsp,
1225 	    KM_FREE | KM_BUFCTL | KM_CONSTRUCTED));
1226 }
1227 
1228 typedef struct bufctl_history_walk {
1229 	void		*bhw_next;
1230 	kmem_cache_t	*bhw_cache;
1231 	kmem_slab_t	*bhw_slab;
1232 	hrtime_t	bhw_timestamp;
1233 } bufctl_history_walk_t;
1234 
1235 int
1236 bufctl_history_walk_init(mdb_walk_state_t *wsp)
1237 {
1238 	bufctl_history_walk_t *bhw;
1239 	kmem_bufctl_audit_t bc;
1240 	kmem_bufctl_audit_t bcn;
1241 
1242 	if (wsp->walk_addr == NULL) {
1243 		mdb_warn("bufctl_history walk doesn't support global walks\n");
1244 		return (WALK_ERR);
1245 	}
1246 
1247 	if (mdb_vread(&bc, sizeof (bc), wsp->walk_addr) == -1) {
1248 		mdb_warn("unable to read bufctl at %p", wsp->walk_addr);
1249 		return (WALK_ERR);
1250 	}
1251 
1252 	bhw = mdb_zalloc(sizeof (*bhw), UM_SLEEP);
1253 	bhw->bhw_timestamp = 0;
1254 	bhw->bhw_cache = bc.bc_cache;
1255 	bhw->bhw_slab = bc.bc_slab;
1256 
1257 	/*
1258 	 * sometimes the first log entry matches the base bufctl;  in that
1259 	 * case, skip the base bufctl.
1260 	 */
1261 	if (bc.bc_lastlog != NULL &&
1262 	    mdb_vread(&bcn, sizeof (bcn), (uintptr_t)bc.bc_lastlog) != -1 &&
1263 	    bc.bc_addr == bcn.bc_addr &&
1264 	    bc.bc_cache == bcn.bc_cache &&
1265 	    bc.bc_slab == bcn.bc_slab &&
1266 	    bc.bc_timestamp == bcn.bc_timestamp &&
1267 	    bc.bc_thread == bcn.bc_thread)
1268 		bhw->bhw_next = bc.bc_lastlog;
1269 	else
1270 		bhw->bhw_next = (void *)wsp->walk_addr;
1271 
1272 	wsp->walk_addr = (uintptr_t)bc.bc_addr;
1273 	wsp->walk_data = bhw;
1274 
1275 	return (WALK_NEXT);
1276 }
1277 
1278 int
1279 bufctl_history_walk_step(mdb_walk_state_t *wsp)
1280 {
1281 	bufctl_history_walk_t *bhw = wsp->walk_data;
1282 	uintptr_t addr = (uintptr_t)bhw->bhw_next;
1283 	uintptr_t baseaddr = wsp->walk_addr;
1284 	kmem_bufctl_audit_t bc;
1285 
1286 	if (addr == NULL)
1287 		return (WALK_DONE);
1288 
1289 	if (mdb_vread(&bc, sizeof (bc), addr) == -1) {
1290 		mdb_warn("unable to read bufctl at %p", bhw->bhw_next);
1291 		return (WALK_ERR);
1292 	}
1293 
1294 	/*
1295 	 * The bufctl is only valid if the address, cache, and slab are
1296 	 * correct.  We also check that the timestamp is decreasing, to
1297 	 * prevent infinite loops.
1298 	 */
1299 	if ((uintptr_t)bc.bc_addr != baseaddr ||
1300 	    bc.bc_cache != bhw->bhw_cache ||
1301 	    bc.bc_slab != bhw->bhw_slab ||
1302 	    (bhw->bhw_timestamp != 0 && bc.bc_timestamp >= bhw->bhw_timestamp))
1303 		return (WALK_DONE);
1304 
1305 	bhw->bhw_next = bc.bc_lastlog;
1306 	bhw->bhw_timestamp = bc.bc_timestamp;
1307 
1308 	return (wsp->walk_callback(addr, &bc, wsp->walk_cbdata));
1309 }
1310 
1311 void
1312 bufctl_history_walk_fini(mdb_walk_state_t *wsp)
1313 {
1314 	bufctl_history_walk_t *bhw = wsp->walk_data;
1315 
1316 	mdb_free(bhw, sizeof (*bhw));
1317 }
1318 
1319 typedef struct kmem_log_walk {
1320 	kmem_bufctl_audit_t *klw_base;
1321 	kmem_bufctl_audit_t **klw_sorted;
1322 	kmem_log_header_t klw_lh;
1323 	size_t klw_size;
1324 	size_t klw_maxndx;
1325 	size_t klw_ndx;
1326 } kmem_log_walk_t;
1327 
1328 int
1329 kmem_log_walk_init(mdb_walk_state_t *wsp)
1330 {
1331 	uintptr_t lp = wsp->walk_addr;
1332 	kmem_log_walk_t *klw;
1333 	kmem_log_header_t *lhp;
1334 	int maxndx, i, j, k;
1335 
1336 	/*
1337 	 * By default (global walk), walk the kmem_transaction_log.  Otherwise
1338 	 * read the log whose kmem_log_header_t is stored at walk_addr.
1339 	 */
1340 	if (lp == NULL && mdb_readvar(&lp, "kmem_transaction_log") == -1) {
1341 		mdb_warn("failed to read 'kmem_transaction_log'");
1342 		return (WALK_ERR);
1343 	}
1344 
1345 	if (lp == NULL) {
1346 		mdb_warn("log is disabled\n");
1347 		return (WALK_ERR);
1348 	}
1349 
1350 	klw = mdb_zalloc(sizeof (kmem_log_walk_t), UM_SLEEP);
1351 	lhp = &klw->klw_lh;
1352 
1353 	if (mdb_vread(lhp, sizeof (kmem_log_header_t), lp) == -1) {
1354 		mdb_warn("failed to read log header at %p", lp);
1355 		mdb_free(klw, sizeof (kmem_log_walk_t));
1356 		return (WALK_ERR);
1357 	}
1358 
1359 	klw->klw_size = lhp->lh_chunksize * lhp->lh_nchunks;
1360 	klw->klw_base = mdb_alloc(klw->klw_size, UM_SLEEP);
1361 	maxndx = lhp->lh_chunksize / sizeof (kmem_bufctl_audit_t) - 1;
1362 
1363 	if (mdb_vread(klw->klw_base, klw->klw_size,
1364 	    (uintptr_t)lhp->lh_base) == -1) {
1365 		mdb_warn("failed to read log at base %p", lhp->lh_base);
1366 		mdb_free(klw->klw_base, klw->klw_size);
1367 		mdb_free(klw, sizeof (kmem_log_walk_t));
1368 		return (WALK_ERR);
1369 	}
1370 
1371 	klw->klw_sorted = mdb_alloc(maxndx * lhp->lh_nchunks *
1372 	    sizeof (kmem_bufctl_audit_t *), UM_SLEEP);
1373 
1374 	for (i = 0, k = 0; i < lhp->lh_nchunks; i++) {
1375 		kmem_bufctl_audit_t *chunk = (kmem_bufctl_audit_t *)
1376 		    ((uintptr_t)klw->klw_base + i * lhp->lh_chunksize);
1377 
1378 		for (j = 0; j < maxndx; j++)
1379 			klw->klw_sorted[k++] = &chunk[j];
1380 	}
1381 
1382 	qsort(klw->klw_sorted, k, sizeof (kmem_bufctl_audit_t *),
1383 	    (int(*)(const void *, const void *))bufctlcmp);
1384 
1385 	klw->klw_maxndx = k;
1386 	wsp->walk_data = klw;
1387 
1388 	return (WALK_NEXT);
1389 }
1390 
1391 int
1392 kmem_log_walk_step(mdb_walk_state_t *wsp)
1393 {
1394 	kmem_log_walk_t *klw = wsp->walk_data;
1395 	kmem_bufctl_audit_t *bcp;
1396 
1397 	if (klw->klw_ndx == klw->klw_maxndx)
1398 		return (WALK_DONE);
1399 
1400 	bcp = klw->klw_sorted[klw->klw_ndx++];
1401 
1402 	return (wsp->walk_callback((uintptr_t)bcp - (uintptr_t)klw->klw_base +
1403 	    (uintptr_t)klw->klw_lh.lh_base, bcp, wsp->walk_cbdata));
1404 }
1405 
1406 void
1407 kmem_log_walk_fini(mdb_walk_state_t *wsp)
1408 {
1409 	kmem_log_walk_t *klw = wsp->walk_data;
1410 
1411 	mdb_free(klw->klw_base, klw->klw_size);
1412 	mdb_free(klw->klw_sorted, klw->klw_maxndx *
1413 	    sizeof (kmem_bufctl_audit_t *));
1414 	mdb_free(klw, sizeof (kmem_log_walk_t));
1415 }
1416 
1417 typedef struct allocdby_bufctl {
1418 	uintptr_t abb_addr;
1419 	hrtime_t abb_ts;
1420 } allocdby_bufctl_t;
1421 
1422 typedef struct allocdby_walk {
1423 	const char *abw_walk;
1424 	uintptr_t abw_thread;
1425 	size_t abw_nbufs;
1426 	size_t abw_size;
1427 	allocdby_bufctl_t *abw_buf;
1428 	size_t abw_ndx;
1429 } allocdby_walk_t;
1430 
1431 int
1432 allocdby_walk_bufctl(uintptr_t addr, const kmem_bufctl_audit_t *bcp,
1433     allocdby_walk_t *abw)
1434 {
1435 	if ((uintptr_t)bcp->bc_thread != abw->abw_thread)
1436 		return (WALK_NEXT);
1437 
1438 	if (abw->abw_nbufs == abw->abw_size) {
1439 		allocdby_bufctl_t *buf;
1440 		size_t oldsize = sizeof (allocdby_bufctl_t) * abw->abw_size;
1441 
1442 		buf = mdb_zalloc(oldsize << 1, UM_SLEEP);
1443 
1444 		bcopy(abw->abw_buf, buf, oldsize);
1445 		mdb_free(abw->abw_buf, oldsize);
1446 
1447 		abw->abw_size <<= 1;
1448 		abw->abw_buf = buf;
1449 	}
1450 
1451 	abw->abw_buf[abw->abw_nbufs].abb_addr = addr;
1452 	abw->abw_buf[abw->abw_nbufs].abb_ts = bcp->bc_timestamp;
1453 	abw->abw_nbufs++;
1454 
1455 	return (WALK_NEXT);
1456 }
1457 
1458 /*ARGSUSED*/
1459 int
1460 allocdby_walk_cache(uintptr_t addr, const kmem_cache_t *c, allocdby_walk_t *abw)
1461 {
1462 	if (mdb_pwalk(abw->abw_walk, (mdb_walk_cb_t)allocdby_walk_bufctl,
1463 	    abw, addr) == -1) {
1464 		mdb_warn("couldn't walk bufctl for cache %p", addr);
1465 		return (WALK_DONE);
1466 	}
1467 
1468 	return (WALK_NEXT);
1469 }
1470 
1471 static int
1472 allocdby_cmp(const allocdby_bufctl_t *lhs, const allocdby_bufctl_t *rhs)
1473 {
1474 	if (lhs->abb_ts < rhs->abb_ts)
1475 		return (1);
1476 	if (lhs->abb_ts > rhs->abb_ts)
1477 		return (-1);
1478 	return (0);
1479 }
1480 
1481 static int
1482 allocdby_walk_init_common(mdb_walk_state_t *wsp, const char *walk)
1483 {
1484 	allocdby_walk_t *abw;
1485 
1486 	if (wsp->walk_addr == NULL) {
1487 		mdb_warn("allocdby walk doesn't support global walks\n");
1488 		return (WALK_ERR);
1489 	}
1490 
1491 	abw = mdb_zalloc(sizeof (allocdby_walk_t), UM_SLEEP);
1492 
1493 	abw->abw_thread = wsp->walk_addr;
1494 	abw->abw_walk = walk;
1495 	abw->abw_size = 128;	/* something reasonable */
1496 	abw->abw_buf =
1497 	    mdb_zalloc(abw->abw_size * sizeof (allocdby_bufctl_t), UM_SLEEP);
1498 
1499 	wsp->walk_data = abw;
1500 
1501 	if (mdb_walk("kmem_cache",
1502 	    (mdb_walk_cb_t)allocdby_walk_cache, abw) == -1) {
1503 		mdb_warn("couldn't walk kmem_cache");
1504 		allocdby_walk_fini(wsp);
1505 		return (WALK_ERR);
1506 	}
1507 
1508 	qsort(abw->abw_buf, abw->abw_nbufs, sizeof (allocdby_bufctl_t),
1509 	    (int(*)(const void *, const void *))allocdby_cmp);
1510 
1511 	return (WALK_NEXT);
1512 }
1513 
1514 int
1515 allocdby_walk_init(mdb_walk_state_t *wsp)
1516 {
1517 	return (allocdby_walk_init_common(wsp, "bufctl"));
1518 }
1519 
1520 int
1521 freedby_walk_init(mdb_walk_state_t *wsp)
1522 {
1523 	return (allocdby_walk_init_common(wsp, "freectl"));
1524 }
1525 
1526 int
1527 allocdby_walk_step(mdb_walk_state_t *wsp)
1528 {
1529 	allocdby_walk_t *abw = wsp->walk_data;
1530 	kmem_bufctl_audit_t bc;
1531 	uintptr_t addr;
1532 
1533 	if (abw->abw_ndx == abw->abw_nbufs)
1534 		return (WALK_DONE);
1535 
1536 	addr = abw->abw_buf[abw->abw_ndx++].abb_addr;
1537 
1538 	if (mdb_vread(&bc, sizeof (bc), addr) == -1) {
1539 		mdb_warn("couldn't read bufctl at %p", addr);
1540 		return (WALK_DONE);
1541 	}
1542 
1543 	return (wsp->walk_callback(addr, &bc, wsp->walk_cbdata));
1544 }
1545 
1546 void
1547 allocdby_walk_fini(mdb_walk_state_t *wsp)
1548 {
1549 	allocdby_walk_t *abw = wsp->walk_data;
1550 
1551 	mdb_free(abw->abw_buf, sizeof (allocdby_bufctl_t) * abw->abw_size);
1552 	mdb_free(abw, sizeof (allocdby_walk_t));
1553 }
1554 
1555 /*ARGSUSED*/
1556 int
1557 allocdby_walk(uintptr_t addr, const kmem_bufctl_audit_t *bcp, void *ignored)
1558 {
1559 	char c[MDB_SYM_NAMLEN];
1560 	GElf_Sym sym;
1561 	int i;
1562 
1563 	mdb_printf("%0?p %12llx ", addr, bcp->bc_timestamp);
1564 	for (i = 0; i < bcp->bc_depth; i++) {
1565 		if (mdb_lookup_by_addr(bcp->bc_stack[i],
1566 		    MDB_SYM_FUZZY, c, sizeof (c), &sym) == -1)
1567 			continue;
1568 		if (strncmp(c, "kmem_", 5) == 0)
1569 			continue;
1570 		mdb_printf("%s+0x%lx",
1571 		    c, bcp->bc_stack[i] - (uintptr_t)sym.st_value);
1572 		break;
1573 	}
1574 	mdb_printf("\n");
1575 
1576 	return (WALK_NEXT);
1577 }
1578 
1579 static int
1580 allocdby_common(uintptr_t addr, uint_t flags, const char *w)
1581 {
1582 	if (!(flags & DCMD_ADDRSPEC))
1583 		return (DCMD_USAGE);
1584 
1585 	mdb_printf("%-?s %12s %s\n", "BUFCTL", "TIMESTAMP", "CALLER");
1586 
1587 	if (mdb_pwalk(w, (mdb_walk_cb_t)allocdby_walk, NULL, addr) == -1) {
1588 		mdb_warn("can't walk '%s' for %p", w, addr);
1589 		return (DCMD_ERR);
1590 	}
1591 
1592 	return (DCMD_OK);
1593 }
1594 
1595 /*ARGSUSED*/
1596 int
1597 allocdby(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1598 {
1599 	return (allocdby_common(addr, flags, "allocdby"));
1600 }
1601 
1602 /*ARGSUSED*/
1603 int
1604 freedby(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1605 {
1606 	return (allocdby_common(addr, flags, "freedby"));
1607 }
1608 
1609 /*
1610  * Return a string describing the address in relation to the given thread's
1611  * stack.
1612  *
1613  * - If the thread state is TS_FREE, return " (inactive interrupt thread)".
1614  *
1615  * - If the address is above the stack pointer, return an empty string
1616  *   signifying that the address is active.
1617  *
1618  * - If the address is below the stack pointer, and the thread is not on proc,
1619  *   return " (below sp)".
1620  *
1621  * - If the address is below the stack pointer, and the thread is on proc,
1622  *   return " (possibly below sp)".  Depending on context, we may or may not
1623  *   have an accurate t_sp.
1624  */
1625 static const char *
1626 stack_active(const kthread_t *t, uintptr_t addr)
1627 {
1628 	uintptr_t panicstk;
1629 	GElf_Sym sym;
1630 
1631 	if (t->t_state == TS_FREE)
1632 		return (" (inactive interrupt thread)");
1633 
1634 	/*
1635 	 * Check to see if we're on the panic stack.  If so, ignore t_sp, as it
1636 	 * no longer relates to the thread's real stack.
1637 	 */
1638 	if (mdb_lookup_by_name("panic_stack", &sym) == 0) {
1639 		panicstk = (uintptr_t)sym.st_value;
1640 
1641 		if (t->t_sp >= panicstk && t->t_sp < panicstk + PANICSTKSIZE)
1642 			return ("");
1643 	}
1644 
1645 	if (addr >= t->t_sp + STACK_BIAS)
1646 		return ("");
1647 
1648 	if (t->t_state == TS_ONPROC)
1649 		return (" (possibly below sp)");
1650 
1651 	return (" (below sp)");
1652 }
1653 
1654 typedef struct whatis {
1655 	uintptr_t w_addr;
1656 	const kmem_cache_t *w_cache;
1657 	const vmem_t *w_vmem;
1658 	size_t w_slab_align;
1659 	int w_slab_found;
1660 	int w_found;
1661 	int w_kmem_lite_count;
1662 	uint_t w_verbose;
1663 	uint_t w_freemem;
1664 	uint_t w_all;
1665 	uint_t w_bufctl;
1666 	uint_t w_idspace;
1667 } whatis_t;
1668 
1669 static void
1670 whatis_print_kmem(uintptr_t addr, uintptr_t baddr, whatis_t *w)
1671 {
1672 	/* LINTED pointer cast may result in improper alignment */
1673 	uintptr_t btaddr = (uintptr_t)KMEM_BUFTAG(w->w_cache, addr);
1674 	intptr_t stat;
1675 	int count = 0;
1676 	int i;
1677 	pc_t callers[16];
1678 
1679 	if (w->w_cache->cache_flags & KMF_REDZONE) {
1680 		kmem_buftag_t bt;
1681 
1682 		if (mdb_vread(&bt, sizeof (bt), btaddr) == -1)
1683 			goto done;
1684 
1685 		stat = (intptr_t)bt.bt_bufctl ^ bt.bt_bxstat;
1686 
1687 		if (stat != KMEM_BUFTAG_ALLOC && stat != KMEM_BUFTAG_FREE)
1688 			goto done;
1689 
1690 		/*
1691 		 * provide the bufctl ptr if it has useful information
1692 		 */
1693 		if (baddr == 0 && (w->w_cache->cache_flags & KMF_AUDIT))
1694 			baddr = (uintptr_t)bt.bt_bufctl;
1695 
1696 		if (w->w_cache->cache_flags & KMF_LITE) {
1697 			count = w->w_kmem_lite_count;
1698 
1699 			if (count * sizeof (pc_t) > sizeof (callers))
1700 				count = 0;
1701 
1702 			if (count > 0 &&
1703 			    mdb_vread(callers, count * sizeof (pc_t),
1704 			    btaddr +
1705 			    offsetof(kmem_buftag_lite_t, bt_history)) == -1)
1706 				count = 0;
1707 
1708 			/*
1709 			 * skip unused callers
1710 			 */
1711 			while (count > 0 && callers[count - 1] ==
1712 			    (pc_t)KMEM_UNINITIALIZED_PATTERN)
1713 				count--;
1714 		}
1715 	}
1716 
1717 done:
1718 	if (baddr == 0)
1719 		mdb_printf("%p is %p+%p, %s from %s\n",
1720 		    w->w_addr, addr, w->w_addr - addr,
1721 		    w->w_freemem == FALSE ? "allocated" : "freed",
1722 		    w->w_cache->cache_name);
1723 	else
1724 		mdb_printf("%p is %p+%p, bufctl %p %s from %s\n",
1725 		    w->w_addr, addr, w->w_addr - addr, baddr,
1726 		    w->w_freemem == FALSE ? "allocated" : "freed",
1727 		    w->w_cache->cache_name);
1728 
1729 	if (count > 0) {
1730 		mdb_inc_indent(8);
1731 		mdb_printf("recent caller%s: %a%s", (count != 1)? "s":"",
1732 		    callers[0], (count != 1)? ", ":"\n");
1733 		for (i = 1; i < count; i++)
1734 			mdb_printf("%a%s", callers[i],
1735 			    (i + 1 < count)? ", ":"\n");
1736 		mdb_dec_indent(8);
1737 	}
1738 }
1739 
1740 /*ARGSUSED*/
1741 static int
1742 whatis_walk_kmem(uintptr_t addr, void *ignored, whatis_t *w)
1743 {
1744 	if (w->w_addr < addr || w->w_addr >= addr + w->w_cache->cache_bufsize)
1745 		return (WALK_NEXT);
1746 
1747 	whatis_print_kmem(addr, 0, w);
1748 	w->w_found++;
1749 	return (w->w_all == TRUE ? WALK_NEXT : WALK_DONE);
1750 }
1751 
1752 static int
1753 whatis_walk_seg(uintptr_t addr, const vmem_seg_t *vs, whatis_t *w)
1754 {
1755 	if (w->w_addr < vs->vs_start || w->w_addr >= vs->vs_end)
1756 		return (WALK_NEXT);
1757 
1758 	mdb_printf("%p is %p+%p ", w->w_addr,
1759 	    vs->vs_start, w->w_addr - vs->vs_start);
1760 
1761 	/*
1762 	 * Always provide the vmem_seg pointer if it has a stack trace.
1763 	 */
1764 	if (w->w_bufctl == TRUE ||
1765 	    (vs->vs_type == VMEM_ALLOC && vs->vs_depth != 0)) {
1766 		mdb_printf("(vmem_seg %p) ", addr);
1767 	}
1768 
1769 	mdb_printf("%sfrom %s vmem arena\n", w->w_freemem == TRUE ?
1770 	    "freed " : "", w->w_vmem->vm_name);
1771 
1772 	w->w_found++;
1773 	return (w->w_all == TRUE ? WALK_NEXT : WALK_DONE);
1774 }
1775 
1776 static int
1777 whatis_walk_vmem(uintptr_t addr, const vmem_t *vmem, whatis_t *w)
1778 {
1779 	const char *nm = vmem->vm_name;
1780 	w->w_vmem = vmem;
1781 	w->w_freemem = FALSE;
1782 
1783 	if (((vmem->vm_cflags & VMC_IDENTIFIER) != 0) ^ w->w_idspace)
1784 		return (WALK_NEXT);
1785 
1786 	if (w->w_verbose)
1787 		mdb_printf("Searching vmem arena %s...\n", nm);
1788 
1789 	if (mdb_pwalk("vmem_alloc",
1790 	    (mdb_walk_cb_t)whatis_walk_seg, w, addr) == -1) {
1791 		mdb_warn("can't walk vmem seg for %p", addr);
1792 		return (WALK_NEXT);
1793 	}
1794 
1795 	if (w->w_found && w->w_all == FALSE)
1796 		return (WALK_DONE);
1797 
1798 	if (w->w_verbose)
1799 		mdb_printf("Searching vmem arena %s for free virtual...\n", nm);
1800 
1801 	w->w_freemem = TRUE;
1802 
1803 	if (mdb_pwalk("vmem_free",
1804 	    (mdb_walk_cb_t)whatis_walk_seg, w, addr) == -1) {
1805 		mdb_warn("can't walk vmem seg for %p", addr);
1806 		return (WALK_NEXT);
1807 	}
1808 
1809 	return (w->w_found && w->w_all == FALSE ? WALK_DONE : WALK_NEXT);
1810 }
1811 
1812 /*ARGSUSED*/
1813 static int
1814 whatis_walk_bufctl(uintptr_t baddr, const kmem_bufctl_t *bcp, whatis_t *w)
1815 {
1816 	uintptr_t addr;
1817 
1818 	if (bcp == NULL)
1819 		return (WALK_NEXT);
1820 
1821 	addr = (uintptr_t)bcp->bc_addr;
1822 
1823 	if (w->w_addr < addr || w->w_addr >= addr + w->w_cache->cache_bufsize)
1824 		return (WALK_NEXT);
1825 
1826 	whatis_print_kmem(addr, baddr, w);
1827 	w->w_found++;
1828 	return (w->w_all == TRUE ? WALK_NEXT : WALK_DONE);
1829 }
1830 
1831 /*ARGSUSED*/
1832 static int
1833 whatis_walk_slab(uintptr_t saddr, const kmem_slab_t *sp, whatis_t *w)
1834 {
1835 	uintptr_t base = P2ALIGN((uintptr_t)sp->slab_base, w->w_slab_align);
1836 
1837 	if ((w->w_addr - base) >= w->w_cache->cache_slabsize)
1838 		return (WALK_NEXT);
1839 
1840 	w->w_slab_found++;
1841 	return (WALK_DONE);
1842 }
1843 
1844 static int
1845 whatis_walk_cache(uintptr_t addr, const kmem_cache_t *c, whatis_t *w)
1846 {
1847 	char *walk, *freewalk;
1848 	mdb_walk_cb_t func;
1849 	vmem_t *vmp = c->cache_arena;
1850 
1851 	if (((c->cache_flags & VMC_IDENTIFIER) != 0) ^ w->w_idspace)
1852 		return (WALK_NEXT);
1853 
1854 	if (w->w_bufctl == FALSE) {
1855 		walk = "kmem";
1856 		freewalk = "freemem";
1857 		func = (mdb_walk_cb_t)whatis_walk_kmem;
1858 	} else {
1859 		walk = "bufctl";
1860 		freewalk = "freectl";
1861 		func = (mdb_walk_cb_t)whatis_walk_bufctl;
1862 	}
1863 
1864 	w->w_cache = c;
1865 
1866 	if (w->w_verbose)
1867 		mdb_printf("Searching %s's slabs...\n", c->cache_name);
1868 
1869 	/*
1870 	 * Verify that the address is in one of the cache's slabs.  If not,
1871 	 * we can skip the more expensive walkers.  (this is purely a
1872 	 * heuristic -- as long as there are no false-negatives, we'll be fine)
1873 	 *
1874 	 * We try to get the cache's arena's quantum, since to accurately
1875 	 * get the base of a slab, you have to align it to the quantum.  If
1876 	 * it doesn't look sensible, we fall back to not aligning.
1877 	 */
1878 	if (mdb_vread(&w->w_slab_align, sizeof (w->w_slab_align),
1879 	    (uintptr_t)&vmp->vm_quantum) == -1) {
1880 		mdb_warn("unable to read %p->cache_arena->vm_quantum", c);
1881 		w->w_slab_align = 1;
1882 	}
1883 
1884 	if ((c->cache_slabsize < w->w_slab_align) || w->w_slab_align == 0 ||
1885 	    (w->w_slab_align & (w->w_slab_align - 1))) {
1886 		mdb_warn("%p's arena has invalid quantum (0x%p)\n", c,
1887 		    w->w_slab_align);
1888 		w->w_slab_align = 1;
1889 	}
1890 
1891 	w->w_slab_found = 0;
1892 	if (mdb_pwalk("kmem_slab", (mdb_walk_cb_t)whatis_walk_slab, w,
1893 	    addr) == -1) {
1894 		mdb_warn("can't find kmem_slab walker");
1895 		return (WALK_DONE);
1896 	}
1897 	if (w->w_slab_found == 0)
1898 		return (WALK_NEXT);
1899 
1900 	if (c->cache_flags & KMF_LITE) {
1901 		if (mdb_readvar(&w->w_kmem_lite_count,
1902 		    "kmem_lite_count") == -1 || w->w_kmem_lite_count > 16)
1903 			w->w_kmem_lite_count = 0;
1904 	}
1905 
1906 	if (w->w_verbose)
1907 		mdb_printf("Searching %s...\n", c->cache_name);
1908 
1909 	w->w_freemem = FALSE;
1910 
1911 	if (mdb_pwalk(walk, func, w, addr) == -1) {
1912 		mdb_warn("can't find %s walker", walk);
1913 		return (WALK_DONE);
1914 	}
1915 
1916 	if (w->w_found && w->w_all == FALSE)
1917 		return (WALK_DONE);
1918 
1919 	/*
1920 	 * We have searched for allocated memory; now search for freed memory.
1921 	 */
1922 	if (w->w_verbose)
1923 		mdb_printf("Searching %s for free memory...\n", c->cache_name);
1924 
1925 	w->w_freemem = TRUE;
1926 
1927 	if (mdb_pwalk(freewalk, func, w, addr) == -1) {
1928 		mdb_warn("can't find %s walker", freewalk);
1929 		return (WALK_DONE);
1930 	}
1931 
1932 	return (w->w_found && w->w_all == FALSE ? WALK_DONE : WALK_NEXT);
1933 }
1934 
1935 static int
1936 whatis_walk_touch(uintptr_t addr, const kmem_cache_t *c, whatis_t *w)
1937 {
1938 	if (c->cache_cflags & KMC_NOTOUCH)
1939 		return (WALK_NEXT);
1940 
1941 	return (whatis_walk_cache(addr, c, w));
1942 }
1943 
1944 static int
1945 whatis_walk_notouch(uintptr_t addr, const kmem_cache_t *c, whatis_t *w)
1946 {
1947 	if (!(c->cache_cflags & KMC_NOTOUCH))
1948 		return (WALK_NEXT);
1949 
1950 	return (whatis_walk_cache(addr, c, w));
1951 }
1952 
1953 static int
1954 whatis_walk_thread(uintptr_t addr, const kthread_t *t, whatis_t *w)
1955 {
1956 	/*
1957 	 * Often, one calls ::whatis on an address from a thread structure.
1958 	 * We use this opportunity to short circuit this case...
1959 	 */
1960 	if (w->w_addr >= addr && w->w_addr < addr + sizeof (kthread_t)) {
1961 		mdb_printf("%p is %p+%p, allocated as a thread structure\n",
1962 		    w->w_addr, addr, w->w_addr - addr);
1963 		w->w_found++;
1964 		return (w->w_all == TRUE ? WALK_NEXT : WALK_DONE);
1965 	}
1966 
1967 	if (w->w_addr < (uintptr_t)t->t_stkbase ||
1968 	    w->w_addr > (uintptr_t)t->t_stk)
1969 		return (WALK_NEXT);
1970 
1971 	if (t->t_stkbase == NULL)
1972 		return (WALK_NEXT);
1973 
1974 	mdb_printf("%p is in thread %p's stack%s\n", w->w_addr, addr,
1975 	    stack_active(t, w->w_addr));
1976 
1977 	w->w_found++;
1978 	return (w->w_all == TRUE ? WALK_NEXT : WALK_DONE);
1979 }
1980 
1981 static int
1982 whatis_walk_modctl(uintptr_t addr, const struct modctl *m, whatis_t *w)
1983 {
1984 	struct module mod;
1985 	char name[MODMAXNAMELEN], *where;
1986 	char c[MDB_SYM_NAMLEN];
1987 	Shdr shdr;
1988 	GElf_Sym sym;
1989 
1990 	if (m->mod_mp == NULL)
1991 		return (WALK_NEXT);
1992 
1993 	if (mdb_vread(&mod, sizeof (mod), (uintptr_t)m->mod_mp) == -1) {
1994 		mdb_warn("couldn't read modctl %p's module", addr);
1995 		return (WALK_NEXT);
1996 	}
1997 
1998 	if (w->w_addr >= (uintptr_t)mod.text &&
1999 	    w->w_addr < (uintptr_t)mod.text + mod.text_size) {
2000 		where = "text segment";
2001 		goto found;
2002 	}
2003 
2004 	if (w->w_addr >= (uintptr_t)mod.data &&
2005 	    w->w_addr < (uintptr_t)mod.data + mod.data_size) {
2006 		where = "data segment";
2007 		goto found;
2008 	}
2009 
2010 	if (w->w_addr >= (uintptr_t)mod.bss &&
2011 	    w->w_addr < (uintptr_t)mod.bss + mod.bss_size) {
2012 		where = "bss";
2013 		goto found;
2014 	}
2015 
2016 	if (mdb_vread(&shdr, sizeof (shdr), (uintptr_t)mod.symhdr) == -1) {
2017 		mdb_warn("couldn't read symbol header for %p's module", addr);
2018 		return (WALK_NEXT);
2019 	}
2020 
2021 	if (w->w_addr >= (uintptr_t)mod.symtbl && w->w_addr <
2022 	    (uintptr_t)mod.symtbl + (uintptr_t)mod.nsyms * shdr.sh_entsize) {
2023 		where = "symtab";
2024 		goto found;
2025 	}
2026 
2027 	if (w->w_addr >= (uintptr_t)mod.symspace &&
2028 	    w->w_addr < (uintptr_t)mod.symspace + (uintptr_t)mod.symsize) {
2029 		where = "symspace";
2030 		goto found;
2031 	}
2032 
2033 	return (WALK_NEXT);
2034 
2035 found:
2036 	if (mdb_readstr(name, sizeof (name), (uintptr_t)m->mod_modname) == -1)
2037 		(void) mdb_snprintf(name, sizeof (name), "0x%p", addr);
2038 
2039 	mdb_printf("%p is ", w->w_addr);
2040 
2041 	/*
2042 	 * If we found this address in a module, then there's a chance that
2043 	 * it's actually a named symbol.  Try the symbol lookup.
2044 	 */
2045 	if (mdb_lookup_by_addr(w->w_addr, MDB_SYM_FUZZY, c, sizeof (c),
2046 	    &sym) != -1 && w->w_addr >= (uintptr_t)sym.st_value &&
2047 	    w->w_addr < (uintptr_t)sym.st_value + sym.st_size) {
2048 		mdb_printf("%s+%lx ", c, w->w_addr - (uintptr_t)sym.st_value);
2049 	}
2050 
2051 	mdb_printf("in %s's %s\n", name, where);
2052 
2053 	w->w_found++;
2054 	return (w->w_all == TRUE ? WALK_NEXT : WALK_DONE);
2055 }
2056 
2057 /*ARGSUSED*/
2058 static int
2059 whatis_walk_page(uintptr_t addr, const void *ignored, whatis_t *w)
2060 {
2061 	static int machsize = 0;
2062 	mdb_ctf_id_t id;
2063 
2064 	if (machsize == 0) {
2065 		if (mdb_ctf_lookup_by_name("unix`page_t", &id) == 0)
2066 			machsize = mdb_ctf_type_size(id);
2067 		else {
2068 			mdb_warn("could not get size of page_t");
2069 			machsize = sizeof (page_t);
2070 		}
2071 	}
2072 
2073 	if (w->w_addr < addr || w->w_addr >= addr + machsize)
2074 		return (WALK_NEXT);
2075 
2076 	mdb_printf("%p is %p+%p, allocated as a page structure\n",
2077 	    w->w_addr, addr, w->w_addr - addr);
2078 
2079 	w->w_found++;
2080 	return (w->w_all == TRUE ? WALK_NEXT : WALK_DONE);
2081 }
2082 
2083 int
2084 whatis(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2085 {
2086 	whatis_t w;
2087 
2088 	if (!(flags & DCMD_ADDRSPEC))
2089 		return (DCMD_USAGE);
2090 
2091 	w.w_verbose = FALSE;
2092 	w.w_bufctl = FALSE;
2093 	w.w_all = FALSE;
2094 	w.w_idspace = FALSE;
2095 
2096 	if (mdb_getopts(argc, argv,
2097 	    'v', MDB_OPT_SETBITS, TRUE, &w.w_verbose,
2098 	    'a', MDB_OPT_SETBITS, TRUE, &w.w_all,
2099 	    'i', MDB_OPT_SETBITS, TRUE, &w.w_idspace,
2100 	    'b', MDB_OPT_SETBITS, TRUE, &w.w_bufctl, NULL) != argc)
2101 		return (DCMD_USAGE);
2102 
2103 	w.w_addr = addr;
2104 	w.w_found = 0;
2105 
2106 	if (w.w_verbose)
2107 		mdb_printf("Searching modules...\n");
2108 
2109 	if (!w.w_idspace) {
2110 		if (mdb_walk("modctl", (mdb_walk_cb_t)whatis_walk_modctl, &w)
2111 		    == -1) {
2112 			mdb_warn("couldn't find modctl walker");
2113 			return (DCMD_ERR);
2114 		}
2115 
2116 		if (w.w_found && w.w_all == FALSE)
2117 			return (DCMD_OK);
2118 
2119 		/*
2120 		 * Now search all thread stacks.  Yes, this is a little weak; we
2121 		 * can save a lot of work by first checking to see if the
2122 		 * address is in segkp vs. segkmem.  But hey, computers are
2123 		 * fast.
2124 		 */
2125 		if (w.w_verbose)
2126 			mdb_printf("Searching threads...\n");
2127 
2128 		if (mdb_walk("thread", (mdb_walk_cb_t)whatis_walk_thread, &w)
2129 		    == -1) {
2130 			mdb_warn("couldn't find thread walker");
2131 			return (DCMD_ERR);
2132 		}
2133 
2134 		if (w.w_found && w.w_all == FALSE)
2135 			return (DCMD_OK);
2136 
2137 		if (w.w_verbose)
2138 			mdb_printf("Searching page structures...\n");
2139 
2140 		if (mdb_walk("page", (mdb_walk_cb_t)whatis_walk_page, &w)
2141 		    == -1) {
2142 			mdb_warn("couldn't find page walker");
2143 			return (DCMD_ERR);
2144 		}
2145 
2146 		if (w.w_found && w.w_all == FALSE)
2147 			return (DCMD_OK);
2148 	}
2149 
2150 	if (mdb_walk("kmem_cache",
2151 	    (mdb_walk_cb_t)whatis_walk_touch, &w) == -1) {
2152 		mdb_warn("couldn't find kmem_cache walker");
2153 		return (DCMD_ERR);
2154 	}
2155 
2156 	if (w.w_found && w.w_all == FALSE)
2157 		return (DCMD_OK);
2158 
2159 	if (mdb_walk("kmem_cache",
2160 	    (mdb_walk_cb_t)whatis_walk_notouch, &w) == -1) {
2161 		mdb_warn("couldn't find kmem_cache walker");
2162 		return (DCMD_ERR);
2163 	}
2164 
2165 	if (w.w_found && w.w_all == FALSE)
2166 		return (DCMD_OK);
2167 
2168 	if (mdb_walk("vmem_postfix",
2169 	    (mdb_walk_cb_t)whatis_walk_vmem, &w) == -1) {
2170 		mdb_warn("couldn't find vmem_postfix walker");
2171 		return (DCMD_ERR);
2172 	}
2173 
2174 	if (w.w_found == 0)
2175 		mdb_printf("%p is unknown\n", addr);
2176 
2177 	return (DCMD_OK);
2178 }
2179 
2180 void
2181 whatis_help(void)
2182 {
2183 	mdb_printf(
2184 	    "Given a virtual address, attempt to determine where it came\n"
2185 	    "from.\n"
2186 	    "\n"
2187 	    "\t-v\tVerbose output; display caches/arenas/etc as they are\n"
2188 	    "\t\tsearched\n"
2189 	    "\t-a\tFind all possible sources.  Default behavior is to stop at\n"
2190 	    "\t\tthe first (most specific) source.\n"
2191 	    "\t-i\tSearch only identifier arenas and caches.  By default\n"
2192 	    "\t\tthese are ignored.\n"
2193 	    "\t-b\tReport bufctls and vmem_segs for matches in kmem and vmem,\n"
2194 	    "\t\trespectively.  Warning: if the buffer exists, but does not\n"
2195 	    "\t\thave a bufctl, it will not be reported.\n");
2196 }
2197 
2198 typedef struct kmem_log_cpu {
2199 	uintptr_t kmc_low;
2200 	uintptr_t kmc_high;
2201 } kmem_log_cpu_t;
2202 
2203 typedef struct kmem_log_data {
2204 	uintptr_t kmd_addr;
2205 	kmem_log_cpu_t *kmd_cpu;
2206 } kmem_log_data_t;
2207 
2208 int
2209 kmem_log_walk(uintptr_t addr, const kmem_bufctl_audit_t *b,
2210     kmem_log_data_t *kmd)
2211 {
2212 	int i;
2213 	kmem_log_cpu_t *kmc = kmd->kmd_cpu;
2214 	size_t bufsize;
2215 
2216 	for (i = 0; i < NCPU; i++) {
2217 		if (addr >= kmc[i].kmc_low && addr < kmc[i].kmc_high)
2218 			break;
2219 	}
2220 
2221 	if (kmd->kmd_addr) {
2222 		if (b->bc_cache == NULL)
2223 			return (WALK_NEXT);
2224 
2225 		if (mdb_vread(&bufsize, sizeof (bufsize),
2226 		    (uintptr_t)&b->bc_cache->cache_bufsize) == -1) {
2227 			mdb_warn(
2228 			    "failed to read cache_bufsize for cache at %p",
2229 			    b->bc_cache);
2230 			return (WALK_ERR);
2231 		}
2232 
2233 		if (kmd->kmd_addr < (uintptr_t)b->bc_addr ||
2234 		    kmd->kmd_addr >= (uintptr_t)b->bc_addr + bufsize)
2235 			return (WALK_NEXT);
2236 	}
2237 
2238 	if (i == NCPU)
2239 		mdb_printf("   ");
2240 	else
2241 		mdb_printf("%3d", i);
2242 
2243 	mdb_printf(" %0?p %0?p %16llx %0?p\n", addr, b->bc_addr,
2244 	    b->bc_timestamp, b->bc_thread);
2245 
2246 	return (WALK_NEXT);
2247 }
2248 
2249 /*ARGSUSED*/
2250 int
2251 kmem_log(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2252 {
2253 	kmem_log_header_t lh;
2254 	kmem_cpu_log_header_t clh;
2255 	uintptr_t lhp, clhp;
2256 	int ncpus;
2257 	uintptr_t *cpu;
2258 	GElf_Sym sym;
2259 	kmem_log_cpu_t *kmc;
2260 	int i;
2261 	kmem_log_data_t kmd;
2262 	uint_t opt_b = FALSE;
2263 
2264 	if (mdb_getopts(argc, argv,
2265 	    'b', MDB_OPT_SETBITS, TRUE, &opt_b, NULL) != argc)
2266 		return (DCMD_USAGE);
2267 
2268 	if (mdb_readvar(&lhp, "kmem_transaction_log") == -1) {
2269 		mdb_warn("failed to read 'kmem_transaction_log'");
2270 		return (DCMD_ERR);
2271 	}
2272 
2273 	if (lhp == NULL) {
2274 		mdb_warn("no kmem transaction log\n");
2275 		return (DCMD_ERR);
2276 	}
2277 
2278 	mdb_readvar(&ncpus, "ncpus");
2279 
2280 	if (mdb_vread(&lh, sizeof (kmem_log_header_t), lhp) == -1) {
2281 		mdb_warn("failed to read log header at %p", lhp);
2282 		return (DCMD_ERR);
2283 	}
2284 
2285 	clhp = lhp + ((uintptr_t)&lh.lh_cpu[0] - (uintptr_t)&lh);
2286 
2287 	cpu = mdb_alloc(sizeof (uintptr_t) * NCPU, UM_SLEEP | UM_GC);
2288 
2289 	if (mdb_lookup_by_name("cpu", &sym) == -1) {
2290 		mdb_warn("couldn't find 'cpu' array");
2291 		return (DCMD_ERR);
2292 	}
2293 
2294 	if (sym.st_size != NCPU * sizeof (uintptr_t)) {
2295 		mdb_warn("expected 'cpu' to be of size %d; found %d\n",
2296 		    NCPU * sizeof (uintptr_t), sym.st_size);
2297 		return (DCMD_ERR);
2298 	}
2299 
2300 	if (mdb_vread(cpu, sym.st_size, (uintptr_t)sym.st_value) == -1) {
2301 		mdb_warn("failed to read cpu array at %p", sym.st_value);
2302 		return (DCMD_ERR);
2303 	}
2304 
2305 	kmc = mdb_zalloc(sizeof (kmem_log_cpu_t) * NCPU, UM_SLEEP | UM_GC);
2306 	kmd.kmd_addr = NULL;
2307 	kmd.kmd_cpu = kmc;
2308 
2309 	for (i = 0; i < NCPU; i++) {
2310 
2311 		if (cpu[i] == NULL)
2312 			continue;
2313 
2314 		if (mdb_vread(&clh, sizeof (clh), clhp) == -1) {
2315 			mdb_warn("cannot read cpu %d's log header at %p",
2316 			    i, clhp);
2317 			return (DCMD_ERR);
2318 		}
2319 
2320 		kmc[i].kmc_low = clh.clh_chunk * lh.lh_chunksize +
2321 		    (uintptr_t)lh.lh_base;
2322 		kmc[i].kmc_high = (uintptr_t)clh.clh_current;
2323 
2324 		clhp += sizeof (kmem_cpu_log_header_t);
2325 	}
2326 
2327 	mdb_printf("%3s %-?s %-?s %16s %-?s\n", "CPU", "ADDR", "BUFADDR",
2328 	    "TIMESTAMP", "THREAD");
2329 
2330 	/*
2331 	 * If we have been passed an address, print out only log entries
2332 	 * corresponding to that address.  If opt_b is specified, then interpret
2333 	 * the address as a bufctl.
2334 	 */
2335 	if (flags & DCMD_ADDRSPEC) {
2336 		kmem_bufctl_audit_t b;
2337 
2338 		if (opt_b) {
2339 			kmd.kmd_addr = addr;
2340 		} else {
2341 			if (mdb_vread(&b,
2342 			    sizeof (kmem_bufctl_audit_t), addr) == -1) {
2343 				mdb_warn("failed to read bufctl at %p", addr);
2344 				return (DCMD_ERR);
2345 			}
2346 
2347 			(void) kmem_log_walk(addr, &b, &kmd);
2348 
2349 			return (DCMD_OK);
2350 		}
2351 	}
2352 
2353 	if (mdb_walk("kmem_log", (mdb_walk_cb_t)kmem_log_walk, &kmd) == -1) {
2354 		mdb_warn("can't find kmem log walker");
2355 		return (DCMD_ERR);
2356 	}
2357 
2358 	return (DCMD_OK);
2359 }
2360 
2361 typedef struct bufctl_history_cb {
2362 	int		bhc_flags;
2363 	int		bhc_argc;
2364 	const mdb_arg_t	*bhc_argv;
2365 	int		bhc_ret;
2366 } bufctl_history_cb_t;
2367 
2368 /*ARGSUSED*/
2369 static int
2370 bufctl_history_callback(uintptr_t addr, const void *ign, void *arg)
2371 {
2372 	bufctl_history_cb_t *bhc = arg;
2373 
2374 	bhc->bhc_ret =
2375 	    bufctl(addr, bhc->bhc_flags, bhc->bhc_argc, bhc->bhc_argv);
2376 
2377 	bhc->bhc_flags &= ~DCMD_LOOPFIRST;
2378 
2379 	return ((bhc->bhc_ret == DCMD_OK)? WALK_NEXT : WALK_DONE);
2380 }
2381 
2382 void
2383 bufctl_help(void)
2384 {
2385 	mdb_printf("%s\n",
2386 "Display the contents of kmem_bufctl_audit_ts, with optional filtering.\n");
2387 	mdb_dec_indent(2);
2388 	mdb_printf("%<b>OPTIONS%</b>\n");
2389 	mdb_inc_indent(2);
2390 	mdb_printf("%s",
2391 "  -v    Display the full content of the bufctl, including its stack trace\n"
2392 "  -h    retrieve the bufctl's transaction history, if available\n"
2393 "  -a addr\n"
2394 "        filter out bufctls not involving the buffer at addr\n"
2395 "  -c caller\n"
2396 "        filter out bufctls without the function/PC in their stack trace\n"
2397 "  -e earliest\n"
2398 "        filter out bufctls timestamped before earliest\n"
2399 "  -l latest\n"
2400 "        filter out bufctls timestamped after latest\n"
2401 "  -t thread\n"
2402 "        filter out bufctls not involving thread\n");
2403 }
2404 
2405 int
2406 bufctl(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2407 {
2408 	kmem_bufctl_audit_t bc;
2409 	uint_t verbose = FALSE;
2410 	uint_t history = FALSE;
2411 	uint_t in_history = FALSE;
2412 	uintptr_t caller = NULL, thread = NULL;
2413 	uintptr_t laddr, haddr, baddr = NULL;
2414 	hrtime_t earliest = 0, latest = 0;
2415 	int i, depth;
2416 	char c[MDB_SYM_NAMLEN];
2417 	GElf_Sym sym;
2418 
2419 	if (mdb_getopts(argc, argv,
2420 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
2421 	    'h', MDB_OPT_SETBITS, TRUE, &history,
2422 	    'H', MDB_OPT_SETBITS, TRUE, &in_history,		/* internal */
2423 	    'c', MDB_OPT_UINTPTR, &caller,
2424 	    't', MDB_OPT_UINTPTR, &thread,
2425 	    'e', MDB_OPT_UINT64, &earliest,
2426 	    'l', MDB_OPT_UINT64, &latest,
2427 	    'a', MDB_OPT_UINTPTR, &baddr, NULL) != argc)
2428 		return (DCMD_USAGE);
2429 
2430 	if (!(flags & DCMD_ADDRSPEC))
2431 		return (DCMD_USAGE);
2432 
2433 	if (in_history && !history)
2434 		return (DCMD_USAGE);
2435 
2436 	if (history && !in_history) {
2437 		mdb_arg_t *nargv = mdb_zalloc(sizeof (*nargv) * (argc + 1),
2438 		    UM_SLEEP | UM_GC);
2439 		bufctl_history_cb_t bhc;
2440 
2441 		nargv[0].a_type = MDB_TYPE_STRING;
2442 		nargv[0].a_un.a_str = "-H";		/* prevent recursion */
2443 
2444 		for (i = 0; i < argc; i++)
2445 			nargv[i + 1] = argv[i];
2446 
2447 		/*
2448 		 * When in history mode, we treat each element as if it
2449 		 * were in a seperate loop, so that the headers group
2450 		 * bufctls with similar histories.
2451 		 */
2452 		bhc.bhc_flags = flags | DCMD_LOOP | DCMD_LOOPFIRST;
2453 		bhc.bhc_argc = argc + 1;
2454 		bhc.bhc_argv = nargv;
2455 		bhc.bhc_ret = DCMD_OK;
2456 
2457 		if (mdb_pwalk("bufctl_history", bufctl_history_callback, &bhc,
2458 		    addr) == -1) {
2459 			mdb_warn("unable to walk bufctl_history");
2460 			return (DCMD_ERR);
2461 		}
2462 
2463 		if (bhc.bhc_ret == DCMD_OK && !(flags & DCMD_PIPE_OUT))
2464 			mdb_printf("\n");
2465 
2466 		return (bhc.bhc_ret);
2467 	}
2468 
2469 	if (DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) {
2470 		if (verbose) {
2471 			mdb_printf("%16s %16s %16s %16s\n"
2472 			    "%<u>%16s %16s %16s %16s%</u>\n",
2473 			    "ADDR", "BUFADDR", "TIMESTAMP", "THREAD",
2474 			    "", "CACHE", "LASTLOG", "CONTENTS");
2475 		} else {
2476 			mdb_printf("%<u>%-?s %-?s %-12s %-?s %s%</u>\n",
2477 			    "ADDR", "BUFADDR", "TIMESTAMP", "THREAD", "CALLER");
2478 		}
2479 	}
2480 
2481 	if (mdb_vread(&bc, sizeof (bc), addr) == -1) {
2482 		mdb_warn("couldn't read bufctl at %p", addr);
2483 		return (DCMD_ERR);
2484 	}
2485 
2486 	/*
2487 	 * Guard against bogus bc_depth in case the bufctl is corrupt or
2488 	 * the address does not really refer to a bufctl.
2489 	 */
2490 	depth = MIN(bc.bc_depth, KMEM_STACK_DEPTH);
2491 
2492 	if (caller != NULL) {
2493 		laddr = caller;
2494 		haddr = caller + sizeof (caller);
2495 
2496 		if (mdb_lookup_by_addr(caller, MDB_SYM_FUZZY, c, sizeof (c),
2497 		    &sym) != -1 && caller == (uintptr_t)sym.st_value) {
2498 			/*
2499 			 * We were provided an exact symbol value; any
2500 			 * address in the function is valid.
2501 			 */
2502 			laddr = (uintptr_t)sym.st_value;
2503 			haddr = (uintptr_t)sym.st_value + sym.st_size;
2504 		}
2505 
2506 		for (i = 0; i < depth; i++)
2507 			if (bc.bc_stack[i] >= laddr && bc.bc_stack[i] < haddr)
2508 				break;
2509 
2510 		if (i == depth)
2511 			return (DCMD_OK);
2512 	}
2513 
2514 	if (thread != NULL && (uintptr_t)bc.bc_thread != thread)
2515 		return (DCMD_OK);
2516 
2517 	if (earliest != 0 && bc.bc_timestamp < earliest)
2518 		return (DCMD_OK);
2519 
2520 	if (latest != 0 && bc.bc_timestamp > latest)
2521 		return (DCMD_OK);
2522 
2523 	if (baddr != 0 && (uintptr_t)bc.bc_addr != baddr)
2524 		return (DCMD_OK);
2525 
2526 	if (flags & DCMD_PIPE_OUT) {
2527 		mdb_printf("%#lr\n", addr);
2528 		return (DCMD_OK);
2529 	}
2530 
2531 	if (verbose) {
2532 		mdb_printf(
2533 		    "%<b>%16p%</b> %16p %16llx %16p\n"
2534 		    "%16s %16p %16p %16p\n",
2535 		    addr, bc.bc_addr, bc.bc_timestamp, bc.bc_thread,
2536 		    "", bc.bc_cache, bc.bc_lastlog, bc.bc_contents);
2537 
2538 		mdb_inc_indent(17);
2539 		for (i = 0; i < depth; i++)
2540 			mdb_printf("%a\n", bc.bc_stack[i]);
2541 		mdb_dec_indent(17);
2542 		mdb_printf("\n");
2543 	} else {
2544 		mdb_printf("%0?p %0?p %12llx %0?p", addr, bc.bc_addr,
2545 		    bc.bc_timestamp, bc.bc_thread);
2546 
2547 		for (i = 0; i < depth; i++) {
2548 			if (mdb_lookup_by_addr(bc.bc_stack[i],
2549 			    MDB_SYM_FUZZY, c, sizeof (c), &sym) == -1)
2550 				continue;
2551 			if (strncmp(c, "kmem_", 5) == 0)
2552 				continue;
2553 			mdb_printf(" %a\n", bc.bc_stack[i]);
2554 			break;
2555 		}
2556 
2557 		if (i >= depth)
2558 			mdb_printf("\n");
2559 	}
2560 
2561 	return (DCMD_OK);
2562 }
2563 
2564 typedef struct kmem_verify {
2565 	uint64_t *kmv_buf;		/* buffer to read cache contents into */
2566 	size_t kmv_size;		/* number of bytes in kmv_buf */
2567 	int kmv_corruption;		/* > 0 if corruption found. */
2568 	int kmv_besilent;		/* report actual corruption sites */
2569 	struct kmem_cache kmv_cache;	/* the cache we're operating on */
2570 } kmem_verify_t;
2571 
2572 /*
2573  * verify_pattern()
2574  * 	verify that buf is filled with the pattern pat.
2575  */
2576 static int64_t
2577 verify_pattern(uint64_t *buf_arg, size_t size, uint64_t pat)
2578 {
2579 	/*LINTED*/
2580 	uint64_t *bufend = (uint64_t *)((char *)buf_arg + size);
2581 	uint64_t *buf;
2582 
2583 	for (buf = buf_arg; buf < bufend; buf++)
2584 		if (*buf != pat)
2585 			return ((uintptr_t)buf - (uintptr_t)buf_arg);
2586 	return (-1);
2587 }
2588 
2589 /*
2590  * verify_buftag()
2591  *	verify that btp->bt_bxstat == (bcp ^ pat)
2592  */
2593 static int
2594 verify_buftag(kmem_buftag_t *btp, uintptr_t pat)
2595 {
2596 	return (btp->bt_bxstat == ((intptr_t)btp->bt_bufctl ^ pat) ? 0 : -1);
2597 }
2598 
2599 /*
2600  * verify_free()
2601  * 	verify the integrity of a free block of memory by checking
2602  * 	that it is filled with 0xdeadbeef and that its buftag is sane.
2603  */
2604 /*ARGSUSED1*/
2605 static int
2606 verify_free(uintptr_t addr, const void *data, void *private)
2607 {
2608 	kmem_verify_t *kmv = (kmem_verify_t *)private;
2609 	uint64_t *buf = kmv->kmv_buf;	/* buf to validate */
2610 	int64_t corrupt;		/* corruption offset */
2611 	kmem_buftag_t *buftagp;		/* ptr to buftag */
2612 	kmem_cache_t *cp = &kmv->kmv_cache;
2613 	int besilent = kmv->kmv_besilent;
2614 
2615 	/*LINTED*/
2616 	buftagp = KMEM_BUFTAG(cp, buf);
2617 
2618 	/*
2619 	 * Read the buffer to check.
2620 	 */
2621 	if (mdb_vread(buf, kmv->kmv_size, addr) == -1) {
2622 		if (!besilent)
2623 			mdb_warn("couldn't read %p", addr);
2624 		return (WALK_NEXT);
2625 	}
2626 
2627 	if ((corrupt = verify_pattern(buf, cp->cache_verify,
2628 	    KMEM_FREE_PATTERN)) >= 0) {
2629 		if (!besilent)
2630 			mdb_printf("buffer %p (free) seems corrupted, at %p\n",
2631 			    addr, (uintptr_t)addr + corrupt);
2632 		goto corrupt;
2633 	}
2634 	/*
2635 	 * When KMF_LITE is set, buftagp->bt_redzone is used to hold
2636 	 * the first bytes of the buffer, hence we cannot check for red
2637 	 * zone corruption.
2638 	 */
2639 	if ((cp->cache_flags & (KMF_HASH | KMF_LITE)) == KMF_HASH &&
2640 	    buftagp->bt_redzone != KMEM_REDZONE_PATTERN) {
2641 		if (!besilent)
2642 			mdb_printf("buffer %p (free) seems to "
2643 			    "have a corrupt redzone pattern\n", addr);
2644 		goto corrupt;
2645 	}
2646 
2647 	/*
2648 	 * confirm bufctl pointer integrity.
2649 	 */
2650 	if (verify_buftag(buftagp, KMEM_BUFTAG_FREE) == -1) {
2651 		if (!besilent)
2652 			mdb_printf("buffer %p (free) has a corrupt "
2653 			    "buftag\n", addr);
2654 		goto corrupt;
2655 	}
2656 
2657 	return (WALK_NEXT);
2658 corrupt:
2659 	kmv->kmv_corruption++;
2660 	return (WALK_NEXT);
2661 }
2662 
2663 /*
2664  * verify_alloc()
2665  * 	Verify that the buftag of an allocated buffer makes sense with respect
2666  * 	to the buffer.
2667  */
2668 /*ARGSUSED1*/
2669 static int
2670 verify_alloc(uintptr_t addr, const void *data, void *private)
2671 {
2672 	kmem_verify_t *kmv = (kmem_verify_t *)private;
2673 	kmem_cache_t *cp = &kmv->kmv_cache;
2674 	uint64_t *buf = kmv->kmv_buf;	/* buf to validate */
2675 	/*LINTED*/
2676 	kmem_buftag_t *buftagp = KMEM_BUFTAG(cp, buf);
2677 	uint32_t *ip = (uint32_t *)buftagp;
2678 	uint8_t *bp = (uint8_t *)buf;
2679 	int looks_ok = 0, size_ok = 1;	/* flags for finding corruption */
2680 	int besilent = kmv->kmv_besilent;
2681 
2682 	/*
2683 	 * Read the buffer to check.
2684 	 */
2685 	if (mdb_vread(buf, kmv->kmv_size, addr) == -1) {
2686 		if (!besilent)
2687 			mdb_warn("couldn't read %p", addr);
2688 		return (WALK_NEXT);
2689 	}
2690 
2691 	/*
2692 	 * There are two cases to handle:
2693 	 * 1. If the buf was alloc'd using kmem_cache_alloc, it will have
2694 	 *    0xfeedfacefeedface at the end of it
2695 	 * 2. If the buf was alloc'd using kmem_alloc, it will have
2696 	 *    0xbb just past the end of the region in use.  At the buftag,
2697 	 *    it will have 0xfeedface (or, if the whole buffer is in use,
2698 	 *    0xfeedface & bb000000 or 0xfeedfacf & 000000bb depending on
2699 	 *    endianness), followed by 32 bits containing the offset of the
2700 	 *    0xbb byte in the buffer.
2701 	 *
2702 	 * Finally, the two 32-bit words that comprise the second half of the
2703 	 * buftag should xor to KMEM_BUFTAG_ALLOC
2704 	 */
2705 
2706 	if (buftagp->bt_redzone == KMEM_REDZONE_PATTERN)
2707 		looks_ok = 1;
2708 	else if (!KMEM_SIZE_VALID(ip[1]))
2709 		size_ok = 0;
2710 	else if (bp[KMEM_SIZE_DECODE(ip[1])] == KMEM_REDZONE_BYTE)
2711 		looks_ok = 1;
2712 	else
2713 		size_ok = 0;
2714 
2715 	if (!size_ok) {
2716 		if (!besilent)
2717 			mdb_printf("buffer %p (allocated) has a corrupt "
2718 			    "redzone size encoding\n", addr);
2719 		goto corrupt;
2720 	}
2721 
2722 	if (!looks_ok) {
2723 		if (!besilent)
2724 			mdb_printf("buffer %p (allocated) has a corrupt "
2725 			    "redzone signature\n", addr);
2726 		goto corrupt;
2727 	}
2728 
2729 	if (verify_buftag(buftagp, KMEM_BUFTAG_ALLOC) == -1) {
2730 		if (!besilent)
2731 			mdb_printf("buffer %p (allocated) has a "
2732 			    "corrupt buftag\n", addr);
2733 		goto corrupt;
2734 	}
2735 
2736 	return (WALK_NEXT);
2737 corrupt:
2738 	kmv->kmv_corruption++;
2739 	return (WALK_NEXT);
2740 }
2741 
2742 /*ARGSUSED2*/
2743 int
2744 kmem_verify(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2745 {
2746 	if (flags & DCMD_ADDRSPEC) {
2747 		int check_alloc = 0, check_free = 0;
2748 		kmem_verify_t kmv;
2749 
2750 		if (mdb_vread(&kmv.kmv_cache, sizeof (kmv.kmv_cache),
2751 		    addr) == -1) {
2752 			mdb_warn("couldn't read kmem_cache %p", addr);
2753 			return (DCMD_ERR);
2754 		}
2755 
2756 		kmv.kmv_size = kmv.kmv_cache.cache_buftag +
2757 		    sizeof (kmem_buftag_t);
2758 		kmv.kmv_buf = mdb_alloc(kmv.kmv_size, UM_SLEEP | UM_GC);
2759 		kmv.kmv_corruption = 0;
2760 
2761 		if ((kmv.kmv_cache.cache_flags & KMF_REDZONE)) {
2762 			check_alloc = 1;
2763 			if (kmv.kmv_cache.cache_flags & KMF_DEADBEEF)
2764 				check_free = 1;
2765 		} else {
2766 			if (!(flags & DCMD_LOOP)) {
2767 				mdb_warn("cache %p (%s) does not have "
2768 				    "redzone checking enabled\n", addr,
2769 				    kmv.kmv_cache.cache_name);
2770 			}
2771 			return (DCMD_ERR);
2772 		}
2773 
2774 		if (flags & DCMD_LOOP) {
2775 			/*
2776 			 * table mode, don't print out every corrupt buffer
2777 			 */
2778 			kmv.kmv_besilent = 1;
2779 		} else {
2780 			mdb_printf("Summary for cache '%s'\n",
2781 			    kmv.kmv_cache.cache_name);
2782 			mdb_inc_indent(2);
2783 			kmv.kmv_besilent = 0;
2784 		}
2785 
2786 		if (check_alloc)
2787 			(void) mdb_pwalk("kmem", verify_alloc, &kmv, addr);
2788 		if (check_free)
2789 			(void) mdb_pwalk("freemem", verify_free, &kmv, addr);
2790 
2791 		if (flags & DCMD_LOOP) {
2792 			if (kmv.kmv_corruption == 0) {
2793 				mdb_printf("%-*s %?p clean\n",
2794 				    KMEM_CACHE_NAMELEN,
2795 				    kmv.kmv_cache.cache_name, addr);
2796 			} else {
2797 				char *s = "";	/* optional s in "buffer[s]" */
2798 				if (kmv.kmv_corruption > 1)
2799 					s = "s";
2800 
2801 				mdb_printf("%-*s %?p %d corrupt buffer%s\n",
2802 				    KMEM_CACHE_NAMELEN,
2803 				    kmv.kmv_cache.cache_name, addr,
2804 				    kmv.kmv_corruption, s);
2805 			}
2806 		} else {
2807 			/*
2808 			 * This is the more verbose mode, when the user has
2809 			 * type addr::kmem_verify.  If the cache was clean,
2810 			 * nothing will have yet been printed. So say something.
2811 			 */
2812 			if (kmv.kmv_corruption == 0)
2813 				mdb_printf("clean\n");
2814 
2815 			mdb_dec_indent(2);
2816 		}
2817 	} else {
2818 		/*
2819 		 * If the user didn't specify a cache to verify, we'll walk all
2820 		 * kmem_cache's, specifying ourself as a callback for each...
2821 		 * this is the equivalent of '::walk kmem_cache .::kmem_verify'
2822 		 */
2823 		mdb_printf("%<u>%-*s %-?s %-20s%</b>\n", KMEM_CACHE_NAMELEN,
2824 		    "Cache Name", "Addr", "Cache Integrity");
2825 		(void) (mdb_walk_dcmd("kmem_cache", "kmem_verify", 0, NULL));
2826 	}
2827 
2828 	return (DCMD_OK);
2829 }
2830 
2831 typedef struct vmem_node {
2832 	struct vmem_node *vn_next;
2833 	struct vmem_node *vn_parent;
2834 	struct vmem_node *vn_sibling;
2835 	struct vmem_node *vn_children;
2836 	uintptr_t vn_addr;
2837 	int vn_marked;
2838 	vmem_t vn_vmem;
2839 } vmem_node_t;
2840 
2841 typedef struct vmem_walk {
2842 	vmem_node_t *vw_root;
2843 	vmem_node_t *vw_current;
2844 } vmem_walk_t;
2845 
2846 int
2847 vmem_walk_init(mdb_walk_state_t *wsp)
2848 {
2849 	uintptr_t vaddr, paddr;
2850 	vmem_node_t *head = NULL, *root = NULL, *current = NULL, *parent, *vp;
2851 	vmem_walk_t *vw;
2852 
2853 	if (mdb_readvar(&vaddr, "vmem_list") == -1) {
2854 		mdb_warn("couldn't read 'vmem_list'");
2855 		return (WALK_ERR);
2856 	}
2857 
2858 	while (vaddr != NULL) {
2859 		vp = mdb_zalloc(sizeof (vmem_node_t), UM_SLEEP);
2860 		vp->vn_addr = vaddr;
2861 		vp->vn_next = head;
2862 		head = vp;
2863 
2864 		if (vaddr == wsp->walk_addr)
2865 			current = vp;
2866 
2867 		if (mdb_vread(&vp->vn_vmem, sizeof (vmem_t), vaddr) == -1) {
2868 			mdb_warn("couldn't read vmem_t at %p", vaddr);
2869 			goto err;
2870 		}
2871 
2872 		vaddr = (uintptr_t)vp->vn_vmem.vm_next;
2873 	}
2874 
2875 	for (vp = head; vp != NULL; vp = vp->vn_next) {
2876 
2877 		if ((paddr = (uintptr_t)vp->vn_vmem.vm_source) == NULL) {
2878 			vp->vn_sibling = root;
2879 			root = vp;
2880 			continue;
2881 		}
2882 
2883 		for (parent = head; parent != NULL; parent = parent->vn_next) {
2884 			if (parent->vn_addr != paddr)
2885 				continue;
2886 			vp->vn_sibling = parent->vn_children;
2887 			parent->vn_children = vp;
2888 			vp->vn_parent = parent;
2889 			break;
2890 		}
2891 
2892 		if (parent == NULL) {
2893 			mdb_warn("couldn't find %p's parent (%p)\n",
2894 			    vp->vn_addr, paddr);
2895 			goto err;
2896 		}
2897 	}
2898 
2899 	vw = mdb_zalloc(sizeof (vmem_walk_t), UM_SLEEP);
2900 	vw->vw_root = root;
2901 
2902 	if (current != NULL)
2903 		vw->vw_current = current;
2904 	else
2905 		vw->vw_current = root;
2906 
2907 	wsp->walk_data = vw;
2908 	return (WALK_NEXT);
2909 err:
2910 	for (vp = head; head != NULL; vp = head) {
2911 		head = vp->vn_next;
2912 		mdb_free(vp, sizeof (vmem_node_t));
2913 	}
2914 
2915 	return (WALK_ERR);
2916 }
2917 
2918 int
2919 vmem_walk_step(mdb_walk_state_t *wsp)
2920 {
2921 	vmem_walk_t *vw = wsp->walk_data;
2922 	vmem_node_t *vp;
2923 	int rval;
2924 
2925 	if ((vp = vw->vw_current) == NULL)
2926 		return (WALK_DONE);
2927 
2928 	rval = wsp->walk_callback(vp->vn_addr, &vp->vn_vmem, wsp->walk_cbdata);
2929 
2930 	if (vp->vn_children != NULL) {
2931 		vw->vw_current = vp->vn_children;
2932 		return (rval);
2933 	}
2934 
2935 	do {
2936 		vw->vw_current = vp->vn_sibling;
2937 		vp = vp->vn_parent;
2938 	} while (vw->vw_current == NULL && vp != NULL);
2939 
2940 	return (rval);
2941 }
2942 
2943 /*
2944  * The "vmem_postfix" walk walks the vmem arenas in post-fix order; all
2945  * children are visited before their parent.  We perform the postfix walk
2946  * iteratively (rather than recursively) to allow mdb to regain control
2947  * after each callback.
2948  */
2949 int
2950 vmem_postfix_walk_step(mdb_walk_state_t *wsp)
2951 {
2952 	vmem_walk_t *vw = wsp->walk_data;
2953 	vmem_node_t *vp = vw->vw_current;
2954 	int rval;
2955 
2956 	/*
2957 	 * If this node is marked, then we know that we have already visited
2958 	 * all of its children.  If the node has any siblings, they need to
2959 	 * be visited next; otherwise, we need to visit the parent.  Note
2960 	 * that vp->vn_marked will only be zero on the first invocation of
2961 	 * the step function.
2962 	 */
2963 	if (vp->vn_marked) {
2964 		if (vp->vn_sibling != NULL)
2965 			vp = vp->vn_sibling;
2966 		else if (vp->vn_parent != NULL)
2967 			vp = vp->vn_parent;
2968 		else {
2969 			/*
2970 			 * We have neither a parent, nor a sibling, and we
2971 			 * have already been visited; we're done.
2972 			 */
2973 			return (WALK_DONE);
2974 		}
2975 	}
2976 
2977 	/*
2978 	 * Before we visit this node, visit its children.
2979 	 */
2980 	while (vp->vn_children != NULL && !vp->vn_children->vn_marked)
2981 		vp = vp->vn_children;
2982 
2983 	vp->vn_marked = 1;
2984 	vw->vw_current = vp;
2985 	rval = wsp->walk_callback(vp->vn_addr, &vp->vn_vmem, wsp->walk_cbdata);
2986 
2987 	return (rval);
2988 }
2989 
2990 void
2991 vmem_walk_fini(mdb_walk_state_t *wsp)
2992 {
2993 	vmem_walk_t *vw = wsp->walk_data;
2994 	vmem_node_t *root = vw->vw_root;
2995 	int done;
2996 
2997 	if (root == NULL)
2998 		return;
2999 
3000 	if ((vw->vw_root = root->vn_children) != NULL)
3001 		vmem_walk_fini(wsp);
3002 
3003 	vw->vw_root = root->vn_sibling;
3004 	done = (root->vn_sibling == NULL && root->vn_parent == NULL);
3005 	mdb_free(root, sizeof (vmem_node_t));
3006 
3007 	if (done) {
3008 		mdb_free(vw, sizeof (vmem_walk_t));
3009 	} else {
3010 		vmem_walk_fini(wsp);
3011 	}
3012 }
3013 
3014 typedef struct vmem_seg_walk {
3015 	uint8_t vsw_type;
3016 	uintptr_t vsw_start;
3017 	uintptr_t vsw_current;
3018 } vmem_seg_walk_t;
3019 
3020 /*ARGSUSED*/
3021 int
3022 vmem_seg_walk_common_init(mdb_walk_state_t *wsp, uint8_t type, char *name)
3023 {
3024 	vmem_seg_walk_t *vsw;
3025 
3026 	if (wsp->walk_addr == NULL) {
3027 		mdb_warn("vmem_%s does not support global walks\n", name);
3028 		return (WALK_ERR);
3029 	}
3030 
3031 	wsp->walk_data = vsw = mdb_alloc(sizeof (vmem_seg_walk_t), UM_SLEEP);
3032 
3033 	vsw->vsw_type = type;
3034 	vsw->vsw_start = wsp->walk_addr + offsetof(vmem_t, vm_seg0);
3035 	vsw->vsw_current = vsw->vsw_start;
3036 
3037 	return (WALK_NEXT);
3038 }
3039 
3040 /*
3041  * vmem segments can't have type 0 (this should be added to vmem_impl.h).
3042  */
3043 #define	VMEM_NONE	0
3044 
3045 int
3046 vmem_alloc_walk_init(mdb_walk_state_t *wsp)
3047 {
3048 	return (vmem_seg_walk_common_init(wsp, VMEM_ALLOC, "alloc"));
3049 }
3050 
3051 int
3052 vmem_free_walk_init(mdb_walk_state_t *wsp)
3053 {
3054 	return (vmem_seg_walk_common_init(wsp, VMEM_FREE, "free"));
3055 }
3056 
3057 int
3058 vmem_span_walk_init(mdb_walk_state_t *wsp)
3059 {
3060 	return (vmem_seg_walk_common_init(wsp, VMEM_SPAN, "span"));
3061 }
3062 
3063 int
3064 vmem_seg_walk_init(mdb_walk_state_t *wsp)
3065 {
3066 	return (vmem_seg_walk_common_init(wsp, VMEM_NONE, "seg"));
3067 }
3068 
3069 int
3070 vmem_seg_walk_step(mdb_walk_state_t *wsp)
3071 {
3072 	vmem_seg_t seg;
3073 	vmem_seg_walk_t *vsw = wsp->walk_data;
3074 	uintptr_t addr = vsw->vsw_current;
3075 	static size_t seg_size = 0;
3076 	int rval;
3077 
3078 	if (!seg_size) {
3079 		if (mdb_readvar(&seg_size, "vmem_seg_size") == -1) {
3080 			mdb_warn("failed to read 'vmem_seg_size'");
3081 			seg_size = sizeof (vmem_seg_t);
3082 		}
3083 	}
3084 
3085 	if (seg_size < sizeof (seg))
3086 		bzero((caddr_t)&seg + seg_size, sizeof (seg) - seg_size);
3087 
3088 	if (mdb_vread(&seg, seg_size, addr) == -1) {
3089 		mdb_warn("couldn't read vmem_seg at %p", addr);
3090 		return (WALK_ERR);
3091 	}
3092 
3093 	vsw->vsw_current = (uintptr_t)seg.vs_anext;
3094 	if (vsw->vsw_type != VMEM_NONE && seg.vs_type != vsw->vsw_type) {
3095 		rval = WALK_NEXT;
3096 	} else {
3097 		rval = wsp->walk_callback(addr, &seg, wsp->walk_cbdata);
3098 	}
3099 
3100 	if (vsw->vsw_current == vsw->vsw_start)
3101 		return (WALK_DONE);
3102 
3103 	return (rval);
3104 }
3105 
3106 void
3107 vmem_seg_walk_fini(mdb_walk_state_t *wsp)
3108 {
3109 	vmem_seg_walk_t *vsw = wsp->walk_data;
3110 
3111 	mdb_free(vsw, sizeof (vmem_seg_walk_t));
3112 }
3113 
3114 #define	VMEM_NAMEWIDTH	22
3115 
3116 int
3117 vmem(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3118 {
3119 	vmem_t v, parent;
3120 	vmem_kstat_t *vkp = &v.vm_kstat;
3121 	uintptr_t paddr;
3122 	int ident = 0;
3123 	char c[VMEM_NAMEWIDTH];
3124 
3125 	if (!(flags & DCMD_ADDRSPEC)) {
3126 		if (mdb_walk_dcmd("vmem", "vmem", argc, argv) == -1) {
3127 			mdb_warn("can't walk vmem");
3128 			return (DCMD_ERR);
3129 		}
3130 		return (DCMD_OK);
3131 	}
3132 
3133 	if (DCMD_HDRSPEC(flags))
3134 		mdb_printf("%-?s %-*s %10s %12s %9s %5s\n",
3135 		    "ADDR", VMEM_NAMEWIDTH, "NAME", "INUSE",
3136 		    "TOTAL", "SUCCEED", "FAIL");
3137 
3138 	if (mdb_vread(&v, sizeof (v), addr) == -1) {
3139 		mdb_warn("couldn't read vmem at %p", addr);
3140 		return (DCMD_ERR);
3141 	}
3142 
3143 	for (paddr = (uintptr_t)v.vm_source; paddr != NULL; ident += 2) {
3144 		if (mdb_vread(&parent, sizeof (parent), paddr) == -1) {
3145 			mdb_warn("couldn't trace %p's ancestry", addr);
3146 			ident = 0;
3147 			break;
3148 		}
3149 		paddr = (uintptr_t)parent.vm_source;
3150 	}
3151 
3152 	(void) mdb_snprintf(c, VMEM_NAMEWIDTH, "%*s%s", ident, "", v.vm_name);
3153 
3154 	mdb_printf("%0?p %-*s %10llu %12llu %9llu %5llu\n",
3155 	    addr, VMEM_NAMEWIDTH, c,
3156 	    vkp->vk_mem_inuse.value.ui64, vkp->vk_mem_total.value.ui64,
3157 	    vkp->vk_alloc.value.ui64, vkp->vk_fail.value.ui64);
3158 
3159 	return (DCMD_OK);
3160 }
3161 
3162 void
3163 vmem_seg_help(void)
3164 {
3165 	mdb_printf("%s\n",
3166 "Display the contents of vmem_seg_ts, with optional filtering.\n"
3167 "\n"
3168 "A vmem_seg_t represents a range of addresses (or arbitrary numbers),\n"
3169 "representing a single chunk of data.  Only ALLOC segments have debugging\n"
3170 "information.\n");
3171 	mdb_dec_indent(2);
3172 	mdb_printf("%<b>OPTIONS%</b>\n");
3173 	mdb_inc_indent(2);
3174 	mdb_printf("%s",
3175 "  -v    Display the full content of the vmem_seg, including its stack trace\n"
3176 "  -s    report the size of the segment, instead of the end address\n"
3177 "  -c caller\n"
3178 "        filter out segments without the function/PC in their stack trace\n"
3179 "  -e earliest\n"
3180 "        filter out segments timestamped before earliest\n"
3181 "  -l latest\n"
3182 "        filter out segments timestamped after latest\n"
3183 "  -m minsize\n"
3184 "        filer out segments smaller than minsize\n"
3185 "  -M maxsize\n"
3186 "        filer out segments larger than maxsize\n"
3187 "  -t thread\n"
3188 "        filter out segments not involving thread\n"
3189 "  -T type\n"
3190 "        filter out segments not of type 'type'\n"
3191 "        type is one of: ALLOC/FREE/SPAN/ROTOR/WALKER\n");
3192 }
3193 
3194 /*ARGSUSED*/
3195 int
3196 vmem_seg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3197 {
3198 	vmem_seg_t vs;
3199 	pc_t *stk = vs.vs_stack;
3200 	uintptr_t sz;
3201 	uint8_t t;
3202 	const char *type = NULL;
3203 	GElf_Sym sym;
3204 	char c[MDB_SYM_NAMLEN];
3205 	int no_debug;
3206 	int i;
3207 	int depth;
3208 	uintptr_t laddr, haddr;
3209 
3210 	uintptr_t caller = NULL, thread = NULL;
3211 	uintptr_t minsize = 0, maxsize = 0;
3212 
3213 	hrtime_t earliest = 0, latest = 0;
3214 
3215 	uint_t size = 0;
3216 	uint_t verbose = 0;
3217 
3218 	if (!(flags & DCMD_ADDRSPEC))
3219 		return (DCMD_USAGE);
3220 
3221 	if (mdb_getopts(argc, argv,
3222 	    'c', MDB_OPT_UINTPTR, &caller,
3223 	    'e', MDB_OPT_UINT64, &earliest,
3224 	    'l', MDB_OPT_UINT64, &latest,
3225 	    's', MDB_OPT_SETBITS, TRUE, &size,
3226 	    'm', MDB_OPT_UINTPTR, &minsize,
3227 	    'M', MDB_OPT_UINTPTR, &maxsize,
3228 	    't', MDB_OPT_UINTPTR, &thread,
3229 	    'T', MDB_OPT_STR, &type,
3230 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
3231 	    NULL) != argc)
3232 		return (DCMD_USAGE);
3233 
3234 	if (DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) {
3235 		if (verbose) {
3236 			mdb_printf("%16s %4s %16s %16s %16s\n"
3237 			    "%<u>%16s %4s %16s %16s %16s%</u>\n",
3238 			    "ADDR", "TYPE", "START", "END", "SIZE",
3239 			    "", "", "THREAD", "TIMESTAMP", "");
3240 		} else {
3241 			mdb_printf("%?s %4s %?s %?s %s\n", "ADDR", "TYPE",
3242 			    "START", size? "SIZE" : "END", "WHO");
3243 		}
3244 	}
3245 
3246 	if (mdb_vread(&vs, sizeof (vs), addr) == -1) {
3247 		mdb_warn("couldn't read vmem_seg at %p", addr);
3248 		return (DCMD_ERR);
3249 	}
3250 
3251 	if (type != NULL) {
3252 		if (strcmp(type, "ALLC") == 0 || strcmp(type, "ALLOC") == 0)
3253 			t = VMEM_ALLOC;
3254 		else if (strcmp(type, "FREE") == 0)
3255 			t = VMEM_FREE;
3256 		else if (strcmp(type, "SPAN") == 0)
3257 			t = VMEM_SPAN;
3258 		else if (strcmp(type, "ROTR") == 0 ||
3259 		    strcmp(type, "ROTOR") == 0)
3260 			t = VMEM_ROTOR;
3261 		else if (strcmp(type, "WLKR") == 0 ||
3262 		    strcmp(type, "WALKER") == 0)
3263 			t = VMEM_WALKER;
3264 		else {
3265 			mdb_warn("\"%s\" is not a recognized vmem_seg type\n",
3266 			    type);
3267 			return (DCMD_ERR);
3268 		}
3269 
3270 		if (vs.vs_type != t)
3271 			return (DCMD_OK);
3272 	}
3273 
3274 	sz = vs.vs_end - vs.vs_start;
3275 
3276 	if (minsize != 0 && sz < minsize)
3277 		return (DCMD_OK);
3278 
3279 	if (maxsize != 0 && sz > maxsize)
3280 		return (DCMD_OK);
3281 
3282 	t = vs.vs_type;
3283 	depth = vs.vs_depth;
3284 
3285 	/*
3286 	 * debug info, when present, is only accurate for VMEM_ALLOC segments
3287 	 */
3288 	no_debug = (t != VMEM_ALLOC) ||
3289 	    (depth == 0 || depth > VMEM_STACK_DEPTH);
3290 
3291 	if (no_debug) {
3292 		if (caller != NULL || thread != NULL || earliest != 0 ||
3293 		    latest != 0)
3294 			return (DCMD_OK);		/* not enough info */
3295 	} else {
3296 		if (caller != NULL) {
3297 			laddr = caller;
3298 			haddr = caller + sizeof (caller);
3299 
3300 			if (mdb_lookup_by_addr(caller, MDB_SYM_FUZZY, c,
3301 			    sizeof (c), &sym) != -1 &&
3302 			    caller == (uintptr_t)sym.st_value) {
3303 				/*
3304 				 * We were provided an exact symbol value; any
3305 				 * address in the function is valid.
3306 				 */
3307 				laddr = (uintptr_t)sym.st_value;
3308 				haddr = (uintptr_t)sym.st_value + sym.st_size;
3309 			}
3310 
3311 			for (i = 0; i < depth; i++)
3312 				if (vs.vs_stack[i] >= laddr &&
3313 				    vs.vs_stack[i] < haddr)
3314 					break;
3315 
3316 			if (i == depth)
3317 				return (DCMD_OK);
3318 		}
3319 
3320 		if (thread != NULL && (uintptr_t)vs.vs_thread != thread)
3321 			return (DCMD_OK);
3322 
3323 		if (earliest != 0 && vs.vs_timestamp < earliest)
3324 			return (DCMD_OK);
3325 
3326 		if (latest != 0 && vs.vs_timestamp > latest)
3327 			return (DCMD_OK);
3328 	}
3329 
3330 	type = (t == VMEM_ALLOC ? "ALLC" :
3331 	    t == VMEM_FREE ? "FREE" :
3332 	    t == VMEM_SPAN ? "SPAN" :
3333 	    t == VMEM_ROTOR ? "ROTR" :
3334 	    t == VMEM_WALKER ? "WLKR" :
3335 	    "????");
3336 
3337 	if (flags & DCMD_PIPE_OUT) {
3338 		mdb_printf("%#lr\n", addr);
3339 		return (DCMD_OK);
3340 	}
3341 
3342 	if (verbose) {
3343 		mdb_printf("%<b>%16p%</b> %4s %16p %16p %16d\n",
3344 		    addr, type, vs.vs_start, vs.vs_end, sz);
3345 
3346 		if (no_debug)
3347 			return (DCMD_OK);
3348 
3349 		mdb_printf("%16s %4s %16p %16llx\n",
3350 		    "", "", vs.vs_thread, vs.vs_timestamp);
3351 
3352 		mdb_inc_indent(17);
3353 		for (i = 0; i < depth; i++) {
3354 			mdb_printf("%a\n", stk[i]);
3355 		}
3356 		mdb_dec_indent(17);
3357 		mdb_printf("\n");
3358 	} else {
3359 		mdb_printf("%0?p %4s %0?p %0?p", addr, type,
3360 		    vs.vs_start, size? sz : vs.vs_end);
3361 
3362 		if (no_debug) {
3363 			mdb_printf("\n");
3364 			return (DCMD_OK);
3365 		}
3366 
3367 		for (i = 0; i < depth; i++) {
3368 			if (mdb_lookup_by_addr(stk[i], MDB_SYM_FUZZY,
3369 			    c, sizeof (c), &sym) == -1)
3370 				continue;
3371 			if (strncmp(c, "vmem_", 5) == 0)
3372 				continue;
3373 			break;
3374 		}
3375 		mdb_printf(" %a\n", stk[i]);
3376 	}
3377 	return (DCMD_OK);
3378 }
3379 
3380 typedef struct kmalog_data {
3381 	uintptr_t	kma_addr;
3382 	hrtime_t	kma_newest;
3383 } kmalog_data_t;
3384 
3385 /*ARGSUSED*/
3386 static int
3387 showbc(uintptr_t addr, const kmem_bufctl_audit_t *bcp, kmalog_data_t *kma)
3388 {
3389 	char name[KMEM_CACHE_NAMELEN + 1];
3390 	hrtime_t delta;
3391 	int i, depth;
3392 	size_t bufsize;
3393 
3394 	if (bcp->bc_timestamp == 0)
3395 		return (WALK_DONE);
3396 
3397 	if (kma->kma_newest == 0)
3398 		kma->kma_newest = bcp->bc_timestamp;
3399 
3400 	if (kma->kma_addr) {
3401 		if (mdb_vread(&bufsize, sizeof (bufsize),
3402 		    (uintptr_t)&bcp->bc_cache->cache_bufsize) == -1) {
3403 			mdb_warn(
3404 			    "failed to read cache_bufsize for cache at %p",
3405 			    bcp->bc_cache);
3406 			return (WALK_ERR);
3407 		}
3408 
3409 		if (kma->kma_addr < (uintptr_t)bcp->bc_addr ||
3410 		    kma->kma_addr >= (uintptr_t)bcp->bc_addr + bufsize)
3411 			return (WALK_NEXT);
3412 	}
3413 
3414 	delta = kma->kma_newest - bcp->bc_timestamp;
3415 	depth = MIN(bcp->bc_depth, KMEM_STACK_DEPTH);
3416 
3417 	if (mdb_readstr(name, sizeof (name), (uintptr_t)
3418 	    &bcp->bc_cache->cache_name) <= 0)
3419 		(void) mdb_snprintf(name, sizeof (name), "%a", bcp->bc_cache);
3420 
3421 	mdb_printf("\nT-%lld.%09lld  addr=%p  %s\n",
3422 	    delta / NANOSEC, delta % NANOSEC, bcp->bc_addr, name);
3423 
3424 	for (i = 0; i < depth; i++)
3425 		mdb_printf("\t %a\n", bcp->bc_stack[i]);
3426 
3427 	return (WALK_NEXT);
3428 }
3429 
3430 int
3431 kmalog(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3432 {
3433 	const char *logname = "kmem_transaction_log";
3434 	kmalog_data_t kma;
3435 
3436 	if (argc > 1)
3437 		return (DCMD_USAGE);
3438 
3439 	kma.kma_newest = 0;
3440 	if (flags & DCMD_ADDRSPEC)
3441 		kma.kma_addr = addr;
3442 	else
3443 		kma.kma_addr = NULL;
3444 
3445 	if (argc > 0) {
3446 		if (argv->a_type != MDB_TYPE_STRING)
3447 			return (DCMD_USAGE);
3448 		if (strcmp(argv->a_un.a_str, "fail") == 0)
3449 			logname = "kmem_failure_log";
3450 		else if (strcmp(argv->a_un.a_str, "slab") == 0)
3451 			logname = "kmem_slab_log";
3452 		else
3453 			return (DCMD_USAGE);
3454 	}
3455 
3456 	if (mdb_readvar(&addr, logname) == -1) {
3457 		mdb_warn("failed to read %s log header pointer");
3458 		return (DCMD_ERR);
3459 	}
3460 
3461 	if (mdb_pwalk("kmem_log", (mdb_walk_cb_t)showbc, &kma, addr) == -1) {
3462 		mdb_warn("failed to walk kmem log");
3463 		return (DCMD_ERR);
3464 	}
3465 
3466 	return (DCMD_OK);
3467 }
3468 
3469 /*
3470  * As the final lure for die-hard crash(1M) users, we provide ::kmausers here.
3471  * The first piece is a structure which we use to accumulate kmem_cache_t
3472  * addresses of interest.  The kmc_add is used as a callback for the kmem_cache
3473  * walker; we either add all caches, or ones named explicitly as arguments.
3474  */
3475 
3476 typedef struct kmclist {
3477 	const char *kmc_name;			/* Name to match (or NULL) */
3478 	uintptr_t *kmc_caches;			/* List of kmem_cache_t addrs */
3479 	int kmc_nelems;				/* Num entries in kmc_caches */
3480 	int kmc_size;				/* Size of kmc_caches array */
3481 } kmclist_t;
3482 
3483 static int
3484 kmc_add(uintptr_t addr, const kmem_cache_t *cp, kmclist_t *kmc)
3485 {
3486 	void *p;
3487 	int s;
3488 
3489 	if (kmc->kmc_name == NULL ||
3490 	    strcmp(cp->cache_name, kmc->kmc_name) == 0) {
3491 		/*
3492 		 * If we have a match, grow our array (if necessary), and then
3493 		 * add the virtual address of the matching cache to our list.
3494 		 */
3495 		if (kmc->kmc_nelems >= kmc->kmc_size) {
3496 			s = kmc->kmc_size ? kmc->kmc_size * 2 : 256;
3497 			p = mdb_alloc(sizeof (uintptr_t) * s, UM_SLEEP | UM_GC);
3498 
3499 			bcopy(kmc->kmc_caches, p,
3500 			    sizeof (uintptr_t) * kmc->kmc_size);
3501 
3502 			kmc->kmc_caches = p;
3503 			kmc->kmc_size = s;
3504 		}
3505 
3506 		kmc->kmc_caches[kmc->kmc_nelems++] = addr;
3507 		return (kmc->kmc_name ? WALK_DONE : WALK_NEXT);
3508 	}
3509 
3510 	return (WALK_NEXT);
3511 }
3512 
3513 /*
3514  * The second piece of ::kmausers is a hash table of allocations.  Each
3515  * allocation owner is identified by its stack trace and data_size.  We then
3516  * track the total bytes of all such allocations, and the number of allocations
3517  * to report at the end.  Once we have a list of caches, we walk through the
3518  * allocated bufctls of each, and update our hash table accordingly.
3519  */
3520 
3521 typedef struct kmowner {
3522 	struct kmowner *kmo_head;		/* First hash elt in bucket */
3523 	struct kmowner *kmo_next;		/* Next hash elt in chain */
3524 	size_t kmo_signature;			/* Hash table signature */
3525 	uint_t kmo_num;				/* Number of allocations */
3526 	size_t kmo_data_size;			/* Size of each allocation */
3527 	size_t kmo_total_size;			/* Total bytes of allocation */
3528 	int kmo_depth;				/* Depth of stack trace */
3529 	uintptr_t kmo_stack[KMEM_STACK_DEPTH];	/* Stack trace */
3530 } kmowner_t;
3531 
3532 typedef struct kmusers {
3533 	uintptr_t kmu_addr;			/* address of interest */
3534 	const kmem_cache_t *kmu_cache;		/* Current kmem cache */
3535 	kmowner_t *kmu_hash;			/* Hash table of owners */
3536 	int kmu_nelems;				/* Number of entries in use */
3537 	int kmu_size;				/* Total number of entries */
3538 } kmusers_t;
3539 
3540 static void
3541 kmu_add(kmusers_t *kmu, const kmem_bufctl_audit_t *bcp,
3542     size_t size, size_t data_size)
3543 {
3544 	int i, depth = MIN(bcp->bc_depth, KMEM_STACK_DEPTH);
3545 	size_t bucket, signature = data_size;
3546 	kmowner_t *kmo, *kmoend;
3547 
3548 	/*
3549 	 * If the hash table is full, double its size and rehash everything.
3550 	 */
3551 	if (kmu->kmu_nelems >= kmu->kmu_size) {
3552 		int s = kmu->kmu_size ? kmu->kmu_size * 2 : 1024;
3553 
3554 		kmo = mdb_alloc(sizeof (kmowner_t) * s, UM_SLEEP | UM_GC);
3555 		bcopy(kmu->kmu_hash, kmo, sizeof (kmowner_t) * kmu->kmu_size);
3556 		kmu->kmu_hash = kmo;
3557 		kmu->kmu_size = s;
3558 
3559 		kmoend = kmu->kmu_hash + kmu->kmu_size;
3560 		for (kmo = kmu->kmu_hash; kmo < kmoend; kmo++)
3561 			kmo->kmo_head = NULL;
3562 
3563 		kmoend = kmu->kmu_hash + kmu->kmu_nelems;
3564 		for (kmo = kmu->kmu_hash; kmo < kmoend; kmo++) {
3565 			bucket = kmo->kmo_signature & (kmu->kmu_size - 1);
3566 			kmo->kmo_next = kmu->kmu_hash[bucket].kmo_head;
3567 			kmu->kmu_hash[bucket].kmo_head = kmo;
3568 		}
3569 	}
3570 
3571 	/*
3572 	 * Finish computing the hash signature from the stack trace, and then
3573 	 * see if the owner is in the hash table.  If so, update our stats.
3574 	 */
3575 	for (i = 0; i < depth; i++)
3576 		signature += bcp->bc_stack[i];
3577 
3578 	bucket = signature & (kmu->kmu_size - 1);
3579 
3580 	for (kmo = kmu->kmu_hash[bucket].kmo_head; kmo; kmo = kmo->kmo_next) {
3581 		if (kmo->kmo_signature == signature) {
3582 			size_t difference = 0;
3583 
3584 			difference |= kmo->kmo_data_size - data_size;
3585 			difference |= kmo->kmo_depth - depth;
3586 
3587 			for (i = 0; i < depth; i++) {
3588 				difference |= kmo->kmo_stack[i] -
3589 				    bcp->bc_stack[i];
3590 			}
3591 
3592 			if (difference == 0) {
3593 				kmo->kmo_total_size += size;
3594 				kmo->kmo_num++;
3595 				return;
3596 			}
3597 		}
3598 	}
3599 
3600 	/*
3601 	 * If the owner is not yet hashed, grab the next element and fill it
3602 	 * in based on the allocation information.
3603 	 */
3604 	kmo = &kmu->kmu_hash[kmu->kmu_nelems++];
3605 	kmo->kmo_next = kmu->kmu_hash[bucket].kmo_head;
3606 	kmu->kmu_hash[bucket].kmo_head = kmo;
3607 
3608 	kmo->kmo_signature = signature;
3609 	kmo->kmo_num = 1;
3610 	kmo->kmo_data_size = data_size;
3611 	kmo->kmo_total_size = size;
3612 	kmo->kmo_depth = depth;
3613 
3614 	for (i = 0; i < depth; i++)
3615 		kmo->kmo_stack[i] = bcp->bc_stack[i];
3616 }
3617 
3618 /*
3619  * When ::kmausers is invoked without the -f flag, we simply update our hash
3620  * table with the information from each allocated bufctl.
3621  */
3622 /*ARGSUSED*/
3623 static int
3624 kmause1(uintptr_t addr, const kmem_bufctl_audit_t *bcp, kmusers_t *kmu)
3625 {
3626 	const kmem_cache_t *cp = kmu->kmu_cache;
3627 
3628 	kmu_add(kmu, bcp, cp->cache_bufsize, cp->cache_bufsize);
3629 	return (WALK_NEXT);
3630 }
3631 
3632 /*
3633  * When ::kmausers is invoked with the -f flag, we print out the information
3634  * for each bufctl as well as updating the hash table.
3635  */
3636 static int
3637 kmause2(uintptr_t addr, const kmem_bufctl_audit_t *bcp, kmusers_t *kmu)
3638 {
3639 	int i, depth = MIN(bcp->bc_depth, KMEM_STACK_DEPTH);
3640 	const kmem_cache_t *cp = kmu->kmu_cache;
3641 	kmem_bufctl_t bufctl;
3642 
3643 	if (kmu->kmu_addr) {
3644 		if (mdb_vread(&bufctl, sizeof (bufctl),  addr) == -1)
3645 			mdb_warn("couldn't read bufctl at %p", addr);
3646 		else if (kmu->kmu_addr < (uintptr_t)bufctl.bc_addr ||
3647 		    kmu->kmu_addr >= (uintptr_t)bufctl.bc_addr +
3648 		    cp->cache_bufsize)
3649 			return (WALK_NEXT);
3650 	}
3651 
3652 	mdb_printf("size %d, addr %p, thread %p, cache %s\n",
3653 	    cp->cache_bufsize, addr, bcp->bc_thread, cp->cache_name);
3654 
3655 	for (i = 0; i < depth; i++)
3656 		mdb_printf("\t %a\n", bcp->bc_stack[i]);
3657 
3658 	kmu_add(kmu, bcp, cp->cache_bufsize, cp->cache_bufsize);
3659 	return (WALK_NEXT);
3660 }
3661 
3662 /*
3663  * We sort our results by allocation size before printing them.
3664  */
3665 static int
3666 kmownercmp(const void *lp, const void *rp)
3667 {
3668 	const kmowner_t *lhs = lp;
3669 	const kmowner_t *rhs = rp;
3670 
3671 	return (rhs->kmo_total_size - lhs->kmo_total_size);
3672 }
3673 
3674 /*
3675  * The main engine of ::kmausers is relatively straightforward: First we
3676  * accumulate our list of kmem_cache_t addresses into the kmclist_t. Next we
3677  * iterate over the allocated bufctls of each cache in the list.  Finally,
3678  * we sort and print our results.
3679  */
3680 /*ARGSUSED*/
3681 int
3682 kmausers(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3683 {
3684 	int mem_threshold = 8192;	/* Minimum # bytes for printing */
3685 	int cnt_threshold = 100;	/* Minimum # blocks for printing */
3686 	int audited_caches = 0;		/* Number of KMF_AUDIT caches found */
3687 	int do_all_caches = 1;		/* Do all caches (no arguments) */
3688 	int opt_e = FALSE;		/* Include "small" users */
3689 	int opt_f = FALSE;		/* Print stack traces */
3690 
3691 	mdb_walk_cb_t callback = (mdb_walk_cb_t)kmause1;
3692 	kmowner_t *kmo, *kmoend;
3693 	int i, oelems;
3694 
3695 	kmclist_t kmc;
3696 	kmusers_t kmu;
3697 
3698 	bzero(&kmc, sizeof (kmc));
3699 	bzero(&kmu, sizeof (kmu));
3700 
3701 	while ((i = mdb_getopts(argc, argv,
3702 	    'e', MDB_OPT_SETBITS, TRUE, &opt_e,
3703 	    'f', MDB_OPT_SETBITS, TRUE, &opt_f, NULL)) != argc) {
3704 
3705 		argv += i;	/* skip past options we just processed */
3706 		argc -= i;	/* adjust argc */
3707 
3708 		if (argv->a_type != MDB_TYPE_STRING || *argv->a_un.a_str == '-')
3709 			return (DCMD_USAGE);
3710 
3711 		oelems = kmc.kmc_nelems;
3712 		kmc.kmc_name = argv->a_un.a_str;
3713 		(void) mdb_walk("kmem_cache", (mdb_walk_cb_t)kmc_add, &kmc);
3714 
3715 		if (kmc.kmc_nelems == oelems) {
3716 			mdb_warn("unknown kmem cache: %s\n", kmc.kmc_name);
3717 			return (DCMD_ERR);
3718 		}
3719 
3720 		do_all_caches = 0;
3721 		argv++;
3722 		argc--;
3723 	}
3724 
3725 	if (flags & DCMD_ADDRSPEC) {
3726 		opt_f = TRUE;
3727 		kmu.kmu_addr = addr;
3728 	} else {
3729 		kmu.kmu_addr = NULL;
3730 	}
3731 
3732 	if (opt_e)
3733 		mem_threshold = cnt_threshold = 0;
3734 
3735 	if (opt_f)
3736 		callback = (mdb_walk_cb_t)kmause2;
3737 
3738 	if (do_all_caches) {
3739 		kmc.kmc_name = NULL; /* match all cache names */
3740 		(void) mdb_walk("kmem_cache", (mdb_walk_cb_t)kmc_add, &kmc);
3741 	}
3742 
3743 	for (i = 0; i < kmc.kmc_nelems; i++) {
3744 		uintptr_t cp = kmc.kmc_caches[i];
3745 		kmem_cache_t c;
3746 
3747 		if (mdb_vread(&c, sizeof (c), cp) == -1) {
3748 			mdb_warn("failed to read cache at %p", cp);
3749 			continue;
3750 		}
3751 
3752 		if (!(c.cache_flags & KMF_AUDIT)) {
3753 			if (!do_all_caches) {
3754 				mdb_warn("KMF_AUDIT is not enabled for %s\n",
3755 				    c.cache_name);
3756 			}
3757 			continue;
3758 		}
3759 
3760 		kmu.kmu_cache = &c;
3761 		(void) mdb_pwalk("bufctl", callback, &kmu, cp);
3762 		audited_caches++;
3763 	}
3764 
3765 	if (audited_caches == 0 && do_all_caches) {
3766 		mdb_warn("KMF_AUDIT is not enabled for any caches\n");
3767 		return (DCMD_ERR);
3768 	}
3769 
3770 	qsort(kmu.kmu_hash, kmu.kmu_nelems, sizeof (kmowner_t), kmownercmp);
3771 	kmoend = kmu.kmu_hash + kmu.kmu_nelems;
3772 
3773 	for (kmo = kmu.kmu_hash; kmo < kmoend; kmo++) {
3774 		if (kmo->kmo_total_size < mem_threshold &&
3775 		    kmo->kmo_num < cnt_threshold)
3776 			continue;
3777 		mdb_printf("%lu bytes for %u allocations with data size %lu:\n",
3778 		    kmo->kmo_total_size, kmo->kmo_num, kmo->kmo_data_size);
3779 		for (i = 0; i < kmo->kmo_depth; i++)
3780 			mdb_printf("\t %a\n", kmo->kmo_stack[i]);
3781 	}
3782 
3783 	return (DCMD_OK);
3784 }
3785 
3786 void
3787 kmausers_help(void)
3788 {
3789 	mdb_printf(
3790 	    "Displays the largest users of the kmem allocator, sorted by \n"
3791 	    "trace.  If one or more caches is specified, only those caches\n"
3792 	    "will be searched.  By default, all caches are searched.  If an\n"
3793 	    "address is specified, then only those allocations which include\n"
3794 	    "the given address are displayed.  Specifying an address implies\n"
3795 	    "-f.\n"
3796 	    "\n"
3797 	    "\t-e\tInclude all users, not just the largest\n"
3798 	    "\t-f\tDisplay individual allocations.  By default, users are\n"
3799 	    "\t\tgrouped by stack\n");
3800 }
3801 
3802 static int
3803 kmem_ready_check(void)
3804 {
3805 	int ready;
3806 
3807 	if (mdb_readvar(&ready, "kmem_ready") < 0)
3808 		return (-1); /* errno is set for us */
3809 
3810 	return (ready);
3811 }
3812 
3813 /*ARGSUSED*/
3814 static void
3815 kmem_statechange_cb(void *arg)
3816 {
3817 	static int been_ready = 0;
3818 
3819 	leaky_cleanup(1);	/* state changes invalidate leaky state */
3820 
3821 	if (been_ready)
3822 		return;
3823 
3824 	if (kmem_ready_check() <= 0)
3825 		return;
3826 
3827 	been_ready = 1;
3828 	(void) mdb_walk("kmem_cache", (mdb_walk_cb_t)kmem_init_walkers, NULL);
3829 }
3830 
3831 void
3832 kmem_init(void)
3833 {
3834 	mdb_walker_t w = {
3835 		"kmem_cache", "walk list of kmem caches", kmem_cache_walk_init,
3836 		kmem_cache_walk_step, kmem_cache_walk_fini
3837 	};
3838 
3839 	/*
3840 	 * If kmem is ready, we'll need to invoke the kmem_cache walker
3841 	 * immediately.  Walkers in the linkage structure won't be ready until
3842 	 * _mdb_init returns, so we'll need to add this one manually.  If kmem
3843 	 * is ready, we'll use the walker to initialize the caches.  If kmem
3844 	 * isn't ready, we'll register a callback that will allow us to defer
3845 	 * cache walking until it is.
3846 	 */
3847 	if (mdb_add_walker(&w) != 0) {
3848 		mdb_warn("failed to add kmem_cache walker");
3849 		return;
3850 	}
3851 
3852 	(void) mdb_callback_add(MDB_CALLBACK_STCHG, kmem_statechange_cb, NULL);
3853 	kmem_statechange_cb(NULL);
3854 }
3855 
3856 typedef struct whatthread {
3857 	uintptr_t	wt_target;
3858 	int		wt_verbose;
3859 } whatthread_t;
3860 
3861 static int
3862 whatthread_walk_thread(uintptr_t addr, const kthread_t *t, whatthread_t *w)
3863 {
3864 	uintptr_t current, data;
3865 
3866 	if (t->t_stkbase == NULL)
3867 		return (WALK_NEXT);
3868 
3869 	/*
3870 	 * Warn about swapped out threads, but drive on anyway
3871 	 */
3872 	if (!(t->t_schedflag & TS_LOAD)) {
3873 		mdb_warn("thread %p's stack swapped out\n", addr);
3874 		return (WALK_NEXT);
3875 	}
3876 
3877 	/*
3878 	 * Search the thread's stack for the given pointer.  Note that it would
3879 	 * be more efficient to follow ::kgrep's lead and read in page-sized
3880 	 * chunks, but this routine is already fast and simple.
3881 	 */
3882 	for (current = (uintptr_t)t->t_stkbase; current < (uintptr_t)t->t_stk;
3883 	    current += sizeof (uintptr_t)) {
3884 		if (mdb_vread(&data, sizeof (data), current) == -1) {
3885 			mdb_warn("couldn't read thread %p's stack at %p",
3886 			    addr, current);
3887 			return (WALK_ERR);
3888 		}
3889 
3890 		if (data == w->wt_target) {
3891 			if (w->wt_verbose) {
3892 				mdb_printf("%p in thread %p's stack%s\n",
3893 				    current, addr, stack_active(t, current));
3894 			} else {
3895 				mdb_printf("%#lr\n", addr);
3896 				return (WALK_NEXT);
3897 			}
3898 		}
3899 	}
3900 
3901 	return (WALK_NEXT);
3902 }
3903 
3904 int
3905 whatthread(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3906 {
3907 	whatthread_t w;
3908 
3909 	if (!(flags & DCMD_ADDRSPEC))
3910 		return (DCMD_USAGE);
3911 
3912 	w.wt_verbose = FALSE;
3913 	w.wt_target = addr;
3914 
3915 	if (mdb_getopts(argc, argv,
3916 	    'v', MDB_OPT_SETBITS, TRUE, &w.wt_verbose, NULL) != argc)
3917 		return (DCMD_USAGE);
3918 
3919 	if (mdb_walk("thread", (mdb_walk_cb_t)whatthread_walk_thread, &w)
3920 	    == -1) {
3921 		mdb_warn("couldn't walk threads");
3922 		return (DCMD_ERR);
3923 	}
3924 
3925 	return (DCMD_OK);
3926 }
3927