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