Commit 5f537a26 authored by Jiri Olsa's avatar Jiri Olsa Committed by Arnaldo Carvalho de Melo

perf tools: Add support to specify pmu style event

Added new event rule to the event definition grammar:

event_def: event_pmu |
           ...
event_pmu: PE_NAME '/' event_config '/'

Using this rule, event could be now specified like:
  cpu/config=1,config1=2,config2=3/u

where pmu name 'cpu' is looked up via following path:
  ${sysfs_mount}/bus/event_source/devices/${pmu}

and config options are bound to the pmu's format definiton:
  ${sysfs_mount}/bus/event_source/devices/${pmu}/format

The hardcoded config options still stays and have precedence
over any format field defined with same name.
Acked-by: default avatarPeter Zijlstra <peterz@infradead.org>
Signed-off-by: default avatarJiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/n/tip-50d8nr94f8k4wkezutrxvthe@git.kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent cd82a32e
...@@ -877,6 +877,22 @@ static int test__checkevent_genhw_modifier(struct perf_evlist *evlist) ...@@ -877,6 +877,22 @@ static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
return test__checkevent_genhw(evlist); return test__checkevent_genhw(evlist);
} }
static int test__checkevent_pmu(struct perf_evlist *evlist)
{
struct perf_evsel *evsel = list_entry(evlist->entries.next,
struct perf_evsel, node);
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
TEST_ASSERT_VAL("wrong config", 10 == evsel->attr.config);
TEST_ASSERT_VAL("wrong config1", 1 == evsel->attr.config1);
TEST_ASSERT_VAL("wrong config2", 3 == evsel->attr.config2);
TEST_ASSERT_VAL("wrong period", 1000 == evsel->attr.sample_period);
return 0;
}
static struct test__event_st { static struct test__event_st {
const char *name; const char *name;
__u32 type; __u32 type;
...@@ -958,6 +974,10 @@ static struct test__event_st { ...@@ -958,6 +974,10 @@ static struct test__event_st {
.name = "L1-dcache-load-miss:kp", .name = "L1-dcache-load-miss:kp",
.check = test__checkevent_genhw_modifier, .check = test__checkevent_genhw_modifier,
}, },
{
.name = "cpu/config=10,config1,config2=3,period=1000/u",
.check = test__checkevent_pmu,
},
}; };
#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st)) #define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
......
This diff is collapsed.
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "header.h" #include "header.h"
#include "debugfs.h" #include "debugfs.h"
#include "parse-events-flex.h" #include "parse-events-flex.h"
#include "pmu.h"
#define MAX_NAME_LEN 100 #define MAX_NAME_LEN 100
...@@ -646,6 +647,30 @@ int parse_events_add_numeric(struct list_head *list, int *idx, ...@@ -646,6 +647,30 @@ int parse_events_add_numeric(struct list_head *list, int *idx,
(char *) __event_name(type, config)); (char *) __event_name(type, config));
} }
int parse_events_add_pmu(struct list_head *list, int *idx,
char *name, struct list_head *head_config)
{
struct perf_event_attr attr;
struct perf_pmu *pmu;
pmu = perf_pmu__find(name);
if (!pmu)
return -EINVAL;
memset(&attr, 0, sizeof(attr));
/*
* Configure hardcoded terms first, no need to check
* return value when called with fail == 0 ;)
*/
config_attr(&attr, head_config, 0);
if (perf_pmu__config(pmu, &attr, head_config))
return -EINVAL;
return add_event(list, idx, &attr, (char *) "pmu");
}
int parse_events_modifier(struct list_head *list, char *str) int parse_events_modifier(struct list_head *list, char *str)
{ {
struct perf_evsel *evsel; struct perf_evsel *evsel;
...@@ -957,8 +982,12 @@ void print_events(const char *event_glob) ...@@ -957,8 +982,12 @@ void print_events(const char *event_glob)
printf("\n"); printf("\n");
printf(" %-50s [%s]\n", printf(" %-50s [%s]\n",
"rNNN (see 'perf list --help' on how to encode it)", "rNNN",
event_type_descriptors[PERF_TYPE_RAW]);
printf(" %-50s [%s]\n",
"cpu/t1=v1[,t2=v2,t3 ...]/modifier",
event_type_descriptors[PERF_TYPE_RAW]); event_type_descriptors[PERF_TYPE_RAW]);
printf(" (see 'perf list --help' on how to encode it)\n");
printf("\n"); printf("\n");
printf(" %-50s [%s]\n", printf(" %-50s [%s]\n",
......
...@@ -74,6 +74,8 @@ int parse_events_add_cache(struct list_head *list, int *idx, ...@@ -74,6 +74,8 @@ int parse_events_add_cache(struct list_head *list, int *idx,
char *type, char *op_result1, char *op_result2); char *type, char *op_result1, char *op_result2);
int parse_events_add_breakpoint(struct list_head *list, int *idx, int parse_events_add_breakpoint(struct list_head *list, int *idx,
void *ptr, char *type); void *ptr, char *type);
int parse_events_add_pmu(struct list_head *list, int *idx,
char *pmu , struct list_head *head_config);
void parse_events_error(struct list_head *list, int *idx, void parse_events_error(struct list_head *list, int *idx,
char const *msg); char const *msg);
......
...@@ -61,13 +61,21 @@ event_def PE_MODIFIER_EVENT ...@@ -61,13 +61,21 @@ event_def PE_MODIFIER_EVENT
| |
event_def event_def
event_def: event_legacy_symbol | event_def: event_pmu |
event_legacy_symbol |
event_legacy_cache sep_dc | event_legacy_cache sep_dc |
event_legacy_mem | event_legacy_mem |
event_legacy_tracepoint sep_dc | event_legacy_tracepoint sep_dc |
event_legacy_numeric sep_dc | event_legacy_numeric sep_dc |
event_legacy_raw sep_dc event_legacy_raw sep_dc
event_pmu:
PE_NAME '/' event_config '/'
{
ABORT_ON(parse_events_add_pmu(list, idx, $1, $3));
parse_events__free_terms($3);
}
event_legacy_symbol: event_legacy_symbol:
PE_VALUE_SYM '/' event_config '/' PE_VALUE_SYM '/' event_config '/'
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment