perf_counter tools: Check for valid cache operations
[firefly-linux-kernel-4.4.55.git] / tools / perf / util / parse-events.c
index 9d5f1ca50e6fe4fc8466f3d97f8051a1e39253f2..7939a21130d2beb7737608ca68e4de5ee3812acb 100644 (file)
@@ -13,35 +13,31 @@ int                                 nr_counters;
 struct perf_counter_attr               attrs[MAX_COUNTERS];
 
 struct event_symbol {
-       __u8    type;
-       __u64   config;
+       u8      type;
+       u64     config;
        char    *symbol;
+       char    *alias;
 };
 
-#define C(x, y) .type = PERF_TYPE_##x, .config = PERF_COUNT_##y
-#define CR(x, y) .type = PERF_TYPE_##x, .config = y
+#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
+#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
 
 static struct event_symbol event_symbols[] = {
-  { C(HARDWARE, HW_CPU_CYCLES),                "cpu-cycles",           },
-  { C(HARDWARE, HW_CPU_CYCLES),                "cycles",               },
-  { C(HARDWARE, HW_INSTRUCTIONS),      "instructions",         },
-  { C(HARDWARE, HW_CACHE_REFERENCES),  "cache-references",     },
-  { C(HARDWARE, HW_CACHE_MISSES),      "cache-misses",         },
-  { C(HARDWARE, HW_BRANCH_INSTRUCTIONS),"branch-instructions", },
-  { C(HARDWARE, HW_BRANCH_INSTRUCTIONS),"branches",            },
-  { C(HARDWARE, HW_BRANCH_MISSES),     "branch-misses",        },
-  { C(HARDWARE, HW_BUS_CYCLES),                "bus-cycles",           },
-
-  { C(SOFTWARE, SW_CPU_CLOCK),         "cpu-clock",            },
-  { C(SOFTWARE, SW_TASK_CLOCK),                "task-clock",           },
-  { C(SOFTWARE, SW_PAGE_FAULTS),       "page-faults",          },
-  { C(SOFTWARE, SW_PAGE_FAULTS),       "faults",               },
-  { C(SOFTWARE, SW_PAGE_FAULTS_MIN),   "minor-faults",         },
-  { C(SOFTWARE, SW_PAGE_FAULTS_MAJ),   "major-faults",         },
-  { C(SOFTWARE, SW_CONTEXT_SWITCHES),  "context-switches",     },
-  { C(SOFTWARE, SW_CONTEXT_SWITCHES),  "cs",                   },
-  { C(SOFTWARE, SW_CPU_MIGRATIONS),    "cpu-migrations",       },
-  { C(SOFTWARE, SW_CPU_MIGRATIONS),    "migrations",           },
+  { CHW(CPU_CYCLES),           "cpu-cycles",           "cycles"        },
+  { CHW(INSTRUCTIONS),         "instructions",         ""              },
+  { CHW(CACHE_REFERENCES),     "cache-references",     ""              },
+  { CHW(CACHE_MISSES),         "cache-misses",         ""              },
+  { CHW(BRANCH_INSTRUCTIONS),  "branch-instructions",  "branches"      },
+  { CHW(BRANCH_MISSES),                "branch-misses",        ""              },
+  { CHW(BUS_CYCLES),           "bus-cycles",           ""              },
+
+  { CSW(CPU_CLOCK),            "cpu-clock",            ""              },
+  { CSW(TASK_CLOCK),           "task-clock",           ""              },
+  { CSW(PAGE_FAULTS),          "page-faults",          "faults"        },
+  { CSW(PAGE_FAULTS_MIN),      "minor-faults",         ""              },
+  { CSW(PAGE_FAULTS_MAJ),      "major-faults",         ""              },
+  { CSW(CONTEXT_SWITCHES),     "context-switches",     "cs"            },
+  { CSW(CPU_MIGRATIONS),       "cpu-migrations",       "migrations"    },
 };
 
 #define __PERF_COUNTER_FIELD(config, name) \
