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 #include "op_hw_specific.h" 20 21 #include <string.h> 22 #include <stdlib.h> 23 #include <stdio.h> 24 25 static LIST_HEAD(events_list); 26 static LIST_HEAD(um_list); 27 28 static char const * filename; 29 static unsigned int line_nr; 30 31 static void delete_event(struct op_event * event); 32 static void read_events(char const * file); 33 static void read_unit_masks(char const * file); 34 static void free_unit_mask(struct op_unit_mask * um); 35 36 static char *build_fn(const char *cpu_name, const char *fn) 37 { 38 char *s; 39 static const char *dir; 40 if (dir == NULL) 41 dir = getenv("OPROFILE_EVENTS_DIR"); 42 if (dir == NULL) 43 dir = OP_DATADIR; 44 s = xmalloc(strlen(dir) + strlen(cpu_name) + strlen(fn) + 5); 45 sprintf(s, "%s/%s/%s", dir, cpu_name, fn); 46 return s; 47 } 48 49 static void parse_error(char const * context) 50 { 51 fprintf(stderr, "oprofile: parse error in %s, line %u\n", 52 filename, line_nr); 53 fprintf(stderr, "%s\n", context); 54 exit(EXIT_FAILURE); 55 } 56 57 58 static int parse_int(char const * str) 59 { 60 int value; 61 if (sscanf(str, "%d", &value) != 1) 62 parse_error("expected decimal value"); 63 64 return value; 65 } 66 67 68 static int parse_hex(char const * str) 69 { 70 int value; 71 /* 0x/0X to force the use of hexa notation for field intended to 72 be in hexadecimal */ 73 if (sscanf(str, "0x%x", &value) != 1 && 74 sscanf(str, "0X%x", &value) != 1) 75 parse_error("expected hexadecimal value"); 76 77 return value; 78 } 79 80 81 static u64 parse_long_hex(char const * str) 82 { 83 u64 value; 84 if (sscanf(str, "%Lx", &value) != 1) 85 parse_error("expected long hexadecimal value"); 86 87 fflush(stderr); 88 return value; 89 } 90 91 static void include_um(const char *start, const char *end) 92 { 93 char *s; 94 char cpu[end - start + 1]; 95 int old_line_nr; 96 const char *old_filename; 97 98 strncpy(cpu, start, end - start); 99 cpu[end - start] = 0; 100 s = build_fn(cpu, "unit_masks"); 101 old_line_nr = line_nr; 102 old_filename = filename; 103 read_unit_masks(s); 104 line_nr = old_line_nr; 105 filename = old_filename; 106 free(s); 107 } 108 109 /* name:MESI type:bitmask default:0x0f */ 110 static void parse_um(struct op_unit_mask * um, char const * line) 111 { 112 int seen_name = 0; 113 int seen_type = 0; 114 int seen_default = 0; 115 char const * valueend = line + 1; 116 char const * tagend = line + 1; 117 char const * start = line; 118 119 while (*valueend) { 120 valueend = skip_nonws(valueend); 121 122 while (*tagend != ':' && *tagend) 123 ++tagend; 124 125 if (valueend == tagend) 126 break; 127 128 if (!*tagend) 129 parse_error("parse_um() expected :value"); 130 131 ++tagend; 132 133 if (strisprefix(start, "include")) { 134 if (seen_name + seen_type + seen_default > 0) 135 parse_error("include must be on its own"); 136 free_unit_mask(um); 137 include_um(tagend, valueend); 138 return; 139 } 140 141 if (strisprefix(start, "name")) { 142 if (seen_name) 143 parse_error("duplicate name: tag"); 144 seen_name = 1; 145 um->name = op_xstrndup(tagend, valueend - tagend); 146 } else if (strisprefix(start, "type")) { 147 if (seen_type) 148 parse_error("duplicate type: tag"); 149 seen_type = 1; 150 if (strisprefix(tagend, "mandatory")) { 151 um->unit_type_mask = utm_mandatory; 152 } else if (strisprefix(tagend, "bitmask")) { 153 um->unit_type_mask = utm_bitmask; 154 } else if (strisprefix(tagend, "exclusive")) { 155 um->unit_type_mask = utm_exclusive; 156 } else { 157 parse_error("invalid unit mask type"); 158 } 159 } else if (strisprefix(start, "default")) { 160 if (seen_default) 161 parse_error("duplicate default: tag"); 162 seen_default = 1; 163 um->default_mask = parse_hex(tagend); 164 } else { 165 parse_error("invalid unit mask tag"); 166 } 167 168 valueend = skip_ws(valueend); 169 tagend = valueend; 170 start = valueend; 171 } 172 173 if (!um->name) 174 parse_error("Missing name for unit mask"); 175 if (!seen_type) 176 parse_error("Missing type for unit mask"); 177 } 178 179 180 /* \t0x08 (M)odified cache state */ 181 static void parse_um_entry(struct op_described_um * entry, char const * line) 182 { 183 char const * c = line; 184 185 c = skip_ws(c); 186 entry->value = parse_hex(c); 187 c = skip_nonws(c); 188 189 if (!*c) 190 parse_error("invalid unit mask entry"); 191 192 c = skip_ws(c); 193 194 if (!*c) 195 parse_error("invalid unit mask entry"); 196 197 entry->desc = xstrdup(c); 198 } 199 200 201 static struct op_unit_mask * new_unit_mask(void) 202 { 203 struct op_unit_mask * um = xmalloc(sizeof(struct op_unit_mask)); 204 memset(um, '\0', sizeof(struct op_unit_mask)); 205 list_add_tail(&um->um_next, &um_list); 206 207 return um; 208 } 209 210 static void free_unit_mask(struct op_unit_mask * um) 211 { 212 list_del(&um->um_next); 213 free(um); 214 } 215 216 /* 217 * name:zero type:mandatory default:0x0 218 * \t0x0 No unit mask 219 */ 220 static void read_unit_masks(char const * file) 221 { 222 struct op_unit_mask * um = NULL; 223 char * line; 224 FILE * fp = fopen(file, "r"); 225 226 if (!fp) { 227 fprintf(stderr, 228 "oprofile: could not open unit mask description file %s\n", file); 229 exit(EXIT_FAILURE); 230 } 231 232 filename = file; 233 line_nr = 1; 234 235 line = op_get_line(fp); 236 237 while (line) { 238 if (empty_line(line) || comment_line(line)) 239 goto next; 240 241 if (line[0] != '\t') { 242 um = new_unit_mask(); 243 parse_um(um, line); 244 } else { 245 if (!um) 246 parse_error("no unit mask name line"); 247 if (um->num >= MAX_UNIT_MASK) 248 parse_error("oprofile: maximum unit mask entries exceeded"); 249 250 parse_um_entry(&um->um[um->num], line); 251 ++(um->num); 252 } 253 254 next: 255 free(line); 256 line = op_get_line(fp); 257 ++line_nr; 258 } 259 260 fclose(fp); 261 } 262 263 264 static u32 parse_counter_mask(char const * str) 265 { 266 u32 mask = 0; 267 char const * numstart = str; 268 269 while (*numstart) { 270 mask |= 1 << parse_int(numstart); 271 272 while (*numstart && *numstart != ',') 273 ++numstart; 274 /* skip , unless we reach eos */ 275 if (*numstart) 276 ++numstart; 277 278 numstart = skip_ws(numstart); 279 } 280 281 return mask; 282 } 283 284 static struct op_unit_mask * try_find_um(char const * value) 285 { 286 struct list_head * pos; 287 288 list_for_each(pos, &um_list) { 289 struct op_unit_mask * um = list_entry(pos, struct op_unit_mask, um_next); 290 if (strcmp(value, um->name) == 0) { 291 um->used = 1; 292 return um; 293 } 294 } 295 return NULL; 296 } 297 298 static struct op_unit_mask * find_um(char const * value) 299 { 300 struct op_unit_mask * um = try_find_um(value); 301 if (um) 302 return um; 303 fprintf(stderr, "oprofile: could not find unit mask %s\n", value); 304 exit(EXIT_FAILURE); 305 } 306 307 /* um:a,b,c,d merge multiple unit masks */ 308 static struct op_unit_mask * merge_um(char * value) 309 { 310 int num; 311 char *s; 312 struct op_unit_mask *new, *um; 313 enum unit_mask_type type = -1U; 314 315 um = try_find_um(value); 316 if (um) 317 return um; 318 319 new = new_unit_mask(); 320 new->name = xstrdup(value); 321 new->used = 1; 322 num = 0; 323 while ((s = strsep(&value, ",")) != NULL) { 324 unsigned c; 325 um = find_um(s); 326 if (type == -1U) 327 type = um->unit_type_mask; 328 if (um->unit_type_mask != type) 329 parse_error("combined unit mask must be all the same types"); 330 if (type != utm_bitmask && type != utm_exclusive) 331 parse_error("combined unit mask must be all bitmasks or exclusive"); 332 new->default_mask |= um->default_mask; 333 new->num += um->num; 334 if (new->num > MAX_UNIT_MASK) 335 parse_error("too many members in combined unit mask"); 336 for (c = 0; c < um->num; c++, num++) { 337 new->um[num] = um->um[c]; 338 new->um[num].desc = xstrdup(new->um[num].desc); 339 } 340 } 341 if (type == -1U) 342 parse_error("Empty unit mask"); 343 new->unit_type_mask = type; 344 return new; 345 } 346 347 /* parse either a "tag:value" or a ": trailing description string" */ 348 static int next_token(char const ** cp, char ** name, char ** value) 349 { 350 size_t tag_len; 351 size_t val_len; 352 char const * c = *cp; 353 char const * end; 354 char const * colon; 355 356 c = skip_ws(c); 357 end = colon = c; 358 end = skip_nonws(end); 359 360 colon = strchr(colon, ':'); 361 362 if (!colon) { 363 if (*c) 364 parse_error("next_token(): garbage at end of line"); 365 return 0; 366 } 367 368 if (colon >= end) 369 parse_error("next_token() expected ':'"); 370 371 tag_len = colon - c; 372 val_len = end - (colon + 1); 373 374 if (!tag_len) { 375 /* : trailing description */ 376 end = skip_ws(end); 377 *name = xstrdup("desc"); 378 *value = xstrdup(end); 379 end += strlen(end); 380 } else { 381 /* tag:value */ 382 *name = op_xstrndup(c, tag_len); 383 *value = op_xstrndup(colon + 1, val_len); 384 end = skip_ws(end); 385 } 386 387 *cp = end; 388 return 1; 389 } 390 391 static void include_events (char *value) 392 { 393 char * event_file; 394 const char *old_filename; 395 int old_line_nr; 396 397 event_file = build_fn(value, "events"); 398 old_line_nr = line_nr; 399 old_filename = filename; 400 read_events(event_file); 401 line_nr = old_line_nr; 402 filename = old_filename; 403 free(event_file); 404 } 405 406 static struct op_event * new_event(void) 407 { 408 struct op_event * event = xmalloc(sizeof(struct op_event)); 409 memset(event, '\0', sizeof(struct op_event)); 410 list_add_tail(&event->event_next, &events_list); 411 412 return event; 413 } 414 415 static void free_event(struct op_event * event) 416 { 417 list_del(&event->event_next); 418 free(event); 419 } 420 421 /* event:0x00 counters:0 um:zero minimum:4096 name:ISSUES : Total issues */ 422 /* event:0x00 ext:xxxxxx um:zero minimum:4096 name:ISSUES : Total issues */ 423 static void read_events(char const * file) 424 { 425 struct op_event * event = NULL; 426 char * line; 427 char * name; 428 char * value; 429 char const * c; 430 int seen_event, seen_counters, seen_um, seen_minimum, seen_name, seen_ext; 431 FILE * fp = fopen(file, "r"); 432 int tags; 433 434 if (!fp) { 435 fprintf(stderr, "oprofile: could not open event description file %s\n", file); 436 exit(EXIT_FAILURE); 437 } 438 439 filename = file; 440 line_nr = 1; 441 442 line = op_get_line(fp); 443 444 while (line) { 445 if (empty_line(line) || comment_line(line)) 446 goto next; 447 448 tags = 0; 449 seen_name = 0; 450 seen_event = 0; 451 seen_counters = 0; 452 seen_ext = 0; 453 seen_um = 0; 454 seen_minimum = 0; 455 event = new_event(); 456 event->filter = -1; 457 event->ext = NULL; 458 459 c = line; 460 while (next_token(&c, &name, &value)) { 461 if (strcmp(name, "name") == 0) { 462 if (seen_name) 463 parse_error("duplicate name: tag"); 464 seen_name = 1; 465 if (strchr(value, '/') != NULL) 466 parse_error("invalid event name"); 467 if (strchr(value, '.') != NULL) 468 parse_error("invalid event name"); 469 event->name = value; 470 } else if (strcmp(name, "event") == 0) { 471 if (seen_event) 472 parse_error("duplicate event: tag"); 473 seen_event = 1; 474 event->val = parse_hex(value); 475 free(value); 476 } else if (strcmp(name, "counters") == 0) { 477 if (seen_counters) 478 parse_error("duplicate counters: tag"); 479 seen_counters = 1; 480 if (!strcmp(value, "cpuid")) 481 event->counter_mask = arch_get_counter_mask(); 482 else 483 event->counter_mask = parse_counter_mask(value); 484 free(value); 485 } else if (strcmp(name, "ext") == 0) { 486 if (seen_ext) 487 parse_error("duplicate ext: tag"); 488 seen_ext = 1; 489 event->ext = value; 490 } else if (strcmp(name, "um") == 0) { 491 if (seen_um) 492 parse_error("duplicate um: tag"); 493 seen_um = 1; 494 if (strchr(value, ',')) 495 event->unit = merge_um(value); 496 else 497 event->unit = find_um(value); 498 free(value); 499 } else if (strcmp(name, "minimum") == 0) { 500 if (seen_minimum) 501 parse_error("duplicate minimum: tag"); 502 seen_minimum = 1; 503 event->min_count = parse_int(value); 504 free(value); 505 } else if (strcmp(name, "desc") == 0) { 506 event->desc = value; 507 } else if (strcmp(name, "filter") == 0) { 508 event->filter = parse_int(value); 509 free(value); 510 } else if (strcmp(name, "include") == 0) { 511 if (tags > 0) 512 parse_error("tags before include:"); 513 free_event(event); 514 include_events(value); 515 free(value); 516 c = skip_ws(c); 517 if (*c != '\0' && *c != '#') 518 parse_error("non whitespace after include:"); 519 } else { 520 parse_error("unknown tag"); 521 } 522 tags++; 523 524 free(name); 525 } 526 next: 527 free(line); 528 line = op_get_line(fp); 529 ++line_nr; 530 } 531 532 fclose(fp); 533 } 534 535 536 /* usefull for make check */ 537 static int check_unit_mask(struct op_unit_mask const * um, 538 char const * cpu_name) 539 { 540 u32 i; 541 int err = 0; 542 543 if (!um->used) { 544 fprintf(stderr, "um %s is not used\n", um->name); 545 err = EXIT_FAILURE; 546 } 547 548 if (um->unit_type_mask == utm_mandatory && um->num != 1) { 549 fprintf(stderr, "mandatory um %s doesn't contain exactly one " 550 "entry (%s)\n", um->name, cpu_name); 551 err = EXIT_FAILURE; 552 } else if (um->unit_type_mask == utm_bitmask) { 553 u32 default_mask = um->default_mask; 554 for (i = 0; i < um->num; ++i) 555 default_mask &= ~um->um[i].value; 556 557 if (default_mask) { 558 fprintf(stderr, "um %s default mask is not valid " 559 "(%s)\n", um->name, cpu_name); 560 err = EXIT_FAILURE; 561 } 562 } else { 563 for (i = 0; i < um->num; ++i) { 564 if (um->default_mask == um->um[i].value) 565 break; 566 } 567 568 if (i == um->num) { 569 fprintf(stderr, "exclusive um %s default value is not " 570 "valid (%s)\n", um->name, cpu_name); 571 err = EXIT_FAILURE; 572 } 573 } 574 return err; 575 } 576 577 static void arch_filter_events(op_cpu cpu_type) 578 { 579 struct list_head * pos, * pos2; 580 unsigned filter = arch_get_filter(cpu_type); 581 if (!filter) 582 return; 583 list_for_each_safe (pos, pos2, &events_list) { 584 struct op_event * event = list_entry(pos, struct op_event, event_next); 585 if (event->filter >= 0 && ((1U << event->filter) & filter)) 586 delete_event(event); 587 } 588 } 589 590 static void load_events_name(const char *cpu_name) 591 { 592 char * event_file; 593 char * um_file; 594 595 event_file = build_fn(cpu_name, "events"); 596 um_file = build_fn(cpu_name, "unit_masks"); 597 598 read_unit_masks(um_file); 599 read_events(event_file); 600 601 free(um_file); 602 free(event_file); 603 } 604 605 static void load_events(op_cpu cpu_type) 606 { 607 const char * cpu_name = op_get_cpu_name(cpu_type); 608 struct list_head * pos; 609 int err = 0; 610 611 if (!list_empty(&events_list)) 612 return; 613 614 load_events_name(cpu_name); 615 616 arch_filter_events(cpu_type); 617 618 /* sanity check: all unit mask must be used */ 619 list_for_each(pos, &um_list) { 620 struct op_unit_mask * um = list_entry(pos, struct op_unit_mask, um_next); 621 err |= check_unit_mask(um, cpu_name); 622 } 623 if (err) 624 exit(err); 625 } 626 627 struct list_head * op_events(op_cpu cpu_type) 628 { 629 load_events(cpu_type); 630 arch_filter_events(cpu_type); 631 return &events_list; 632 } 633 634 635 static void delete_unit_mask(struct op_unit_mask * unit) 636 { 637 u32 cur; 638 for (cur = 0 ; cur < unit->num ; ++cur) { 639 if (unit->um[cur].desc) 640 free(unit->um[cur].desc); 641 } 642 643 if (unit->name) 644 free(unit->name); 645 646 list_del(&unit->um_next); 647 free(unit); 648 } 649 650 651 static void delete_event(struct op_event * event) 652 { 653 if (event->name) 654 free(event->name); 655 if (event->desc) 656 free(event->desc); 657 658 list_del(&event->event_next); 659 free(event); 660 } 661 662 663 void op_free_events(void) 664 { 665 struct list_head * pos, * pos2; 666 list_for_each_safe(pos, pos2, &events_list) { 667 struct op_event * event = list_entry(pos, struct op_event, event_next); 668 delete_event(event); 669 } 670 671 list_for_each_safe(pos, pos2, &um_list) { 672 struct op_unit_mask * unit = list_entry(pos, struct op_unit_mask, um_next); 673 delete_unit_mask(unit); 674 } 675 } 676 677 /* There can be actually multiple events here, so this is not quite correct */ 678 static struct op_event * find_event_any(u32 nr) 679 { 680 struct list_head * pos; 681 682 list_for_each(pos, &events_list) { 683 struct op_event * event = list_entry(pos, struct op_event, event_next); 684 if (event->val == nr) 685 return event; 686 } 687 688 return NULL; 689 } 690 691 static struct op_event * find_event_um(u32 nr, u32 um) 692 { 693 struct list_head * pos; 694 unsigned int i; 695 696 list_for_each(pos, &events_list) { 697 struct op_event * event = list_entry(pos, struct op_event, event_next); 698 if (event->val == nr) { 699 for (i = 0; i < event->unit->num; i++) { 700 if (event->unit->um[i].value == um) 701 return event; 702 } 703 } 704 } 705 706 return NULL; 707 } 708 709 static FILE * open_event_mapping_file(char const * cpu_name) 710 { 711 char * ev_map_file; 712 char * dir; 713 dir = getenv("OPROFILE_EVENTS_DIR"); 714 if (dir == NULL) 715 dir = OP_DATADIR; 716 717 ev_map_file = xmalloc(strlen(dir) + strlen("/") + strlen(cpu_name) + 718 strlen("/") + + strlen("event_mappings") + 1); 719 strcpy(ev_map_file, dir); 720 strcat(ev_map_file, "/"); 721 722 strcat(ev_map_file, cpu_name); 723 strcat(ev_map_file, "/"); 724 strcat(ev_map_file, "event_mappings"); 725 filename = ev_map_file; 726 return (fopen(ev_map_file, "r")); 727 } 728 729 730 /** 731 * This function is PPC64-specific. 732 */ 733 static char const * get_mapping(u32 nr, FILE * fp) 734 { 735 char * line; 736 char * name; 737 char * value; 738 char const * c; 739 char * map = NULL; 740 int seen_event = 0, seen_mmcr0 = 0, seen_mmcr1 = 0, seen_mmcra = 0; 741 u32 mmcr0 = 0; 742 u64 mmcr1 = 0; 743 u32 mmcra = 0; 744 int event_found = 0; 745 746 line_nr = 1; 747 line = op_get_line(fp); 748 while (line && !event_found) { 749 if (empty_line(line) || comment_line(line)) 750 goto next; 751 752 seen_event = 0; 753 seen_mmcr0 = 0; 754 seen_mmcr1 = 0; 755 seen_mmcra = 0; 756 mmcr0 = 0; 757 mmcr1 = 0; 758 mmcra = 0; 759 760 c = line; 761 while (next_token(&c, &name, &value)) { 762 if (strcmp(name, "event") == 0) { 763 u32 evt; 764 if (seen_event) 765 parse_error("duplicate event tag"); 766 seen_event = 1; 767 evt = parse_hex(value); 768 if (evt == nr) 769 event_found = 1; 770 free(value); 771 } else if (strcmp(name, "mmcr0") == 0) { 772 if (seen_mmcr0) 773 parse_error("duplicate mmcr0 tag"); 774 seen_mmcr0 = 1; 775 mmcr0 = parse_hex(value); 776 free(value); 777 } else if (strcmp(name, "mmcr1") == 0) { 778 if (seen_mmcr1) 779 parse_error("duplicate mmcr1: tag"); 780 seen_mmcr1 = 1; 781 mmcr1 = parse_long_hex(value); 782 free(value); 783 } else if (strcmp(name, "mmcra") == 0) { 784 if (seen_mmcra) 785 parse_error("duplicate mmcra: tag"); 786 seen_mmcra = 1; 787 mmcra = parse_hex(value); 788 free(value); 789 } else { 790 parse_error("unknown tag"); 791 } 792 793 free(name); 794 } 795 next: 796 free(line); 797 line = op_get_line(fp); 798 ++line_nr; 799 } 800 if (event_found) { 801 if (!seen_mmcr0 || !seen_mmcr1 || !seen_mmcra) { 802 fprintf(stderr, "Error: Missing information in line %d of event mapping file %s\n", line_nr, filename); 803 exit(EXIT_FAILURE); 804 } 805 map = xmalloc(70); 806 snprintf(map, 70, "mmcr0:%u mmcr1:%Lu mmcra:%u", 807 mmcr0, mmcr1, mmcra); 808 } 809 810 return map; 811 } 812 813 814 char const * find_mapping_for_event(u32 nr, op_cpu cpu_type) 815 { 816 char const * cpu_name = op_get_cpu_name(cpu_type); 817 FILE * fp = open_event_mapping_file(cpu_name); 818 char const * map = NULL; 819 switch (cpu_type) { 820 case CPU_PPC64_PA6T: 821 case CPU_PPC64_970: 822 case CPU_PPC64_970MP: 823 case CPU_PPC64_POWER4: 824 case CPU_PPC64_POWER5: 825 case CPU_PPC64_POWER5p: 826 case CPU_PPC64_POWER5pp: 827 case CPU_PPC64_POWER6: 828 case CPU_PPC64_POWER7: 829 case CPU_PPC64_IBM_COMPAT_V1: 830 if (!fp) { 831 fprintf(stderr, "oprofile: could not open event mapping file %s\n", filename); 832 exit(EXIT_FAILURE); 833 } else { 834 map = get_mapping(nr, fp); 835 } 836 break; 837 default: 838 break; 839 } 840 841 if (fp) 842 fclose(fp); 843 844 return map; 845 } 846 847 static int match_event(int i, struct op_event *event, unsigned um) 848 { 849 unsigned v = event->unit->um[i].value; 850 851 switch (event->unit->unit_type_mask) { 852 case utm_exclusive: 853 case utm_mandatory: 854 return v == um; 855 856 case utm_bitmask: 857 return (v & um) || (!v && v == 0); 858 } 859 860 abort(); 861 } 862 863 struct op_event * find_event_by_name(char const * name, unsigned um, int um_valid) 864 { 865 struct list_head * pos; 866 867 list_for_each(pos, &events_list) { 868 struct op_event * event = list_entry(pos, struct op_event, event_next); 869 if (strcmp(event->name, name) == 0) { 870 if (um_valid) { 871 unsigned i; 872 873 for (i = 0; i < event->unit->num; i++) 874 if (match_event(i, event, um)) 875 return event; 876 continue; 877 } 878 return event; 879 } 880 } 881 882 return NULL; 883 } 884 885 886 struct op_event * op_find_event(op_cpu cpu_type, u32 nr, u32 um) 887 { 888 struct op_event * event; 889 890 load_events(cpu_type); 891 892 event = find_event_um(nr, um); 893 894 return event; 895 } 896 897 struct op_event * op_find_event_any(op_cpu cpu_type, u32 nr) 898 { 899 load_events(cpu_type); 900 901 return find_event_any(nr); 902 } 903 904 int op_check_events(int ctr, u32 nr, u32 um, op_cpu cpu_type) 905 { 906 int ret = OP_INVALID_EVENT; 907 size_t i; 908 u32 ctr_mask = 1 << ctr; 909 struct list_head * pos; 910 911 load_events(cpu_type); 912 913 list_for_each(pos, &events_list) { 914 struct op_event * event = list_entry(pos, struct op_event, event_next); 915 if (event->val != nr) 916 continue; 917 918 ret = OP_OK_EVENT; 919 920 if ((event->counter_mask & ctr_mask) == 0) 921 ret |= OP_INVALID_COUNTER; 922 923 if (event->unit->unit_type_mask == utm_bitmask) { 924 for (i = 0; i < event->unit->num; ++i) 925 um &= ~(event->unit->um[i].value); 926 927 if (um) 928 ret |= OP_INVALID_UM; 929 930 } else { 931 for (i = 0; i < event->unit->num; ++i) { 932 if (event->unit->um[i].value == um) 933 break; 934 } 935 936 if (i == event->unit->num) 937 ret |= OP_INVALID_UM; 938 939 } 940 941 if (ret == OP_OK_EVENT) 942 return ret; 943 } 944 945 return ret; 946 } 947 948 949 void op_default_event(op_cpu cpu_type, struct op_default_event_descr * descr) 950 { 951 descr->name = ""; 952 descr->um = 0x0; 953 /* A fixed value of CPU cycles; this should ensure good 954 * granulity even on faster CPUs, though it will generate more 955 * interrupts. 956 */ 957 descr->count = 100000; 958 959 switch (cpu_type) { 960 case CPU_PPRO: 961 case CPU_PII: 962 case CPU_PIII: 963 case CPU_P6_MOBILE: 964 case CPU_CORE: 965 case CPU_CORE_2: 966 case CPU_ATHLON: 967 case CPU_HAMMER: 968 case CPU_FAMILY10: 969 case CPU_ARCH_PERFMON: 970 case CPU_FAMILY11H: 971 case CPU_ATOM: 972 case CPU_CORE_I7: 973 case CPU_NEHALEM: 974 case CPU_WESTMERE: 975 case CPU_MIPS_LOONGSON2: 976 case CPU_FAMILY12H: 977 case CPU_FAMILY14H: 978 case CPU_FAMILY15H: 979 descr->name = "CPU_CLK_UNHALTED"; 980 break; 981 982 case CPU_RTC: 983 descr->name = "RTC_INTERRUPTS"; 984 descr->count = 1024; 985 break; 986 987 case CPU_P4: 988 case CPU_P4_HT2: 989 descr->name = "GLOBAL_POWER_EVENTS"; 990 descr->um = 0x1; 991 break; 992 993 case CPU_IA64: 994 case CPU_IA64_1: 995 case CPU_IA64_2: 996 descr->count = 1000000; 997 descr->name = "CPU_CYCLES"; 998 break; 999 1000 case CPU_AXP_EV4: 1001 case CPU_AXP_EV5: 1002 case CPU_AXP_PCA56: 1003 case CPU_AXP_EV6: 1004 case CPU_AXP_EV67: 1005 descr->name = "CYCLES"; 1006 break; 1007 1008 // we could possibly use the CCNT 1009 case CPU_ARM_XSCALE1: 1010 case CPU_ARM_XSCALE2: 1011 case CPU_ARM_MPCORE: 1012 case CPU_ARM_V6: 1013 case CPU_ARM_V7: 1014 case CPU_ARM_V7_CA9: 1015 case CPU_AVR32: 1016 descr->name = "CPU_CYCLES"; 1017 break; 1018 1019 case CPU_PPC64_PA6T: 1020 case CPU_PPC64_970: 1021 case CPU_PPC64_970MP: 1022 case CPU_PPC_7450: 1023 case CPU_PPC64_POWER4: 1024 case CPU_PPC64_POWER5: 1025 case CPU_PPC64_POWER6: 1026 case CPU_PPC64_POWER5p: 1027 case CPU_PPC64_POWER5pp: 1028 case CPU_PPC64_CELL: 1029 case CPU_PPC64_POWER7: 1030 case CPU_PPC64_IBM_COMPAT_V1: 1031 descr->name = "CYCLES"; 1032 break; 1033 1034 case CPU_MIPS_20K: 1035 descr->name = "CYCLES"; 1036 break; 1037 1038 case CPU_MIPS_24K: 1039 case CPU_MIPS_34K: 1040 case CPU_MIPS_74K: 1041 case CPU_MIPS_1004K: 1042 descr->name = "INSTRUCTIONS"; 1043 break; 1044 1045 case CPU_MIPS_5K: 1046 case CPU_MIPS_25K: 1047 descr->name = "CYCLES"; 1048 break; 1049 1050 case CPU_MIPS_R10000: 1051 case CPU_MIPS_R12000: 1052 descr->name = "INSTRUCTIONS_GRADUATED"; 1053 break; 1054 1055 case CPU_MIPS_RM7000: 1056 case CPU_MIPS_RM9000: 1057 descr->name = "INSTRUCTIONS_ISSUED"; 1058 break; 1059 1060 case CPU_MIPS_SB1: 1061 descr->name = "INSN_SURVIVED_STAGE7"; 1062 break; 1063 1064 case CPU_MIPS_VR5432: 1065 case CPU_MIPS_VR5500: 1066 descr->name = "INSTRUCTIONS_EXECUTED"; 1067 break; 1068 1069 case CPU_PPC_E500: 1070 case CPU_PPC_E500_2: 1071 case CPU_PPC_E300: 1072 descr->name = "CPU_CLK"; 1073 break; 1074 1075 // don't use default, if someone add a cpu he wants a compiler 1076 // warning if he forgets to handle it here. 1077 case CPU_TIMER_INT: 1078 case CPU_NO_GOOD: 1079 case MAX_CPU_TYPE: 1080 break; 1081 } 1082 } 1083