[PATCHv2 5/8] perf tools: Get precise_ip from the pmu config

Jiri Olsa
2019-03-07T15:35:06Z

On Tue, Mar 05, 2019 at 08:40:17AM -0800, Andi Kleen wrote:
> On Tue, Mar 05, 2019 at 05:28:54PM +0100, Jiri Olsa wrote:
> > On Tue, Mar 05, 2019 at 08:13:19AM -0800, Andi Kleen wrote:
> > > On Tue, Mar 05, 2019 at 04:25:33PM +0100, Jiri Olsa wrote:
> > > > Getting precise_ip field from the perf_pmu::max_precise
> > > > config read from sysfs. If it's not available falling
> > > > back to current detection function.
> > >
> > > max_precise depends on the event. This won't work for all
> > > events. For example only instructions and cycles support
> > > ppp
> >
> > I'm getting precise_ip=3 on mem-* events as well, that's why I
> > was fixing this.. now it's not working for any event
>
> I don't think it means anything for mem-*
>
> There's some support for it on Goldmont plus for other events,
> but it doesn't support mem-*. On big core it's only
> for instructions and cycles, all implemented with the same
> event. All other PEBS events only have two levels
> switching between the two IPs.

ok, so how about this, it's the change I posted merged with the patch

jirka

---
Currently we probe for precise_ip with user specified
perf_event_attr, which might fail because of unsupported
kernel features, which would get disabled during the
open time anyway.

Switching the probe to take place on simple event,
only configured with users type/config, so the
following record sets proper precise_ip:

# perf record -e cycles:P ls
# perf evlist -v
cycles:P: size: 112, ... precise_ip: 3, ...

Link: http://lkml.kernel.org/n/tip-rwncfxifbhnmd89yx0va5zg0@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/util/evlist.c | 25 ++++++++++++++++++++-----
tools/perf/util/evsel.c | 8 --------
2 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 08cedb643ea6..cee2f83feb89 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -230,18 +230,33 @@ void perf_evlist__set_leader(struct perf_evlist *evlist)
}
}

-void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr)
+void perf_event_attr__set_max_precise_ip(struct perf_event_attr *pattr)
{
- attr->precise_ip = 3;
+ struct perf_event_attr attr = {
+ .type = pattr->type,
+ .config = pattr->config,
+ .exclude_kernel = 1,
+ .precise_ip = 3,
+ };

- while (attr->precise_ip != 0) {
- int fd = sys_perf_event_open(attr, 0, -1, -1, 0);
+ event_attr_init(&attr);
+
+ /*
+ * Unnamed union member, not supported as struct member named
+ * initializer in older compilers such as gcc 4.4.7
+ */
+ attr.sample_period = 1;
+
+ while (attr.precise_ip != 0) {
+ int fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
if (fd != -1) {
close(fd);
break;
}
- --attr->precise_ip;
+ --attr.precise_ip;
}
+
+ pattr->precise_ip = attr.precise_ip;
}

int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index eec542bab815..2ef229e24b6f 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -294,20 +294,12 @@ struct perf_evsel *perf_evsel__new_cycles(bool precise)

if (!precise)
goto new_event;
- /*
- * Unnamed union member, not supported as struct member named
- * initializer in older compilers such as gcc 4.4.7
- *
- * Just for probing the precise_ip:
- */
- attr.sample_period = 1;

perf_event_attr__set_max_precise_ip(&attr);
/*
* Now let the usual logic to set up the perf_event_attr defaults
* to kick in when we return and before perf_evsel__open() is called.
*/
- attr.sample_period = 0;
new_event:
evsel = perf_evsel__new(&attr);
if (evsel == NULL)
--
2.17.2