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