diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index a56c4574b3fec07b7c878e695a33b1b18b8e1ced..6a258c90e7ce2fc3347b0f3a12cadc82d0f8bd0e 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -68,6 +68,8 @@ struct perf_evsel { } handler; unsigned int sample_size; bool supported; + /* parse modifier helper */ + int exclude_GH; }; struct cpu_map; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 57d5809f28604f2dcdb4ca72c3d824565ea2ceef..4364575ce6acbf33c4509cc33e78783a5969192f 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -633,14 +633,38 @@ void parse_events_update_lists(struct list_head *list_event, free(list_event); } -int parse_events__modifier_event(struct list_head *list, char *str) +struct event_modifier { + int eu; + int ek; + int eh; + int eH; + int eG; + int precise; + int exclude_GH; +}; + +static int get_event_modifier(struct event_modifier *mod, char *str, + struct perf_evsel *evsel) { - struct perf_evsel *evsel; - int exclude = 0, exclude_GH = 0; - int eu = 0, ek = 0, eh = 0, eH = 0, eG = 0, precise = 0; + int eu = evsel ? evsel->attr.exclude_user : 0; + int ek = evsel ? evsel->attr.exclude_kernel : 0; + int eh = evsel ? evsel->attr.exclude_hv : 0; + int eH = evsel ? evsel->attr.exclude_host : 0; + int eG = evsel ? evsel->attr.exclude_guest : 0; + int precise = evsel ? evsel->attr.precise_ip : 0; - if (str == NULL) - return 0; + int exclude = eu | ek | eh; + int exclude_GH = evsel ? evsel->exclude_GH : 0; + + /* + * We are here for group and 'GH' was not set as event + * modifier and whatever event/group modifier override + * default 'GH' setup. + */ + if (evsel && !exclude_GH) + eH = eG = 0; + + memset(mod, 0, sizeof(*mod)); while (*str) { if (*str == 'u') { @@ -684,13 +708,39 @@ int parse_events__modifier_event(struct list_head *list, char *str) if (precise > 3) return -EINVAL; + mod->eu = eu; + mod->ek = ek; + mod->eh = eh; + mod->eH = eH; + mod->eG = eG; + mod->precise = precise; + mod->exclude_GH = exclude_GH; + return 0; +} + +int parse_events__modifier_event(struct list_head *list, char *str, bool add) +{ + struct perf_evsel *evsel; + struct event_modifier mod; + + if (str == NULL) + return 0; + + if (!add && get_event_modifier(&mod, str, NULL)) + return -EINVAL; + list_for_each_entry(evsel, list, node) { - evsel->attr.exclude_user = eu; - evsel->attr.exclude_kernel = ek; - evsel->attr.exclude_hv = eh; - evsel->attr.precise_ip = precise; - evsel->attr.exclude_host = eH; - evsel->attr.exclude_guest = eG; + + if (add && get_event_modifier(&mod, str, evsel)) + return -EINVAL; + + evsel->attr.exclude_user = mod.eu; + evsel->attr.exclude_kernel = mod.ek; + evsel->attr.exclude_hv = mod.eh; + evsel->attr.precise_ip = mod.precise; + evsel->attr.exclude_host = mod.eH; + evsel->attr.exclude_guest = mod.eG; + evsel->exclude_GH = mod.exclude_GH; } return 0; diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index c3bb04c6f0253a9344b55b922141f6cc0e38baa2..75a6800082a1d358ad2d0186cfdbe44609f9f8cc 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -79,7 +79,7 @@ int parse_events__term_str(struct parse_events__term **_term, int parse_events__term_clone(struct parse_events__term **new, struct parse_events__term *term); void parse_events__free_terms(struct list_head *terms); -int parse_events__modifier_event(struct list_head *list, char *str); +int parse_events__modifier_event(struct list_head *list, char *str, bool add); int parse_events__modifier_group(struct list_head *list, char *event_mod); int parse_events_add_tracepoint(struct list_head **list, int *idx, char *sys, char *event); diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 15e6e97e5b346d20769b8afb8b48f84c82a071ef..084c35fc2d261bdd88af0dc6232781cedb17d57b 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -153,7 +153,7 @@ event_def PE_MODIFIER_EVENT * (there could be more events added for multiple tracepoint * definitions via '*?'. */ - ABORT_ON(parse_events__modifier_event(list, $2)); + ABORT_ON(parse_events__modifier_event(list, $2, false)); $$ = list; } |