@@ -63,8 +59,8 @@ static char *hw_event_names[] = {
 };
 
 static char *sw_event_names[] = {
-       "cpu-clock-ticks",
-       "task-clock-ticks",
+       "cpu-clock-msecs",
+       "task-clock-msecs",
        "page-faults",
        "context-switches",
        "CPU-migrations",
@@ -74,29 +70,57 @@ static char *sw_event_names[] = {
 
 #define MAX_ALIASES 8
 
-static char *hw_cache [][MAX_ALIASES] = {
-       { "L1-data"             , "l1-d", "l1d", "l1"                           },
-       { "L1-instruction"      , "l1-i", "l1i"                                 },
-       { "L2"                  , "l2"                                          },
-       { "Data-TLB"            , "dtlb", "d-tlb"                               },
-       { "Instruction-TLB"     , "itlb", "i-tlb"                               },
-       { "Branch"              , "bpu" , "btb", "bpc"                          },
+static char *hw_cache[][MAX_ALIASES] = {
+       { "L1-data",            "l1-d",         "l1d"                   },
+       { "L1-instruction",     "l1-i",         "l1i"                   },
+       { "L2",                 "l2"                                    },
+       { "Data-TLB",           "dtlb",         "d-tlb"                 },
+       { "Instruction-TLB",    "itlb",         "i-tlb"                 },
+       { "Branch",             "bpu" ,         "btb",          "bpc"   },
 };
 
-static char *hw_cache_op [][MAX_ALIASES] = {
-       { "Load"                , "read"                                        },
-       { "Store"               , "write"                                       },
-       { "Prefetch"            , "speculative-read", "speculative-load"        },
+static char *hw_cache_op[][MAX_ALIASES] = {
+       { "Load",               "read"                                  },
+       { "Store",              "write"                                 },
+       { "Prefetch",           "speculative-read", "speculative-load"  },
 };
 
-static char *hw_cache_result [][MAX_ALIASES] = {
-       { "Reference"           , "ops", "access"                               },
-       { "Miss"                                                                },
+static char *hw_cache_result[][MAX_ALIASES] = {
+       { "Reference",          "ops",          "access"                },
+       { "Miss"                                                        },
 };
 
+#define C(x)           PERF_COUNT_HW_CACHE_##x
+#define CACHE_READ     (1 << C(OP_READ))
+#define CACHE_WRITE    (1 << C(OP_WRITE))
+#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
+#define COP(x)         (1 << x)
+
+/*
+ * cache operartion stat
+ * L1I : Read and prefetch only
+ * ITLB and BPU : Read-only
+ */
+static unsigned long hw_cache_stat[C(MAX)] = {
+ [C(L1D)]      = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
+ [C(L1I)]      = (CACHE_READ | CACHE_PREFETCH),
+ [C(LL)]       = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
+ [C(DTLB)]     = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
+ [C(ITLB)]     = (CACHE_READ),
+ [C(BPU)]      = (CACHE_READ),
+};
+
+static int is_cache_op_valid(u8 cache_type, u8 cache_op)
+{
+       if (hw_cache_stat[cache_type] & COP(cache_op))
+               return 1;       /* valid */
+       else
+               return 0;       /* invalid */
+}
+
 char *event_name(int counter)
 {
-       __u64 config = attrs[counter].config;
+       u64 config = attrs[counter].config;
        int type = attrs[counter].type;
        static char buf[32];
 
@@ -112,7 +136,7 @@ char *event_name(int counter)
                return "unknown-hardware";
 
        case PERF_TYPE_HW_CACHE: {
-               __u8 cache_type, cache_op, cache_result;
+               u8 cache_type, cache_op, cache_result;
                static char name[100];
 
                cache_type   = (config >>  0) & 0xff;
@@ -127,6 +151,8 @@ char *event_name(int counter)
                if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
                        return "unknown-ext-hardware-cache-result";
 
+               if (!is_cache_op_valid(cache_type, cache_op))
+                       return "invalid-cache";
                sprintf(name, "%s-Cache-%s-%ses",
                        hw_cache[cache_type][0],
                        hw_cache_op[cache_op][0],
@@ -163,7 +189,8 @@ static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size)
        return -1;
 }
 
-static int parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr)
+static int
+parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr)
 {
        int cache_type = -1, cache_op = 0, cache_result = 0;
 
@@ -182,6 +209,9 @@ static int parse_generic_hw_symbols(const char *str, struct perf_counter_attr *a
        if (cache_op == -1)
                cache_op = PERF_COUNT_HW_CACHE_OP_READ;
 
+       if (!is_cache_op_valid(cache_type, cache_op))
+               return -EINVAL;
+
        cache_result = parse_aliases(str, hw_cache_result,
                                        PERF_COUNT_HW_CACHE_RESULT_MAX);
        /*
@@ -196,13 +226,26 @@ static int parse_generic_hw_symbols(const char *str, struct perf_counter_attr *a
        return 0;
 }
 
+static int check_events(const char *str, unsigned int i)
+{
+       if (!strncmp(str, event_symbols[i].symbol,
+                    strlen(event_symbols[i].symbol)))
+               return 1;
+
+       if (strlen(event_symbols[i].alias))
+               if (!strncmp(str, event_symbols[i].alias,
+                            strlen(event_symbols[i].alias)))
+                       return 1;
+       return 0;
+}
+
 /*
  * Each event can have multiple symbolic names.
  * Symbolic names are (almost) exactly matched.
  */
 static int parse_event_symbols(const char *str, struct perf_counter_attr *attr)
 {
-       __u64 config, id;
+       u64 config, id;
        int type;
        unsigned int i;
        const char *sep, *pstr;
@@ -235,9 +278,7 @@ static int parse_event_symbols(const char *str, struct perf_counter_attr *attr)
        }
 
        for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
-               if (!strncmp(str, event_symbols[i].symbol,
-                            strlen(event_symbols[i].symbol))) {
-
+               if (check_events(str, i)) {
                        attr->type = event_symbols[i].type;
                        attr->config = event_symbols[i].config;
 
@@ -289,6 +330,7 @@ void print_events(void)
 {
        struct event_symbol *syms = event_symbols;
        unsigned int i, type, prev_type = -1;
+       char name[40];
 
        fprintf(stderr, "\n");
        fprintf(stderr, "List of pre-defined events (to be used in -e):\n");
@@ -301,14 +343,18 @@ void print_events(void)
                if (type != prev_type)
                        fprintf(stderr, "\n");
 
-               fprintf(stderr, "  %-30s [%s]\n", syms->symbol,
+               if (strlen(syms->alias))
+                       sprintf(name, "%s OR %s", syms->symbol, syms->alias);
+               else
+                       strcpy(name, syms->symbol);
+               fprintf(stderr, "  %-40s [%s]\n", name,
                        event_type_descriptors[type]);
 
                prev_type = type;
        }
 
        fprintf(stderr, "\n");
-       fprintf(stderr, "  %-30s [raw hardware event descriptor]\n",
+       fprintf(stderr, "  %-40s [raw hardware event descriptor]\n",
                "rNNN");
        fprintf(stderr, "\n");