00001
00014 #include "op_events.h"
00015 #include "op_libiberty.h"
00016 #include "op_fileio.h"
00017 #include "op_string.h"
00018 #include "op_cpufreq.h"
00019 #include "op_hw_specific.h"
00020 #include "op_parse_event.h"
00021
00022 #include <string.h>
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <ctype.h>
00026
00027 static LIST_HEAD(events_list);
00028 static LIST_HEAD(um_list);
00029
00030 static char const * filename;
00031 static unsigned int line_nr;
00032
00033 static void delete_event(struct op_event * event);
00034 static void read_events(char const * file);
00035 static void read_unit_masks(char const * file);
00036 static void free_unit_mask(struct op_unit_mask * um);
00037
00038 static char *build_fn(const char *cpu_name, const char *fn)
00039 {
00040 char *s;
00041 static const char *dir;
00042 if (dir == NULL)
00043 dir = getenv("OPROFILE_EVENTS_DIR");
00044 if (dir == NULL)
00045 dir = OP_DATADIR;
00046 s = xmalloc(strlen(dir) + strlen(cpu_name) + strlen(fn) + 5);
00047 sprintf(s, "%s/%s/%s", dir, cpu_name, fn);
00048 return s;
00049 }
00050
00051 static void parse_error(char const * context)
00052 {
00053 fprintf(stderr, "oprofile: parse error in %s, line %u\n",
00054 filename, line_nr);
00055 fprintf(stderr, "%s\n", context);
00056 exit(EXIT_FAILURE);
00057 }
00058
00059
00060 static int parse_int(char const * str)
00061 {
00062 int value;
00063 if (sscanf(str, "%d", &value) != 1)
00064 parse_error("expected decimal value");
00065
00066 return value;
00067 }
00068
00069
00070 static int parse_hex(char const * str)
00071 {
00072 int value;
00073
00074
00075 if (sscanf(str, "0x%x", &value) != 1 &&
00076 sscanf(str, "0X%x", &value) != 1)
00077 parse_error("expected hexadecimal value");
00078
00079 return value;
00080 }
00081
00082
00083 static u64 parse_long_hex(char const * str)
00084 {
00085 u64 value;
00086 if (sscanf(str, "%Lx", &value) != 1)
00087 parse_error("expected long hexadecimal value");
00088
00089 fflush(stderr);
00090 return value;
00091 }
00092
00093 static void include_um(const char *start, const char *end)
00094 {
00095 char *s;
00096 char cpu[end - start + 1];
00097 int old_line_nr;
00098 const char *old_filename;
00099
00100 strncpy(cpu, start, end - start);
00101 cpu[end - start] = 0;
00102 s = build_fn(cpu, "unit_masks");
00103 old_line_nr = line_nr;
00104 old_filename = filename;
00105 read_unit_masks(s);
00106 line_nr = old_line_nr;
00107 filename = old_filename;
00108 free(s);
00109 }
00110
00111
00112 unsigned parse_extra(const char *s)
00113 {
00114 unsigned v, w;
00115 int o;
00116
00117 v = 0;
00118 while (*s) {
00119 if (isspace(*s))
00120 break;
00121 if (strisprefix(s, "edge")) {
00122 v |= EXTRA_EDGE;
00123 s += 4;
00124 } else if (strisprefix(s, "inv")) {
00125 v |= EXTRA_INV;
00126 s += 3;
00127 } else if (sscanf(s, "cmask=%x%n", &w, &o) >= 1) {
00128 v |= (w & EXTRA_CMASK_MASK) << EXTRA_CMASK_SHIFT;
00129 s += o;
00130 } else if (strisprefix(s, "any")) {
00131 v |= EXTRA_ANY;
00132 s += 3;
00133 } else {
00134 parse_error("Illegal extra field modifier");
00135 }
00136 if (*s == ',')
00137 ++s;
00138 }
00139 return v;
00140 }
00141
00142
00143 static void parse_um(struct op_unit_mask * um, char const * line)
00144 {
00145 int seen_name = 0;
00146 int seen_type = 0;
00147 int seen_default = 0;
00148 char const * valueend = line + 1;
00149 char const * tagend = line + 1;
00150 char const * start = line;
00151
00152 while (*valueend) {
00153 valueend = skip_nonws(valueend);
00154
00155 while (*tagend != ':' && *tagend)
00156 ++tagend;
00157
00158 if (valueend == tagend)
00159 break;
00160
00161 if (!*tagend)
00162 parse_error("parse_um() expected :value");
00163
00164 ++tagend;
00165
00166 if (strisprefix(start, "include")) {
00167 if (seen_name + seen_type + seen_default > 0)
00168 parse_error("include must be on its own");
00169 free_unit_mask(um);
00170 include_um(tagend, valueend);
00171 return;
00172 }
00173
00174 if (strisprefix(start, "name")) {
00175 if (seen_name)
00176 parse_error("duplicate name: tag");
00177 seen_name = 1;
00178 um->name = op_xstrndup(tagend, valueend - tagend);
00179 } else if (strisprefix(start, "type")) {
00180 if (seen_type)
00181 parse_error("duplicate type: tag");
00182 seen_type = 1;
00183 if (strisprefix(tagend, "mandatory")) {
00184 um->unit_type_mask = utm_mandatory;
00185 } else if (strisprefix(tagend, "bitmask")) {
00186 um->unit_type_mask = utm_bitmask;
00187 } else if (strisprefix(tagend, "exclusive")) {
00188 um->unit_type_mask = utm_exclusive;
00189 } else {
00190 parse_error("invalid unit mask type");
00191 }
00192 } else if (strisprefix(start, "default")) {
00193 if (seen_default)
00194 parse_error("duplicate default: tag");
00195 seen_default = 1;
00196 um->default_mask = parse_hex(tagend);
00197 } else {
00198 parse_error("invalid unit mask tag");
00199 }
00200
00201 valueend = skip_ws(valueend);
00202 tagend = valueend;
00203 start = valueend;
00204 }
00205
00206 if (!um->name)
00207 parse_error("Missing name for unit mask");
00208 if (!seen_type)
00209 parse_error("Missing type for unit mask");
00210 }
00211
00212
00213
00214
00215 static void parse_um_entry(struct op_described_um * entry, char const * line)
00216 {
00217 char const * c = line;
00218
00219 c = skip_ws(c);
00220 entry->value = parse_hex(c);
00221 c = skip_nonws(c);
00222
00223 c = skip_ws(c);
00224 if (strisprefix(c, "extra:")) {
00225 c += 6;
00226 entry->extra = parse_extra(c);
00227 c = skip_nonws(c);
00228 } else
00229 entry->extra = 0;
00230
00231 if (!*c)
00232 parse_error("invalid unit mask entry");
00233
00234 c = skip_ws(c);
00235
00236 if (!*c)
00237 parse_error("invalid unit mask entry");
00238
00239 entry->desc = xstrdup(c);
00240 }
00241
00242
00243 static struct op_unit_mask * new_unit_mask(void)
00244 {
00245 struct op_unit_mask * um = xmalloc(sizeof(struct op_unit_mask));
00246 memset(um, '\0', sizeof(struct op_unit_mask));
00247 list_add_tail(&um->um_next, &um_list);
00248
00249 return um;
00250 }
00251
00252 static void free_unit_mask(struct op_unit_mask * um)
00253 {
00254 list_del(&um->um_next);
00255 free(um);
00256 }
00257
00258
00259
00260
00261
00262 static void read_unit_masks(char const * file)
00263 {
00264 struct op_unit_mask * um = NULL;
00265 char * line;
00266 FILE * fp = fopen(file, "r");
00267
00268 if (!fp) {
00269 fprintf(stderr,
00270 "oprofile: could not open unit mask description file %s\n", file);
00271 exit(EXIT_FAILURE);
00272 }
00273
00274 filename = file;
00275 line_nr = 1;
00276
00277 line = op_get_line(fp);
00278
00279 while (line) {
00280 if (empty_line(line) || comment_line(line))
00281 goto next;
00282
00283 if (line[0] != '\t') {
00284 um = new_unit_mask();
00285 parse_um(um, line);
00286 } else {
00287 if (!um)
00288 parse_error("no unit mask name line");
00289 if (um->num >= MAX_UNIT_MASK)
00290 parse_error("oprofile: maximum unit mask entries exceeded");
00291
00292 parse_um_entry(&um->um[um->num], line);
00293 ++(um->num);
00294 }
00295
00296 next:
00297 free(line);
00298 line = op_get_line(fp);
00299 ++line_nr;
00300 }
00301
00302 fclose(fp);
00303 }
00304
00305
00306 static u32 parse_counter_mask(char const * str)
00307 {
00308 u32 mask = 0;
00309 char const * numstart = str;
00310
00311 while (*numstart) {
00312 mask |= 1 << parse_int(numstart);
00313
00314 while (*numstart && *numstart != ',')
00315 ++numstart;
00316
00317 if (*numstart)
00318 ++numstart;
00319
00320 numstart = skip_ws(numstart);
00321 }
00322
00323 return mask;
00324 }
00325
00326 static struct op_unit_mask * try_find_um(char const * value)
00327 {
00328 struct list_head * pos;
00329
00330 list_for_each(pos, &um_list) {
00331 struct op_unit_mask * um = list_entry(pos, struct op_unit_mask, um_next);
00332 if (strcmp(value, um->name) == 0) {
00333 um->used = 1;
00334 return um;
00335 }
00336 }
00337 return NULL;
00338 }
00339
00340 static struct op_unit_mask * find_um(char const * value)
00341 {
00342 struct op_unit_mask * um = try_find_um(value);
00343 if (um)
00344 return um;
00345 fprintf(stderr, "oprofile: could not find unit mask %s\n", value);
00346 exit(EXIT_FAILURE);
00347 }
00348
00349
00350 static struct op_unit_mask * merge_um(char * value)
00351 {
00352 int num;
00353 char *s;
00354 struct op_unit_mask *new, *um;
00355 enum unit_mask_type type = -1U;
00356
00357 um = try_find_um(value);
00358 if (um)
00359 return um;
00360
00361 new = new_unit_mask();
00362 new->name = xstrdup(value);
00363 new->used = 1;
00364 num = 0;
00365 while ((s = strsep(&value, ",")) != NULL) {
00366 unsigned c;
00367 um = find_um(s);
00368 if (type == -1U)
00369 type = um->unit_type_mask;
00370 if (um->unit_type_mask != type)
00371 parse_error("combined unit mask must be all the same types");
00372 if (type != utm_bitmask && type != utm_exclusive)
00373 parse_error("combined unit mask must be all bitmasks or exclusive");
00374 new->default_mask |= um->default_mask;
00375 new->num += um->num;
00376 if (new->num > MAX_UNIT_MASK)
00377 parse_error("too many members in combined unit mask");
00378 for (c = 0; c < um->num; c++, num++) {
00379 new->um[num] = um->um[c];
00380 new->um[num].desc = xstrdup(new->um[num].desc);
00381 }
00382 }
00383 if (type == -1U)
00384 parse_error("Empty unit mask");
00385 new->unit_type_mask = type;
00386 return new;
00387 }
00388
00389
00390 static int next_token(char const ** cp, char ** name, char ** value)
00391 {
00392 size_t tag_len;
00393 size_t val_len;
00394 char const * c = *cp;
00395 char const * end;
00396 char const * colon;
00397
00398 c = skip_ws(c);
00399 end = colon = c;
00400 end = skip_nonws(end);
00401
00402 colon = strchr(colon, ':');
00403
00404 if (!colon) {
00405 if (*c)
00406 parse_error("next_token(): garbage at end of line");
00407 return 0;
00408 }
00409
00410 if (colon >= end)
00411 parse_error("next_token() expected ':'");
00412
00413 tag_len = colon - c;
00414 val_len = end - (colon + 1);
00415
00416 if (!tag_len) {
00417
00418 end = skip_ws(end);
00419 *name = xstrdup("desc");
00420 *value = xstrdup(end);
00421 end += strlen(end);
00422 } else {
00423
00424 *name = op_xstrndup(c, tag_len);
00425 *value = op_xstrndup(colon + 1, val_len);
00426 end = skip_ws(end);
00427 }
00428
00429 *cp = end;
00430 return 1;
00431 }
00432
00433 static void include_events (char *value)
00434 {
00435 char * event_file;
00436 const char *old_filename;
00437 int old_line_nr;
00438
00439 event_file = build_fn(value, "events");
00440 old_line_nr = line_nr;
00441 old_filename = filename;
00442 read_events(event_file);
00443 line_nr = old_line_nr;
00444 filename = old_filename;
00445 free(event_file);
00446 }
00447
00448 static struct op_event * new_event(void)
00449 {
00450 struct op_event * event = xmalloc(sizeof(struct op_event));
00451 memset(event, '\0', sizeof(struct op_event));
00452 list_add_tail(&event->event_next, &events_list);
00453
00454 return event;
00455 }
00456
00457 static void free_event(struct op_event * event)
00458 {
00459 list_del(&event->event_next);
00460 free(event);
00461 }
00462
00463
00464
00465 static void read_events(char const * file)
00466 {
00467 struct op_event * event = NULL;
00468 char * line;
00469 char * name;
00470 char * value;
00471 char const * c;
00472 int seen_event, seen_counters, seen_um, seen_minimum, seen_name, seen_ext;
00473 FILE * fp = fopen(file, "r");
00474 int tags;
00475
00476 if (!fp) {
00477 fprintf(stderr, "oprofile: could not open event description file %s\n", file);
00478 exit(EXIT_FAILURE);
00479 }
00480
00481 filename = file;
00482 line_nr = 1;
00483
00484 line = op_get_line(fp);
00485
00486 while (line) {
00487 if (empty_line(line) || comment_line(line))
00488 goto next;
00489
00490 tags = 0;
00491 seen_name = 0;
00492 seen_event = 0;
00493 seen_counters = 0;
00494 seen_ext = 0;
00495 seen_um = 0;
00496 seen_minimum = 0;
00497 event = new_event();
00498 event->filter = -1;
00499 event->ext = NULL;
00500
00501 c = line;
00502 while (next_token(&c, &name, &value)) {
00503 if (strcmp(name, "name") == 0) {
00504 if (seen_name)
00505 parse_error("duplicate name: tag");
00506 seen_name = 1;
00507 if (strchr(value, '/') != NULL)
00508 parse_error("invalid event name");
00509 if (strchr(value, '.') != NULL)
00510 parse_error("invalid event name");
00511 event->name = value;
00512 } else if (strcmp(name, "event") == 0) {
00513 if (seen_event)
00514 parse_error("duplicate event: tag");
00515 seen_event = 1;
00516 event->val = parse_hex(value);
00517 free(value);
00518 } else if (strcmp(name, "counters") == 0) {
00519 if (seen_counters)
00520 parse_error("duplicate counters: tag");
00521 seen_counters = 1;
00522 if (!strcmp(value, "cpuid"))
00523 event->counter_mask = arch_get_counter_mask();
00524 else
00525 event->counter_mask = parse_counter_mask(value);
00526 free(value);
00527 } else if (strcmp(name, "ext") == 0) {
00528 if (seen_ext)
00529 parse_error("duplicate ext: tag");
00530 seen_ext = 1;
00531 event->ext = value;
00532 } else if (strcmp(name, "um") == 0) {
00533 if (seen_um)
00534 parse_error("duplicate um: tag");
00535 seen_um = 1;
00536 if (strchr(value, ','))
00537 event->unit = merge_um(value);
00538 else
00539 event->unit = find_um(value);
00540 free(value);
00541 } else if (strcmp(name, "minimum") == 0) {
00542 if (seen_minimum)
00543 parse_error("duplicate minimum: tag");
00544 seen_minimum = 1;
00545 event->min_count = parse_int(value);
00546 free(value);
00547 } else if (strcmp(name, "desc") == 0) {
00548 event->desc = value;
00549 } else if (strcmp(name, "filter") == 0) {
00550 event->filter = parse_int(value);
00551 free(value);
00552 } else if (strcmp(name, "include") == 0) {
00553 if (tags > 0)
00554 parse_error("tags before include:");
00555 free_event(event);
00556 include_events(value);
00557 free(value);
00558 c = skip_ws(c);
00559 if (*c != '\0' && *c != '#')
00560 parse_error("non whitespace after include:");
00561 } else {
00562 parse_error("unknown tag");
00563 }
00564 tags++;
00565
00566 free(name);
00567 }
00568 next:
00569 free(line);
00570 line = op_get_line(fp);
00571 ++line_nr;
00572 }
00573
00574 fclose(fp);
00575 }
00576
00577
00578
00579 static int check_unit_mask(struct op_unit_mask const * um,
00580 char const * cpu_name)
00581 {
00582 u32 i;
00583 int err = 0;
00584
00585 if (!um->used) {
00586 fprintf(stderr, "um %s is not used\n", um->name);
00587 err = EXIT_FAILURE;
00588 }
00589
00590 if (um->unit_type_mask == utm_mandatory && um->num != 1) {
00591 fprintf(stderr, "mandatory um %s doesn't contain exactly one "
00592 "entry (%s)\n", um->name, cpu_name);
00593 err = EXIT_FAILURE;
00594 } else if (um->unit_type_mask == utm_bitmask) {
00595 u32 default_mask = um->default_mask;
00596 for (i = 0; i < um->num; ++i)
00597 default_mask &= ~um->um[i].value;
00598
00599 if (default_mask) {
00600 fprintf(stderr, "um %s default mask is not valid "
00601 "(%s)\n", um->name, cpu_name);
00602 err = EXIT_FAILURE;
00603 }
00604 } else {
00605 for (i = 0; i < um->num; ++i) {
00606 if (um->default_mask == um->um[i].value)
00607 break;
00608 }
00609
00610 if (i == um->num) {
00611 fprintf(stderr, "exclusive um %s default value is not "
00612 "valid (%s)\n", um->name, cpu_name);
00613 err = EXIT_FAILURE;
00614 }
00615 }
00616 return err;
00617 }
00618
00619 static void arch_filter_events(op_cpu cpu_type)
00620 {
00621 struct list_head * pos, * pos2;
00622 unsigned filter = arch_get_filter(cpu_type);
00623 if (!filter)
00624 return;
00625 list_for_each_safe (pos, pos2, &events_list) {
00626 struct op_event * event = list_entry(pos, struct op_event, event_next);
00627 if (event->filter >= 0 && ((1U << event->filter) & filter))
00628 delete_event(event);
00629 }
00630 }
00631
00632 static void load_events_name(const char *cpu_name)
00633 {
00634 char * event_file;
00635 char * um_file;
00636
00637 event_file = build_fn(cpu_name, "events");
00638 um_file = build_fn(cpu_name, "unit_masks");
00639
00640 read_unit_masks(um_file);
00641 read_events(event_file);
00642
00643 free(um_file);
00644 free(event_file);
00645 }
00646
00647 static void load_events(op_cpu cpu_type)
00648 {
00649 const char * cpu_name = op_get_cpu_name(cpu_type);
00650 struct list_head * pos;
00651 struct op_event *event;
00652 struct op_unit_mask *unit_mask;
00653 int err = 0;
00654
00655 if (!list_empty(&events_list))
00656 return;
00657
00658 load_events_name(cpu_name);
00659
00660 arch_filter_events(cpu_type);
00661
00662
00663 list_for_each(pos, &um_list) {
00664 struct op_unit_mask * um = list_entry(pos, struct op_unit_mask, um_next);
00665 err |= check_unit_mask(um, cpu_name);
00666 }
00667 if (err)
00668 exit(err);
00669
00670 if (!op_cpu_has_timer_fs())
00671 return;
00672
00673
00674 list_for_each(pos, &events_list) {
00675 struct op_event * event = list_entry(pos, struct op_event,
00676 event_next);
00677
00678 if (strcmp(event->name, TIMER_EVENT_NAME) == 0) {
00679 fprintf(stderr, "Error: " TIMER_EVENT_NAME
00680 " event cannot be redefined.\n");
00681 exit(EXIT_FAILURE);
00682 }
00683 if (event->val == TIMER_EVENT_VALUE) {
00684 fprintf(stderr, "Error: Event %s uses " TIMER_EVENT_NAME
00685 " which is reserverd for timer based sampling.\n",
00686 event->name);
00687 exit(EXIT_FAILURE);
00688 }
00689 }
00690
00691 list_for_each(pos, &um_list) {
00692 struct op_unit_mask * um = list_entry(pos, struct op_unit_mask,
00693 um_next);
00694 if (strcmp(um->name, TIMER_EVENT_UNIT_MASK_NAME) == 0) {
00695 fprintf(stderr, "Error: " TIMER_EVENT_UNIT_MASK_NAME
00696 " unit mask cannot be redefined.\n");
00697 exit(EXIT_FAILURE);
00698 }
00699 }
00700
00701 unit_mask = new_unit_mask();
00702 unit_mask->name = xstrdup(TIMER_EVENT_UNIT_MASK_NAME);
00703 unit_mask->num = 1;
00704 unit_mask->unit_type_mask = utm_mandatory;
00705 unit_mask->um[0].extra = 0;
00706 unit_mask->um[0].value = 0;
00707 unit_mask->um[0].desc = xstrdup("No unit mask");
00708 unit_mask->used = 1;
00709
00710 event = new_event();
00711 event->name = xstrdup(TIMER_EVENT_NAME);
00712 event->desc = xstrdup(TIMER_EVENT_DESC);
00713 event->val = TIMER_EVENT_VALUE;
00714 event->unit = unit_mask;
00715 event->min_count = 0;
00716 event->filter = 0;
00717 event->counter_mask = 1 << (op_get_nr_counters(cpu_type) - 1);
00718 event->ext = NULL;
00719 event->filter = -1;
00720 }
00721
00722 struct list_head * op_events(op_cpu cpu_type)
00723 {
00724 load_events(cpu_type);
00725 arch_filter_events(cpu_type);
00726 return &events_list;
00727 }
00728
00729
00730 static void delete_unit_mask(struct op_unit_mask * unit)
00731 {
00732 u32 cur;
00733 for (cur = 0 ; cur < unit->num ; ++cur) {
00734 if (unit->um[cur].desc)
00735 free(unit->um[cur].desc);
00736 }
00737
00738 if (unit->name)
00739 free(unit->name);
00740
00741 list_del(&unit->um_next);
00742 free(unit);
00743 }
00744
00745
00746 static void delete_event(struct op_event * event)
00747 {
00748 if (event->name)
00749 free(event->name);
00750 if (event->desc)
00751 free(event->desc);
00752
00753 list_del(&event->event_next);
00754 free(event);
00755 }
00756
00757
00758 void op_free_events(void)
00759 {
00760 struct list_head * pos, * pos2;
00761 list_for_each_safe(pos, pos2, &events_list) {
00762 struct op_event * event = list_entry(pos, struct op_event, event_next);
00763 delete_event(event);
00764 }
00765
00766 list_for_each_safe(pos, pos2, &um_list) {
00767 struct op_unit_mask * unit = list_entry(pos, struct op_unit_mask, um_next);
00768 delete_unit_mask(unit);
00769 }
00770 }
00771
00772
00773 static struct op_event * find_event_any(u32 nr)
00774 {
00775 struct list_head * pos;
00776
00777 list_for_each(pos, &events_list) {
00778 struct op_event * event = list_entry(pos, struct op_event, event_next);
00779 if (event->val == nr)
00780 return event;
00781 }
00782
00783 return NULL;
00784 }
00785
00786 static struct op_event * find_event_um(u32 nr, u32 um)
00787 {
00788 struct list_head * pos;
00789 unsigned int i;
00790
00791 list_for_each(pos, &events_list) {
00792 struct op_event * event = list_entry(pos, struct op_event, event_next);
00793 if (event->val == nr) {
00794 for (i = 0; i < event->unit->num; i++) {
00795 if (event->unit->um[i].value == um)
00796 return event;
00797 }
00798 }
00799 }
00800
00801 return NULL;
00802 }
00803
00804 static FILE * open_event_mapping_file(char const * cpu_name)
00805 {
00806 char * ev_map_file;
00807 char * dir;
00808 dir = getenv("OPROFILE_EVENTS_DIR");
00809 if (dir == NULL)
00810 dir = OP_DATADIR;
00811
00812 ev_map_file = xmalloc(strlen(dir) + strlen("/") + strlen(cpu_name) +
00813 strlen("/") + + strlen("event_mappings") + 1);
00814 strcpy(ev_map_file, dir);
00815 strcat(ev_map_file, "/");
00816
00817 strcat(ev_map_file, cpu_name);
00818 strcat(ev_map_file, "/");
00819 strcat(ev_map_file, "event_mappings");
00820 filename = ev_map_file;
00821 return (fopen(ev_map_file, "r"));
00822 }
00823
00824
00828 static char const * get_mapping(u32 nr, FILE * fp)
00829 {
00830 char * line;
00831 char * name;
00832 char * value;
00833 char const * c;
00834 char * map = NULL;
00835 int seen_event = 0, seen_mmcr0 = 0, seen_mmcr1 = 0, seen_mmcra = 0;
00836 u32 mmcr0 = 0;
00837 u64 mmcr1 = 0;
00838 u32 mmcra = 0;
00839 int event_found = 0;
00840
00841 line_nr = 1;
00842 line = op_get_line(fp);
00843 while (line && !event_found) {
00844 if (empty_line(line) || comment_line(line))
00845 goto next;
00846
00847 seen_event = 0;
00848 seen_mmcr0 = 0;
00849 seen_mmcr1 = 0;
00850 seen_mmcra = 0;
00851 mmcr0 = 0;
00852 mmcr1 = 0;
00853 mmcra = 0;
00854
00855 c = line;
00856 while (next_token(&c, &name, &value)) {
00857 if (strcmp(name, "event") == 0) {
00858 u32 evt;
00859 if (seen_event)
00860 parse_error("duplicate event tag");
00861 seen_event = 1;
00862 evt = parse_hex(value);
00863 if (evt == nr)
00864 event_found = 1;
00865 free(value);
00866 } else if (strcmp(name, "mmcr0") == 0) {
00867 if (seen_mmcr0)
00868 parse_error("duplicate mmcr0 tag");
00869 seen_mmcr0 = 1;
00870 mmcr0 = parse_hex(value);
00871 free(value);
00872 } else if (strcmp(name, "mmcr1") == 0) {
00873 if (seen_mmcr1)
00874 parse_error("duplicate mmcr1: tag");
00875 seen_mmcr1 = 1;
00876 mmcr1 = parse_long_hex(value);
00877 free(value);
00878 } else if (strcmp(name, "mmcra") == 0) {
00879 if (seen_mmcra)
00880 parse_error("duplicate mmcra: tag");
00881 seen_mmcra = 1;
00882 mmcra = parse_hex(value);
00883 free(value);
00884 } else {
00885 parse_error("unknown tag");
00886 }
00887
00888 free(name);
00889 }
00890 next:
00891 free(line);
00892 line = op_get_line(fp);
00893 ++line_nr;
00894 }
00895 if (event_found) {
00896 if (!seen_mmcr0 || !seen_mmcr1 || !seen_mmcra) {
00897 fprintf(stderr, "Error: Missing information in line %d of event mapping file %s\n", line_nr, filename);
00898 exit(EXIT_FAILURE);
00899 }
00900 map = xmalloc(70);
00901 snprintf(map, 70, "mmcr0:%u mmcr1:%Lu mmcra:%u",
00902 mmcr0, mmcr1, mmcra);
00903 }
00904
00905 return map;
00906 }
00907
00908
00909 char const * find_mapping_for_event(u32 nr, op_cpu cpu_type)
00910 {
00911 char const * cpu_name = op_get_cpu_name(cpu_type);
00912 FILE * fp = open_event_mapping_file(cpu_name);
00913 char const * map = NULL;
00914 switch (cpu_type) {
00915 case CPU_PPC64_PA6T:
00916 case CPU_PPC64_970:
00917 case CPU_PPC64_970MP:
00918 case CPU_PPC64_POWER4:
00919 case CPU_PPC64_POWER5:
00920 case CPU_PPC64_POWER5p:
00921 case CPU_PPC64_POWER5pp:
00922 case CPU_PPC64_POWER6:
00923 case CPU_PPC64_POWER7:
00924 case CPU_PPC64_IBM_COMPAT_V1:
00925 if (!fp) {
00926 fprintf(stderr, "oprofile: could not open event mapping file %s\n", filename);
00927 exit(EXIT_FAILURE);
00928 } else {
00929 map = get_mapping(nr, fp);
00930 }
00931 break;
00932 default:
00933 break;
00934 }
00935
00936 if (fp)
00937 fclose(fp);
00938
00939 return map;
00940 }
00941
00942 static int match_event(int i, struct op_event *event, unsigned um)
00943 {
00944 unsigned v = event->unit->um[i].value;
00945
00946 switch (event->unit->unit_type_mask) {
00947 case utm_exclusive:
00948 case utm_mandatory:
00949 return v == um;
00950
00951 case utm_bitmask:
00952 return (v & um) || (!v && v == 0);
00953 }
00954
00955 abort();
00956 }
00957
00958 struct op_event * find_event_by_name(char const * name, unsigned um, int um_valid)
00959 {
00960 struct list_head * pos;
00961
00962 list_for_each(pos, &events_list) {
00963 struct op_event * event = list_entry(pos, struct op_event, event_next);
00964 if (strcmp(event->name, name) == 0) {
00965 if (um_valid) {
00966 unsigned i;
00967
00968 for (i = 0; i < event->unit->num; i++)
00969 if (match_event(i, event, um))
00970 return event;
00971 continue;
00972 }
00973 return event;
00974 }
00975 }
00976
00977 return NULL;
00978 }
00979
00980
00981 static struct op_event * find_next_event(struct op_event * e)
00982 {
00983 struct list_head * n;
00984
00985 for (n = e->event_next.next; n != &events_list; n = n->next) {
00986 struct op_event * ne = list_entry(n, struct op_event, event_next);
00987 if (!strcmp(e->name, ne->name))
00988 return ne;
00989 }
00990 return NULL;
00991 }
00992
00993 struct op_event * op_find_event(op_cpu cpu_type, u32 nr, u32 um)
00994 {
00995 struct op_event * event;
00996
00997 load_events(cpu_type);
00998
00999 event = find_event_um(nr, um);
01000
01001 return event;
01002 }
01003
01004 struct op_event * op_find_event_any(op_cpu cpu_type, u32 nr)
01005 {
01006 load_events(cpu_type);
01007
01008 return find_event_any(nr);
01009 }
01010
01011 int op_check_events(int ctr, u32 nr, u32 um, op_cpu cpu_type)
01012 {
01013 int ret = OP_INVALID_EVENT;
01014 size_t i;
01015 u32 ctr_mask = 1 << ctr;
01016 struct list_head * pos;
01017
01018 load_events(cpu_type);
01019
01020 list_for_each(pos, &events_list) {
01021 struct op_event * event = list_entry(pos, struct op_event, event_next);
01022 if (event->val != nr)
01023 continue;
01024
01025 ret = OP_OK_EVENT;
01026
01027 if ((event->counter_mask & ctr_mask) == 0)
01028 ret |= OP_INVALID_COUNTER;
01029
01030 if (event->unit->unit_type_mask == utm_bitmask) {
01031 for (i = 0; i < event->unit->num; ++i)
01032 um &= ~(event->unit->um[i].value);
01033
01034 if (um)
01035 ret |= OP_INVALID_UM;
01036
01037 } else {
01038 for (i = 0; i < event->unit->num; ++i) {
01039 if (event->unit->um[i].value == um)
01040 break;
01041 }
01042
01043 if (i == event->unit->num)
01044 ret |= OP_INVALID_UM;
01045
01046 }
01047
01048 if (ret == OP_OK_EVENT)
01049 return ret;
01050 }
01051
01052 return ret;
01053 }
01054
01055
01056 void op_default_event(op_cpu cpu_type, struct op_default_event_descr * descr)
01057 {
01058 descr->name = "";
01059 descr->um = 0x0;
01060
01061
01062
01063
01064 descr->count = 100000;
01065
01066 switch (cpu_type) {
01067 case CPU_PPRO:
01068 case CPU_PII:
01069 case CPU_PIII:
01070 case CPU_P6_MOBILE:
01071 case CPU_CORE:
01072 case CPU_CORE_2:
01073 case CPU_ATHLON:
01074 case CPU_HAMMER:
01075 case CPU_FAMILY10:
01076 case CPU_ARCH_PERFMON:
01077 case CPU_FAMILY11H:
01078 case CPU_ATOM:
01079 case CPU_CORE_I7:
01080 case CPU_NEHALEM:
01081 case CPU_WESTMERE:
01082 case CPU_SANDYBRIDGE:
01083 case CPU_IVYBRIDGE:
01084 case CPU_MIPS_LOONGSON2:
01085 case CPU_FAMILY12H:
01086 case CPU_FAMILY14H:
01087 case CPU_FAMILY15H:
01088 descr->name = "CPU_CLK_UNHALTED";
01089 break;
01090
01091 case CPU_RTC:
01092 descr->name = "RTC_INTERRUPTS";
01093 descr->count = 1024;
01094 break;
01095
01096 case CPU_P4:
01097 case CPU_P4_HT2:
01098 descr->name = "GLOBAL_POWER_EVENTS";
01099 descr->um = 0x1;
01100 break;
01101
01102 case CPU_IA64:
01103 case CPU_IA64_1:
01104 case CPU_IA64_2:
01105 descr->count = 1000000;
01106 descr->name = "CPU_CYCLES";
01107 break;
01108
01109 case CPU_AXP_EV4:
01110 case CPU_AXP_EV5:
01111 case CPU_AXP_PCA56:
01112 case CPU_AXP_EV6:
01113 case CPU_AXP_EV67:
01114 descr->name = "CYCLES";
01115 break;
01116
01117
01118 case CPU_ARM_XSCALE1:
01119 case CPU_ARM_XSCALE2:
01120 case CPU_ARM_MPCORE:
01121 case CPU_ARM_V6:
01122 case CPU_ARM_V7:
01123 case CPU_ARM_V7_CA5:
01124 case CPU_ARM_V7_CA7:
01125 case CPU_ARM_V7_CA9:
01126 case CPU_ARM_V7_CA15:
01127 case CPU_AVR32:
01128 case CPU_ARM_SCORPION:
01129 case CPU_ARM_SCORPIONMP:
01130 descr->name = "CPU_CYCLES";
01131 break;
01132
01133 case CPU_PPC64_PA6T:
01134 case CPU_PPC64_970:
01135 case CPU_PPC64_970MP:
01136 case CPU_PPC_7450:
01137 case CPU_PPC64_POWER4:
01138 case CPU_PPC64_POWER5:
01139 case CPU_PPC64_POWER6:
01140 case CPU_PPC64_POWER5p:
01141 case CPU_PPC64_POWER5pp:
01142 case CPU_PPC64_CELL:
01143 case CPU_PPC64_POWER7:
01144 case CPU_PPC64_IBM_COMPAT_V1:
01145 descr->name = "CYCLES";
01146 break;
01147
01148 case CPU_MIPS_20K:
01149 descr->name = "CYCLES";
01150 break;
01151
01152 case CPU_MIPS_24K:
01153 case CPU_MIPS_34K:
01154 case CPU_MIPS_74K:
01155 case CPU_MIPS_1004K:
01156 descr->name = "INSTRUCTIONS";
01157 break;
01158
01159 case CPU_MIPS_5K:
01160 case CPU_MIPS_25K:
01161 descr->name = "CYCLES";
01162 break;
01163
01164 case CPU_MIPS_R10000:
01165 case CPU_MIPS_R12000:
01166 descr->name = "INSTRUCTIONS_GRADUATED";
01167 break;
01168
01169 case CPU_MIPS_RM7000:
01170 case CPU_MIPS_RM9000:
01171 descr->name = "INSTRUCTIONS_ISSUED";
01172 break;
01173
01174 case CPU_MIPS_SB1:
01175 descr->name = "INSN_SURVIVED_STAGE7";
01176 break;
01177
01178 case CPU_MIPS_VR5432:
01179 case CPU_MIPS_VR5500:
01180 descr->name = "INSTRUCTIONS_EXECUTED";
01181 break;
01182
01183 case CPU_PPC_E500:
01184 case CPU_PPC_E500_2:
01185 case CPU_PPC_E300:
01186 descr->name = "CPU_CLK";
01187 break;
01188 case CPU_S390_Z10:
01189 case CPU_S390_Z196:
01190 if (op_get_nr_counters(cpu_type) > 1) {
01191 descr->name = "HWSAMPLING";
01192 descr->count = 4127518;
01193 } else {
01194 descr->name = TIMER_EVENT_NAME;
01195 descr->count = 10000;
01196 }
01197 break;
01198
01199 case CPU_TILE_TILE64:
01200 case CPU_TILE_TILEPRO:
01201 case CPU_TILE_TILEGX:
01202 descr->name = "ONE";
01203 break;
01204
01205
01206
01207 case CPU_TIMER_INT:
01208 case CPU_NO_GOOD:
01209 case MAX_CPU_TYPE:
01210 break;
01211 }
01212 }
01213
01214 static void extra_check(struct op_event *e, u32 unit_mask)
01215 {
01216 unsigned i;
01217 int found = 0;
01218
01219 for (i = 0; i < e->unit->num; i++)
01220 if (e->unit->um[i].value == unit_mask)
01221 found++;
01222 if (found > 1) {
01223 fprintf(stderr,
01224 "Named unit masks not allowed for events without 'extra:' values.\n"
01225 "Please specify the numerical value for the unit mask. See 'opcontrol'"
01226 " man page for more info.\n");
01227 exit(EXIT_FAILURE);
01228 }
01229 }
01230
01231 static void another_extra_check(struct op_event *e, char *name, unsigned w)
01232 {
01233 int found;
01234 unsigned i;
01235
01236 if (!e->unit->um[w].extra) {
01237 fprintf(stderr,
01238 "Named unit mask (%s) not allowed for event without 'extra:' values.\n"
01239 "Please specify the numerical value for the unit mask. See 'opcontrol'"
01240 " man page for more info.\n", name);
01241 exit(EXIT_FAILURE);
01242 }
01243
01244 found = 0;
01245 for (i = 0; i < e->unit->num; i++) {
01246 int len = strcspn(e->unit->um[i].desc, " \t");
01247 if (!strncmp(name, e->unit->um[i].desc, len) &&
01248 name[len] == '\0')
01249 found++;
01250 }
01251 if (found > 1) {
01252 fprintf(stderr,
01253 "Unit mask name `%s' not unique. Sorry please use a numerical unit mask\n", name);
01254 exit(EXIT_FAILURE);
01255 }
01256 }
01257
01258 static void do_resolve_unit_mask(struct op_event *e, struct parsed_event *pe,
01259 u32 *extra)
01260 {
01261 unsigned i;
01262 int found;
01263
01264 for (;;) {
01265 if (pe->unit_mask_name == NULL) {
01266 int had_unit_mask = pe->unit_mask_valid;
01267
01268 found = 0;
01269 for (i = 0; i < e->unit->num; i++) {
01270 if (!pe->unit_mask_valid &&
01271 e->unit->um[i].value == e->unit->default_mask) {
01272 pe->unit_mask_valid = 1;
01273 pe->unit_mask = e->unit->default_mask;
01274 break;
01275 }
01276 }
01277 if (found > 1 && had_unit_mask) {
01278 fprintf(stderr,
01279 "Non unique numerical unit mask.\n"
01280 "Please specify the unit mask using the first word of the description\n");
01281 exit(EXIT_FAILURE);
01282 }
01283 extra_check(e, pe->unit_mask);
01284 if (i == e->unit->num) {
01285 e = find_next_event(e);
01286 if (e != NULL)
01287 continue;
01288 } else {
01289 if (extra)
01290 *extra = e->unit->um[i].extra;
01291 }
01292 return;
01293 }
01294 for (i = 0; i < e->unit->num; i++) {
01295 int len = strcspn(e->unit->um[i].desc, " \t");
01296 if (!strncmp(pe->unit_mask_name, e->unit->um[i].desc,
01297 len) && pe->unit_mask_name[len] == '\0')
01298 break;
01299 }
01300 if (i == e->unit->num) {
01301 e = find_next_event(e);
01302 if (e != NULL)
01303 continue;
01304 fprintf(stderr, "Cannot find unit mask %s for %s\n",
01305 pe->unit_mask_name, pe->name);
01306 exit(EXIT_FAILURE);
01307 }
01308 another_extra_check(e, pe->unit_mask_name, i);
01309 pe->unit_mask_valid = 1;
01310 pe->unit_mask = e->unit->um[i].value;
01311 if (extra)
01312 *extra = e->unit->um[i].extra;
01313 return;
01314 }
01315 }
01316
01317 void op_resolve_unit_mask(struct parsed_event *pe, u32 *extra)
01318 {
01319 struct op_event *e;
01320
01321 e = find_event_by_name(pe->name, 0, 0);
01322 if (!e) {
01323 fprintf(stderr, "Cannot find event %s\n", pe->name);
01324 exit(EXIT_FAILURE);
01325 }
01326 return do_resolve_unit_mask(e, pe, extra);
01327 }