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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright (c) 2018, Joyent, Inc. 29 */ 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <strings.h> 34 #include <time.h> 35 #include <signal.h> 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <sys/time.h> 39 #include <sys/modctl.h> 40 #include <sys/systeminfo.h> 41 #include <limits.h> 42 #include <signal.h> 43 #include <fcntl.h> 44 #include <unistd.h> 45 #include <stropts.h> 46 #include <locale.h> 47 #include <libintl.h> 48 #include <libgen.h> 49 #include <nl_types.h> 50 #include <kstat.h> 51 #include <ctype.h> 52 #include <signal.h> 53 #include <errno.h> 54 #include <time.h> 55 56 #include "busstat.h" 57 58 59 /* Global defines */ 60 static int delta = TRUE; 61 static int banner = TRUE; 62 static int max_pic_num = 1; 63 static int initial_read = TRUE; 64 static char *pgmname; 65 static kstat_ctl_t *kc; /* libkstat cookie */ 66 static dev_node_t *dev_list_head = NULL; 67 static dev_node_t *dev_list_tail = NULL; 68 69 /* 70 * Global flags. 71 */ 72 static char curr_dev_name[KSTAT_STRLEN]; 73 static int curr_inst_num; 74 75 static void print_evt(void); 76 static void print_dev(int, char *); 77 static void parse_cmd(int); 78 static void parse_dev_inst(char *); 79 static void parse_pic_evt(char *); 80 static void add_dev_node(char *, int); 81 static void add_all_dev_node(char *); 82 static void add_evt_node(dev_node_t *); 83 static void modify_evt_node(dev_node_t *, char *); 84 static void prune_evt_nodes(dev_node_t *); 85 static void setup_evts(void); 86 static void set_evt(dev_node_t *); 87 static void read_evts(void); 88 static void read_r_evt_node(dev_node_t *, int, kstat_named_t *); 89 static void read_w_evt_node(dev_node_t *, int, kstat_named_t *); 90 static void check_dr_ops(void); 91 static void remove_dev_node(dev_node_t *); 92 static dev_node_t *find_dev_node(char *, int, int); 93 static kstat_t *find_pic_kstat(char *, int, char *); 94 static int64_t is_num(char *); 95 static void print_banner(void); 96 static void print_timestamp(void); 97 static void usage(void); 98 static void *safe_malloc(size_t); 99 static void set_timer(int); 100 static void handle_sig(int); 101 static int strisnum(const char *); 102 103 int 104 main(int argc, char **argv) 105 { 106 int c, i; 107 int interval = 1; /* Interval between displays */ 108 int count = 0; /* Number of times to sample */ 109 int write_evts = FALSE; 110 int pos = 0; 111 112 #if !defined(TEXT_DOMAIN) 113 #define TEXT_DOMAIN "SYS_TEST" 114 #endif 115 116 /* For I18N */ 117 (void) setlocale(LC_ALL, ""); 118 (void) textdomain(TEXT_DOMAIN); 119 120 pgmname = basename(argv[0]); 121 122 if ((kc = kstat_open()) == NULL) { 123 (void) fprintf(stderr, gettext("%s: could not " 124 "open /dev/kstat\n"), pgmname); 125 exit(1); 126 } 127 128 while ((c = getopt(argc, argv, "e:w:r:ahln")) != EOF) { 129 switch (c) { 130 case 'a': 131 delta = FALSE; 132 break; 133 case 'e': 134 (void) print_evt(); 135 break; 136 case 'h': 137 usage(); 138 break; 139 case 'l': 140 (void) print_dev(argc, argv[argc-1]); 141 break; 142 case 'n': 143 banner = FALSE; 144 break; 145 case 'r': 146 (void) parse_cmd(READ_EVT); 147 break; 148 case 'w': 149 (void) parse_cmd(WRITE_EVT); 150 write_evts = TRUE; 151 break; 152 default: 153 (void) fprintf(stderr, gettext("%s: invalid " 154 "option\n"), pgmname); 155 usage(); 156 break; 157 } 158 } 159 160 if ((argc == 1) || (dev_list_head == NULL)) 161 usage(); 162 163 /* 164 * validate remaining operands are numeric. 165 */ 166 pos = optind; 167 while (pos < argc) { 168 if (strisnum(argv[pos]) == 0) { 169 (void) fprintf(stderr, 170 gettext("%s: syntax error\n"), 171 pgmname); 172 usage(); 173 } 174 pos++; 175 } 176 177 if (optind < argc) { 178 if ((interval = atoi(argv[optind])) == 0) { 179 (void) fprintf(stderr, gettext("%s: invalid " 180 "interval value\n"), pgmname); 181 exit(1); 182 } 183 184 optind++; 185 if (optind < argc) 186 if ((count = atoi(argv[optind])) <= 0) { 187 (void) fprintf(stderr, gettext("%s: " 188 "invalid iteration value.\n"), 189 pgmname); 190 exit(1); 191 } 192 } 193 194 set_timer(interval); 195 196 /* 197 * Set events for the first time. 198 */ 199 if (write_evts == TRUE) 200 setup_evts(); 201 202 203 if (count > 0) { 204 for (i = 0; i < count; i++) { 205 if (banner) 206 print_banner(); 207 208 check_dr_ops(); 209 read_evts(); 210 (void) fflush(stdout); 211 (void) pause(); 212 } 213 } else { 214 for (;;) { 215 if (banner) 216 print_banner(); 217 218 check_dr_ops(); 219 read_evts(); 220 (void) fflush(stdout); 221 (void) pause(); 222 } 223 } 224 225 read_evts(); 226 return (0); 227 } 228 229 230 /* 231 * Display all the events that can be set on a device. 232 */ 233 void 234 print_evt() 235 { 236 kstat_t *cnt_ksp; 237 kstat_t *pic_ksp; 238 kstat_named_t *cnt_data; 239 kstat_named_t *pic_data; 240 char *device = NULL; 241 char *value; 242 int inst_num = -1; 243 int i = 0; 244 int j; 245 246 value = optarg; 247 248 /* 249 * Search through the value string for a numeric char which will 250 * be the device instance number, if the user specified one. If 251 * the user did not specify an instance then the return value from 252 * strscpn will be equal to the string length. In this case we 253 * use a default value of -1 for the kstat_lookup which causes 254 * the device number to be ignored during the search. 255 */ 256 if (((i = strcspn(value, "0123456789")) > 0) && (i != strlen(value))) { 257 258 device = safe_malloc(sizeof (char) * i+1); 259 device[i] = '\0'; 260 (void) strncpy(device, value, i); 261 262 value = value + i; 263 inst_num = atoi(value); 264 } 265 266 /* 267 * No instance specified. 268 */ 269 if (device == NULL) 270 device = value; 271 272 /* 273 * Get the "counters" kstat, so that we can get 274 * the names of the "picN" kstats, which hold the 275 * event names. 276 */ 277 if ((cnt_ksp = kstat_lookup(kc, device, inst_num, "counters")) 278 == NULL) { 279 (void) fprintf(stderr, gettext("%s: invalid device " 280 "name or instance (%s)\n"), pgmname, device); 281 exit(1); 282 } 283 284 if (kstat_read(kc, cnt_ksp, NULL) == FAIL) { 285 (void) fprintf(stderr, gettext("%s: could not read " 286 "kstat.\n"), pgmname); 287 exit(1); 288 } 289 290 cnt_data = (kstat_named_t *)cnt_ksp->ks_data; 291 292 /* 293 * Start at 1 as the first entry in the "counters" 294 * kstat is the pcr value/name. We are looking for the 295 * name of the "picN" kstats. For each one found store 296 * a pointer to it in pic_data[]. 297 */ 298 if (cnt_ksp->ks_ndata <= 1) { 299 (void) fprintf(stderr, gettext("%s: invalid kstat " 300 "structure.\n"), pgmname); 301 exit(1); 302 } 303 304 for (i = 1; i < cnt_ksp->ks_ndata; i++) { 305 if ((pic_ksp = find_pic_kstat(device, inst_num, 306 cnt_data[i].name)) == NULL) { 307 308 (void) fprintf(stderr, gettext("%s: could not read " 309 "pic kstat data structure for %s\n"), 310 pgmname, cnt_ksp->ks_module); 311 312 exit(1); 313 } 314 315 if (kstat_read(kc, pic_ksp, NULL) == FAIL) { 316 (void) fprintf(stderr, gettext("%s: could not read " 317 "pic kstat.\n"), pgmname); 318 319 exit(1); 320 } 321 322 pic_data = (kstat_named_t *)pic_ksp->ks_data; 323 324 (void) printf(gettext("pic%-8d\n"), i-1); 325 326 for (j = 0; j < pic_ksp->ks_ndata-1; j++) { 327 (void) printf("%-30s\n", pic_data[j].name); 328 } 329 330 (void) printf("\n"); 331 } 332 333 exit(0); 334 } 335 336 337 /* 338 * Display the names and instances of the devices on the system 339 * which can support performance monitoring. 340 */ 341 void 342 print_dev(int argc, char *str) 343 { 344 kstat_t *ksp; 345 static int first_time = 1; 346 347 if ((argc > 2) || (strcmp(str, "-l") != 0)) { 348 (void) fprintf(stderr, gettext("%s: no arguments " 349 "permitted with -l option.\n"), 350 pgmname); 351 usage(); 352 exit(1); 353 } 354 355 /* 356 * For each device node, print the node name (device 357 * name) and the instance numbers. 358 */ 359 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 360 if ((strcmp(ksp->ks_class, "bus") == 0) && 361 (strcmp(ksp->ks_name, "counters") == 0)) { 362 if (first_time) { 363 (void) printf(gettext("Busstat " 364 "Device(s):\n")); 365 first_time = 0; 366 } 367 (void) printf("%s%d ", ksp->ks_module, 368 ksp->ks_instance); 369 } 370 } 371 372 if (first_time) 373 (void) fprintf(stderr, gettext("%s: No devices available " 374 "in system."), pgmname); 375 376 (void) printf("\n"); 377 378 exit(0); 379 } 380 381 /* 382 * Parses the cmd line, checks all the values and 383 * creates the appropiate data structures. 384 */ 385 void 386 parse_cmd(int mode) 387 { 388 char *options = optarg, *value; 389 int arg_num = 0; 390 391 while ((value = (char *)strtok(options, ",=")) != NULL) { 392 /* 393 * First arg must be device name. 394 */ 395 if (!arg_num) { 396 parse_dev_inst(value); 397 } else { 398 if (mode == READ_EVT) { 399 (void) fprintf(stderr, gettext("%s: " 400 "event names or pic values not " 401 "permitted with -r option.\n"), 402 pgmname); 403 usage(); 404 exit(1); 405 } 406 /* 407 * Now dealing with pic values. 408 */ 409 parse_pic_evt(value); 410 } 411 /* 412 * After first strtok call, must set first arg 413 * to null if wish to parse rest of string. 414 * See strtok man page. 415 */ 416 if (options != NULL) 417 options = NULL; 418 arg_num++; 419 } 420 } 421 422 423 /* 424 * Parse the device name/instance section of the 425 * command line. 426 */ 427 void 428 parse_dev_inst(char *value) 429 { 430 int i; 431 char *device = NULL; 432 int malloc_flag = FALSE; 433 434 if (strlen(value) == 0) { 435 (void) fprintf(stderr, gettext("%s: No device name given.\n"), 436 pgmname); 437 exit(1); 438 } 439 440 /* 441 * Break string into device name and 442 * instance number (if given). 443 */ 444 if ((i = strcspn(value, "0123456789")) > 0) { 445 if (i != strlen(value)) { 446 device = safe_malloc(sizeof (char) * i+1); 447 device[i] = '\0'; 448 449 (void) strncpy(device, value, i); 450 malloc_flag = TRUE; 451 452 value = value + i; 453 } 454 } 455 456 /* 457 * No instance was specified so we assume 458 * the user wants to use ALL instances. 459 */ 460 if (device == NULL) { 461 if ((device = value) == NULL) { 462 (void) fprintf(stderr, gettext("%s: no device " 463 "specified\n"), pgmname); 464 exit(1); 465 } 466 467 /* 468 * Set global flags. 469 */ 470 (void) strcpy(curr_dev_name, device); 471 curr_inst_num = -1; 472 473 add_all_dev_node(device); 474 goto clean_up; 475 } 476 477 /* 478 * Set global flags. 479 */ 480 (void) strcpy(curr_dev_name, device); 481 curr_inst_num = atoi(value); 482 483 add_dev_node(device, curr_inst_num); 484 485 clean_up: 486 if (malloc_flag) { 487 free(device); 488 } 489 } 490 491 492 /* 493 * Adds new event nodes to existing ones, modifies existing ones, or 494 * prunes existing ones. 495 * 496 * A specific instance call will overwrite an earlier all 497 * instances call, but *not* vice-versa. 498 * 499 * All the state transitions are given below. 500 * 501 * 502 * Call Type 503 * STATE | Specific Instance All Instances. 504 * ====================================================== 505 * INIT | Change state to | Change state to ALL, 506 * | INST, add events | add events. 507 * | | 508 * INST | State unchanged, | No change. 509 * | Add events. | 510 * | | 511 * ALL | Change state to | State unchanged, 512 * | INST, replace events. | add events. 513 */ 514 void 515 parse_pic_evt(char *value) 516 { 517 dev_node_t *dev_node; 518 char *evt_name; 519 int pic_num; 520 521 if (strlen(value) <= PIC_STR_LEN) { 522 (void) fprintf(stderr, gettext("%s: no pic number " 523 "specified.\n"), pgmname); 524 exit(1); 525 } 526 527 if (strncmp(value, "pic", PIC_STR_LEN) != 0) { 528 (void) fprintf(stderr, gettext("%s: missing pic " 529 "specifier\n"), pgmname); 530 usage(); 531 } 532 533 /* 534 * Step over the 'pic' part of the string to 535 * get the pic number. 536 */ 537 value = value + PIC_STR_LEN; 538 pic_num = atoi(value); 539 540 if ((pic_num == -1) || (pic_num > max_pic_num -1)) { 541 (void) fprintf(stderr, gettext("%s: invalid pic " 542 "number.\n"), pgmname); 543 exit(1); 544 } 545 546 if ((evt_name = (char *)strtok(NULL, "=,")) == NULL) { 547 (void) fprintf(stderr, gettext("%s: no event " 548 "specified.\n"), pgmname); 549 exit(1); 550 } 551 552 /* 553 * Dealing with a specific instance. 554 */ 555 if (curr_inst_num >= 0) { 556 if ((dev_node = find_dev_node(curr_dev_name, 557 curr_inst_num, pic_num)) == NULL) { 558 (void) fprintf(stderr, gettext("%s: could not find " 559 "data structures for %s\n"), 560 pgmname, curr_dev_name); 561 exit(1); 562 } 563 564 if (dev_node->r_w == EVT_READ) { 565 modify_evt_node(dev_node, evt_name); 566 dev_node->r_w = EVT_WRITE; 567 dev_node->state = STATE_INST; 568 569 } else if ((dev_node->r_w == EVT_WRITE) && 570 (dev_node->state == STATE_ALL)) { 571 572 prune_evt_nodes(dev_node); 573 modify_evt_node(dev_node, evt_name); 574 dev_node->state = STATE_INST; 575 576 } else if ((dev_node->r_w == EVT_WRITE) && 577 (dev_node->state == STATE_INST)) { 578 579 add_evt_node(dev_node); 580 modify_evt_node(dev_node, evt_name); 581 } 582 583 return; 584 } 585 586 /* 587 * Dealing with all instances of a specific device. 588 */ 589 dev_node = dev_list_head; 590 while (dev_node != NULL) { 591 if ((strcmp(dev_node->name, curr_dev_name) == 0) && 592 (dev_node->pic_num == pic_num)) { 593 594 if (dev_node->r_w == EVT_READ) { 595 modify_evt_node(dev_node, 596 evt_name); 597 598 dev_node->r_w = EVT_WRITE; 599 dev_node->state = STATE_ALL; 600 601 } else if ((dev_node->r_w == EVT_WRITE) && 602 (dev_node->state == STATE_ALL)) { 603 604 add_evt_node(dev_node); 605 modify_evt_node(dev_node, evt_name); 606 607 } 608 } 609 dev_node = dev_node->next; 610 } 611 } 612 613 614 /* 615 * Create a dev_node structure for this device if one does not 616 * already exist. 617 */ 618 void 619 add_dev_node(char *dev_name, int inst_num) 620 { 621 dev_node_t *new_dev_node; 622 kstat_named_t *cnt_data; 623 kstat_t *cnt_ksp; 624 kstat_t *pic_ksp; 625 int pic_num; 626 627 628 if ((cnt_ksp = kstat_lookup(kc, dev_name, 629 inst_num, "counters")) == NULL) { 630 (void) fprintf(stderr, gettext("%s: invalid device " 631 "name or instance (%s%d)\n"), pgmname, 632 dev_name, inst_num); 633 exit(1); 634 } 635 636 if (kstat_read(kc, cnt_ksp, NULL) == FAIL) { 637 (void) fprintf(stderr, gettext("%s : could not read counters " 638 "kstat for device %s.\n"), pgmname, dev_name); 639 exit(1); 640 } 641 642 cnt_data = (kstat_named_t *)cnt_ksp->ks_data; 643 644 if (cnt_ksp->ks_ndata <= 1) { 645 (void) fprintf(stderr, gettext("%s : invalid " 646 "kstat structure.\n"), pgmname); 647 exit(1); 648 } 649 650 /* 651 * max_pic_num used to format headers correctly 652 * for printing. 653 */ 654 if (cnt_ksp->ks_ndata-1 > max_pic_num) 655 max_pic_num = cnt_ksp->ks_ndata-1; 656 657 /* for each pic... */ 658 for (pic_num = 0; pic_num < cnt_ksp->ks_ndata-1; pic_num++) { 659 if (find_dev_node(dev_name, inst_num, pic_num) != NULL) { 660 /* Node already exists */ 661 continue; 662 } 663 664 new_dev_node = safe_malloc(sizeof (dev_node_t)); 665 bzero(new_dev_node, sizeof (dev_node_t)); 666 667 (void) strcpy(new_dev_node->name, dev_name); 668 new_dev_node->dev_inst = inst_num; 669 new_dev_node->pic_num = pic_num; 670 671 new_dev_node->cnt_ksp = cnt_ksp; 672 673 if ((pic_ksp = find_pic_kstat(dev_name, inst_num, 674 cnt_data[pic_num+1].name)) == NULL) { 675 676 (void) fprintf(stderr, gettext("%s: could not find " 677 "pic kstat structure for %s.\n"), 678 pgmname, cnt_ksp->ks_module); 679 exit(1); 680 } 681 682 new_dev_node->pic_ksp = pic_ksp; 683 684 add_evt_node(new_dev_node); 685 686 new_dev_node->state = STATE_INIT; 687 new_dev_node->r_w = EVT_READ; 688 689 if (dev_list_head == NULL) { 690 dev_list_head = new_dev_node; 691 dev_list_tail = new_dev_node; 692 693 } else if (find_dev_node(dev_name, inst_num, pic_num) == NULL) { 694 dev_list_tail->next = new_dev_node; 695 dev_list_tail = new_dev_node; 696 } 697 } 698 } 699 700 701 /* 702 * Add all possible instances of a device. 703 */ 704 void 705 add_all_dev_node(char *dev_name) 706 { 707 kstat_t *ksp; 708 int match = 0; 709 710 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 711 if ((strcmp(ksp->ks_class, "bus") == 0) && 712 (strcmp(ksp->ks_name, "counters") == 0) && 713 (strcmp(ksp->ks_module, dev_name) == 0)) { 714 match = 1; 715 add_dev_node(dev_name, ksp->ks_instance); 716 } 717 } 718 719 if (match == 0) { 720 (void) fprintf(stderr, 721 gettext("%s: invalid device name (%s)\n"), 722 pgmname, dev_name); 723 exit(1); 724 } 725 } 726 727 728 /* 729 * Add an event node to a specified device node. 730 */ 731 void 732 add_evt_node(dev_node_t *dev_node) 733 { 734 evt_node_t *new_evt_node; 735 evt_node_t *curr_evt_node; 736 737 new_evt_node = safe_malloc(sizeof (evt_node_t)); 738 bzero(new_evt_node, sizeof (evt_node_t)); 739 740 (void) strcpy(new_evt_node->evt_name, ""); 741 742 if (dev_node->evt_node == NULL) { 743 dev_node->evt_node = new_evt_node; 744 new_evt_node->next = new_evt_node; 745 return; 746 } else { 747 curr_evt_node = dev_node->evt_node; 748 while (curr_evt_node->next != dev_node->evt_node) 749 curr_evt_node = curr_evt_node->next; 750 751 curr_evt_node->next = new_evt_node; 752 new_evt_node->next = dev_node->evt_node; 753 } 754 } 755 756 757 /* 758 * Fill in or change the fields of an evt node. 759 */ 760 void 761 modify_evt_node(dev_node_t *dev_node, char *evt_name) 762 { 763 evt_node_t *evt_node; 764 kstat_t *pic_ksp; 765 kstat_named_t *pic_data; 766 int64_t evt_num = 0; 767 int evt_match = 0; 768 int i; 769 770 evt_node = dev_node->evt_node; 771 772 /* 773 * Find the last event node. 774 */ 775 if (evt_node->next != evt_node) { 776 while (evt_node->next != dev_node->evt_node) { 777 evt_node = evt_node->next; 778 } 779 } 780 781 evt_node->prev_count = 0; 782 evt_node->total = 0; 783 784 pic_ksp = dev_node->pic_ksp; 785 786 if (kstat_read(kc, pic_ksp, NULL) == FAIL) { 787 (void) fprintf(stderr, gettext("%s: could not read " 788 "pic kstat.\n"), pgmname); 789 exit(1); 790 } 791 792 pic_data = (kstat_named_t *)dev_node->pic_ksp->ks_data; 793 794 /* 795 * The event can either be given as a event name (string) or 796 * as a pcr mask. If given as pcr mask, we try to match it 797 * to an event name, and use that name. Otherwise we just use 798 * the pcr mask value. 799 */ 800 if ((evt_num = is_num(evt_name)) == EVT_STR) { 801 (void) strcpy(evt_node->evt_name, evt_name); 802 803 for (i = 0; i < dev_node->pic_ksp->ks_ndata; i++) { 804 if (strcmp(evt_name, pic_data[i].name) == 0) { 805 evt_node->evt_pcr_mask = pic_data[i].value.ui64; 806 return; 807 } 808 } 809 810 (void) fprintf(stderr, 811 gettext("%s: %s is not a valid event name.\n"), 812 pgmname, evt_name); 813 exit(1); 814 815 } else { 816 /* 817 * See if the pcr mask given by the user matches that for any 818 * existing event. 819 */ 820 for (i = 0; i < dev_node->pic_ksp->ks_ndata; i++) { 821 if (evt_num == pic_data[i].value.ui64) { 822 (void) strcpy(evt_node->evt_name, 823 pic_data[i].name); 824 evt_match = 1; 825 break; 826 } 827 } 828 829 if (evt_match == 0) 830 (void) sprintf(evt_node->evt_name, "%llx", evt_num); 831 832 evt_node->evt_pcr_mask = evt_num; 833 } 834 } 835 836 837 /* 838 * Removes all bar one of the evt_nodes that are hanging off the 839 * specified dev_node. 840 */ 841 void 842 prune_evt_nodes(dev_node_t *dev_node) 843 { 844 evt_node_t *next_evt_node; 845 evt_node_t *curr_evt_node; 846 847 /* 848 * Only one evt node, nothing for us to do. 849 */ 850 if (dev_node->evt_node->next == dev_node->evt_node) { 851 return; 852 } 853 854 curr_evt_node = dev_node->evt_node->next; 855 dev_node->evt_node->next = dev_node->evt_node; 856 857 while (curr_evt_node != dev_node->evt_node) { 858 next_evt_node = curr_evt_node->next; 859 free(curr_evt_node); 860 curr_evt_node = next_evt_node; 861 } 862 } 863 864 865 /* 866 * Set the events for each pic on each device instance. 867 */ 868 void 869 setup_evts() 870 { 871 dev_node_t *dev_node; 872 873 dev_node = dev_list_head; 874 875 while (dev_node != NULL) { 876 if (dev_node->r_w == EVT_WRITE) 877 set_evt(dev_node); 878 879 dev_node = dev_node->next; 880 } 881 } 882 883 884 /* 885 * Set the appropiate events. Only called for event nodes 886 * that are marked EVT_WRITE. 887 */ 888 void 889 set_evt(dev_node_t *dev_node) 890 { 891 kstat_named_t *cnt_data; 892 kstat_named_t *pic_data; 893 kstat_t *cnt_ksp; 894 kstat_t *pic_ksp; 895 evt_node_t *evt_node; 896 uint64_t clear_pcr_mask; 897 uint64_t pcr; 898 int pic_num; 899 900 cnt_ksp = dev_node->cnt_ksp; 901 pic_ksp = dev_node->pic_ksp; 902 pic_num = dev_node->pic_num; 903 evt_node = dev_node->evt_node; 904 905 /* Read the "counters" kstat */ 906 if (kstat_read(kc, cnt_ksp, NULL) == FAIL) { 907 (void) fprintf(stderr, gettext("%s: could " 908 "not set event's.\n"), pgmname); 909 exit(1); 910 } 911 912 cnt_data = (kstat_named_t *)cnt_ksp->ks_data; 913 914 if (kstat_read(kc, pic_ksp, NULL) == FAIL) { 915 (void) fprintf(stderr, gettext("%s: could " 916 "not set event's.\n"), pgmname); 917 exit(1); 918 } 919 920 pic_data = (kstat_named_t *)pic_ksp->ks_data; 921 clear_pcr_mask = pic_data[pic_ksp->ks_ndata-1].value.ui64; 922 923 if ((pic_num < 0) || (pic_num > cnt_ksp->ks_ndata-1)) { 924 (void) fprintf(stderr, 925 gettext("%s: invalid pic #%d.\n"), 926 pgmname, pic_num); 927 exit(1); 928 } 929 930 /* 931 * Store the previous value that is on the pic 932 * so that we can calculate the delta value 933 * later. 934 */ 935 evt_node->prev_count = cnt_data[pic_num+1].value.ui64; 936 937 938 /* 939 * Read the current pcr value from device. 940 */ 941 pcr = cnt_data[0].value.ui64; 942 943 /* 944 * Clear the section of the pcr which corresponds to the 945 * pic we are setting events on. Also clear the pcr value 946 * which is stored in the instance node. 947 * 948 */ 949 pcr = pcr & clear_pcr_mask; 950 951 /* 952 * Set the event. 953 */ 954 pcr = pcr | evt_node->evt_pcr_mask; 955 cnt_data[0].value.ui64 = pcr; 956 957 /* 958 * Write the value back to the kstat, to make it 959 * visible to the underlying driver. 960 */ 961 if (kstat_write(kc, cnt_ksp, NULL) == FAIL) { 962 (void) fprintf(stderr, gettext("%s: could not set events " 963 "(setting events requires root " 964 "permission).\n"), pgmname); 965 exit(1); 966 } 967 } 968 969 970 /* 971 * Works through the list of device nodes, reading events 972 * and where appropiate setting new events (multiplexing). 973 */ 974 void 975 read_evts() 976 { 977 dev_node_t *dev_node; 978 kstat_t *cnt_ksp; 979 kstat_named_t *cnt_data; 980 char tmp_str[30]; 981 int iter = 0; 982 983 dev_node = dev_list_head; 984 985 while (dev_node != NULL) { 986 if (iter == 0) 987 print_timestamp(); 988 /* 989 * First read of all the counters is done 990 * to establish a baseline for the counts. 991 * This data is not printed. 992 */ 993 if ((!initial_read) && (iter == 0)) { 994 (void) snprintf(tmp_str, sizeof (tmp_str), "%s%d", 995 dev_node->name, dev_node->dev_inst); 996 (void) printf("%-7s", tmp_str); 997 } 998 999 cnt_ksp = (kstat_t *)dev_node->cnt_ksp; 1000 1001 if (kstat_read(kc, cnt_ksp, NULL) == FAIL) { 1002 (void) fprintf(stderr, gettext("%s: device %s%d " 1003 "(pic %d) no longer valid.\n"), 1004 pgmname, dev_node->name, 1005 dev_node->dev_inst, 1006 dev_node->pic_num); 1007 remove_dev_node(dev_node); 1008 dev_node = dev_list_head; 1009 continue; 1010 } 1011 1012 cnt_data = (kstat_named_t *)cnt_ksp->ks_data; 1013 1014 if (dev_node->r_w == EVT_READ) { 1015 read_r_evt_node(dev_node, dev_node->pic_num, cnt_data); 1016 iter++; 1017 } else { 1018 read_w_evt_node(dev_node, dev_node->pic_num, cnt_data); 1019 iter++; 1020 } 1021 1022 if ((!initial_read) && (iter == max_pic_num)) { 1023 iter = 0; 1024 (void) printf("\n"); 1025 } 1026 1027 /* 1028 * If there is more than one event node 1029 * per-pic then we are multiplexing. 1030 */ 1031 if ((dev_node->evt_node->next != dev_node->evt_node) && 1032 (!initial_read)) { 1033 dev_node->evt_node = dev_node->evt_node->next; 1034 set_evt(dev_node); 1035 } 1036 dev_node = dev_node->next; 1037 } 1038 initial_read = FALSE; 1039 } 1040 1041 1042 /* 1043 * Read a node that is marked as EVT_READ 1044 */ 1045 void 1046 read_r_evt_node(dev_node_t *dev_node, int pic_num, kstat_named_t *cnt_data) 1047 { 1048 evt_node_t *evt_node; 1049 kstat_t *pic_ksp; 1050 kstat_named_t *pic_data; 1051 uint64_t pcr_read; 1052 uint64_t clear_pcr_mask; 1053 uint64_t delta_count; 1054 int i; 1055 int match = 0; 1056 int evt_blank = 1; 1057 1058 evt_node = dev_node->evt_node; 1059 1060 pic_ksp = (kstat_t *)dev_node->pic_ksp; 1061 1062 if (kstat_read(kc, pic_ksp, NULL) == FAIL) { 1063 (void) fprintf(stderr, gettext("%s: device %s%d " 1064 "(pic %d) no longer valid.\n"), pgmname, 1065 dev_node->name, dev_node->dev_inst, 1066 dev_node->pic_num); 1067 remove_dev_node(dev_node); 1068 return; 1069 } 1070 1071 pic_data = (kstat_named_t *)pic_ksp->ks_data; 1072 clear_pcr_mask = pic_data[pic_ksp->ks_ndata-1].value.ui64; 1073 1074 /* 1075 * Get PCR value from device. We extract the portion 1076 * of the PCR relating to the pic we are interested by 1077 * AND'ing the inverse of the clear mask for this pic. 1078 * 1079 * The clear mask is usually used to clear the appropiate 1080 * section of the PCR before we write events into it. So 1081 * by using the inverse of the mask, we zero everything 1082 * *but* the section we are interested in. 1083 */ 1084 pcr_read = cnt_data[0].value.ui64; 1085 pcr_read = pcr_read & ~(clear_pcr_mask); 1086 1087 /* 1088 * If the event name is blank this is the first time that 1089 * this node has been accessed, so we read the pcr and 1090 * from that we get the event name if it exists. 1091 * 1092 * If the pcr read from the device does not match that 1093 * stored in the node, then it means that the event has 1094 * changed from its previous value, so we need to re-read 1095 * all the values. 1096 */ 1097 if ((strcmp(evt_node->evt_name, "") == 0) || 1098 (pcr_read != evt_node->evt_pcr_mask)) { 1099 1100 for (i = 0; i < pic_ksp->ks_ndata-1; i++) { 1101 if (pcr_read == pic_data[i].value.ui64) { 1102 match = TRUE; 1103 break; 1104 } 1105 } 1106 1107 /* 1108 * Able to resolve pcr value to a event name. 1109 */ 1110 if (match) { 1111 (void) strcpy(evt_node->evt_name, pic_data[i].name); 1112 evt_node->evt_pcr_mask = pcr_read; 1113 evt_node->total = 0; 1114 evt_node->prev_count = 1115 cnt_data[pic_num+1].value.ui64; 1116 1117 if ((evt_blank) && (!initial_read)) { 1118 (void) printf("%s\t%-8d\t", 1119 evt_node->evt_name, 0); 1120 evt_blank = 0; 1121 } 1122 1123 } else { 1124 (void) sprintf(evt_node->evt_name, "0x%llx", pcr_read); 1125 evt_node->evt_pcr_mask = pcr_read; 1126 evt_node->total = 0; 1127 evt_node->prev_count = 1128 cnt_data[pic_num+1].value.ui64; 1129 1130 if ((evt_blank) && (!initial_read)) { 1131 (void) printf("%s\t%-8d\t", 1132 evt_node->evt_name, 0); 1133 evt_blank = 0; 1134 } 1135 1136 } 1137 } else { 1138 /* Deal with wraparound of the counters */ 1139 if (cnt_data[pic_num+1].value.ui64 < evt_node->prev_count) { 1140 1141 delta_count = (UINT32_MAX-evt_node->prev_count) + 1142 cnt_data[pic_num+1].value.ui64; 1143 } else { 1144 /* Calcalate delta value */ 1145 delta_count = cnt_data[pic_num+1].value.ui64 1146 - evt_node->prev_count; 1147 } 1148 1149 1150 /* 1151 * Store value so that we can calculate delta next 1152 * time through. 1153 */ 1154 evt_node->prev_count = cnt_data[pic_num+1].value.ui64; 1155 1156 /* Update count total */ 1157 evt_node->total += delta_count; 1158 1159 if (delta) { 1160 (void) printf("%-20s %-9lld ", 1161 evt_node->evt_name, delta_count); 1162 } else { 1163 1164 (void) printf("%-20s %-9lld ", 1165 evt_node->evt_name, evt_node->total); 1166 } 1167 } 1168 } 1169 1170 1171 /* 1172 * Read event nodes marked as EVT_WRITE 1173 */ 1174 void 1175 read_w_evt_node(dev_node_t *dev_node, int pic_num, kstat_named_t *cnt_data) 1176 { 1177 kstat_t *pic_ksp; 1178 kstat_named_t *pic_data; 1179 evt_node_t *evt_node; 1180 uint64_t delta_count; 1181 uint64_t pcr_read; 1182 uint64_t clear_pcr_mask; 1183 1184 evt_node = dev_node->evt_node; 1185 1186 pic_ksp = (kstat_t *)dev_node->pic_ksp; 1187 1188 if (kstat_read(kc, pic_ksp, NULL) == FAIL) { 1189 (void) fprintf(stderr, gettext("%s: could not read " 1190 "%s%d\n"), pgmname, dev_node->name, 1191 dev_node->dev_inst); 1192 remove_dev_node(dev_node); 1193 return; 1194 } 1195 1196 pic_data = (kstat_named_t *)pic_ksp->ks_data; 1197 clear_pcr_mask = pic_data[pic_ksp->ks_ndata-1].value.ui64; 1198 1199 /* 1200 * Get PCR value from device. We extract the portion 1201 * of the PCR relating to the pic we are interested by 1202 * AND'ing the inverse of the clear mask for this pic. 1203 * 1204 * The clear mask is usually used to clear the appropiate 1205 * section of the PCR before we write events into it. So 1206 * by using the inverse of the mask, we zero everything 1207 * *but* the section we are interested in. 1208 */ 1209 pcr_read = cnt_data[0].value.ui64; 1210 pcr_read = pcr_read & ~(clear_pcr_mask); 1211 1212 /* 1213 * If the pcr value from the device does not match the 1214 * stored value, then the events on at least one of the 1215 * pics must have been change by another busstat instance. 1216 * 1217 * Regard this as a fatal error. 1218 */ 1219 if (pcr_read != evt_node->evt_pcr_mask) { 1220 (void) fprintf(stderr, gettext("%s: events changed (possibly " 1221 "by another busstat).\n"), pgmname); 1222 exit(2); 1223 } 1224 1225 /* 1226 * Calculate delta, and then store value just read to allow us to 1227 * calculate delta next time around. 1228 */ 1229 /* Deal with wraparound of the counters */ 1230 if (cnt_data[pic_num+1].value.ui64 < evt_node->prev_count) { 1231 1232 delta_count = (UINT32_MAX-evt_node->prev_count) + 1233 cnt_data[pic_num+1].value.ui64; 1234 } else { 1235 /* Calcalate delta value */ 1236 delta_count = cnt_data[pic_num+1].value.ui64 1237 - evt_node->prev_count; 1238 } 1239 1240 evt_node->prev_count = cnt_data[pic_num+1].value.ui64; 1241 1242 if (initial_read) { 1243 evt_node->total = 0; 1244 1245 } else { 1246 /* Update count total */ 1247 evt_node->total += delta_count; 1248 1249 if (delta) { 1250 (void) printf("%-20s %-9lld ", 1251 evt_node->evt_name, delta_count); 1252 } else { 1253 (void) printf("%-20s %-9lld ", 1254 evt_node->evt_name, evt_node->total); 1255 } 1256 } 1257 } 1258 1259 1260 /* 1261 * Check to see if any DR operations have occured, and deal with the 1262 * consequences. 1263 * 1264 * Use the Kstat chain ID to check for DR operations. If the ID has 1265 * changed then some kstats on system have been modified, we check 1266 * all the data structures to see are they still valid. If they are 1267 * not we remove them. 1268 */ 1269 void 1270 check_dr_ops() 1271 { 1272 dev_node_t *dev_node; 1273 kid_t new_id; 1274 kstat_t *ksp; 1275 int match = 0; 1276 1277 if ((new_id = kstat_chain_update(kc)) < 0) { 1278 (void) fprintf(stderr, gettext("%s: could not get " 1279 "kstat chain id\n"), pgmname); 1280 exit(1); 1281 } 1282 1283 if (new_id == 0) { 1284 /* Kstat chain has not changed. */ 1285 return; 1286 } 1287 1288 /* 1289 * Scan the chain of device nodes, making sure that their associated 1290 * kstats are still present. If not we remove the appropiate node. 1291 */ 1292 dev_node = dev_list_head; 1293 1294 while (dev_node != NULL) { 1295 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 1296 if ((strcmp("bus", ksp->ks_class) == 0) && 1297 (strcmp("counters", ksp->ks_name) == 0) && 1298 (strcmp(dev_node->name, ksp->ks_module) == 0) && 1299 (ksp->ks_instance == dev_node->dev_inst)) { 1300 match = 1; 1301 break; 1302 } 1303 } 1304 if (match == 0) { 1305 (void) fprintf(stderr, gettext("%s: device %s%d" 1306 " (pic %d) no longer valid.\n"), pgmname, 1307 dev_node->name, dev_node->dev_inst, 1308 dev_node->pic_num); 1309 1310 remove_dev_node(dev_node); 1311 } 1312 dev_node = dev_node->next; 1313 } 1314 } 1315 1316 1317 1318 /* 1319 * Remove a device node and its associated event nodes. 1320 */ 1321 void 1322 remove_dev_node(dev_node_t *dev_node) 1323 { 1324 dev_node_t *curr_node; 1325 dev_node_t *prev_node; 1326 evt_node_t *curr_evt_node; 1327 evt_node_t *next_evt_node; 1328 evt_node_t *start_pos; 1329 1330 curr_node = dev_list_head; 1331 1332 if (curr_node == dev_node) { 1333 dev_list_head = dev_node->next; 1334 1335 if (dev_list_head == NULL) { 1336 (void) fprintf(stderr, gettext("%s: no " 1337 "devices left to monitor.\n"), 1338 pgmname); 1339 exit(1); 1340 } 1341 1342 /* Remove each event node first */ 1343 start_pos = dev_node->evt_node; 1344 curr_evt_node = start_pos->next; 1345 1346 while (curr_evt_node != start_pos) { 1347 next_evt_node = curr_evt_node->next; 1348 1349 free(curr_evt_node); 1350 curr_evt_node = next_evt_node; 1351 } 1352 1353 free(start_pos); 1354 free(dev_node); 1355 return; 1356 } 1357 1358 /* Find the device node */ 1359 prev_node = dev_list_head; 1360 curr_node = prev_node->next; 1361 1362 while (curr_node != NULL) { 1363 if (curr_node == dev_node) { 1364 prev_node->next = curr_node->next; 1365 1366 /* Remove each event node first */ 1367 start_pos = dev_node->evt_node; 1368 curr_evt_node = start_pos->next; 1369 1370 while (curr_evt_node != start_pos) { 1371 next_evt_node = curr_evt_node->next; 1372 1373 free(curr_evt_node); 1374 curr_evt_node = next_evt_node; 1375 } 1376 free(start_pos); 1377 1378 free(dev_node); 1379 return; 1380 } 1381 prev_node = curr_node; 1382 curr_node = curr_node->next; 1383 } 1384 } 1385 1386 1387 /* 1388 * Find a device node in the linked list of dev_nodes. Match 1389 * is done on device name, and instance number. 1390 */ 1391 dev_node_t * 1392 find_dev_node(char *name, int inst_num, int pic_num) 1393 { 1394 dev_node_t *curr_node; 1395 1396 curr_node = dev_list_head; 1397 1398 while (curr_node != NULL) { 1399 if ((strcmp(curr_node->name, name) == 0) && 1400 (curr_node->dev_inst == inst_num) && 1401 (curr_node->pic_num == pic_num)) { 1402 return (curr_node); 1403 } 1404 1405 curr_node = curr_node->next; 1406 } 1407 1408 return (NULL); 1409 } 1410 1411 1412 /* 1413 * Determines whether the string represents a event name 1414 * or a numeric value. Numeric value can be dec, hex 1415 * or octal. All are converted to long int. 1416 */ 1417 int64_t 1418 is_num(char *name) 1419 { 1420 char *remainder = NULL; 1421 int64_t num; 1422 1423 num = (int64_t)strtol(name, &remainder, 0); 1424 1425 if (name == remainder) { 1426 return (EVT_STR); 1427 } else { 1428 return (num); 1429 } 1430 } 1431 1432 1433 /* 1434 * Find a pointer to the specified picN kstat. First 1435 * search for the specific kstat, and if that can't 1436 * be found search for any picN kstat belonging to this device. 1437 */ 1438 kstat_t * 1439 find_pic_kstat(char *dev_name, int inst_num, char *pic) 1440 { 1441 kstat_t *ksp; 1442 kstat_t *p_ksp; 1443 1444 /* Look for specific picN kstat */ 1445 if ((p_ksp = kstat_lookup(kc, dev_name, inst_num, pic)) == NULL) { 1446 1447 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 1448 if ((strcmp(ksp->ks_class, "bus") == 0) && 1449 (strcmp(ksp->ks_name, pic) == 0) && 1450 (strcmp(ksp->ks_module, dev_name) == 0)) { 1451 1452 return (ksp); 1453 } 1454 } 1455 } 1456 return (p_ksp); 1457 } 1458 1459 1460 /* 1461 * Print column titles. 1462 * Can be turned off by -n option. 1463 */ 1464 void 1465 print_banner() 1466 { 1467 int i; 1468 1469 (void) printf("time dev "); 1470 1471 for (i = 0; i < max_pic_num; i++) 1472 (void) printf("event%d " 1473 "pic%d ", i, i); 1474 1475 (void) printf("\n"); 1476 1477 banner = FALSE; 1478 } 1479 1480 1481 /* 1482 * Print the elapsed time in seconds, since the last call. 1483 */ 1484 void 1485 print_timestamp() 1486 { 1487 static hrtime_t curr_time = 0; 1488 static hrtime_t total_elapsed = 0; 1489 hrtime_t new_time = 0; 1490 hrtime_t elapsed = 0; 1491 hrtime_t rem = 0; 1492 1493 if (initial_read) { 1494 curr_time = (uint64_t)gethrtime(); 1495 return; 1496 } 1497 1498 new_time = gethrtime(); 1499 1500 elapsed = (new_time - curr_time)/NANO; 1501 1502 /* Round up time value if necessary */ 1503 rem = (new_time - curr_time)%NANO; 1504 if (rem >= NANO/2) 1505 elapsed += 1; 1506 1507 total_elapsed += elapsed; 1508 1509 (void) printf("%-4llu ", total_elapsed); 1510 1511 curr_time = new_time; 1512 } 1513 1514 1515 void 1516 usage() 1517 { 1518 (void) printf(gettext("Usage : busstat [-a] [-h] [-l] [-n]\n" 1519 " [-e device-inst]\n" 1520 " [-w device-inst " 1521 "[,pic0=<event>] [,picN=<event>] ]\n" 1522 " [-r device-inst]\n" 1523 " [ interval [count] ]\n")); 1524 1525 exit(2); 1526 } 1527 1528 1529 void * 1530 safe_malloc(size_t size) 1531 { 1532 void *a; 1533 1534 if ((a = malloc(size)) == NULL) { 1535 (void) fprintf(stderr, 1536 gettext("%s: out of memory.\n"), pgmname); 1537 exit(1); 1538 } 1539 1540 return (a); 1541 } 1542 1543 /* 1544 * Create and arm the timer. 1545 */ 1546 void 1547 set_timer(int interval) 1548 { 1549 timer_t t_id; /* Timer id */ 1550 itimerspec_t time_struct; 1551 struct sigevent sig_struct; 1552 struct sigaction act; 1553 1554 bzero(&sig_struct, sizeof (struct sigevent)); 1555 bzero(&act, sizeof (struct sigaction)); 1556 1557 /* Create timer */ 1558 sig_struct.sigev_notify = SIGEV_SIGNAL; 1559 sig_struct.sigev_signo = SIGUSR1; 1560 sig_struct.sigev_value.sival_int = 0; 1561 1562 if (timer_create(CLOCK_REALTIME, &sig_struct, &t_id) != 0) { 1563 (void) fprintf(stderr, gettext("%s: Timer creation failed.\n"), 1564 pgmname); 1565 exit(1); 1566 } 1567 1568 act.sa_handler = handle_sig; 1569 1570 if (sigaction(SIGUSR1, &act, NULL) != 0) { 1571 (void) fprintf(stderr, gettext("%s: could not setup signal " 1572 "handler"), pgmname); 1573 exit(1); 1574 } 1575 1576 time_struct.it_value.tv_sec = interval; 1577 time_struct.it_value.tv_nsec = 0; 1578 time_struct.it_interval.tv_sec = interval; 1579 time_struct.it_interval.tv_nsec = 0; 1580 1581 /* Arm timer */ 1582 if ((timer_settime(t_id, 0, &time_struct, NULL)) != 0) { 1583 (void) fprintf(stderr, gettext("%s: Setting timer failed.\n"), 1584 pgmname); 1585 exit(1); 1586 } 1587 } 1588 1589 1590 /* ARGSUSED */ 1591 void 1592 handle_sig(int x) 1593 { 1594 } 1595 1596 /* 1597 * return a boolean value indicating whether or not 1598 * a string consists solely of characters which are 1599 * digits 0..9 1600 */ 1601 int 1602 strisnum(const char *s) 1603 { 1604 for (; *s != '\0'; s++) { 1605 if (*s < '0' || *s > '9') 1606 return (0); 1607 } 1608 return (1); 1609 } 1610