linux/tools/perf/util/parse-events.c
<<
>>
Prefs
   1
   2#include "util.h"
   3#include "../perf.h"
   4#include "parse-options.h"
   5#include "parse-events.h"
   6#include "exec_cmd.h"
   7#include "string.h"
   8#include "cache.h"
   9#include "header.h"
  10
  11int                                     nr_counters;
  12
  13struct perf_event_attr          attrs[MAX_COUNTERS];
  14
  15struct event_symbol {
  16        u8              type;
  17        u64             config;
  18        const char      *symbol;
  19        const char      *alias;
  20};
  21
  22enum event_result {
  23        EVT_FAILED,
  24        EVT_HANDLED,
  25        EVT_HANDLED_ALL
  26};
  27
  28char debugfs_path[MAXPATHLEN];
  29
  30#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
  31#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
  32
  33static struct event_symbol event_symbols[] = {
  34  { CHW(CPU_CYCLES),            "cpu-cycles",           "cycles"        },
  35  { CHW(INSTRUCTIONS),          "instructions",         ""              },
  36  { CHW(CACHE_REFERENCES),      "cache-references",     ""              },
  37  { CHW(CACHE_MISSES),          "cache-misses",         ""              },
  38  { CHW(BRANCH_INSTRUCTIONS),   "branch-instructions",  "branches"      },
  39  { CHW(BRANCH_MISSES),         "branch-misses",        ""              },
  40  { CHW(BUS_CYCLES),            "bus-cycles",           ""              },
  41
  42  { CSW(CPU_CLOCK),             "cpu-clock",            ""              },
  43  { CSW(TASK_CLOCK),            "task-clock",           ""              },
  44  { CSW(PAGE_FAULTS),           "page-faults",          "faults"        },
  45  { CSW(PAGE_FAULTS_MIN),       "minor-faults",         ""              },
  46  { CSW(PAGE_FAULTS_MAJ),       "major-faults",         ""              },
  47  { CSW(CONTEXT_SWITCHES),      "context-switches",     "cs"            },
  48  { CSW(CPU_MIGRATIONS),        "cpu-migrations",       "migrations"    },
  49};
  50
  51#define __PERF_EVENT_FIELD(config, name) \
  52        ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
  53
  54#define PERF_EVENT_RAW(config)  __PERF_EVENT_FIELD(config, RAW)
  55#define PERF_EVENT_CONFIG(config)       __PERF_EVENT_FIELD(config, CONFIG)
  56#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
  57#define PERF_EVENT_ID(config)           __PERF_EVENT_FIELD(config, EVENT)
  58
  59static const char *hw_event_names[] = {
  60        "cycles",
  61        "instructions",
  62        "cache-references",
  63        "cache-misses",
  64        "branches",
  65        "branch-misses",
  66        "bus-cycles",
  67};
  68
  69static const char *sw_event_names[] = {
  70        "cpu-clock-msecs",
  71        "task-clock-msecs",
  72        "page-faults",
  73        "context-switches",
  74        "CPU-migrations",
  75        "minor-faults",
  76        "major-faults",
  77};
  78
  79#define MAX_ALIASES 8
  80
  81static const char *hw_cache[][MAX_ALIASES] = {
  82 { "L1-dcache", "l1-d",         "l1d",          "L1-data",              },
  83 { "L1-icache", "l1-i",         "l1i",          "L1-instruction",       },
  84 { "LLC",       "L2"                                                    },
  85 { "dTLB",      "d-tlb",        "Data-TLB",                             },
  86 { "iTLB",      "i-tlb",        "Instruction-TLB",                      },
  87 { "branch",    "branches",     "bpu",          "btb",          "bpc",  },
  88};
  89
  90static const char *hw_cache_op[][MAX_ALIASES] = {
  91 { "load",      "loads",        "read",                                 },
  92 { "store",     "stores",       "write",                                },
  93 { "prefetch",  "prefetches",   "speculative-read", "speculative-load", },
  94};
  95
  96static const char *hw_cache_result[][MAX_ALIASES] = {
  97 { "refs",      "Reference",    "ops",          "access",               },
  98 { "misses",    "miss",                                                 },
  99};
 100
 101#define C(x)            PERF_COUNT_HW_CACHE_##x
 102#define CACHE_READ      (1 << C(OP_READ))
 103#define CACHE_WRITE     (1 << C(OP_WRITE))
 104#define CACHE_PREFETCH  (1 << C(OP_PREFETCH))
 105#define COP(x)          (1 << x)
 106
 107/*
 108 * cache operartion stat
 109 * L1I : Read and prefetch only
 110 * ITLB and BPU : Read-only
 111 */
 112static unsigned long hw_cache_stat[C(MAX)] = {
 113 [C(L1D)]       = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
 114 [C(L1I)]       = (CACHE_READ | CACHE_PREFETCH),
 115 [C(LL)]        = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
 116 [C(DTLB)]      = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
 117 [C(ITLB)]      = (CACHE_READ),
 118 [C(BPU)]       = (CACHE_READ),
 119};
 120
 121#define for_each_subsystem(sys_dir, sys_dirent, sys_next)              \
 122        while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)        \
 123        if (sys_dirent.d_type == DT_DIR &&                                     \
 124           (strcmp(sys_dirent.d_name, ".")) &&                                 \
 125           (strcmp(sys_dirent.d_name, "..")))
 126
 127static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
 128{
 129        char evt_path[MAXPATHLEN];
 130        int fd;
 131
 132        snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
 133                        sys_dir->d_name, evt_dir->d_name);
 134        fd = open(evt_path, O_RDONLY);
 135        if (fd < 0)
 136                return -EINVAL;
 137        close(fd);
 138
 139        return 0;
 140}
 141
 142#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next)              \
 143        while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next)        \
 144        if (evt_dirent.d_type == DT_DIR &&                                     \
 145           (strcmp(evt_dirent.d_name, ".")) &&                                 \
 146           (strcmp(evt_dirent.d_name, "..")) &&                                \
 147           (!tp_event_has_id(&sys_dirent, &evt_dirent)))
 148
 149#define MAX_EVENT_LENGTH 512
 150
 151int valid_debugfs_mount(const char *debugfs)
 152{
 153        struct statfs st_fs;
 154
 155        if (statfs(debugfs, &st_fs) < 0)
 156                return -ENOENT;
 157        else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
 158                return -ENOENT;
 159        return 0;
 160}
 161
 162struct tracepoint_path *tracepoint_id_to_path(u64 config)
 163{
 164        struct tracepoint_path *path = NULL;
 165        DIR *sys_dir, *evt_dir;
 166        struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
 167        char id_buf[4];
 168        int fd;
 169        u64 id;
 170        char evt_path[MAXPATHLEN];
 171        char dir_path[MAXPATHLEN];
 172
 173        if (valid_debugfs_mount(debugfs_path))
 174                return NULL;
 175
 176        sys_dir = opendir(debugfs_path);
 177        if (!sys_dir)
 178                return NULL;
 179
 180        for_each_subsystem(sys_dir, sys_dirent, sys_next) {
 181
 182                snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
 183                         sys_dirent.d_name);
 184                evt_dir = opendir(dir_path);
 185                if (!evt_dir)
 186                        continue;
 187
 188                for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
 189
 190                        snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
 191                                 evt_dirent.d_name);
 192                        fd = open(evt_path, O_RDONLY);
 193                        if (fd < 0)
 194                                continue;
 195                        if (read(fd, id_buf, sizeof(id_buf)) < 0) {
 196                                close(fd);
 197                                continue;
 198                        }
 199                        close(fd);
 200                        id = atoll(id_buf);
 201                        if (id == config) {
 202                                closedir(evt_dir);
 203                                closedir(sys_dir);
 204                                path = calloc(1, sizeof(path));
 205                                path->system = malloc(MAX_EVENT_LENGTH);
 206                                if (!path->system) {
 207                                        free(path);
 208                                        return NULL;
 209                                }
 210                                path->name = malloc(MAX_EVENT_LENGTH);
 211                                if (!path->name) {
 212                                        free(path->system);
 213                                        free(path);
 214                                        return NULL;
 215                                }
 216                                strncpy(path->system, sys_dirent.d_name,
 217                                        MAX_EVENT_LENGTH);
 218                                strncpy(path->name, evt_dirent.d_name,
 219                                        MAX_EVENT_LENGTH);
 220                                return path;
 221                        }
 222                }
 223                closedir(evt_dir);
 224        }
 225
 226        closedir(sys_dir);
 227        return NULL;
 228}
 229
 230#define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
 231static const char *tracepoint_id_to_name(u64 config)
 232{
 233        static char buf[TP_PATH_LEN];
 234        struct tracepoint_path *path;
 235
 236        path = tracepoint_id_to_path(config);
 237        if (path) {
 238                snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
 239                free(path->name);
 240                free(path->system);
 241                free(path);
 242        } else
 243                snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");
 244
 245        return buf;
 246}
 247
 248static int is_cache_op_valid(u8 cache_type, u8 cache_op)
 249{
 250        if (hw_cache_stat[cache_type] & COP(cache_op))
 251                return 1;       /* valid */
 252        else
 253                return 0;       /* invalid */
 254}
 255
 256static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
 257{
 258        static char name[50];
 259
 260        if (cache_result) {
 261                sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
 262                        hw_cache_op[cache_op][0],
 263                        hw_cache_result[cache_result][0]);
 264        } else {
 265                sprintf(name, "%s-%s", hw_cache[cache_type][0],
 266                        hw_cache_op[cache_op][1]);
 267        }
 268
 269        return name;
 270}
 271
 272const char *event_name(int counter)
 273{
 274        u64 config = attrs[counter].config;
 275        int type = attrs[counter].type;
 276
 277        return __event_name(type, config);
 278}
 279
 280const char *__event_name(int type, u64 config)
 281{
 282        static char buf[32];
 283
 284        if (type == PERF_TYPE_RAW) {
 285                sprintf(buf, "raw 0x%llx", config);
 286                return buf;
 287        }
 288
 289        switch (type) {
 290        case PERF_TYPE_HARDWARE:
 291                if (config < PERF_COUNT_HW_MAX)
 292                        return hw_event_names[config];
 293                return "unknown-hardware";
 294
 295        case PERF_TYPE_HW_CACHE: {
 296                u8 cache_type, cache_op, cache_result;
 297
 298                cache_type   = (config >>  0) & 0xff;
 299                if (cache_type > PERF_COUNT_HW_CACHE_MAX)
 300                        return "unknown-ext-hardware-cache-type";
 301
 302                cache_op     = (config >>  8) & 0xff;
 303                if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
 304                        return "unknown-ext-hardware-cache-op";
 305
 306                cache_result = (config >> 16) & 0xff;
 307                if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
 308                        return "unknown-ext-hardware-cache-result";
 309
 310                if (!is_cache_op_valid(cache_type, cache_op))
 311                        return "invalid-cache";
 312
 313                return event_cache_name(cache_type, cache_op, cache_result);
 314        }
 315
 316        case PERF_TYPE_SOFTWARE:
 317                if (config < PERF_COUNT_SW_MAX)
 318                        return sw_event_names[config];
 319                return "unknown-software";
 320
 321        case PERF_TYPE_TRACEPOINT:
 322                return tracepoint_id_to_name(config);
 323
 324        default:
 325                break;
 326        }
 327
 328        return "unknown";
 329}
 330
 331static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size)
 332{
 333        int i, j;
 334        int n, longest = -1;
 335
 336        for (i = 0; i < size; i++) {
 337                for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
 338                        n = strlen(names[i][j]);
 339                        if (n > longest && !strncasecmp(*str, names[i][j], n))
 340                                longest = n;
 341                }
 342                if (longest > 0) {
 343                        *str += longest;
 344                        return i;
 345                }
 346        }
 347
 348        return -1;
 349}
 350
 351static enum event_result
 352parse_generic_hw_event(const char **str, struct perf_event_attr *attr)
 353{
 354        const char *s = *str;
 355        int cache_type = -1, cache_op = -1, cache_result = -1;
 356
 357        cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX);
 358        /*
 359         * No fallback - if we cannot get a clear cache type
 360         * then bail out:
 361         */
 362        if (cache_type == -1)
 363                return EVT_FAILED;
 364
 365        while ((cache_op == -1 || cache_result == -1) && *s == '-') {
 366                ++s;
 367
 368                if (cache_op == -1) {
 369                        cache_op = parse_aliases(&s, hw_cache_op,
 370                                                PERF_COUNT_HW_CACHE_OP_MAX);
 371                        if (cache_op >= 0) {
 372                                if (!is_cache_op_valid(cache_type, cache_op))
 373                                        return 0;
 374                                continue;
 375                        }
 376                }
 377
 378                if (cache_result == -1) {
 379                        cache_result = parse_aliases(&s, hw_cache_result,
 380                                                PERF_COUNT_HW_CACHE_RESULT_MAX);
 381                        if (cache_result >= 0)
 382                                continue;
 383                }
 384
 385                /*
 386                 * Can't parse this as a cache op or result, so back up
 387                 * to the '-'.
 388                 */
 389                --s;
 390                break;
 391        }
 392
 393        /*
 394         * Fall back to reads:
 395         */
 396        if (cache_op == -1)
 397                cache_op = PERF_COUNT_HW_CACHE_OP_READ;
 398
 399        /*
 400         * Fall back to accesses:
 401         */
 402        if (cache_result == -1)
 403                cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
 404
 405        attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
 406        attr->type = PERF_TYPE_HW_CACHE;
 407
 408        *str = s;
 409        return EVT_HANDLED;
 410}
 411
 412static enum event_result
 413parse_single_tracepoint_event(char *sys_name,
 414                              const char *evt_name,
 415                              unsigned int evt_length,
 416                              char *flags,
 417                              struct perf_event_attr *attr,
 418                              const char **strp)
 419{
 420        char evt_path[MAXPATHLEN];
 421        char id_buf[4];
 422        u64 id;
 423        int fd;
 424
 425        if (flags) {
 426                if (!strncmp(flags, "record", strlen(flags))) {
 427                        attr->sample_type |= PERF_SAMPLE_RAW;
 428                        attr->sample_type |= PERF_SAMPLE_TIME;
 429                        attr->sample_type |= PERF_SAMPLE_CPU;
 430                }
 431        }
 432
 433        snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
 434                 sys_name, evt_name);
 435
 436        fd = open(evt_path, O_RDONLY);
 437        if (fd < 0)
 438                return EVT_FAILED;
 439
 440        if (read(fd, id_buf, sizeof(id_buf)) < 0) {
 441                close(fd);
 442                return EVT_FAILED;
 443        }
 444
 445        close(fd);
 446        id = atoll(id_buf);
 447        attr->config = id;
 448        attr->type = PERF_TYPE_TRACEPOINT;
 449        *strp = evt_name + evt_length;
 450
 451        return EVT_HANDLED;
 452}
 453
 454/* sys + ':' + event + ':' + flags*/
 455#define MAX_EVOPT_LEN   (MAX_EVENT_LENGTH * 2 + 2 + 128)
 456static enum event_result
 457parse_subsystem_tracepoint_event(char *sys_name, char *flags)
 458{
 459        char evt_path[MAXPATHLEN];
 460        struct dirent *evt_ent;
 461        DIR *evt_dir;
 462
 463        snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name);
 464        evt_dir = opendir(evt_path);
 465
 466        if (!evt_dir) {
 467                perror("Can't open event dir");
 468                return EVT_FAILED;
 469        }
 470
 471        while ((evt_ent = readdir(evt_dir))) {
 472                char event_opt[MAX_EVOPT_LEN + 1];
 473                int len;
 474                unsigned int rem = MAX_EVOPT_LEN;
 475
 476                if (!strcmp(evt_ent->d_name, ".")
 477                    || !strcmp(evt_ent->d_name, "..")
 478                    || !strcmp(evt_ent->d_name, "enable")
 479                    || !strcmp(evt_ent->d_name, "filter"))
 480                        continue;
 481
 482                len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s", sys_name,
 483                               evt_ent->d_name);
 484                if (len < 0)
 485                        return EVT_FAILED;
 486
 487                rem -= len;
 488                if (flags) {
 489                        if (rem < strlen(flags) + 1)
 490                                return EVT_FAILED;
 491
 492                        strcat(event_opt, ":");
 493                        strcat(event_opt, flags);
 494                }
 495
 496                if (parse_events(NULL, event_opt, 0))
 497                        return EVT_FAILED;
 498        }
 499
 500        return EVT_HANDLED_ALL;
 501}
 502
 503
 504static enum event_result parse_tracepoint_event(const char **strp,
 505                                    struct perf_event_attr *attr)
 506{
 507        const char *evt_name;
 508        char *flags;
 509        char sys_name[MAX_EVENT_LENGTH];
 510        unsigned int sys_length, evt_length;
 511
 512        if (valid_debugfs_mount(debugfs_path))
 513                return 0;
 514
 515        evt_name = strchr(*strp, ':');
 516        if (!evt_name)
 517                return EVT_FAILED;
 518
 519        sys_length = evt_name - *strp;
 520        if (sys_length >= MAX_EVENT_LENGTH)
 521                return 0;
 522
 523        strncpy(sys_name, *strp, sys_length);
 524        sys_name[sys_length] = '\0';
 525        evt_name = evt_name + 1;
 526
 527        flags = strchr(evt_name, ':');
 528        if (flags) {
 529                /* split it out: */
 530                evt_name = strndup(evt_name, flags - evt_name);
 531                flags++;
 532        }
 533
 534        evt_length = strlen(evt_name);
 535        if (evt_length >= MAX_EVENT_LENGTH)
 536                return EVT_FAILED;
 537
 538        if (!strcmp(evt_name, "*")) {
 539                *strp = evt_name + evt_length;
 540                return parse_subsystem_tracepoint_event(sys_name, flags);
 541        } else
 542                return parse_single_tracepoint_event(sys_name, evt_name,
 543                                                     evt_length, flags,
 544                                                     attr, strp);
 545}
 546
 547static int check_events(const char *str, unsigned int i)
 548{
 549        int n;
 550
 551        n = strlen(event_symbols[i].symbol);
 552        if (!strncmp(str, event_symbols[i].symbol, n))
 553                return n;
 554
 555        n = strlen(event_symbols[i].alias);
 556        if (n)
 557                if (!strncmp(str, event_symbols[i].alias, n))
 558                        return n;
 559        return 0;
 560}
 561
 562static enum event_result
 563parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
 564{
 565        const char *str = *strp;
 566        unsigned int i;
 567        int n;
 568
 569        for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
 570                n = check_events(str, i);
 571                if (n > 0) {
 572                        attr->type = event_symbols[i].type;
 573                        attr->config = event_symbols[i].config;
 574                        *strp = str + n;
 575                        return EVT_HANDLED;
 576                }
 577        }
 578        return EVT_FAILED;
 579}
 580
 581static enum event_result
 582parse_raw_event(const char **strp, struct perf_event_attr *attr)
 583{
 584        const char *str = *strp;
 585        u64 config;
 586        int n;
 587
 588        if (*str != 'r')
 589                return EVT_FAILED;
 590        n = hex2u64(str + 1, &config);
 591        if (n > 0) {
 592                *strp = str + n + 1;
 593                attr->type = PERF_TYPE_RAW;
 594                attr->config = config;
 595                return EVT_HANDLED;
 596        }
 597        return EVT_FAILED;
 598}
 599
 600static enum event_result
 601parse_numeric_event(const char **strp, struct perf_event_attr *attr)
 602{
 603        const char *str = *strp;
 604        char *endp;
 605        unsigned long type;
 606        u64 config;
 607
 608        type = strtoul(str, &endp, 0);
 609        if (endp > str && type < PERF_TYPE_MAX && *endp == ':') {
 610                str = endp + 1;
 611                config = strtoul(str, &endp, 0);
 612                if (endp > str) {
 613                        attr->type = type;
 614                        attr->config = config;
 615                        *strp = endp;
 616                        return EVT_HANDLED;
 617                }
 618        }
 619        return EVT_FAILED;
 620}
 621
 622static enum event_result
 623parse_event_modifier(const char **strp, struct perf_event_attr *attr)
 624{
 625        const char *str = *strp;
 626        int eu = 1, ek = 1, eh = 1;
 627
 628        if (*str++ != ':')
 629                return 0;
 630        while (*str) {
 631                if (*str == 'u')
 632                        eu = 0;
 633                else if (*str == 'k')
 634                        ek = 0;
 635                else if (*str == 'h')
 636                        eh = 0;
 637                else
 638                        break;
 639                ++str;
 640        }
 641        if (str >= *strp + 2) {
 642                *strp = str;
 643                attr->exclude_user   = eu;
 644                attr->exclude_kernel = ek;
 645                attr->exclude_hv     = eh;
 646                return 1;
 647        }
 648        return 0;
 649}
 650
 651/*
 652 * Each event can have multiple symbolic names.
 653 * Symbolic names are (almost) exactly matched.
 654 */
 655static enum event_result
 656parse_event_symbols(const char **str, struct perf_event_attr *attr)
 657{
 658        enum event_result ret;
 659
 660        ret = parse_tracepoint_event(str, attr);
 661        if (ret != EVT_FAILED)
 662                goto modifier;
 663
 664        ret = parse_raw_event(str, attr);
 665        if (ret != EVT_FAILED)
 666                goto modifier;
 667
 668        ret = parse_numeric_event(str, attr);
 669        if (ret != EVT_FAILED)
 670                goto modifier;
 671
 672        ret = parse_symbolic_event(str, attr);
 673        if (ret != EVT_FAILED)
 674                goto modifier;
 675
 676        ret = parse_generic_hw_event(str, attr);
 677        if (ret != EVT_FAILED)
 678                goto modifier;
 679
 680        return EVT_FAILED;
 681
 682modifier:
 683        parse_event_modifier(str, attr);
 684
 685        return ret;
 686}
 687
 688static void store_event_type(const char *orgname)
 689{
 690        char filename[PATH_MAX], *c;
 691        FILE *file;
 692        int id;
 693
 694        sprintf(filename, "%s/", debugfs_path);
 695        strncat(filename, orgname, strlen(orgname));
 696        strcat(filename, "/id");
 697
 698        c = strchr(filename, ':');
 699        if (c)
 700                *c = '/';
 701
 702        file = fopen(filename, "r");
 703        if (!file)
 704                return;
 705        if (fscanf(file, "%i", &id) < 1)
 706                die("cannot store event ID");
 707        fclose(file);
 708        perf_header__push_event(id, orgname);
 709}
 710
 711
 712int parse_events(const struct option *opt __used, const char *str, int unset __used)
 713{
 714        struct perf_event_attr attr;
 715        enum event_result ret;
 716
 717        if (strchr(str, ':'))
 718                store_event_type(str);
 719
 720        for (;;) {
 721                if (nr_counters == MAX_COUNTERS)
 722                        return -1;
 723
 724                memset(&attr, 0, sizeof(attr));
 725                ret = parse_event_symbols(&str, &attr);
 726                if (ret == EVT_FAILED)
 727                        return -1;
 728
 729                if (!(*str == 0 || *str == ',' || isspace(*str)))
 730                        return -1;
 731
 732                if (ret != EVT_HANDLED_ALL) {
 733                        attrs[nr_counters] = attr;
 734                        nr_counters++;
 735                }
 736
 737                if (*str == 0)
 738                        break;
 739                if (*str == ',')
 740                        ++str;
 741                while (isspace(*str))
 742                        ++str;
 743        }
 744
 745        return 0;
 746}
 747
 748static const char * const event_type_descriptors[] = {
 749        "",
 750        "Hardware event",
 751        "Software event",
 752        "Tracepoint event",
 753        "Hardware cache event",
 754};
 755
 756/*
 757 * Print the events from <debugfs_mount_point>/tracing/events
 758 */
 759
 760static void print_tracepoint_events(void)
 761{
 762        DIR *sys_dir, *evt_dir;
 763        struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
 764        char evt_path[MAXPATHLEN];
 765        char dir_path[MAXPATHLEN];
 766
 767        if (valid_debugfs_mount(debugfs_path))
 768                return;
 769
 770        sys_dir = opendir(debugfs_path);
 771        if (!sys_dir)
 772                return;
 773
 774        for_each_subsystem(sys_dir, sys_dirent, sys_next) {
 775
 776                snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
 777                         sys_dirent.d_name);
 778                evt_dir = opendir(dir_path);
 779                if (!evt_dir)
 780                        continue;
 781
 782                for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
 783                        snprintf(evt_path, MAXPATHLEN, "%s:%s",
 784                                 sys_dirent.d_name, evt_dirent.d_name);
 785                        fprintf(stderr, "  %-42s [%s]\n", evt_path,
 786                                event_type_descriptors[PERF_TYPE_TRACEPOINT+1]);
 787                }
 788                closedir(evt_dir);
 789        }
 790        closedir(sys_dir);
 791}
 792
 793/*
 794 * Print the help text for the event symbols:
 795 */
 796void print_events(void)
 797{
 798        struct event_symbol *syms = event_symbols;
 799        unsigned int i, type, op, prev_type = -1;
 800        char name[40];
 801
 802        fprintf(stderr, "\n");
 803        fprintf(stderr, "List of pre-defined events (to be used in -e):\n");
 804
 805        for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
 806                type = syms->type + 1;
 807                if (type >= ARRAY_SIZE(event_type_descriptors))
 808                        type = 0;
 809
 810                if (type != prev_type)
 811                        fprintf(stderr, "\n");
 812
 813                if (strlen(syms->alias))
 814                        sprintf(name, "%s OR %s", syms->symbol, syms->alias);
 815                else
 816                        strcpy(name, syms->symbol);
 817                fprintf(stderr, "  %-42s [%s]\n", name,
 818                        event_type_descriptors[type]);
 819
 820                prev_type = type;
 821        }
 822
 823        fprintf(stderr, "\n");
 824        for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
 825                for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
 826                        /* skip invalid cache type */
 827                        if (!is_cache_op_valid(type, op))
 828                                continue;
 829
 830                        for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
 831                                fprintf(stderr, "  %-42s [%s]\n",
 832                                        event_cache_name(type, op, i),
 833                                        event_type_descriptors[4]);
 834                        }
 835                }
 836        }
 837
 838        fprintf(stderr, "\n");
 839        fprintf(stderr, "  %-42s [raw hardware event descriptor]\n",
 840                "rNNN");
 841        fprintf(stderr, "\n");
 842
 843        print_tracepoint_events();
 844
 845        exit(129);
 846}
 847