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