diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt index eb03f063f0a2..6fce6a622206 100644 --- a/tools/perf/Documentation/perf-list.txt +++ b/tools/perf/Documentation/perf-list.txt @@ -30,6 +30,7 @@ counted. The following modifiers exist: H - host counting (not in KVM guests) p - precise level S - read sample value (PERF_SAMPLE_READ) + D - pin the event to the PMU The 'p' modifier can be used for specifying how precise the instruction address should be. The 'p' modifier can be specified multiple times: diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index dba877dc9482..9cba92386a82 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -688,6 +688,7 @@ struct event_modifier { int precise; int exclude_GH; int sample_read; + int pinned; }; static int get_event_modifier(struct event_modifier *mod, char *str, @@ -700,6 +701,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str, int eG = evsel ? evsel->attr.exclude_guest : 0; int precise = evsel ? evsel->attr.precise_ip : 0; int sample_read = 0; + int pinned = evsel ? evsel->attr.pinned : 0; int exclude = eu | ek | eh; int exclude_GH = evsel ? evsel->exclude_GH : 0; @@ -734,6 +736,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str, eG = 1; } else if (*str == 'S') { sample_read = 1; + } else if (*str == 'D') { + pinned = 1; } else break; @@ -761,6 +765,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str, mod->precise = precise; mod->exclude_GH = exclude_GH; mod->sample_read = sample_read; + mod->pinned = pinned; + return 0; } @@ -773,7 +779,7 @@ static int check_modifier(char *str) char *p = str; /* The sizeof includes 0 byte as well. */ - if (strlen(str) > (sizeof("ukhGHpppS") - 1)) + if (strlen(str) > (sizeof("ukhGHpppSD") - 1)) return -1; while (*p) { @@ -812,6 +818,9 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add) evsel->attr.exclude_guest = mod.eG; evsel->exclude_GH = mod.exclude_GH; evsel->sample_read = mod.sample_read; + + if (perf_evsel__is_group_leader(evsel)) + evsel->attr.pinned = mod.pinned; } return 0; diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index b36115fe416a..0790452658b3 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -82,7 +82,8 @@ num_hex 0x[a-fA-F0-9]+ num_raw_hex [a-fA-F0-9]+ name [a-zA-Z_*?][a-zA-Z0-9_*?]* name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]* -modifier_event [ukhpGHS]+ +/* If you add a modifier you need to update check_modifier() */ +modifier_event [ukhpGHSD]+ modifier_bp [rwx]{1,3} %%