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 /* 23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright (c) 2013 David Hoeppner. All rights reserved. 25 * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 26 * Copyright (c) 2013, Joyent, Inc. All rights reserved. 27 * Copyright 2016 Garrett D'Amore 28 */ 29 30 /* 31 * Display kernel statistics 32 * 33 * This is a reimplementation of the perl kstat command originally found 34 * under usr/src/cmd/kstat/kstat.pl 35 * 36 * Incompatibilities: 37 * - perl regular expressions replaced with extended REs bracketed by '/' 38 * 39 * Flags added: 40 * -C similar to the -p option but value is separated by a colon 41 * -h display help 42 * -j json format 43 * -H b display hrtime as seconds since boot 44 * -H d display hrtime as date 45 * -H u display hrtime as UNIX seconds (since epoch) 46 * -H I display hrtime as ISO-8601 local time 47 * -H Z display hrtime as ISO-8601 UTC 48 * -H n display hrtime as nanoseconds (since epoch) 49 */ 50 51 #include <assert.h> 52 #include <ctype.h> 53 #include <errno.h> 54 #include <kstat.h> 55 #include <langinfo.h> 56 #include <libgen.h> 57 #include <limits.h> 58 #include <locale.h> 59 #include <signal.h> 60 #include <stddef.h> 61 #include <stdio.h> 62 #include <stdlib.h> 63 #include <string.h> 64 #include <strings.h> 65 #include <time.h> 66 #include <unistd.h> 67 #include <sys/list.h> 68 #include <sys/time.h> 69 #include <sys/types.h> 70 71 #include "kstat.h" 72 #include "statcommon.h" 73 74 char *cmdname = "kstat"; /* Name of this command */ 75 int caught_cont = 0; /* Have caught a SIGCONT */ 76 77 static uint_t g_timestamp_fmt = NODATE; 78 static uint_t g_hrtime_fmt = KS_HRFMT_DEFAULT; 79 80 /* Helper flag - header was printed already? */ 81 static boolean_t g_headerflg; 82 83 /* Saved command line options */ 84 static boolean_t g_cflg = B_FALSE; 85 static boolean_t g_jflg = B_FALSE; 86 static boolean_t g_lflg = B_FALSE; 87 static boolean_t g_pflg = B_FALSE; 88 static boolean_t g_qflg = B_FALSE; 89 static ks_pattern_t g_ks_class = {"*", 0}; 90 91 /* Return zero if a selector did match */ 92 static int g_matched = 1; 93 94 /* Sorted list of kstat instances */ 95 static list_t instances_list; 96 static list_t selector_list; 97 98 static hrtime_t hrtime_origin; 99 100 int 101 main(int argc, char **argv) 102 { 103 ks_selector_t *nselector; 104 ks_selector_t *uselector; 105 kstat_ctl_t *kc; 106 hrtime_t start_n; 107 hrtime_t period_n; 108 boolean_t errflg = B_FALSE; 109 boolean_t nselflg = B_FALSE; 110 boolean_t uselflg = B_FALSE; 111 char *q; 112 int count = 1; 113 int infinite_cycles = 0; 114 int interval = 0; 115 int n = 0; 116 int c, m, tmp; 117 118 (void) setlocale(LC_ALL, ""); 119 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 120 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 121 #endif 122 (void) textdomain(TEXT_DOMAIN); 123 124 /* 125 * Create the selector list and a dummy default selector to match 126 * everything. While we process the cmdline options we will add 127 * selectors to this list. 128 */ 129 list_create(&selector_list, sizeof (ks_selector_t), 130 offsetof(ks_selector_t, ks_next)); 131 132 nselector = new_selector(); 133 134 /* 135 * Parse named command line arguments. 136 */ 137 while ((c = getopt(argc, argv, "h?CqjlpT:m:i:n:s:c:H:")) != EOF) 138 switch (c) { 139 case 'h': 140 case '?': 141 usage(); 142 exit(0); 143 break; 144 case 'C': 145 g_pflg = g_cflg = B_TRUE; 146 break; 147 case 'q': 148 g_qflg = B_TRUE; 149 break; 150 case 'j': 151 g_jflg = B_TRUE; 152 break; 153 case 'l': 154 g_pflg = g_lflg = B_TRUE; 155 break; 156 case 'p': 157 g_pflg = B_TRUE; 158 break; 159 case 'T': 160 if (strlen(optarg) != 1) { 161 errflg = B_TRUE; 162 } 163 switch (*optarg) { 164 case 'd': 165 g_timestamp_fmt = DDATE; 166 break; 167 case 'u': 168 g_timestamp_fmt = UDATE; 169 break; 170 default: 171 errflg = B_TRUE; 172 } 173 break; 174 case 'm': 175 nselflg = B_TRUE; 176 nselector->ks_module.pstr = 177 (char *)ks_safe_strdup(optarg); 178 break; 179 case 'i': 180 nselflg = B_TRUE; 181 nselector->ks_instance.pstr = 182 (char *)ks_safe_strdup(optarg); 183 break; 184 case 'n': 185 nselflg = B_TRUE; 186 nselector->ks_name.pstr = 187 (char *)ks_safe_strdup(optarg); 188 break; 189 case 's': 190 nselflg = B_TRUE; 191 nselector->ks_statistic.pstr = 192 (char *)ks_safe_strdup(optarg); 193 break; 194 case 'c': 195 g_ks_class.pstr = 196 (char *)ks_safe_strdup(optarg); 197 break; 198 case 'H': 199 switch (*optarg) { 200 case 'o': 201 case 'b': 202 case 'n': 203 case 'I': 204 case 'Z': 205 case 'd': 206 case 'u': 207 if (strlen(optarg) != 1) { 208 errflg = B_TRUE; 209 } 210 g_hrtime_fmt = *optarg; 211 break; 212 default: 213 errflg = B_TRUE; 214 break; 215 } 216 break; 217 default: 218 errflg = B_TRUE; 219 break; 220 } 221 222 if (g_qflg && (g_jflg || g_pflg)) { 223 (void) fprintf(stderr, gettext( 224 "-q and -lpj are mutually exclusive\n")); 225 errflg = B_TRUE; 226 } 227 228 switch (g_hrtime_fmt) { 229 case KS_HRFMT_DEFAULT: 230 case KS_HRFMT_BOOT: 231 break; 232 default: { 233 struct timespec ts; 234 if (clock_gettime(CLOCK_REALTIME, &ts) != 0) { 235 perror("clock_gettime(CLOCK_REALTIME)"); 236 exit(3); 237 } 238 hrtime_origin = ts.tv_sec; 239 hrtime_origin *= 1000000000; 240 hrtime_origin += ts.tv_nsec; 241 hrtime_origin -= gethrtime(); 242 } 243 } 244 245 if (errflg) { 246 usage(); 247 exit(2); 248 } 249 250 argc -= optind; 251 argv += optind; 252 253 /* 254 * Consume the rest of the command line. Parsing the 255 * unnamed command line arguments. 256 */ 257 while (argc--) { 258 errno = 0; 259 tmp = strtoul(*argv, &q, 10); 260 if (tmp == ULONG_MAX && errno == ERANGE) { 261 if (n == 0) { 262 (void) fprintf(stderr, gettext( 263 "Interval is too large\n")); 264 } else if (n == 1) { 265 (void) fprintf(stderr, gettext( 266 "Count is too large\n")); 267 } 268 usage(); 269 exit(2); 270 } 271 272 if (errno != 0 || *q != '\0') { 273 m = 0; 274 uselector = new_selector(); 275 while ((q = (char *)strsep(argv, ":")) != NULL) { 276 m++; 277 if (m > 4) { 278 free(uselector); 279 usage(); 280 exit(2); 281 } 282 283 if (*q != '\0') { 284 switch (m) { 285 case 1: 286 uselector->ks_module.pstr = 287 (char *)ks_safe_strdup(q); 288 break; 289 case 2: 290 uselector->ks_instance.pstr = 291 (char *)ks_safe_strdup(q); 292 break; 293 case 3: 294 uselector->ks_name.pstr = 295 (char *)ks_safe_strdup(q); 296 break; 297 case 4: 298 uselector->ks_statistic.pstr = 299 (char *)ks_safe_strdup(q); 300 break; 301 default: 302 assert(B_FALSE); 303 } 304 } 305 } 306 307 uselflg = B_TRUE; 308 list_insert_tail(&selector_list, uselector); 309 } else { 310 if (tmp < 1) { 311 if (n == 0) { 312 (void) fprintf(stderr, gettext( 313 "Interval must be an " 314 "integer >= 1")); 315 } else if (n == 1) { 316 (void) fprintf(stderr, gettext( 317 "Count must be an integer >= 1")); 318 } 319 usage(); 320 exit(2); 321 } else { 322 if (n == 0) { 323 interval = tmp; 324 count = -1; 325 } else if (n == 1) { 326 count = tmp; 327 } else { 328 usage(); 329 exit(2); 330 } 331 } 332 n++; 333 } 334 argv++; 335 } 336 337 /* 338 * Check if we founded a named selector on the cmdline. 339 */ 340 if (uselflg) { 341 if (nselflg) { 342 (void) fprintf(stderr, gettext( 343 "[module[:instance[:name[:statistic]]]] and " 344 "-m -i -n -s are mutually exclusive")); 345 usage(); 346 exit(2); 347 } else { 348 free(nselector); 349 } 350 } else { 351 list_insert_tail(&selector_list, nselector); 352 } 353 354 assert(!list_is_empty(&selector_list)); 355 356 list_create(&instances_list, sizeof (ks_instance_t), 357 offsetof(ks_instance_t, ks_next)); 358 359 while ((kc = kstat_open()) == NULL) { 360 if (errno == EAGAIN) { 361 (void) poll(NULL, 0, 200); 362 } else { 363 perror("kstat_open"); 364 exit(3); 365 } 366 } 367 368 if (count > 1) { 369 if (signal(SIGCONT, cont_handler) == SIG_ERR) { 370 (void) fprintf(stderr, gettext( 371 "signal failed")); 372 exit(3); 373 } 374 } 375 376 period_n = (hrtime_t)interval * NANOSEC; 377 start_n = gethrtime(); 378 379 while (count == -1 || count-- > 0) { 380 ks_instances_read(kc); 381 ks_instances_print(); 382 383 if (interval && count) { 384 ks_sleep_until(&start_n, period_n, infinite_cycles, 385 &caught_cont); 386 (void) kstat_chain_update(kc); 387 (void) putchar('\n'); 388 } 389 } 390 391 (void) kstat_close(kc); 392 393 return (g_matched); 394 } 395 396 /* 397 * Print usage. 398 */ 399 static void 400 usage(void) 401 { 402 (void) fprintf(stderr, gettext( 403 "Usage:\n" 404 "kstat [ -Cjlpq ] [ -T d|u ] [ -H d|n|u|I|Z ] [ -c class ]\n" 405 " [ -m module ] [ -i instance ] [ -n name ] [ -s statistic ]\n" 406 " [ interval [ count ] ]\n" 407 "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ] [ -H d|n|u|I|Z ]\n" 408 " [ module[:instance[:name[:statistic]]] ... ]\n" 409 " [ interval [ count ] ]\n")); 410 } 411 412 /* 413 * Sort compare function. 414 */ 415 static int 416 compare_instances(ks_instance_t *l_arg, ks_instance_t *r_arg) 417 { 418 int rval; 419 420 rval = strcasecmp(l_arg->ks_module, r_arg->ks_module); 421 if (rval == 0) { 422 if (l_arg->ks_instance == r_arg->ks_instance) { 423 return (strcasecmp(l_arg->ks_name, r_arg->ks_name)); 424 } else if (l_arg->ks_instance < r_arg->ks_instance) { 425 return (-1); 426 } else { 427 return (1); 428 } 429 } else { 430 return (rval); 431 } 432 } 433 434 static char * 435 ks_safe_strdup(char *str) 436 { 437 char *ret; 438 439 if (str == NULL) { 440 return (NULL); 441 } 442 443 while ((ret = strdup(str)) == NULL) { 444 if (errno == EAGAIN) { 445 (void) poll(NULL, 0, 200); 446 } else { 447 perror("strdup"); 448 exit(3); 449 } 450 } 451 452 return (ret); 453 } 454 455 static void 456 ks_sleep_until(hrtime_t *wakeup, hrtime_t interval, int forever, 457 int *caught_cont) 458 { 459 hrtime_t now, pause, pause_left; 460 struct timespec pause_tv; 461 int status; 462 463 now = gethrtime(); 464 pause = *wakeup + interval - now; 465 466 if (pause <= 0 || pause < (interval / 4)) { 467 if (forever || *caught_cont) { 468 *wakeup = now + interval; 469 pause = interval; 470 } else { 471 pause = interval / 2; 472 *wakeup += interval; 473 } 474 } else { 475 *wakeup += interval; 476 } 477 478 if (pause < 1000) { 479 return; 480 } 481 482 pause_left = pause; 483 do { 484 pause_tv.tv_sec = pause_left / NANOSEC; 485 pause_tv.tv_nsec = pause_left % NANOSEC; 486 status = nanosleep(&pause_tv, (struct timespec *)NULL); 487 if (status < 0) { 488 if (errno == EINTR) { 489 now = gethrtime(); 490 pause_left = *wakeup - now; 491 if (pause_left < 1000) { 492 return; 493 } 494 } else { 495 perror("nanosleep"); 496 exit(3); 497 } 498 } 499 } while (status != 0); 500 } 501 502 /* 503 * Inserts an instance in the per selector list. 504 */ 505 static void 506 nvpair_insert(ks_instance_t *ksi, char *name, ks_value_t *value, 507 uchar_t data_type) 508 { 509 ks_nvpair_t *instance; 510 ks_nvpair_t *tmp; 511 512 instance = (ks_nvpair_t *)malloc(sizeof (ks_nvpair_t)); 513 if (instance == NULL) { 514 perror("malloc"); 515 exit(3); 516 } 517 518 (void) strlcpy(instance->name, name, KSTAT_STRLEN); 519 (void) memcpy(&instance->value, value, sizeof (ks_value_t)); 520 instance->data_type = data_type; 521 522 tmp = list_head(&ksi->ks_nvlist); 523 while (tmp != NULL && strcasecmp(instance->name, tmp->name) > 0) 524 tmp = list_next(&ksi->ks_nvlist, tmp); 525 526 list_insert_before(&ksi->ks_nvlist, tmp, instance); 527 } 528 529 /* 530 * Allocates a new all-matching selector. 531 */ 532 static ks_selector_t * 533 new_selector(void) 534 { 535 ks_selector_t *selector; 536 537 selector = (ks_selector_t *)malloc(sizeof (ks_selector_t)); 538 if (selector == NULL) { 539 perror("malloc"); 540 exit(3); 541 } 542 543 list_link_init(&selector->ks_next); 544 545 selector->ks_module.pstr = "*"; 546 selector->ks_instance.pstr = "*"; 547 selector->ks_name.pstr = "*"; 548 selector->ks_statistic.pstr = "*"; 549 550 return (selector); 551 } 552 553 /* 554 * This function was taken from the perl kstat module code - please 555 * see for further comments there. 556 */ 557 static kstat_raw_reader_t 558 lookup_raw_kstat_fn(char *module, char *name) 559 { 560 char key[KSTAT_STRLEN * 2]; 561 register char *f, *t; 562 int n = 0; 563 564 for (f = module, t = key; *f != '\0'; f++, t++) { 565 while (*f != '\0' && isdigit(*f)) 566 f++; 567 *t = *f; 568 } 569 *t++ = ':'; 570 571 for (f = name; *f != '\0'; f++, t++) { 572 while (*f != '\0' && isdigit(*f)) 573 f++; 574 *t = *f; 575 } 576 *t = '\0'; 577 578 while (ks_raw_lookup[n].fn != NULL) { 579 if (strncmp(ks_raw_lookup[n].name, key, strlen(key)) == 0) 580 return (ks_raw_lookup[n].fn); 581 n++; 582 } 583 584 return (0); 585 } 586 587 /* 588 * Match a string against a shell glob or extended regular expression. 589 */ 590 static boolean_t 591 ks_match(const char *str, ks_pattern_t *pattern) 592 { 593 int regcode; 594 char *regstr; 595 char *errbuf; 596 size_t bufsz; 597 598 if (pattern->pstr != NULL && gmatch(pattern->pstr, "/*/") != 0) { 599 /* All regex patterns are strdup'd copies */ 600 regstr = pattern->pstr + 1; 601 *(strrchr(regstr, '/')) = '\0'; 602 603 regcode = regcomp(&pattern->preg, regstr, 604 REG_EXTENDED | REG_NOSUB); 605 if (regcode != 0) { 606 bufsz = regerror(regcode, NULL, NULL, 0); 607 if (bufsz != 0) { 608 errbuf = malloc(bufsz); 609 if (errbuf == NULL) { 610 perror("malloc"); 611 exit(3); 612 } 613 (void) regerror(regcode, NULL, errbuf, bufsz); 614 (void) fprintf(stderr, "kstat: %s\n", errbuf); 615 } 616 usage(); 617 exit(2); 618 } 619 620 pattern->pstr = NULL; 621 } 622 623 if (pattern->pstr == NULL) { 624 return (regexec(&pattern->preg, str, 0, NULL, 0) == 0); 625 } 626 627 return ((gmatch(str, pattern->pstr) != 0)); 628 } 629 630 /* 631 * Iterate over all kernel statistics and save matches. 632 */ 633 static void 634 ks_instances_read(kstat_ctl_t *kc) 635 { 636 kstat_raw_reader_t save_raw = NULL; 637 kid_t id; 638 ks_selector_t *selector; 639 ks_instance_t *ksi; 640 ks_instance_t *tmp; 641 kstat_t *kp; 642 boolean_t skip; 643 644 for (kp = kc->kc_chain; kp != NULL; kp = kp->ks_next) { 645 /* Don't bother storing the kstat headers */ 646 if (strncmp(kp->ks_name, "kstat_", 6) == 0) { 647 continue; 648 } 649 650 /* Don't bother storing raw stats we don't understand */ 651 if (kp->ks_type == KSTAT_TYPE_RAW) { 652 save_raw = lookup_raw_kstat_fn(kp->ks_module, 653 kp->ks_name); 654 if (save_raw == NULL) { 655 #ifdef REPORT_UNKNOWN 656 (void) fprintf(stderr, 657 "Unknown kstat type %s:%d:%s - " 658 "%d of size %d\n", kp->ks_module, 659 kp->ks_instance, kp->ks_name, 660 kp->ks_ndata, kp->ks_data_size); 661 #endif 662 continue; 663 } 664 } 665 666 /* 667 * Iterate over the list of selectors and skip 668 * instances we dont want. We filter for statistics 669 * later, as we dont know them yet. 670 */ 671 skip = B_TRUE; 672 selector = list_head(&selector_list); 673 while (selector != NULL) { 674 if (ks_match(kp->ks_module, &selector->ks_module) && 675 ks_match(kp->ks_name, &selector->ks_name)) { 676 skip = B_FALSE; 677 break; 678 } 679 selector = list_next(&selector_list, selector); 680 } 681 682 if (skip) { 683 continue; 684 } 685 686 /* 687 * Allocate a new instance and fill in the values 688 * we know so far. 689 */ 690 ksi = (ks_instance_t *)malloc(sizeof (ks_instance_t)); 691 if (ksi == NULL) { 692 perror("malloc"); 693 exit(3); 694 } 695 696 list_link_init(&ksi->ks_next); 697 698 (void) strlcpy(ksi->ks_module, kp->ks_module, KSTAT_STRLEN); 699 (void) strlcpy(ksi->ks_name, kp->ks_name, KSTAT_STRLEN); 700 (void) strlcpy(ksi->ks_class, kp->ks_class, KSTAT_STRLEN); 701 702 ksi->ks_instance = kp->ks_instance; 703 ksi->ks_snaptime = kp->ks_snaptime; 704 ksi->ks_type = kp->ks_type; 705 706 list_create(&ksi->ks_nvlist, sizeof (ks_nvpair_t), 707 offsetof(ks_nvpair_t, nv_next)); 708 709 SAVE_HRTIME_X(ksi, "crtime", kp->ks_crtime); 710 SAVE_HRTIME_X(ksi, "snaptime", kp->ks_snaptime); 711 if (g_pflg) { 712 SAVE_STRING_X(ksi, "class", kp->ks_class); 713 } 714 715 /* Insert this instance into a sorted list */ 716 tmp = list_head(&instances_list); 717 while (tmp != NULL && compare_instances(ksi, tmp) > 0) 718 tmp = list_next(&instances_list, tmp); 719 720 list_insert_before(&instances_list, tmp, ksi); 721 722 /* Read the actual statistics */ 723 id = kstat_read(kc, kp, NULL); 724 if (id == -1) { 725 #ifdef REPORT_UNKNOWN 726 perror("kstat_read"); 727 #endif 728 continue; 729 } 730 731 switch (kp->ks_type) { 732 case KSTAT_TYPE_RAW: 733 save_raw(kp, ksi); 734 break; 735 case KSTAT_TYPE_NAMED: 736 save_named(kp, ksi); 737 break; 738 case KSTAT_TYPE_INTR: 739 save_intr(kp, ksi); 740 break; 741 case KSTAT_TYPE_IO: 742 save_io(kp, ksi); 743 break; 744 case KSTAT_TYPE_TIMER: 745 save_timer(kp, ksi); 746 break; 747 default: 748 assert(B_FALSE); /* Invalid type */ 749 break; 750 } 751 } 752 } 753 754 /* 755 * Print the value of a name-value pair. 756 */ 757 static void 758 ks_value_print(ks_nvpair_t *nvpair) 759 { 760 char dstr[64]; 761 char zstr[8]; 762 time_t t; 763 764 switch (nvpair->data_type) { 765 case KSTAT_DATA_CHAR: 766 (void) fprintf(stdout, "%s", nvpair->value.c); 767 break; 768 case KSTAT_DATA_INT32: 769 (void) fprintf(stdout, "%d", nvpair->value.i32); 770 break; 771 case KSTAT_DATA_UINT32: 772 (void) fprintf(stdout, "%u", nvpair->value.ui32); 773 break; 774 case KSTAT_DATA_INT64: 775 (void) fprintf(stdout, "%lld", nvpair->value.i64); 776 break; 777 case KSTAT_DATA_UINT64: 778 (void) fprintf(stdout, "%llu", nvpair->value.ui64); 779 break; 780 case KSTAT_DATA_STRING: 781 (void) fprintf(stdout, "%s", KSTAT_NAMED_STR_PTR(nvpair)); 782 break; 783 case KSTAT_DATA_TIME: 784 switch (g_hrtime_fmt) { 785 case KS_HRFMT_UNIX: 786 (void) fprintf(stdout, "%.9f", 787 (nvpair->value.t + hrtime_origin) / 1000000000.0); 788 break; 789 case KS_HRFMT_NANO: 790 (void) fprintf(stdout, "%llu", 791 (nvpair->value.t + hrtime_origin)); 792 break; 793 case KS_HRFMT_DATE: 794 t = (time_t) 795 ((nvpair->value.t + hrtime_origin) / 1000000000); 796 (void) strftime(dstr, 797 sizeof (dstr), "%+", localtime(&t)); 798 (void) fprintf(stdout, "%s", dstr); 799 break; 800 case KS_HRFMT_ZISO: 801 t = (time_t) 802 ((nvpair->value.t + hrtime_origin) / 1000000000); 803 (void) strftime(dstr, sizeof (dstr), "%FT%T", 804 gmtime(&t)); 805 (void) fprintf(stdout, "%s.%06uZ", dstr, 806 (unsigned)(nvpair->value.t % 1000000000)/1000); 807 break; 808 case KS_HRFMT_ISO: 809 t = (time_t) 810 ((nvpair->value.t + hrtime_origin) / 1000000000); 811 (void) strftime(dstr, sizeof (dstr), "%FT%T", 812 localtime(&t)); 813 (void) strftime(zstr, sizeof (zstr), "%z", 814 localtime(&t)); 815 (void) fprintf(stdout, "%s.%06u%s", dstr, 816 (unsigned)(nvpair->value.t % 1000000000)/1000, 817 zstr); 818 break; 819 case KS_HRFMT_DEFAULT: 820 case KS_HRFMT_BOOT: 821 if (nvpair->value.ui64 == 0) 822 (void) fprintf(stdout, "0"); 823 else 824 (void) fprintf(stdout, "%.9f", 825 nvpair->value.ui64 / 1000000000.0); 826 break; 827 default: 828 abort(); 829 } 830 break; 831 default: 832 assert(B_FALSE); 833 } 834 } 835 836 /* 837 * Print a single instance. 838 */ 839 static void 840 ks_instance_print(ks_instance_t *ksi, ks_nvpair_t *nvpair) 841 { 842 if (g_headerflg) { 843 if (!g_pflg) { 844 (void) fprintf(stdout, DFLT_FMT, 845 ksi->ks_module, ksi->ks_instance, 846 ksi->ks_name, ksi->ks_class); 847 } 848 g_headerflg = B_FALSE; 849 } 850 851 if (g_pflg) { 852 (void) fprintf(stdout, KS_PFMT, 853 ksi->ks_module, ksi->ks_instance, 854 ksi->ks_name, nvpair->name); 855 if (!g_lflg) { 856 (void) putchar(g_cflg ? ':': '\t'); 857 ks_value_print(nvpair); 858 } 859 } else { 860 (void) fprintf(stdout, KS_DFMT, nvpair->name); 861 ks_value_print(nvpair); 862 } 863 864 (void) putchar('\n'); 865 } 866 867 /* 868 * Print a single instance in JSON format. 869 */ 870 static void 871 ks_instance_print_json(ks_instance_t *ksi, ks_nvpair_t *nvpair) 872 { 873 if (g_headerflg) { 874 (void) fprintf(stdout, JSON_FMT, 875 ksi->ks_module, ksi->ks_instance, 876 ksi->ks_name, ksi->ks_class, 877 ksi->ks_type); 878 879 if (ksi->ks_snaptime == 0) 880 (void) fprintf(stdout, "\t\"snaptime\": 0,\n"); 881 else 882 (void) fprintf(stdout, "\t\"snaptime\": %.9f,\n", 883 ksi->ks_snaptime / 1000000000.0); 884 885 (void) fprintf(stdout, "\t\"data\": {\n"); 886 887 g_headerflg = B_FALSE; 888 } 889 890 (void) fprintf(stdout, KS_JFMT, nvpair->name); 891 if (nvpair->data_type == KSTAT_DATA_STRING) { 892 (void) putchar('\"'); 893 ks_value_print(nvpair); 894 (void) putchar('\"'); 895 } else if (nvpair->data_type == KSTAT_DATA_TIME) { 896 switch (g_hrtime_fmt) { 897 case KS_HRFMT_ISO: 898 case KS_HRFMT_ZISO: 899 case KS_HRFMT_DATE: 900 (void) putchar('\"'); 901 ks_value_print(nvpair); 902 (void) putchar('\"'); 903 break; 904 default: 905 ks_value_print(nvpair); 906 } 907 } else { 908 ks_value_print(nvpair); 909 } 910 if (nvpair != list_tail(&ksi->ks_nvlist)) 911 (void) putchar(','); 912 913 (void) putchar('\n'); 914 } 915 916 /* 917 * Print all instances. 918 */ 919 static void 920 ks_instances_print(void) 921 { 922 ks_selector_t *selector; 923 ks_instance_t *ksi, *ktmp; 924 ks_nvpair_t *nvpair, *ntmp; 925 void (*ks_print_fn)(ks_instance_t *, ks_nvpair_t *); 926 char *ks_number; 927 928 if (g_timestamp_fmt != NODATE) 929 print_timestamp(g_timestamp_fmt); 930 931 if (g_jflg) { 932 ks_print_fn = &ks_instance_print_json; 933 (void) putchar('['); 934 } else { 935 ks_print_fn = &ks_instance_print; 936 } 937 938 /* Iterate over each selector */ 939 selector = list_head(&selector_list); 940 while (selector != NULL) { 941 942 /* Iterate over each instance */ 943 for (ksi = list_head(&instances_list); ksi != NULL; 944 ksi = list_next(&instances_list, ksi)) { 945 946 (void) asprintf(&ks_number, "%d", ksi->ks_instance); 947 if (!(ks_match(ksi->ks_module, &selector->ks_module) && 948 ks_match(ksi->ks_name, &selector->ks_name) && 949 ks_match(ks_number, &selector->ks_instance) && 950 ks_match(ksi->ks_class, &g_ks_class))) { 951 free(ks_number); 952 continue; 953 } 954 955 free(ks_number); 956 957 /* Finally iterate over each statistic */ 958 g_headerflg = B_TRUE; 959 for (nvpair = list_head(&ksi->ks_nvlist); 960 nvpair != NULL; 961 nvpair = list_next(&ksi->ks_nvlist, nvpair)) { 962 if (!ks_match(nvpair->name, 963 &selector->ks_statistic)) 964 continue; 965 966 g_matched = 0; 967 if (!g_qflg) 968 (*ks_print_fn)(ksi, nvpair); 969 } 970 971 if (!g_headerflg) { 972 if (g_jflg) { 973 (void) fprintf(stdout, "\t}\n}"); 974 if (ksi != list_tail(&instances_list)) 975 (void) putchar(','); 976 } else if (!g_pflg) { 977 (void) putchar('\n'); 978 } 979 } 980 } 981 982 selector = list_next(&selector_list, selector); 983 } 984 985 if (g_jflg) 986 (void) fprintf(stdout, "]\n"); 987 988 (void) fflush(stdout); 989 990 /* Free the instances list */ 991 ksi = list_head(&instances_list); 992 while (ksi != NULL) { 993 nvpair = list_head(&ksi->ks_nvlist); 994 while (nvpair != NULL) { 995 ntmp = nvpair; 996 nvpair = list_next(&ksi->ks_nvlist, nvpair); 997 list_remove(&ksi->ks_nvlist, ntmp); 998 if (ntmp->data_type == KSTAT_DATA_STRING) 999 free(ntmp->value.str.addr.ptr); 1000 free(ntmp); 1001 } 1002 1003 ktmp = ksi; 1004 ksi = list_next(&instances_list, ksi); 1005 list_remove(&instances_list, ktmp); 1006 list_destroy(&ktmp->ks_nvlist); 1007 free(ktmp); 1008 } 1009 } 1010 1011 static void 1012 save_cpu_stat(kstat_t *kp, ks_instance_t *ksi) 1013 { 1014 cpu_stat_t *stat; 1015 cpu_sysinfo_t *sysinfo; 1016 cpu_syswait_t *syswait; 1017 cpu_vminfo_t *vminfo; 1018 1019 stat = (cpu_stat_t *)(kp->ks_data); 1020 sysinfo = &stat->cpu_sysinfo; 1021 syswait = &stat->cpu_syswait; 1022 vminfo = &stat->cpu_vminfo; 1023 1024 SAVE_UINT32_X(ksi, "idle", sysinfo->cpu[CPU_IDLE]); 1025 SAVE_UINT32_X(ksi, "user", sysinfo->cpu[CPU_USER]); 1026 SAVE_UINT32_X(ksi, "kernel", sysinfo->cpu[CPU_KERNEL]); 1027 SAVE_UINT32_X(ksi, "wait", sysinfo->cpu[CPU_WAIT]); 1028 SAVE_UINT32_X(ksi, "wait_io", sysinfo->wait[W_IO]); 1029 SAVE_UINT32_X(ksi, "wait_swap", sysinfo->wait[W_SWAP]); 1030 SAVE_UINT32_X(ksi, "wait_pio", sysinfo->wait[W_PIO]); 1031 SAVE_UINT32(ksi, sysinfo, bread); 1032 SAVE_UINT32(ksi, sysinfo, bwrite); 1033 SAVE_UINT32(ksi, sysinfo, lread); 1034 SAVE_UINT32(ksi, sysinfo, lwrite); 1035 SAVE_UINT32(ksi, sysinfo, phread); 1036 SAVE_UINT32(ksi, sysinfo, phwrite); 1037 SAVE_UINT32(ksi, sysinfo, pswitch); 1038 SAVE_UINT32(ksi, sysinfo, trap); 1039 SAVE_UINT32(ksi, sysinfo, intr); 1040 SAVE_UINT32(ksi, sysinfo, syscall); 1041 SAVE_UINT32(ksi, sysinfo, sysread); 1042 SAVE_UINT32(ksi, sysinfo, syswrite); 1043 SAVE_UINT32(ksi, sysinfo, sysfork); 1044 SAVE_UINT32(ksi, sysinfo, sysvfork); 1045 SAVE_UINT32(ksi, sysinfo, sysexec); 1046 SAVE_UINT32(ksi, sysinfo, readch); 1047 SAVE_UINT32(ksi, sysinfo, writech); 1048 SAVE_UINT32(ksi, sysinfo, rcvint); 1049 SAVE_UINT32(ksi, sysinfo, xmtint); 1050 SAVE_UINT32(ksi, sysinfo, mdmint); 1051 SAVE_UINT32(ksi, sysinfo, rawch); 1052 SAVE_UINT32(ksi, sysinfo, canch); 1053 SAVE_UINT32(ksi, sysinfo, outch); 1054 SAVE_UINT32(ksi, sysinfo, msg); 1055 SAVE_UINT32(ksi, sysinfo, sema); 1056 SAVE_UINT32(ksi, sysinfo, namei); 1057 SAVE_UINT32(ksi, sysinfo, ufsiget); 1058 SAVE_UINT32(ksi, sysinfo, ufsdirblk); 1059 SAVE_UINT32(ksi, sysinfo, ufsipage); 1060 SAVE_UINT32(ksi, sysinfo, ufsinopage); 1061 SAVE_UINT32(ksi, sysinfo, inodeovf); 1062 SAVE_UINT32(ksi, sysinfo, fileovf); 1063 SAVE_UINT32(ksi, sysinfo, procovf); 1064 SAVE_UINT32(ksi, sysinfo, intrthread); 1065 SAVE_UINT32(ksi, sysinfo, intrblk); 1066 SAVE_UINT32(ksi, sysinfo, idlethread); 1067 SAVE_UINT32(ksi, sysinfo, inv_swtch); 1068 SAVE_UINT32(ksi, sysinfo, nthreads); 1069 SAVE_UINT32(ksi, sysinfo, cpumigrate); 1070 SAVE_UINT32(ksi, sysinfo, xcalls); 1071 SAVE_UINT32(ksi, sysinfo, mutex_adenters); 1072 SAVE_UINT32(ksi, sysinfo, rw_rdfails); 1073 SAVE_UINT32(ksi, sysinfo, rw_wrfails); 1074 SAVE_UINT32(ksi, sysinfo, modload); 1075 SAVE_UINT32(ksi, sysinfo, modunload); 1076 SAVE_UINT32(ksi, sysinfo, bawrite); 1077 #ifdef STATISTICS /* see header file */ 1078 SAVE_UINT32(ksi, sysinfo, rw_enters); 1079 SAVE_UINT32(ksi, sysinfo, win_uo_cnt); 1080 SAVE_UINT32(ksi, sysinfo, win_uu_cnt); 1081 SAVE_UINT32(ksi, sysinfo, win_so_cnt); 1082 SAVE_UINT32(ksi, sysinfo, win_su_cnt); 1083 SAVE_UINT32(ksi, sysinfo, win_suo_cnt); 1084 #endif 1085 1086 SAVE_INT32(ksi, syswait, iowait); 1087 SAVE_INT32(ksi, syswait, swap); 1088 SAVE_INT32(ksi, syswait, physio); 1089 1090 SAVE_UINT32(ksi, vminfo, pgrec); 1091 SAVE_UINT32(ksi, vminfo, pgfrec); 1092 SAVE_UINT32(ksi, vminfo, pgin); 1093 SAVE_UINT32(ksi, vminfo, pgpgin); 1094 SAVE_UINT32(ksi, vminfo, pgout); 1095 SAVE_UINT32(ksi, vminfo, pgpgout); 1096 SAVE_UINT32(ksi, vminfo, swapin); 1097 SAVE_UINT32(ksi, vminfo, pgswapin); 1098 SAVE_UINT32(ksi, vminfo, swapout); 1099 SAVE_UINT32(ksi, vminfo, pgswapout); 1100 SAVE_UINT32(ksi, vminfo, zfod); 1101 SAVE_UINT32(ksi, vminfo, dfree); 1102 SAVE_UINT32(ksi, vminfo, scan); 1103 SAVE_UINT32(ksi, vminfo, rev); 1104 SAVE_UINT32(ksi, vminfo, hat_fault); 1105 SAVE_UINT32(ksi, vminfo, as_fault); 1106 SAVE_UINT32(ksi, vminfo, maj_fault); 1107 SAVE_UINT32(ksi, vminfo, cow_fault); 1108 SAVE_UINT32(ksi, vminfo, prot_fault); 1109 SAVE_UINT32(ksi, vminfo, softlock); 1110 SAVE_UINT32(ksi, vminfo, kernel_asflt); 1111 SAVE_UINT32(ksi, vminfo, pgrrun); 1112 SAVE_UINT32(ksi, vminfo, execpgin); 1113 SAVE_UINT32(ksi, vminfo, execpgout); 1114 SAVE_UINT32(ksi, vminfo, execfree); 1115 SAVE_UINT32(ksi, vminfo, anonpgin); 1116 SAVE_UINT32(ksi, vminfo, anonpgout); 1117 SAVE_UINT32(ksi, vminfo, anonfree); 1118 SAVE_UINT32(ksi, vminfo, fspgin); 1119 SAVE_UINT32(ksi, vminfo, fspgout); 1120 SAVE_UINT32(ksi, vminfo, fsfree); 1121 } 1122 1123 static void 1124 save_var(kstat_t *kp, ks_instance_t *ksi) 1125 { 1126 struct var *var = (struct var *)(kp->ks_data); 1127 1128 assert(kp->ks_data_size == sizeof (struct var)); 1129 1130 SAVE_INT32(ksi, var, v_buf); 1131 SAVE_INT32(ksi, var, v_call); 1132 SAVE_INT32(ksi, var, v_proc); 1133 SAVE_INT32(ksi, var, v_maxupttl); 1134 SAVE_INT32(ksi, var, v_nglobpris); 1135 SAVE_INT32(ksi, var, v_maxsyspri); 1136 SAVE_INT32(ksi, var, v_clist); 1137 SAVE_INT32(ksi, var, v_maxup); 1138 SAVE_INT32(ksi, var, v_hbuf); 1139 SAVE_INT32(ksi, var, v_hmask); 1140 SAVE_INT32(ksi, var, v_pbuf); 1141 SAVE_INT32(ksi, var, v_sptmap); 1142 SAVE_INT32(ksi, var, v_maxpmem); 1143 SAVE_INT32(ksi, var, v_autoup); 1144 SAVE_INT32(ksi, var, v_bufhwm); 1145 } 1146 1147 static void 1148 save_ncstats(kstat_t *kp, ks_instance_t *ksi) 1149 { 1150 struct ncstats *ncstats = (struct ncstats *)(kp->ks_data); 1151 1152 assert(kp->ks_data_size == sizeof (struct ncstats)); 1153 1154 SAVE_INT32(ksi, ncstats, hits); 1155 SAVE_INT32(ksi, ncstats, misses); 1156 SAVE_INT32(ksi, ncstats, enters); 1157 SAVE_INT32(ksi, ncstats, dbl_enters); 1158 SAVE_INT32(ksi, ncstats, long_enter); 1159 SAVE_INT32(ksi, ncstats, long_look); 1160 SAVE_INT32(ksi, ncstats, move_to_front); 1161 SAVE_INT32(ksi, ncstats, purges); 1162 } 1163 1164 static void 1165 save_sysinfo(kstat_t *kp, ks_instance_t *ksi) 1166 { 1167 sysinfo_t *sysinfo = (sysinfo_t *)(kp->ks_data); 1168 1169 assert(kp->ks_data_size == sizeof (sysinfo_t)); 1170 1171 SAVE_UINT32(ksi, sysinfo, updates); 1172 SAVE_UINT32(ksi, sysinfo, runque); 1173 SAVE_UINT32(ksi, sysinfo, runocc); 1174 SAVE_UINT32(ksi, sysinfo, swpque); 1175 SAVE_UINT32(ksi, sysinfo, swpocc); 1176 SAVE_UINT32(ksi, sysinfo, waiting); 1177 } 1178 1179 static void 1180 save_vminfo(kstat_t *kp, ks_instance_t *ksi) 1181 { 1182 vminfo_t *vminfo = (vminfo_t *)(kp->ks_data); 1183 1184 assert(kp->ks_data_size == sizeof (vminfo_t)); 1185 1186 SAVE_UINT64(ksi, vminfo, freemem); 1187 SAVE_UINT64(ksi, vminfo, swap_resv); 1188 SAVE_UINT64(ksi, vminfo, swap_alloc); 1189 SAVE_UINT64(ksi, vminfo, swap_avail); 1190 SAVE_UINT64(ksi, vminfo, swap_free); 1191 SAVE_UINT64(ksi, vminfo, updates); 1192 } 1193 1194 static void 1195 save_nfs(kstat_t *kp, ks_instance_t *ksi) 1196 { 1197 struct mntinfo_kstat *mntinfo = (struct mntinfo_kstat *)(kp->ks_data); 1198 1199 assert(kp->ks_data_size == sizeof (struct mntinfo_kstat)); 1200 1201 SAVE_STRING(ksi, mntinfo, mik_proto); 1202 SAVE_UINT32(ksi, mntinfo, mik_vers); 1203 SAVE_UINT32(ksi, mntinfo, mik_flags); 1204 SAVE_UINT32(ksi, mntinfo, mik_secmod); 1205 SAVE_UINT32(ksi, mntinfo, mik_curread); 1206 SAVE_UINT32(ksi, mntinfo, mik_curwrite); 1207 SAVE_INT32(ksi, mntinfo, mik_timeo); 1208 SAVE_INT32(ksi, mntinfo, mik_retrans); 1209 SAVE_UINT32(ksi, mntinfo, mik_acregmin); 1210 SAVE_UINT32(ksi, mntinfo, mik_acregmax); 1211 SAVE_UINT32(ksi, mntinfo, mik_acdirmin); 1212 SAVE_UINT32(ksi, mntinfo, mik_acdirmax); 1213 SAVE_UINT32_X(ksi, "lookup_srtt", mntinfo->mik_timers[0].srtt); 1214 SAVE_UINT32_X(ksi, "lookup_deviate", mntinfo->mik_timers[0].deviate); 1215 SAVE_UINT32_X(ksi, "lookup_rtxcur", mntinfo->mik_timers[0].rtxcur); 1216 SAVE_UINT32_X(ksi, "read_srtt", mntinfo->mik_timers[1].srtt); 1217 SAVE_UINT32_X(ksi, "read_deviate", mntinfo->mik_timers[1].deviate); 1218 SAVE_UINT32_X(ksi, "read_rtxcur", mntinfo->mik_timers[1].rtxcur); 1219 SAVE_UINT32_X(ksi, "write_srtt", mntinfo->mik_timers[2].srtt); 1220 SAVE_UINT32_X(ksi, "write_deviate", mntinfo->mik_timers[2].deviate); 1221 SAVE_UINT32_X(ksi, "write_rtxcur", mntinfo->mik_timers[2].rtxcur); 1222 SAVE_UINT32(ksi, mntinfo, mik_noresponse); 1223 SAVE_UINT32(ksi, mntinfo, mik_failover); 1224 SAVE_UINT32(ksi, mntinfo, mik_remap); 1225 SAVE_STRING(ksi, mntinfo, mik_curserver); 1226 } 1227 1228 #ifdef __sparc 1229 static void 1230 save_sfmmu_global_stat(kstat_t *kp, ks_instance_t *ksi) 1231 { 1232 struct sfmmu_global_stat *sfmmug = 1233 (struct sfmmu_global_stat *)(kp->ks_data); 1234 1235 assert(kp->ks_data_size == sizeof (struct sfmmu_global_stat)); 1236 1237 SAVE_INT32(ksi, sfmmug, sf_tsb_exceptions); 1238 SAVE_INT32(ksi, sfmmug, sf_tsb_raise_exception); 1239 SAVE_INT32(ksi, sfmmug, sf_pagefaults); 1240 SAVE_INT32(ksi, sfmmug, sf_uhash_searches); 1241 SAVE_INT32(ksi, sfmmug, sf_uhash_links); 1242 SAVE_INT32(ksi, sfmmug, sf_khash_searches); 1243 SAVE_INT32(ksi, sfmmug, sf_khash_links); 1244 SAVE_INT32(ksi, sfmmug, sf_swapout); 1245 SAVE_INT32(ksi, sfmmug, sf_tsb_alloc); 1246 SAVE_INT32(ksi, sfmmug, sf_tsb_allocfail); 1247 SAVE_INT32(ksi, sfmmug, sf_tsb_sectsb_create); 1248 SAVE_INT32(ksi, sfmmug, sf_scd_1sttsb_alloc); 1249 SAVE_INT32(ksi, sfmmug, sf_scd_2ndtsb_alloc); 1250 SAVE_INT32(ksi, sfmmug, sf_scd_1sttsb_allocfail); 1251 SAVE_INT32(ksi, sfmmug, sf_scd_2ndtsb_allocfail); 1252 SAVE_INT32(ksi, sfmmug, sf_tteload8k); 1253 SAVE_INT32(ksi, sfmmug, sf_tteload64k); 1254 SAVE_INT32(ksi, sfmmug, sf_tteload512k); 1255 SAVE_INT32(ksi, sfmmug, sf_tteload4m); 1256 SAVE_INT32(ksi, sfmmug, sf_tteload32m); 1257 SAVE_INT32(ksi, sfmmug, sf_tteload256m); 1258 SAVE_INT32(ksi, sfmmug, sf_tsb_load8k); 1259 SAVE_INT32(ksi, sfmmug, sf_tsb_load4m); 1260 SAVE_INT32(ksi, sfmmug, sf_hblk_hit); 1261 SAVE_INT32(ksi, sfmmug, sf_hblk8_ncreate); 1262 SAVE_INT32(ksi, sfmmug, sf_hblk8_nalloc); 1263 SAVE_INT32(ksi, sfmmug, sf_hblk1_ncreate); 1264 SAVE_INT32(ksi, sfmmug, sf_hblk1_nalloc); 1265 SAVE_INT32(ksi, sfmmug, sf_hblk_slab_cnt); 1266 SAVE_INT32(ksi, sfmmug, sf_hblk_reserve_cnt); 1267 SAVE_INT32(ksi, sfmmug, sf_hblk_recurse_cnt); 1268 SAVE_INT32(ksi, sfmmug, sf_hblk_reserve_hit); 1269 SAVE_INT32(ksi, sfmmug, sf_get_free_success); 1270 SAVE_INT32(ksi, sfmmug, sf_get_free_throttle); 1271 SAVE_INT32(ksi, sfmmug, sf_get_free_fail); 1272 SAVE_INT32(ksi, sfmmug, sf_put_free_success); 1273 SAVE_INT32(ksi, sfmmug, sf_put_free_fail); 1274 SAVE_INT32(ksi, sfmmug, sf_pgcolor_conflict); 1275 SAVE_INT32(ksi, sfmmug, sf_uncache_conflict); 1276 SAVE_INT32(ksi, sfmmug, sf_unload_conflict); 1277 SAVE_INT32(ksi, sfmmug, sf_ism_uncache); 1278 SAVE_INT32(ksi, sfmmug, sf_ism_recache); 1279 SAVE_INT32(ksi, sfmmug, sf_recache); 1280 SAVE_INT32(ksi, sfmmug, sf_steal_count); 1281 SAVE_INT32(ksi, sfmmug, sf_pagesync); 1282 SAVE_INT32(ksi, sfmmug, sf_clrwrt); 1283 SAVE_INT32(ksi, sfmmug, sf_pagesync_invalid); 1284 SAVE_INT32(ksi, sfmmug, sf_kernel_xcalls); 1285 SAVE_INT32(ksi, sfmmug, sf_user_xcalls); 1286 SAVE_INT32(ksi, sfmmug, sf_tsb_grow); 1287 SAVE_INT32(ksi, sfmmug, sf_tsb_shrink); 1288 SAVE_INT32(ksi, sfmmug, sf_tsb_resize_failures); 1289 SAVE_INT32(ksi, sfmmug, sf_tsb_reloc); 1290 SAVE_INT32(ksi, sfmmug, sf_user_vtop); 1291 SAVE_INT32(ksi, sfmmug, sf_ctx_inv); 1292 SAVE_INT32(ksi, sfmmug, sf_tlb_reprog_pgsz); 1293 SAVE_INT32(ksi, sfmmug, sf_region_remap_demap); 1294 SAVE_INT32(ksi, sfmmug, sf_create_scd); 1295 SAVE_INT32(ksi, sfmmug, sf_join_scd); 1296 SAVE_INT32(ksi, sfmmug, sf_leave_scd); 1297 SAVE_INT32(ksi, sfmmug, sf_destroy_scd); 1298 } 1299 #endif 1300 1301 #ifdef __sparc 1302 static void 1303 save_sfmmu_tsbsize_stat(kstat_t *kp, ks_instance_t *ksi) 1304 { 1305 struct sfmmu_tsbsize_stat *sfmmut; 1306 1307 assert(kp->ks_data_size == sizeof (struct sfmmu_tsbsize_stat)); 1308 sfmmut = (struct sfmmu_tsbsize_stat *)(kp->ks_data); 1309 1310 SAVE_INT32(ksi, sfmmut, sf_tsbsz_8k); 1311 SAVE_INT32(ksi, sfmmut, sf_tsbsz_16k); 1312 SAVE_INT32(ksi, sfmmut, sf_tsbsz_32k); 1313 SAVE_INT32(ksi, sfmmut, sf_tsbsz_64k); 1314 SAVE_INT32(ksi, sfmmut, sf_tsbsz_128k); 1315 SAVE_INT32(ksi, sfmmut, sf_tsbsz_256k); 1316 SAVE_INT32(ksi, sfmmut, sf_tsbsz_512k); 1317 SAVE_INT32(ksi, sfmmut, sf_tsbsz_1m); 1318 SAVE_INT32(ksi, sfmmut, sf_tsbsz_2m); 1319 SAVE_INT32(ksi, sfmmut, sf_tsbsz_4m); 1320 } 1321 #endif 1322 1323 #ifdef __sparc 1324 static void 1325 save_simmstat(kstat_t *kp, ks_instance_t *ksi) 1326 { 1327 uchar_t *simmstat; 1328 char *simm_buf; 1329 char *list = NULL; 1330 int i; 1331 1332 assert(kp->ks_data_size == sizeof (uchar_t) * SIMM_COUNT); 1333 1334 for (i = 0, simmstat = (uchar_t *)(kp->ks_data); i < SIMM_COUNT - 1; 1335 i++, simmstat++) { 1336 if (list == NULL) { 1337 (void) asprintf(&simm_buf, "%d,", *simmstat); 1338 } else { 1339 (void) asprintf(&simm_buf, "%s%d,", list, *simmstat); 1340 free(list); 1341 } 1342 list = simm_buf; 1343 } 1344 1345 (void) asprintf(&simm_buf, "%s%d", list, *simmstat); 1346 SAVE_STRING_X(ksi, "status", simm_buf); 1347 free(list); 1348 free(simm_buf); 1349 } 1350 #endif 1351 1352 #ifdef __sparc 1353 /* 1354 * Helper function for save_temperature(). 1355 */ 1356 static char * 1357 short_array_to_string(short *shortp, int len) 1358 { 1359 char *list = NULL; 1360 char *list_buf; 1361 1362 for (; len > 1; len--, shortp++) { 1363 if (list == NULL) { 1364 (void) asprintf(&list_buf, "%hd,", *shortp); 1365 } else { 1366 (void) asprintf(&list_buf, "%s%hd,", list, *shortp); 1367 free(list); 1368 } 1369 list = list_buf; 1370 } 1371 1372 (void) asprintf(&list_buf, "%s%hd", list, *shortp); 1373 free(list); 1374 return (list_buf); 1375 } 1376 1377 static void 1378 save_temperature(kstat_t *kp, ks_instance_t *ksi) 1379 { 1380 struct temp_stats *temps = (struct temp_stats *)(kp->ks_data); 1381 char *buf; 1382 1383 assert(kp->ks_data_size == sizeof (struct temp_stats)); 1384 1385 SAVE_UINT32(ksi, temps, index); 1386 1387 buf = short_array_to_string(temps->l1, L1_SZ); 1388 SAVE_STRING_X(ksi, "l1", buf); 1389 free(buf); 1390 1391 buf = short_array_to_string(temps->l2, L2_SZ); 1392 SAVE_STRING_X(ksi, "l2", buf); 1393 free(buf); 1394 1395 buf = short_array_to_string(temps->l3, L3_SZ); 1396 SAVE_STRING_X(ksi, "l3", buf); 1397 free(buf); 1398 1399 buf = short_array_to_string(temps->l4, L4_SZ); 1400 SAVE_STRING_X(ksi, "l4", buf); 1401 free(buf); 1402 1403 buf = short_array_to_string(temps->l5, L5_SZ); 1404 SAVE_STRING_X(ksi, "l5", buf); 1405 free(buf); 1406 1407 SAVE_INT32(ksi, temps, max); 1408 SAVE_INT32(ksi, temps, min); 1409 SAVE_INT32(ksi, temps, state); 1410 SAVE_INT32(ksi, temps, temp_cnt); 1411 SAVE_INT32(ksi, temps, shutdown_cnt); 1412 SAVE_INT32(ksi, temps, version); 1413 SAVE_INT32(ksi, temps, trend); 1414 SAVE_INT32(ksi, temps, override); 1415 } 1416 #endif 1417 1418 #ifdef __sparc 1419 static void 1420 save_temp_over(kstat_t *kp, ks_instance_t *ksi) 1421 { 1422 short *sh = (short *)(kp->ks_data); 1423 char *value; 1424 1425 assert(kp->ks_data_size == sizeof (short)); 1426 1427 (void) asprintf(&value, "%hu", *sh); 1428 SAVE_STRING_X(ksi, "override", value); 1429 free(value); 1430 } 1431 #endif 1432 1433 #ifdef __sparc 1434 static void 1435 save_ps_shadow(kstat_t *kp, ks_instance_t *ksi) 1436 { 1437 uchar_t *uchar = (uchar_t *)(kp->ks_data); 1438 1439 assert(kp->ks_data_size == SYS_PS_COUNT); 1440 1441 SAVE_CHAR_X(ksi, "core_0", *uchar++); 1442 SAVE_CHAR_X(ksi, "core_1", *uchar++); 1443 SAVE_CHAR_X(ksi, "core_2", *uchar++); 1444 SAVE_CHAR_X(ksi, "core_3", *uchar++); 1445 SAVE_CHAR_X(ksi, "core_4", *uchar++); 1446 SAVE_CHAR_X(ksi, "core_5", *uchar++); 1447 SAVE_CHAR_X(ksi, "core_6", *uchar++); 1448 SAVE_CHAR_X(ksi, "core_7", *uchar++); 1449 SAVE_CHAR_X(ksi, "pps_0", *uchar++); 1450 SAVE_CHAR_X(ksi, "clk_33", *uchar++); 1451 SAVE_CHAR_X(ksi, "clk_50", *uchar++); 1452 SAVE_CHAR_X(ksi, "v5_p", *uchar++); 1453 SAVE_CHAR_X(ksi, "v12_p", *uchar++); 1454 SAVE_CHAR_X(ksi, "v5_aux", *uchar++); 1455 SAVE_CHAR_X(ksi, "v5_p_pch", *uchar++); 1456 SAVE_CHAR_X(ksi, "v12_p_pch", *uchar++); 1457 SAVE_CHAR_X(ksi, "v3_pch", *uchar++); 1458 SAVE_CHAR_X(ksi, "v5_pch", *uchar++); 1459 SAVE_CHAR_X(ksi, "p_fan", *uchar++); 1460 } 1461 #endif 1462 1463 #ifdef __sparc 1464 static void 1465 save_fault_list(kstat_t *kp, ks_instance_t *ksi) 1466 { 1467 struct ft_list *fault; 1468 char name[KSTAT_STRLEN + 7]; 1469 int i; 1470 1471 for (i = 1, fault = (struct ft_list *)(kp->ks_data); 1472 i <= 999999 && i <= kp->ks_data_size / sizeof (struct ft_list); 1473 i++, fault++) { 1474 (void) snprintf(name, sizeof (name), "unit_%d", i); 1475 SAVE_INT32_X(ksi, name, fault->unit); 1476 (void) snprintf(name, sizeof (name), "type_%d", i); 1477 SAVE_INT32_X(ksi, name, fault->type); 1478 (void) snprintf(name, sizeof (name), "fclass_%d", i); 1479 SAVE_INT32_X(ksi, name, fault->fclass); 1480 (void) snprintf(name, sizeof (name), "create_time_%d", i); 1481 SAVE_HRTIME_X(ksi, name, fault->create_time); 1482 (void) snprintf(name, sizeof (name), "msg_%d", i); 1483 SAVE_STRING_X(ksi, name, fault->msg); 1484 } 1485 } 1486 #endif 1487 1488 static void 1489 save_named(kstat_t *kp, ks_instance_t *ksi) 1490 { 1491 kstat_named_t *knp; 1492 int n; 1493 1494 for (n = kp->ks_ndata, knp = KSTAT_NAMED_PTR(kp); n > 0; n--, knp++) { 1495 switch (knp->data_type) { 1496 case KSTAT_DATA_CHAR: 1497 case KSTAT_DATA_INT32: 1498 case KSTAT_DATA_UINT32: 1499 case KSTAT_DATA_INT64: 1500 case KSTAT_DATA_UINT64: 1501 case KSTAT_DATA_TIME: 1502 nvpair_insert(ksi, knp->name, 1503 (ks_value_t *)&knp->value, knp->data_type); 1504 break; 1505 case KSTAT_DATA_STRING: 1506 SAVE_STRING_X(ksi, knp->name, KSTAT_NAMED_STR_PTR(knp)); 1507 break; 1508 default: 1509 assert(B_FALSE); /* Invalid data type */ 1510 break; 1511 } 1512 } 1513 } 1514 1515 static void 1516 save_intr(kstat_t *kp, ks_instance_t *ksi) 1517 { 1518 kstat_intr_t *intr = KSTAT_INTR_PTR(kp); 1519 char *intr_names[] = {"hard", "soft", "watchdog", "spurious", 1520 "multiple_service"}; 1521 int n; 1522 1523 for (n = 0; n < KSTAT_NUM_INTRS; n++) 1524 SAVE_UINT32_X(ksi, intr_names[n], intr->intrs[n]); 1525 } 1526 1527 static void 1528 save_io(kstat_t *kp, ks_instance_t *ksi) 1529 { 1530 kstat_io_t *ksio = KSTAT_IO_PTR(kp); 1531 1532 SAVE_UINT64(ksi, ksio, nread); 1533 SAVE_UINT64(ksi, ksio, nwritten); 1534 SAVE_UINT32(ksi, ksio, reads); 1535 SAVE_UINT32(ksi, ksio, writes); 1536 SAVE_UINT64(ksi, ksio, wtime); 1537 SAVE_UINT64(ksi, ksio, wlentime); 1538 SAVE_HRTIME(ksi, ksio, wlastupdate); 1539 SAVE_UINT64(ksi, ksio, rtime); 1540 SAVE_UINT64(ksi, ksio, rlentime); 1541 SAVE_HRTIME(ksi, ksio, rlastupdate); 1542 SAVE_UINT32(ksi, ksio, wcnt); 1543 SAVE_UINT32(ksi, ksio, rcnt); 1544 } 1545 1546 static void 1547 save_timer(kstat_t *kp, ks_instance_t *ksi) 1548 { 1549 kstat_timer_t *ktimer = KSTAT_TIMER_PTR(kp); 1550 1551 SAVE_STRING(ksi, ktimer, name); 1552 SAVE_UINT64(ksi, ktimer, num_events); 1553 SAVE_UINT64(ksi, ktimer, elapsed_time); 1554 SAVE_UINT64(ksi, ktimer, min_time); 1555 SAVE_UINT64(ksi, ktimer, max_time); 1556 SAVE_HRTIME(ksi, ktimer, start_time); 1557 SAVE_HRTIME(ksi, ktimer, stop_time); 1558 }