op_events.c revision 2b16b5ffd52ea5c0289e5ce794298bce5d941b2b
1/** 2 * @file op_events.c 3 * Details of PMC profiling events 4 * 5 * You can have silliness here. 6 * 7 * @remark Copyright 2002 OProfile authors 8 * @remark Read the file COPYING 9 * 10 * @author John Levon 11 * @author Philippe Elie 12 */ 13 14#include "op_events.h" 15#include "op_libiberty.h" 16#include "op_fileio.h" 17#include "op_string.h" 18#include "op_cpufreq.h" 19 20#include <string.h> 21#include <stdlib.h> 22#include <stdio.h> 23 24static LIST_HEAD(events_list); 25static LIST_HEAD(um_list); 26 27static char const * filename; 28static unsigned int line_nr; 29 30static void parse_error(char const * context) 31{ 32 fprintf(stderr, "oprofile: parse error in %s, line %u\n", 33 filename, line_nr); 34 fprintf(stderr, "%s\n", context); 35 exit(EXIT_FAILURE); 36} 37 38 39static int parse_int(char const * str) 40{ 41 int value; 42 if (sscanf(str, "%d", &value) != 1) 43 parse_error("expected decimal value"); 44 45 return value; 46} 47 48 49static int parse_hex(char const * str) 50{ 51 int value; 52 /* 0x/0X to force the use of hexa notation for field intended to 53 be in hexadecimal */ 54 if (sscanf(str, "0x%x", &value) != 1 && 55 sscanf(str, "0X%x", &value) != 1) 56 parse_error("expected hexadecimal value"); 57 58 return value; 59} 60 61 62static u64 parse_long_hex(char const * str) 63{ 64 u64 value; 65 if (sscanf(str, "%Lx", &value) != 1) 66 parse_error("expected long hexadecimal value"); 67 68 fflush(stderr); 69 return value; 70} 71 72 73/* name:MESI type:bitmask default:0x0f */ 74static void parse_um(struct op_unit_mask * um, char const * line) 75{ 76 int seen_name = 0; 77 int seen_type = 0; 78 int seen_default = 0; 79 char const * valueend = line + 1; 80 char const * tagend = line + 1; 81 char const * start = line; 82 83 while (*valueend) { 84 valueend = skip_nonws(valueend); 85 86 while (*tagend != ':' && *tagend) 87 ++tagend; 88 89 if (valueend == tagend) 90 break; 91 92 if (!*tagend) 93 parse_error("parse_um() expected :value"); 94 95 ++tagend; 96 97 if (strisprefix(start, "name")) { 98 if (seen_name) 99 parse_error("duplicate name: tag"); 100 seen_name = 1; 101 um->name = op_xstrndup(tagend, valueend - tagend); 102 } else if (strisprefix(start, "type")) { 103 if (seen_type) 104 parse_error("duplicate type: tag"); 105 seen_type = 1; 106 if (strisprefix(tagend, "mandatory")) { 107 um->unit_type_mask = utm_mandatory; 108 } else if (strisprefix(tagend, "bitmask")) { 109 um->unit_type_mask = utm_bitmask; 110 } else if (strisprefix(tagend, "exclusive")) { 111 um->unit_type_mask = utm_exclusive; 112 } else { 113 parse_error("invalid unit mask type"); 114 } 115 } else if (strisprefix(start, "default")) { 116 if (seen_default) 117 parse_error("duplicate default: tag"); 118 seen_default = 1; 119 um->default_mask = parse_hex(tagend); 120 } else { 121 parse_error("invalid unit mask tag"); 122 } 123 124 valueend = skip_ws(valueend); 125 tagend = valueend; 126 start = valueend; 127 } 128} 129 130 131/* \t0x08 (M)odified cache state */ 132static void parse_um_entry(struct op_described_um * entry, char const * line) 133{ 134 char const * c = line; 135 136 c = skip_ws(c); 137 entry->value = parse_hex(c); 138 c = skip_nonws(c); 139 140 if (!*c) 141 parse_error("invalid unit mask entry"); 142 143 c = skip_ws(c); 144 145 if (!*c) 146 parse_error("invalid unit mask entry"); 147 148 entry->desc = xstrdup(c); 149} 150 151 152static struct op_unit_mask * new_unit_mask(void) 153{ 154 struct op_unit_mask * um = xmalloc(sizeof(struct op_unit_mask)); 155 memset(um, '\0', sizeof(struct op_unit_mask)); 156 list_add_tail(&um->um_next, &um_list); 157 158 return um; 159} 160 161 162/* 163 * name:zero type:mandatory default:0x0 164 * \t0x0 No unit mask 165 */ 166static void read_unit_masks(char const * file) 167{ 168 struct op_unit_mask * um = NULL; 169 char * line; 170 FILE * fp = fopen(file, "r"); 171 172 if (!fp) { 173 fprintf(stderr, 174 "oprofile: could not open unit mask description file %s\n", file); 175 exit(EXIT_FAILURE); 176 } 177 178 filename = file; 179 line_nr = 1; 180 181 line = op_get_line(fp); 182 183 while (line) { 184 if (empty_line(line) || comment_line(line)) 185 goto next; 186 187 if (line[0] != '\t') { 188 um = new_unit_mask(); 189 parse_um(um, line); 190 } else { 191 if (!um) 192 parse_error("no unit mask name line"); 193 if (um->num >= MAX_UNIT_MASK) 194 parse_error("oprofile: maximum unit mask entries exceeded"); 195 196 parse_um_entry(&um->um[um->num], line); 197 ++(um->num); 198 } 199 200next: 201 free(line); 202 line = op_get_line(fp); 203 ++line_nr; 204 } 205 206 fclose(fp); 207} 208 209 210static u32 parse_counter_mask(char const * str) 211{ 212 u32 mask = 0; 213 char const * numstart = str; 214 215 while (*numstart) { 216 mask |= 1 << parse_int(numstart); 217 218 while (*numstart && *numstart != ',') 219 ++numstart; 220 /* skip , unless we reach eos */ 221 if (*numstart) 222 ++numstart; 223 224 numstart = skip_ws(numstart); 225 } 226 227 return mask; 228} 229 230 231static struct op_unit_mask * find_um(char const * value) 232{ 233 struct list_head * pos; 234 235 list_for_each(pos, &um_list) { 236 struct op_unit_mask * um = list_entry(pos, struct op_unit_mask, um_next); 237 if (strcmp(value, um->name) == 0) 238 return um; 239 } 240 241 fprintf(stderr, "oprofile: could not find unit mask %s\n", value); 242 exit(EXIT_FAILURE); 243} 244 245 246/* parse either a "tag:value" or a ": trailing description string" */ 247static int next_token(char const ** cp, char ** name, char ** value) 248{ 249 size_t tag_len; 250 size_t val_len; 251 char const * c = *cp; 252 char const * end; 253 char const * colon; 254 255 c = skip_ws(c); 256 end = colon = c; 257 end = skip_nonws(end); 258 259 colon = strchr(colon, ':'); 260 261 if (!colon) { 262 if (*c) 263 parse_error("next_token(): garbage at end of line"); 264 return 0; 265 } 266 267 if (colon >= end) 268 parse_error("next_token() expected ':'"); 269 270 tag_len = colon - c; 271 val_len = end - (colon + 1); 272 273 if (!tag_len) { 274 /* : trailing description */ 275 end = skip_ws(end); 276 *name = xstrdup("desc"); 277 *value = xstrdup(end); 278 end += strlen(end); 279 } else { 280 /* tag:value */ 281 *name = op_xstrndup(c, tag_len); 282 *value = op_xstrndup(colon + 1, val_len); 283 end = skip_ws(end); 284 } 285 286 *cp = end; 287 return 1; 288} 289 290 291static struct op_event * new_event(void) 292{ 293 struct op_event * event = xmalloc(sizeof(struct op_event)); 294 memset(event, '\0', sizeof(struct op_event)); 295 list_add_tail(&event->event_next, &events_list); 296 297 return event; 298} 299 300 301/* event:0x00 counters:0 um:zero minimum:4096 name:ISSUES : Total issues */ 302static void read_events(char const * file) 303{ 304 struct op_event * event = NULL; 305 char * line; 306 char * name; 307 char * value; 308 char const * c; 309 int seen_event, seen_counters, seen_um, seen_minimum, seen_name; 310 FILE * fp = fopen(file, "r"); 311 312 if (!fp) { 313 fprintf(stderr, "oprofile: could not open event description file %s\n", file); 314 exit(EXIT_FAILURE); 315 } 316 317 filename = file; 318 line_nr = 1; 319 320 line = op_get_line(fp); 321 322 while (line) { 323 if (empty_line(line) || comment_line(line)) 324 goto next; 325 326 seen_name = 0; 327 seen_event = 0; 328 seen_counters = 0; 329 seen_um = 0; 330 seen_minimum = 0; 331 event = new_event(); 332 333 c = line; 334 while (next_token(&c, &name, &value)) { 335 if (strcmp(name, "name") == 0) { 336 if (seen_name) 337 parse_error("duplicate name: tag"); 338 seen_name = 1; 339 if (strchr(value, '/') != NULL) 340 parse_error("invalid event name"); 341 if (strchr(value, '.') != NULL) 342 parse_error("invalid event name"); 343 event->name = value; 344 } else if (strcmp(name, "event") == 0) { 345 if (seen_event) 346 parse_error("duplicate event: tag"); 347 seen_event = 1; 348 event->val = parse_hex(value); 349 free(value); 350 } else if (strcmp(name, "counters") == 0) { 351 if (seen_counters) 352 parse_error("duplicate counters: tag"); 353 seen_counters = 1; 354 event->counter_mask = parse_counter_mask(value); 355 free(value); 356 } else if (strcmp(name, "um") == 0) { 357 if (seen_um) 358 parse_error("duplicate um: tag"); 359 seen_um = 1; 360 event->unit = find_um(value); 361 event->unit->used = 1; 362 free(value); 363 } else if (strcmp(name, "minimum") == 0) { 364 if (seen_minimum) 365 parse_error("duplicate minimum: tag"); 366 seen_minimum = 1; 367 event->min_count = parse_int(value); 368 free(value); 369 } else if (strcmp(name, "desc") == 0) { 370 event->desc = value; 371 } else { 372 parse_error("unknown tag"); 373 } 374 375 free(name); 376 } 377next: 378 free(line); 379 line = op_get_line(fp); 380 ++line_nr; 381 } 382 383 fclose(fp); 384} 385 386 387/* usefull for make check */ 388static void check_unit_mask(struct op_unit_mask const * um, 389 char const * cpu_name) 390{ 391 u32 i; 392 393 if (!um->used) { 394 fprintf(stderr, "um %s is not used\n", um->name); 395 exit(EXIT_FAILURE); 396 } 397 398 if (um->unit_type_mask == utm_mandatory && um->num != 1) { 399 fprintf(stderr, "mandatory um %s doesn't contain exactly one " 400 "entry (%s)\n", um->name, cpu_name); 401 exit(EXIT_FAILURE); 402 } else if (um->unit_type_mask == utm_bitmask) { 403 u32 default_mask = um->default_mask; 404 for (i = 0; i < um->num; ++i) 405 default_mask &= ~um->um[i].value; 406 407 if (default_mask) { 408 fprintf(stderr, "um %s default mask is not valid " 409 "(%s)\n", um->name, cpu_name); 410 exit(EXIT_FAILURE); 411 } 412 } else { 413 for (i = 0; i < um->num; ++i) { 414 if (um->default_mask == um->um[i].value) 415 break; 416 } 417 418 if (i == um->num) { 419 fprintf(stderr, "exclusive um %s default value is not " 420 "valid (%s)\n", um->name, cpu_name); 421 exit(EXIT_FAILURE); 422 } 423 } 424} 425 426 427static void load_events(op_cpu cpu_type) 428{ 429 char const * cpu_name = op_get_cpu_name(cpu_type); 430 char * event_dir; 431 char * event_file; 432 char * um_file; 433 char * dir; 434 struct list_head * pos; 435 436 if (!list_empty(&events_list)) 437 return; 438 439 dir = getenv("OPROFILE_EVENTS_DIR"); 440 if (dir == NULL) 441 dir = OP_DATADIR; 442 443 event_dir = xmalloc(strlen(dir) + strlen("/") + strlen(cpu_name) + 444 strlen("/") + 1); 445 strcpy(event_dir, dir); 446 strcat(event_dir, "/"); 447 448 strcat(event_dir, cpu_name); 449 strcat(event_dir, "/"); 450 451 event_file = xmalloc(strlen(event_dir) + strlen("events") + 1); 452 strcpy(event_file, event_dir); 453 strcat(event_file, "events"); 454 455 um_file = xmalloc(strlen(event_dir) + strlen("unit_masks") + 1); 456 strcpy(um_file, event_dir); 457 strcat(um_file, "unit_masks"); 458 459 read_unit_masks(um_file); 460 read_events(event_file); 461 462 /* sanity check: all unit mask must be used */ 463 list_for_each(pos, &um_list) { 464 struct op_unit_mask * um = list_entry(pos, struct op_unit_mask, um_next); 465 466 check_unit_mask(um, cpu_name); 467 } 468 469 free(um_file); 470 free(event_file); 471 free(event_dir); 472} 473 474 475struct list_head * op_events(op_cpu cpu_type) 476{ 477 load_events(cpu_type); 478 return &events_list; 479} 480 481 482static void delete_unit_mask(struct op_unit_mask * unit) 483{ 484 u32 cur; 485 for (cur = 0 ; cur < unit->num ; ++cur) { 486 if (unit->um[cur].desc) 487 free(unit->um[cur].desc); 488 } 489 490 if (unit->name) 491 free(unit->name); 492 493 list_del(&unit->um_next); 494 free(unit); 495} 496 497 498static void delete_event(struct op_event * event) 499{ 500 if (event->name) 501 free(event->name); 502 if (event->desc) 503 free(event->desc); 504 505 list_del(&event->event_next); 506 free(event); 507} 508 509 510void op_free_events(void) 511{ 512 struct list_head * pos, * pos2; 513 list_for_each_safe(pos, pos2, &events_list) { 514 struct op_event * event = list_entry(pos, struct op_event, event_next); 515 delete_event(event); 516 } 517 518 list_for_each_safe(pos, pos2, &um_list) { 519 struct op_unit_mask * unit = list_entry(pos, struct op_unit_mask, um_next); 520 delete_unit_mask(unit); 521 } 522} 523 524 525static struct op_event * find_event(u32 nr) 526{ 527 struct list_head * pos; 528 529 list_for_each(pos, &events_list) { 530 struct op_event * event = list_entry(pos, struct op_event, event_next); 531 if (event->val == nr) 532 return event; 533 } 534 535 return NULL; 536} 537 538 539static FILE * open_event_mapping_file(char const * cpu_name) 540{ 541 char * ev_map_file; 542 char * dir; 543 dir = getenv("OPROFILE_EVENTS_DIR"); 544 if (dir == NULL) 545 dir = OP_DATADIR; 546 547 ev_map_file = xmalloc(strlen(dir) + strlen("/") + strlen(cpu_name) + 548 strlen("/") + + strlen("event_mappings") + 1); 549 strcpy(ev_map_file, dir); 550 strcat(ev_map_file, "/"); 551 552 strcat(ev_map_file, cpu_name); 553 strcat(ev_map_file, "/"); 554 strcat(ev_map_file, "event_mappings"); 555 filename = ev_map_file; 556 return (fopen(ev_map_file, "r")); 557} 558 559 560/** 561 * This function is PPC64-specific. 562 */ 563static char const * get_mapping(u32 nr, FILE * fp) 564{ 565 char * line; 566 char * name; 567 char * value; 568 char const * c; 569 char * map = NULL; 570 int seen_event = 0, seen_mmcr0 = 0, seen_mmcr1 = 0, seen_mmcra = 0; 571 u32 mmcr0 = 0; 572 u64 mmcr1 = 0; 573 u32 mmcra = 0; 574 int event_found = 0; 575 576 line_nr = 1; 577 line = op_get_line(fp); 578 while (line && !event_found) { 579 if (empty_line(line) || comment_line(line)) 580 goto next; 581 582 seen_event = 0; 583 seen_mmcr0 = 0; 584 seen_mmcr1 = 0; 585 seen_mmcra = 0; 586 mmcr0 = 0; 587 mmcr1 = 0; 588 mmcra = 0; 589 590 c = line; 591 while (next_token(&c, &name, &value)) { 592 if (strcmp(name, "event") == 0) { 593 u32 evt; 594 if (seen_event) 595 parse_error("duplicate event tag"); 596 seen_event = 1; 597 evt = parse_hex(value); 598 if (evt == nr) 599 event_found = 1; 600 free(value); 601 } else if (strcmp(name, "mmcr0") == 0) { 602 if (seen_mmcr0) 603 parse_error("duplicate mmcr0 tag"); 604 seen_mmcr0 = 1; 605 mmcr0 = parse_hex(value); 606 free(value); 607 } else if (strcmp(name, "mmcr1") == 0) { 608 if (seen_mmcr1) 609 parse_error("duplicate mmcr1: tag"); 610 seen_mmcr1 = 1; 611 mmcr1 = parse_long_hex(value); 612 free(value); 613 } else if (strcmp(name, "mmcra") == 0) { 614 if (seen_mmcra) 615 parse_error("duplicate mmcra: tag"); 616 seen_mmcra = 1; 617 mmcra = parse_hex(value); 618 free(value); 619 } else { 620 parse_error("unknown tag"); 621 } 622 623 free(name); 624 } 625next: 626 free(line); 627 line = op_get_line(fp); 628 ++line_nr; 629 } 630 if (event_found) { 631 if (!seen_mmcr0 || !seen_mmcr1 || !seen_mmcra) { 632 fprintf(stderr, "Error: Missing information in line %d of event mapping file %s\n", line_nr, filename); 633 exit(EXIT_FAILURE); 634 } 635 map = xmalloc(70); 636 snprintf(map, 70, "mmcr0:%u mmcr1:%Lu mmcra:%u", 637 mmcr0, mmcr1, mmcra); 638 } 639 640 return map; 641} 642 643 644char const * find_mapping_for_event(u32 nr, op_cpu cpu_type) 645{ 646 char const * cpu_name = op_get_cpu_name(cpu_type); 647 FILE * fp = open_event_mapping_file(cpu_name); 648 char const * map = NULL; 649 switch (cpu_type) { 650 case CPU_PPC64_PA6T: 651 case CPU_PPC64_970: 652 case CPU_PPC64_970MP: 653 case CPU_PPC64_POWER4: 654 case CPU_PPC64_POWER5: 655 case CPU_PPC64_POWER5p: 656 case CPU_PPC64_POWER5pp: 657 case CPU_PPC64_POWER6: 658 if (!fp) { 659 fprintf(stderr, "oprofile: could not open event mapping file %s\n", filename); 660 exit(EXIT_FAILURE); 661 } else { 662 map = get_mapping(nr, fp); 663 } 664 break; 665 default: 666 break; 667 } 668 669 if (fp) 670 fclose(fp); 671 672 return map; 673} 674 675 676struct op_event * find_event_by_name(char const * name) 677{ 678 struct list_head * pos; 679 680 list_for_each(pos, &events_list) { 681 struct op_event * event = list_entry(pos, struct op_event, event_next); 682 if (strcmp(event->name, name) == 0) 683 return event; 684 } 685 686 return NULL; 687} 688 689 690struct op_event * op_find_event(op_cpu cpu_type, u32 nr) 691{ 692 struct op_event * event; 693 694 load_events(cpu_type); 695 696 event = find_event(nr); 697 698 return event; 699} 700 701 702int op_check_events(int ctr, u32 nr, u32 um, op_cpu cpu_type) 703{ 704 int ret = OP_OK_EVENT; 705 struct op_event * event; 706 size_t i; 707 u32 ctr_mask = 1 << ctr; 708 709 load_events(cpu_type); 710 711 event = find_event(nr); 712 713 if (!event) { 714 ret |= OP_INVALID_EVENT; 715 return ret; 716 } 717 718 if ((event->counter_mask & ctr_mask) == 0) 719 ret |= OP_INVALID_COUNTER; 720 721 if (event->unit->unit_type_mask == utm_bitmask) { 722 for (i = 0; i < event->unit->num; ++i) 723 um &= ~(event->unit->um[i].value); 724 725 if (um) 726 ret |= OP_INVALID_UM; 727 728 } else { 729 for (i = 0; i < event->unit->num; ++i) { 730 if (event->unit->um[i].value == um) 731 break; 732 } 733 734 if (i == event->unit->num) 735 ret |= OP_INVALID_UM; 736 } 737 738 return ret; 739} 740 741 742void op_default_event(op_cpu cpu_type, struct op_default_event_descr * descr) 743{ 744 descr->name = ""; 745 descr->um = 0x0; 746 /* A fixed value of CPU cycles; this should ensure good 747 * granulity even on faster CPUs, though it will generate more 748 * interrupts. 749 */ 750 descr->count = 100000; 751 752 switch (cpu_type) { 753 case CPU_PPRO: 754 case CPU_PII: 755 case CPU_PIII: 756 case CPU_P6_MOBILE: 757 case CPU_CORE: 758 case CPU_CORE_2: 759 case CPU_ATHLON: 760 case CPU_HAMMER: 761 case CPU_FAMILY10: 762 descr->name = "CPU_CLK_UNHALTED"; 763 break; 764 765 case CPU_RTC: 766 descr->name = "RTC_INTERRUPTS"; 767 descr->count = 1024; 768 break; 769 770 case CPU_P4: 771 case CPU_P4_HT2: 772 descr->name = "GLOBAL_POWER_EVENTS"; 773 descr->um = 0x1; 774 break; 775 776 case CPU_IA64: 777 case CPU_IA64_1: 778 case CPU_IA64_2: 779 descr->count = 1000000; 780 descr->name = "CPU_CYCLES"; 781 break; 782 783 case CPU_AXP_EV4: 784 case CPU_AXP_EV5: 785 case CPU_AXP_PCA56: 786 case CPU_AXP_EV6: 787 case CPU_AXP_EV67: 788 descr->name = "CYCLES"; 789 break; 790 791 // we could possibly use the CCNT 792 case CPU_ARM_XSCALE1: 793 case CPU_ARM_XSCALE2: 794 case CPU_ARM_MPCORE: 795 case CPU_ARM_V6: 796 case CPU_AVR32: 797 descr->name = "CPU_CYCLES"; 798 break; 799 800 case CPU_PPC64_PA6T: 801 case CPU_PPC64_970: 802 case CPU_PPC64_970MP: 803 case CPU_PPC_7450: 804 case CPU_PPC64_POWER4: 805 case CPU_PPC64_POWER5: 806 case CPU_PPC64_POWER6: 807 case CPU_PPC64_POWER5p: 808 case CPU_PPC64_POWER5pp: 809 case CPU_PPC64_CELL: 810 descr->name = "CYCLES"; 811 break; 812 813 case CPU_MIPS_20K: 814 descr->name = "CYCLES"; 815 break; 816 817 case CPU_MIPS_24K: 818 descr->name = "INSTRUCTIONS"; 819 break; 820 821 case CPU_MIPS_34K: 822 descr->name = "INSTRUCTIONS"; 823 break; 824 825 case CPU_MIPS_5K: 826 case CPU_MIPS_25K: 827 descr->name = "CYCLES"; 828 break; 829 830 case CPU_MIPS_R10000: 831 case CPU_MIPS_R12000: 832 descr->name = "INSTRUCTIONS_GRADUATED"; 833 break; 834 835 case CPU_MIPS_RM7000: 836 case CPU_MIPS_RM9000: 837 descr->name = "INSTRUCTIONS_ISSUED"; 838 break; 839 840 case CPU_MIPS_SB1: 841 descr->name = "INSN_SURVIVED_STAGE7"; 842 break; 843 844 case CPU_MIPS_VR5432: 845 case CPU_MIPS_VR5500: 846 descr->name = "INSTRUCTIONS_EXECUTED"; 847 break; 848 849 case CPU_PPC_E500: 850 case CPU_PPC_E500_2: 851 case CPU_PPC_E300: 852 descr->name = "CPU_CLK"; 853 break; 854 855 // don't use default, if someone add a cpu he wants a compiler 856 // warning if he forgets to handle it here. 857 case CPU_TIMER_INT: 858 case CPU_NO_GOOD: 859 case MAX_CPU_TYPE: 860 break; 861 } 862} 863