linux/tools/perf/util/parse-events.c
<<
>>
Prefs
   1#include "../../../include/linux/hw_breakpoint.h"
   2#include "util.h"
   3#include "../perf.h"
   4#include "evlist.h"
   5#include "evsel.h"
   6#include "parse-options.h"
   7#include "parse-events.h"
   8#include "exec_cmd.h"
   9#include "string.h"
  10#include "symbol.h"
  11#include "cache.h"
  12#include "header.h"
  13#include "debugfs.h"
  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(STALLED_CYCLES_FRONTEND),       "stalled-cycles-frontend",      "idle-cycles-frontend"  },
  36  { CHW(STALLED_CYCLES_BACKEND),        "stalled-cycles-backend",       "idle-cycles-backend"   },
  37  { CHW(INSTRUCTIONS),                  "instructions",                 ""                      },
  38  { CHW(CACHE_REFERENCES),              "cache-references",             ""                      },
  39  { CHW(CACHE_MISSES),                  "cache-misses",                 ""                      },
  40  { CHW(BRANCH_INSTRUCTIONS),           "branch-instructions",          "branches"              },
  41  { CHW(BRANCH_MISSES),                 "branch-misses",                ""                      },
  42  { CHW(BUS_CYCLES),                    "bus-cycles",                   ""                      },
  43
  44  { CSW(CPU_CLOCK),                     "cpu-clock",                    ""                      },
  45  { CSW(TASK_CLOCK),                    "task-clock",                   ""                      },
  46  { CSW(PAGE_FAULTS),                   "page-faults",                  "faults"                },
  47  { CSW(PAGE_FAULTS_MIN),               "minor-faults",                 ""                      },
  48  { CSW(PAGE_FAULTS_MAJ),               "major-faults",                 ""                      },
  49  { CSW(CONTEXT_SWITCHES),              "context-switches",             "cs"                    },
  50  { CSW(CPU_MIGRATIONS),                "cpu-migrations",               "migrations"            },
  51  { CSW(ALIGNMENT_FAULTS),              "alignment-faults",             ""                      },
  52  { CSW(EMULATION_FAULTS),              "emulation-faults",             ""                      },
  53};
  54
  55#define __PERF_EVENT_FIELD(config, name) \
  56        ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
  57
  58#define PERF_EVENT_RAW(config)          __PERF_EVENT_FIELD(config, RAW)
  59#define PERF_EVENT_CONFIG(config)       __PERF_EVENT_FIELD(config, CONFIG)
  60#define PERF_EVENT_TYPE(config)         __PERF_EVENT_FIELD(config, TYPE)
  61#define PERF_EVENT_ID(config)           __PERF_EVENT_FIELD(config, EVENT)
  62
  63static const char *hw_event_names[PERF_COUNT_HW_MAX] = {
  64        "cycles",
  65        "instructions",
  66        "cache-references",
  67        "cache-misses",
  68        "branches",
  69        "branch-misses",
  70        "bus-cycles",
  71        "stalled-cycles-frontend",
  72        "stalled-cycles-backend",
  73};
  74
  75static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
  76        "cpu-clock",
  77        "task-clock",
  78        "page-faults",
  79        "context-switches",
  80        "CPU-migrations",
  81        "minor-faults",
  82        "major-faults",
  83        "alignment-faults",
  84        "emulation-faults",
  85};
  86
  87#define MAX_ALIASES 8
  88
  89static const char *hw_cache[PERF_COUNT_HW_CACHE_MAX][MAX_ALIASES] = {
  90 { "L1-dcache", "l1-d",         "l1d",          "L1-data",              },
  91 { "L1-icache", "l1-i",         "l1i",          "L1-instruction",       },
  92 { "LLC",       "L2",                                                   },
  93 { "dTLB",      "d-tlb",        "Data-TLB",                             },
  94 { "iTLB",      "i-tlb",        "Instruction-TLB",                      },
  95 { "branch",    "branches",     "bpu",          "btb",          "bpc",  },
  96 { "node",                                                              },
  97};
  98
  99static const char *hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][MAX_ALIASES] = {
 100 { "load",      "loads",        "read",                                 },
 101 { "store",     "stores",       "write",                                },
 102 { "prefetch",  "prefetches",   "speculative-read", "speculative-load", },
 103};
 104
 105static const char *hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
 106                                  [MAX_ALIASES] = {
 107 { "refs",      "Reference",    "ops",          "access",               },
 108 { "misses",    "miss",                                                 },
 109};
 110
 111#define C(x)            PERF_COUNT_HW_CACHE_##x
 112#define CACHE_READ      (1 << C(OP_READ))
 113#define CACHE_WRITE     (1 << C(OP_WRITE))
 114#define CACHE_PREFETCH  (1 << C(OP_PREFETCH))
 115#define COP(x)          (1 << x)
 116
 117/*
 118 * cache operartion stat
 119 * L1I : Read and prefetch only
 120 * ITLB and BPU : Read-only
 121 */
 122static unsigned long hw_cache_stat[C(MAX)] = {
 123 [C(L1D)]       = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
 124 [C(L1I)]       = (CACHE_READ | CACHE_PREFETCH),
 125 [C(LL)]        = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
 126 [C(DTLB)]      = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
 127 [C(ITLB)]      = (CACHE_READ),
 128 [C(BPU)]       = (CACHE_READ),
 129 [C(NODE)]      = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
 130};
 131
 132#define for_each_subsystem(sys_dir, sys_dirent, sys_next)              \
 133        while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)        \
 134        if (sys_dirent.d_type == DT_DIR &&                                     \
 135           (strcmp(sys_dirent.d_name, ".")) &&                                 \
 136           (strcmp(sys_dirent.d_name, "..")))
 137
 138static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
 139{
 140        char evt_path[MAXPATHLEN];
 141        int fd;
 142
 143        snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
 144                        sys_dir->d_name, evt_dir->d_name);
 145        fd = open(evt_path, O_RDONLY);
 146        if (fd < 0)
 147                return -EINVAL;
 148        close(fd);
 149
 150        return 0;
 151}
 152
 153#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next)              \
 154        while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next)        \
 155        if (evt_dirent.d_type == DT_DIR &&                                     \
 156           (strcmp(evt_dirent.d_name, ".")) &&                                 \
 157           (strcmp(evt_dirent.d_name, "..")) &&                                \
 158           (!tp_event_has_id(&sys_dirent, &evt_dirent)))
 159
 160#define MAX_EVENT_LENGTH 512
 161
 162
 163struct tracepoint_path *tracepoint_id_to_path(u64 config)
 164{
 165        struct tracepoint_path *path = NULL;
 166        DIR *sys_dir, *evt_dir;
 167        struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
 168        char id_buf[4];
 169        int fd;
 170        u64 id;
 171        char evt_path[MAXPATHLEN];
 172        char dir_path[MAXPATHLEN];
 173
 174        if (debugfs_valid_mountpoint(debugfs_path))
 175                return NULL;
 176
 177        sys_dir = opendir(debugfs_path);
 178        if (!sys_dir)
 179                return NULL;
 180
 181        for_each_subsystem(sys_dir, sys_dirent, sys_next) {
 182
 183                snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
 184                         sys_dirent.d_name);
 185                evt_dir = opendir(dir_path);
 186                if (!evt_dir)
 187                        continue;
 188
 189                for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
 190
 191                        snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
 192                                 evt_dirent.d_name);
 193                        fd = open(evt_path, O_RDONLY);
 194                        if (fd < 0)
 195                                continue;
 196                        if (read(fd, id_buf, sizeof(id_buf)) < 0) {
 197                                close(fd);
 198                                continue;
 199                        }
 200                        close(fd);
 201                        id = atoll(id_buf);
 202                        if (id == config) {
 203                                closedir(evt_dir);
 204                                closedir(sys_dir);
 205                                path = zalloc(sizeof(*path));
 206                                path->system = malloc(MAX_EVENT_LENGTH);
 207                                if (!path->system) {
 208                                        free(path);
 209                                        return NULL;
 210                                }
 211                                path->name = malloc(MAX_EVENT_LENGTH);
 212                                if (!path->name) {
 213                                        free(path->system);
 214                                        free(path);
 215                                        return NULL;
 216                                }
 217                                strncpy(path->system, sys_dirent.d_name,
 218                                        MAX_EVENT_LENGTH);
 219                                strncpy(path->name, evt_dirent.d_name,
 220                                        MAX_EVENT_LENGTH);
 221                                return path;
 222                        }
 223                }
 224                closedir(evt_dir);
 225        }
 226
 227        closedir(sys_dir);
 228        return NULL;
 229}
 230
 231#define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
 232static const char *tracepoint_id_to_name(u64 config)
 233{
 234        static char buf[TP_PATH_LEN];
 235        struct tracepoint_path *path;
 236
 237        path = tracepoint_id_to_path(config);
 238        if (path) {
 239                snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
 240                free(path->name);
 241                free(path->system);
 242                free(path);
 243        } else
 244                snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");
 245
 246        return buf;
 247}
 248
 249static int is_cache_op_valid(u8 cache_type, u8 cache_op)
 250{
 251        if (hw_cache_stat[cache_type] & COP(cache_op))
 252                return 1;       /* valid */
 253        else
 254                return 0;       /* invalid */
 255}
 256
 257static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
 258{
 259        static char name[50];
 260
 261        if (cache_result) {
 262                sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
 263                        hw_cache_op[cache_op][0],
 264                        hw_cache_result[cache_result][0]);
 265        } else {
 266                sprintf(name, "%s-%s", hw_cache[cache_type][0],
 267                        hw_cache_op[cache_op][1]);
 268        }
 269
 270        return name;
 271}
 272
 273const char *event_type(int type)
 274{
 275        switch (type) {
 276        case PERF_TYPE_HARDWARE:
 277                return "hardware";
 278
 279        case PERF_TYPE_SOFTWARE:
 280                return "software";
 281
 282        case PERF_TYPE_TRACEPOINT:
 283                return "tracepoint";
 284
 285        case PERF_TYPE_HW_CACHE:
 286                return "hardware-cache";
 287
 288        default:
 289                break;
 290        }
 291
 292        return "unknown";
 293}
 294
 295const char *event_name(struct perf_evsel *evsel)
 296{
 297        u64 config = evsel->attr.config;
 298        int type = evsel->attr.type;
 299
 300        if (evsel->name)
 301                return evsel->name;
 302
 303        return __event_name(type, config);
 304}
 305
 306const char *__event_name(int type, u64 config)
 307{
 308        static char buf[32];
 309
 310        if (type == PERF_TYPE_RAW) {
 311                sprintf(buf, "raw 0x%" PRIx64, config);
 312                return buf;
 313        }
 314
 315        switch (type) {
 316        case PERF_TYPE_HARDWARE:
 317                if (config < PERF_COUNT_HW_MAX && hw_event_names[config])
 318                        return hw_event_names[config];
 319                return "unknown-hardware";
 320
 321        case PERF_TYPE_HW_CACHE: {
 322                u8 cache_type, cache_op, cache_result;
 323
 324                cache_type   = (config >>  0) & 0xff;
 325                if (cache_type > PERF_COUNT_HW_CACHE_MAX)
 326                        return "unknown-ext-hardware-cache-type";
 327
 328                cache_op     = (config >>  8) & 0xff;
 329                if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
 330                        return "unknown-ext-hardware-cache-op";
 331
 332                cache_result = (config >> 16) & 0xff;
 333                if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
 334                        return "unknown-ext-hardware-cache-result";
 335
 336                if (!is_cache_op_valid(cache_type, cache_op))
 337                        return "invalid-cache";
 338
 339                return event_cache_name(cache_type, cache_op, cache_result);
 340        }
 341
 342        case PERF_TYPE_SOFTWARE:
 343                if (config < PERF_COUNT_SW_MAX && sw_event_names[config])
 344                        return sw_event_names[config];
 345                return "unknown-software";
 346
 347        case PERF_TYPE_TRACEPOINT:
 348                return tracepoint_id_to_name(config);
 349
 350        default:
 351                break;
 352        }
 353
 354        return "unknown";
 355}
 356
 357static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size)
 358{
 359        int i, j;
 360        int n, longest = -1;
 361
 362        for (i = 0; i < size; i++) {
 363                for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
 364                        n = strlen(names[i][j]);
 365                        if (n > longest && !strncasecmp(*str, names[i][j], n))
 366                                longest = n;
 367                }
 368                if (longest > 0) {
 369                        *str += longest;
 370                        return i;
 371                }
 372        }
 373
 374        return -1;
 375}
 376
 377static enum event_result
 378parse_generic_hw_event(const char **str, struct perf_event_attr *attr)
 379{
 380        const char *s = *str;
 381        int cache_type = -1, cache_op = -1, cache_result = -1;
 382
 383        cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX);
 384        /*
 385         * No fallback - if we cannot get a clear cache type
 386         * then bail out:
 387         */
 388        if (cache_type == -1)
 389                return EVT_FAILED;
 390
 391        while ((cache_op == -1 || cache_result == -1) && *s == '-') {
 392                ++s;
 393
 394                if (cache_op == -1) {
 395                        cache_op = parse_aliases(&s, hw_cache_op,
 396                                                PERF_COUNT_HW_CACHE_OP_MAX);
 397                        if (cache_op >= 0) {
 398                                if (!is_cache_op_valid(cache_type, cache_op))
 399                                        return EVT_FAILED;
 400                                continue;
 401                        }
 402                }
 403
 404                if (cache_result == -1) {
 405                        cache_result = parse_aliases(&s, hw_cache_result,
 406                                                PERF_COUNT_HW_CACHE_RESULT_MAX);
 407                        if (cache_result >= 0)
 408                                continue;
 409                }
 410
 411                /*
 412                 * Can't parse this as a cache op or result, so back up
 413                 * to the '-'.
 414                 */
 415                --s;
 416                break;
 417        }
 418
 419        /*
 420         * Fall back to reads:
 421         */
 422        if (cache_op == -1)
 423                cache_op = PERF_COUNT_HW_CACHE_OP_READ;
 424
 425        /*
 426         * Fall back to accesses:
 427         */
 428        if (cache_result == -1)
 429                cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
 430
 431        attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
 432        attr->type = PERF_TYPE_HW_CACHE;
 433
 434        *str = s;
 435        return EVT_HANDLED;
 436}
 437
 438static enum event_result
 439parse_single_tracepoint_event(char *sys_name,
 440                              const char *evt_name,
 441                              unsigned int evt_length,
 442                              struct perf_event_attr *attr,
 443                              const char **strp)
 444{
 445        char evt_path[MAXPATHLEN];
 446        char id_buf[4];
 447        u64 id;
 448        int fd;
 449
 450        snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
 451                 sys_name, evt_name);
 452
 453        fd = open(evt_path, O_RDONLY);
 454        if (fd < 0)
 455                return EVT_FAILED;
 456
 457        if (read(fd, id_buf, sizeof(id_buf)) < 0) {
 458                close(fd);
 459                return EVT_FAILED;
 460        }
 461
 462        close(fd);
 463        id = atoll(id_buf);
 464        attr->config = id;
 465        attr->type = PERF_TYPE_TRACEPOINT;
 466        *strp += strlen(sys_name) + evt_length + 1; /* + 1 for the ':' */
 467
 468        attr->sample_type |= PERF_SAMPLE_RAW;
 469        attr->sample_type |= PERF_SAMPLE_TIME;
 470        attr->sample_type |= PERF_SAMPLE_CPU;
 471
 472        attr->sample_period = 1;
 473
 474
 475        return EVT_HANDLED;
 476}
 477
 478/* sys + ':' + event + ':' + flags*/
 479#define MAX_EVOPT_LEN   (MAX_EVENT_LENGTH * 2 + 2 + 128)
 480static enum event_result
 481parse_multiple_tracepoint_event(struct perf_evlist *evlist, char *sys_name,
 482                                const char *evt_exp, char *flags)
 483{
 484        char evt_path[MAXPATHLEN];
 485        struct dirent *evt_ent;
 486        DIR *evt_dir;
 487
 488        snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name);
 489        evt_dir = opendir(evt_path);
 490
 491        if (!evt_dir) {
 492                perror("Can't open event dir");
 493                return EVT_FAILED;
 494        }
 495
 496        while ((evt_ent = readdir(evt_dir))) {
 497                char event_opt[MAX_EVOPT_LEN + 1];
 498                int len;
 499
 500                if (!strcmp(evt_ent->d_name, ".")
 501                    || !strcmp(evt_ent->d_name, "..")
 502                    || !strcmp(evt_ent->d_name, "enable")
 503                    || !strcmp(evt_ent->d_name, "filter"))
 504                        continue;
 505
 506                if (!strglobmatch(evt_ent->d_name, evt_exp))
 507                        continue;
 508
 509                len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s%s%s", sys_name,
 510                               evt_ent->d_name, flags ? ":" : "",
 511                               flags ?: "");
 512                if (len < 0)
 513                        return EVT_FAILED;
 514
 515                if (parse_events(evlist, event_opt, 0))
 516                        return EVT_FAILED;
 517        }
 518
 519        return EVT_HANDLED_ALL;
 520}
 521
 522static enum event_result
 523parse_tracepoint_event(struct perf_evlist *evlist, const char **strp,
 524                       struct perf_event_attr *attr)
 525{
 526        const char *evt_name;
 527        char *flags = NULL, *comma_loc;
 528        char sys_name[MAX_EVENT_LENGTH];
 529        unsigned int sys_length, evt_length;
 530
 531        if (debugfs_valid_mountpoint(debugfs_path))
 532                return 0;
 533
 534        evt_name = strchr(*strp, ':');
 535        if (!evt_name)
 536                return EVT_FAILED;
 537
 538        sys_length = evt_name - *strp;
 539        if (sys_length >= MAX_EVENT_LENGTH)
 540                return 0;
 541
 542        strncpy(sys_name, *strp, sys_length);
 543        sys_name[sys_length] = '\0';
 544        evt_name = evt_name + 1;
 545
 546        comma_loc = strchr(evt_name, ',');
 547        if (comma_loc) {
 548                /* take the event name up to the comma */
 549                evt_name = strndup(evt_name, comma_loc - evt_name);
 550        }
 551        flags = strchr(evt_name, ':');
 552        if (flags) {
 553                /* split it out: */
 554                evt_name = strndup(evt_name, flags - evt_name);
 555                flags++;
 556        }
 557
 558        evt_length = strlen(evt_name);
 559        if (evt_length >= MAX_EVENT_LENGTH)
 560                return EVT_FAILED;
 561        if (strpbrk(evt_name, "*?")) {
 562                *strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */
 563                return parse_multiple_tracepoint_event(evlist, sys_name,
 564                                                       evt_name, flags);
 565        } else {
 566                return parse_single_tracepoint_event(sys_name, evt_name,
 567                                                     evt_length, attr, strp);
 568        }
 569}
 570
 571static enum event_result
 572parse_breakpoint_type(const char *type, const char **strp,
 573                      struct perf_event_attr *attr)
 574{
 575        int i;
 576
 577        for (i = 0; i < 3; i++) {
 578                if (!type[i])
 579                        break;
 580
 581                switch (type[i]) {
 582                case 'r':
 583                        attr->bp_type |= HW_BREAKPOINT_R;
 584                        break;
 585                case 'w':
 586                        attr->bp_type |= HW_BREAKPOINT_W;
 587                        break;
 588                case 'x':
 589                        attr->bp_type |= HW_BREAKPOINT_X;
 590                        break;
 591                default:
 592                        return EVT_FAILED;
 593                }
 594        }
 595        if (!attr->bp_type) /* Default */
 596                attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
 597
 598        *strp = type + i;
 599
 600        return EVT_HANDLED;
 601}
 602
 603static enum event_result
 604parse_breakpoint_event(const char **strp, struct perf_event_attr *attr)
 605{
 606        const char *target;
 607        const char *type;
 608        char *endaddr;
 609        u64 addr;
 610        enum event_result err;
 611
 612        target = strchr(*strp, ':');
 613        if (!target)
 614                return EVT_FAILED;
 615
 616        if (strncmp(*strp, "mem", target - *strp) != 0)
 617                return EVT_FAILED;
 618
 619        target++;
 620
 621        addr = strtoull(target, &endaddr, 0);
 622        if (target == endaddr)
 623                return EVT_FAILED;
 624
 625        attr->bp_addr = addr;
 626        *strp = endaddr;
 627
 628        type = strchr(target, ':');
 629
 630        /* If no type is defined, just rw as default */
 631        if (!type) {
 632                attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
 633        } else {
 634                err = parse_breakpoint_type(++type, strp, attr);
 635                if (err == EVT_FAILED)
 636                        return EVT_FAILED;
 637        }
 638
 639        /*
 640         * We should find a nice way to override the access length
 641         * Provide some defaults for now
 642         */
 643        if (attr->bp_type == HW_BREAKPOINT_X)
 644                attr->bp_len = sizeof(long);
 645        else
 646                attr->bp_len = HW_BREAKPOINT_LEN_4;
 647
 648        attr->type = PERF_TYPE_BREAKPOINT;
 649
 650        return EVT_HANDLED;
 651}
 652
 653static int check_events(const char *str, unsigned int i)
 654{
 655        int n;
 656
 657        n = strlen(event_symbols[i].symbol);
 658        if (!strncasecmp(str, event_symbols[i].symbol, n))
 659                return n;
 660
 661        n = strlen(event_symbols[i].alias);
 662        if (n) {
 663                if (!strncasecmp(str, event_symbols[i].alias, n))
 664                        return n;
 665        }
 666
 667        return 0;
 668}
 669
 670static enum event_result
 671parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
 672{
 673        const char *str = *strp;
 674        unsigned int i;
 675        int n;
 676
 677        for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
 678                n = check_events(str, i);
 679                if (n > 0) {
 680                        attr->type = event_symbols[i].type;
 681                        attr->config = event_symbols[i].config;
 682                        *strp = str + n;
 683                        return EVT_HANDLED;
 684                }
 685        }
 686        return EVT_FAILED;
 687}
 688
 689static enum event_result
 690parse_raw_event(const char **strp, struct perf_event_attr *attr)
 691{
 692        const char *str = *strp;
 693        u64 config;
 694        int n;
 695
 696        if (*str != 'r')
 697                return EVT_FAILED;
 698        n = hex2u64(str + 1, &config);
 699        if (n > 0) {
 700                const char *end = str + n + 1;
 701                if (*end != '\0' && *end != ',' && *end != ':')
 702                        return EVT_FAILED;
 703
 704                *strp = end;
 705                attr->type = PERF_TYPE_RAW;
 706                attr->config = config;
 707                return EVT_HANDLED;
 708        }
 709        return EVT_FAILED;
 710}
 711
 712static enum event_result
 713parse_numeric_event(const char **strp, struct perf_event_attr *attr)
 714{
 715        const char *str = *strp;
 716        char *endp;
 717        unsigned long type;
 718        u64 config;
 719
 720        type = strtoul(str, &endp, 0);
 721        if (endp > str && type < PERF_TYPE_MAX && *endp == ':') {
 722                str = endp + 1;
 723                config = strtoul(str, &endp, 0);
 724                if (endp > str) {
 725                        attr->type = type;
 726                        attr->config = config;
 727                        *strp = endp;
 728                        return EVT_HANDLED;
 729                }
 730        }
 731        return EVT_FAILED;
 732}
 733
 734static int
 735parse_event_modifier(const char **strp, struct perf_event_attr *attr)
 736{
 737        const char *str = *strp;
 738        int exclude = 0;
 739        int eu = 0, ek = 0, eh = 0, precise = 0;
 740
 741        if (!*str)
 742                return 0;
 743
 744        if (*str == ',')
 745                return 0;
 746
 747        if (*str++ != ':')
 748                return -1;
 749
 750        while (*str) {
 751                if (*str == 'u') {
 752                        if (!exclude)
 753                                exclude = eu = ek = eh = 1;
 754                        eu = 0;
 755                } else if (*str == 'k') {
 756                        if (!exclude)
 757                                exclude = eu = ek = eh = 1;
 758                        ek = 0;
 759                } else if (*str == 'h') {
 760                        if (!exclude)
 761                                exclude = eu = ek = eh = 1;
 762                        eh = 0;
 763                } else if (*str == 'p') {
 764                        precise++;
 765                } else
 766                        break;
 767
 768                ++str;
 769        }
 770        if (str < *strp + 2)
 771                return -1;
 772
 773        *strp = str;
 774
 775        attr->exclude_user   = eu;
 776        attr->exclude_kernel = ek;
 777        attr->exclude_hv     = eh;
 778        attr->precise_ip     = precise;
 779
 780        return 0;
 781}
 782
 783/*
 784 * Each event can have multiple symbolic names.
 785 * Symbolic names are (almost) exactly matched.
 786 */
 787static enum event_result
 788parse_event_symbols(struct perf_evlist *evlist, const char **str,
 789                    struct perf_event_attr *attr)
 790{
 791        enum event_result ret;
 792
 793        ret = parse_tracepoint_event(evlist, str, attr);
 794        if (ret != EVT_FAILED)
 795                goto modifier;
 796
 797        ret = parse_raw_event(str, attr);
 798        if (ret != EVT_FAILED)
 799                goto modifier;
 800
 801        ret = parse_numeric_event(str, attr);
 802        if (ret != EVT_FAILED)
 803                goto modifier;
 804
 805        ret = parse_symbolic_event(str, attr);
 806        if (ret != EVT_FAILED)
 807                goto modifier;
 808
 809        ret = parse_generic_hw_event(str, attr);
 810        if (ret != EVT_FAILED)
 811                goto modifier;
 812
 813        ret = parse_breakpoint_event(str, attr);
 814        if (ret != EVT_FAILED)
 815                goto modifier;
 816
 817        fprintf(stderr, "invalid or unsupported event: '%s'\n", *str);
 818        fprintf(stderr, "Run 'perf list' for a list of valid events\n");
 819        return EVT_FAILED;
 820
 821modifier:
 822        if (parse_event_modifier(str, attr) < 0) {
 823                fprintf(stderr, "invalid event modifier: '%s'\n", *str);
 824                fprintf(stderr, "Run 'perf list' for a list of valid events and modifiers\n");
 825
 826                return EVT_FAILED;
 827        }
 828
 829        return ret;
 830}
 831
 832int parse_events(struct perf_evlist *evlist , const char *str, int unset __used)
 833{
 834        struct perf_event_attr attr;
 835        enum event_result ret;
 836        const char *ostr;
 837
 838        for (;;) {
 839                ostr = str;
 840                memset(&attr, 0, sizeof(attr));
 841                ret = parse_event_symbols(evlist, &str, &attr);
 842                if (ret == EVT_FAILED)
 843                        return -1;
 844
 845                if (!(*str == 0 || *str == ',' || isspace(*str)))
 846                        return -1;
 847
 848                if (ret != EVT_HANDLED_ALL) {
 849                        struct perf_evsel *evsel;
 850                        evsel = perf_evsel__new(&attr, evlist->nr_entries);
 851                        if (evsel == NULL)
 852                                return -1;
 853                        perf_evlist__add(evlist, evsel);
 854
 855                        evsel->name = calloc(str - ostr + 1, 1);
 856                        if (!evsel->name)
 857                                return -1;
 858                        strncpy(evsel->name, ostr, str - ostr);
 859                }
 860
 861                if (*str == 0)
 862                        break;
 863                if (*str == ',')
 864                        ++str;
 865                while (isspace(*str))
 866                        ++str;
 867        }
 868
 869        return 0;
 870}
 871
 872int parse_events_option(const struct option *opt, const char *str,
 873                        int unset __used)
 874{
 875        struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
 876        return parse_events(evlist, str, unset);
 877}
 878
 879int parse_filter(const struct option *opt, const char *str,
 880                 int unset __used)
 881{
 882        struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
 883        struct perf_evsel *last = NULL;
 884
 885        if (evlist->nr_entries > 0)
 886                last = list_entry(evlist->entries.prev, struct perf_evsel, node);
 887
 888        if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
 889                fprintf(stderr,
 890                        "-F option should follow a -e tracepoint option\n");
 891                return -1;
 892        }
 893
 894        last->filter = strdup(str);
 895        if (last->filter == NULL) {
 896                fprintf(stderr, "not enough memory to hold filter string\n");
 897                return -1;
 898        }
 899
 900        return 0;
 901}
 902
 903static const char * const event_type_descriptors[] = {
 904        "Hardware event",
 905        "Software event",
 906        "Tracepoint event",
 907        "Hardware cache event",
 908        "Raw hardware event descriptor",
 909        "Hardware breakpoint",
 910};
 911
 912/*
 913 * Print the events from <debugfs_mount_point>/tracing/events
 914 */
 915
 916void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
 917{
 918        DIR *sys_dir, *evt_dir;
 919        struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
 920        char evt_path[MAXPATHLEN];
 921        char dir_path[MAXPATHLEN];
 922
 923        if (debugfs_valid_mountpoint(debugfs_path))
 924                return;
 925
 926        sys_dir = opendir(debugfs_path);
 927        if (!sys_dir)
 928                return;
 929
 930        for_each_subsystem(sys_dir, sys_dirent, sys_next) {
 931                if (subsys_glob != NULL && 
 932                    !strglobmatch(sys_dirent.d_name, subsys_glob))
 933                        continue;
 934
 935                snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
 936                         sys_dirent.d_name);
 937                evt_dir = opendir(dir_path);
 938                if (!evt_dir)
 939                        continue;
 940
 941                for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
 942                        if (event_glob != NULL && 
 943                            !strglobmatch(evt_dirent.d_name, event_glob))
 944                                continue;
 945
 946                        snprintf(evt_path, MAXPATHLEN, "%s:%s",
 947                                 sys_dirent.d_name, evt_dirent.d_name);
 948                        printf("  %-50s [%s]\n", evt_path,
 949                                event_type_descriptors[PERF_TYPE_TRACEPOINT]);
 950                }
 951                closedir(evt_dir);
 952        }
 953        closedir(sys_dir);
 954}
 955
 956/*
 957 * Check whether event is in <debugfs_mount_point>/tracing/events
 958 */
 959
 960int is_valid_tracepoint(const char *event_string)
 961{
 962        DIR *sys_dir, *evt_dir;
 963        struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
 964        char evt_path[MAXPATHLEN];
 965        char dir_path[MAXPATHLEN];
 966
 967        if (debugfs_valid_mountpoint(debugfs_path))
 968                return 0;
 969
 970        sys_dir = opendir(debugfs_path);
 971        if (!sys_dir)
 972                return 0;
 973
 974        for_each_subsystem(sys_dir, sys_dirent, sys_next) {
 975
 976                snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
 977                         sys_dirent.d_name);
 978                evt_dir = opendir(dir_path);
 979                if (!evt_dir)
 980                        continue;
 981
 982                for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
 983                        snprintf(evt_path, MAXPATHLEN, "%s:%s",
 984                                 sys_dirent.d_name, evt_dirent.d_name);
 985                        if (!strcmp(evt_path, event_string)) {
 986                                closedir(evt_dir);
 987                                closedir(sys_dir);
 988                                return 1;
 989                        }
 990                }
 991                closedir(evt_dir);
 992        }
 993        closedir(sys_dir);
 994        return 0;
 995}
 996
 997void print_events_type(u8 type)
 998{
 999        struct event_symbol *syms = event_symbols;
1000        unsigned int i;
1001        char name[64];
1002
1003        for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
1004                if (type != syms->type)
1005                        continue;
1006
1007                if (strlen(syms->alias))
1008                        snprintf(name, sizeof(name),  "%s OR %s",
1009                                 syms->symbol, syms->alias);
1010                else
1011                        snprintf(name, sizeof(name), "%s", syms->symbol);
1012
1013                printf("  %-50s [%s]\n", name,
1014                        event_type_descriptors[type]);
1015        }
1016}
1017
1018int print_hwcache_events(const char *event_glob)
1019{
1020        unsigned int type, op, i, printed = 0;
1021
1022        for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
1023                for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
1024                        /* skip invalid cache type */
1025                        if (!is_cache_op_valid(type, op))
1026                                continue;
1027
1028                        for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
1029                                char *name = event_cache_name(type, op, i);
1030
1031                                if (event_glob != NULL && !strglobmatch(name, event_glob))
1032                                        continue;
1033
1034                                printf("  %-50s [%s]\n", name,
1035                                        event_type_descriptors[PERF_TYPE_HW_CACHE]);
1036                                ++printed;
1037                        }
1038                }
1039        }
1040
1041        return printed;
1042}
1043
1044#define MAX_NAME_LEN 100
1045
1046/*
1047 * Print the help text for the event symbols:
1048 */
1049void print_events(const char *event_glob)
1050{
1051        unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
1052        struct event_symbol *syms = event_symbols;
1053        char name[MAX_NAME_LEN];
1054
1055        printf("\n");
1056        printf("List of pre-defined events (to be used in -e):\n");
1057
1058        for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
1059                type = syms->type;
1060
1061                if (type != prev_type && printed) {
1062                        printf("\n");
1063                        printed = 0;
1064                        ntypes_printed++;
1065                }
1066
1067                if (event_glob != NULL && 
1068                    !(strglobmatch(syms->symbol, event_glob) ||
1069                      (syms->alias && strglobmatch(syms->alias, event_glob))))
1070                        continue;
1071
1072                if (strlen(syms->alias))
1073                        snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
1074                else
1075                        strncpy(name, syms->symbol, MAX_NAME_LEN);
1076                printf("  %-50s [%s]\n", name,
1077                        event_type_descriptors[type]);
1078
1079                prev_type = type;
1080                ++printed;
1081        }
1082
1083        if (ntypes_printed) {
1084                printed = 0;
1085                printf("\n");
1086        }
1087        print_hwcache_events(event_glob);
1088
1089        if (event_glob != NULL)
1090                return;
1091
1092        printf("\n");
1093        printf("  %-50s [%s]\n",
1094                "rNNN (see 'perf list --help' on how to encode it)",
1095               event_type_descriptors[PERF_TYPE_RAW]);
1096        printf("\n");
1097
1098        printf("  %-50s [%s]\n",
1099                        "mem:<addr>[:access]",
1100                        event_type_descriptors[PERF_TYPE_BREAKPOINT]);
1101        printf("\n");
1102
1103        print_tracepoint_events(NULL, NULL);
1104}
1105