The 'P' will cause the event to get maximum possible
detected precise level.

Following record:
  $ perf record -e cycles:P ...

will detect maximum precise level for 'cycles' event
and use it.

Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Jiri Olsa <[email protected]>
---
 tools/perf/Documentation/perf-list.txt | 1 +
 tools/perf/util/evsel.c                | 3 +++
 tools/perf/util/evsel.h                | 1 +
 tools/perf/util/parse-events.c         | 8 +++++++-
 tools/perf/util/parse-events.l         | 2 +-
 5 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Documentation/perf-list.txt 
b/tools/perf/Documentation/perf-list.txt
index ad60c6ea1997..79483f40e991 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -30,6 +30,7 @@ counted. The following modifiers exist:
  G - guest counting (in KVM guests)
  H - host counting (not in KVM guests)
  p - precise level
+ P - use maximum detected precise level
  S - read sample value (PERF_SAMPLE_READ)
  D - pin the event to the PMU
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 0b1c289da36d..8be867ccefe9 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -882,6 +882,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct 
record_opts *opts)
                attr->clockid = opts->clockid;
        }
 
+       if (evsel->precise_max)
+               perf_event_attr__set_max_precise_ip(attr);
+
        /*
         * Apply event specific term settings,
         * it overloads any global configuration.
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 7906666580da..02a5fed8d924 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -111,6 +111,7 @@ struct perf_evsel {
        bool                    system_wide;
        bool                    tracking;
        bool                    per_pkg;
+       bool                    precise_max;
        /* parse modifier helper */
        int                     exclude_GH;
        int                     nr_members;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 5d0cfce2599b..3ed8bf175163 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -923,6 +923,7 @@ struct event_modifier {
        int eG;
        int eI;
        int precise;
+       int precise_max;
        int exclude_GH;
        int sample_read;
        int pinned;
@@ -938,6 +939,7 @@ static int get_event_modifier(struct event_modifier *mod, 
char *str,
        int eG = evsel ? evsel->attr.exclude_guest : 0;
        int eI = evsel ? evsel->attr.exclude_idle : 0;
        int precise = evsel ? evsel->attr.precise_ip : 0;
+       int precise_max = 0;
        int sample_read = 0;
        int pinned = evsel ? evsel->attr.pinned : 0;
 
@@ -974,6 +976,8 @@ static int get_event_modifier(struct event_modifier *mod, 
char *str,
                        /* use of precise requires exclude_guest */
                        if (!exclude_GH)
                                eG = 1;
+               } else if (*str == 'P') {
+                       precise_max = 1;
                } else if (*str == 'S') {
                        sample_read = 1;
                } else if (*str == 'D') {
@@ -1004,6 +1008,7 @@ static int get_event_modifier(struct event_modifier *mod, 
char *str,
        mod->eG = eG;
        mod->eI = eI;
        mod->precise = precise;
+       mod->precise_max = precise_max;
        mod->exclude_GH = exclude_GH;
        mod->sample_read = sample_read;
        mod->pinned = pinned;
@@ -1020,7 +1025,7 @@ static int check_modifier(char *str)
        char *p = str;
 
        /* The sizeof includes 0 byte as well. */
-       if (strlen(str) > (sizeof("ukhGHpppSDI") - 1))
+       if (strlen(str) > (sizeof("ukhGHpppPSDI") - 1))
                return -1;
 
        while (*p) {
@@ -1059,6 +1064,7 @@ int parse_events__modifier_event(struct list_head *list, 
char *str, bool add)
                evsel->attr.exclude_idle   = mod.eI;
                evsel->exclude_GH          = mod.exclude_GH;
                evsel->sample_read         = mod.sample_read;
+               evsel->precise_max         = mod.precise_max;
 
                if (perf_evsel__is_group_leader(evsel))
                        evsel->attr.pinned = mod.pinned;
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index c29832bce496..be244573a02e 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -122,7 +122,7 @@ num_raw_hex [a-fA-F0-9]+
 name           [a-zA-Z_*?][a-zA-Z0-9_*?.]*
 name_minus     [a-zA-Z_*?][a-zA-Z0-9\-_*?.]*
 /* If you add a modifier you need to update check_modifier() */
-modifier_event [ukhpGHSDI]+
+modifier_event [ukhpPGHSDI]+
 modifier_bp    [rwx]{1,3}
 
 %%
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to