Skip to content

Commit 71c86cd

Browse files
ZhengjunXingacmel
authored andcommitted
perf parse-events: Remove "not supported" hybrid cache events
By default, we create two hybrid cache events, one is for cpu_core, and another is for cpu_atom. But Some hybrid hardware cache events are only available on one CPU PMU. For example, the 'L1-dcache-load-misses' is only available on cpu_core, while the 'L1-icache-loads' is only available on cpu_atom. We need to remove "not supported" hybrid cache events. By extending is_event_supported() to global API and using it to check if the hybrid cache events are supported before being created, we can remove the "not supported" hybrid cache events. Before: # ./perf stat -e L1-dcache-load-misses,L1-icache-loads -a sleep 1 Performance counter stats for 'system wide': 52,570 cpu_core/L1-dcache-load-misses/ <not supported> cpu_atom/L1-dcache-load-misses/ <not supported> cpu_core/L1-icache-loads/ 1,471,817 cpu_atom/L1-icache-loads/ 1.004915229 seconds time elapsed After: # ./perf stat -e L1-dcache-load-misses,L1-icache-loads -a sleep 1 Performance counter stats for 'system wide': 54,510 cpu_core/L1-dcache-load-misses/ 1,441,286 cpu_atom/L1-icache-loads/ 1.005114281 seconds time elapsed Fixes: 30def61 ("perf parse-events: Create two hybrid cache events") Reported-by: Yi Ammy <ammy.yi@intel.com> Reviewed-by: Kan Liang <kan.liang@linux.intel.com> Signed-off-by: Xing Zhengjun <zhengjun.xing@linux.intel.com> Acked-by: Ian Rogers <irogers@google.com> Cc: Alexander Shishkin <alexander.shishkin@intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jin Yao <yao.jin@linux.intel.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: https://lore.kernel.org/r/20220923030013.3726410-2-zhengjun.xing@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
1 parent e28c078 commit 71c86cd

File tree

4 files changed

+57
-43
lines changed

4 files changed

+57
-43
lines changed

tools/perf/util/parse-events-hybrid.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ static void config_hybrid_attr(struct perf_event_attr *attr,
3333
* If the PMU type ID is 0, the PERF_TYPE_RAW will be applied.
3434
*/
3535
attr->type = type;
36-
attr->config = attr->config | ((__u64)pmu_type << PERF_PMU_TYPE_SHIFT);
36+
attr->config = (attr->config & PERF_HW_EVENT_MASK) |
37+
((__u64)pmu_type << PERF_PMU_TYPE_SHIFT);
3738
}
3839

3940
static int create_event_hybrid(__u32 config_type, int *idx,
@@ -48,13 +49,25 @@ static int create_event_hybrid(__u32 config_type, int *idx,
4849
__u64 config = attr->config;
4950

5051
config_hybrid_attr(attr, config_type, pmu->type);
52+
53+
/*
54+
* Some hybrid hardware cache events are only available on one CPU
55+
* PMU. For example, the 'L1-dcache-load-misses' is only available
56+
* on cpu_core, while the 'L1-icache-loads' is only available on
57+
* cpu_atom. We need to remove "not supported" hybrid cache events.
58+
*/
59+
if (attr->type == PERF_TYPE_HW_CACHE
60+
&& !is_event_supported(attr->type, attr->config))
61+
return 0;
62+
5163
evsel = parse_events__add_event_hybrid(list, idx, attr, name, metric_id,
5264
pmu, config_terms);
53-
if (evsel)
65+
if (evsel) {
5466
evsel->pmu_name = strdup(pmu->name);
55-
else
67+
if (!evsel->pmu_name)
68+
return -ENOMEM;
69+
} else
5670
return -ENOMEM;
57-
5871
attr->type = type;
5972
attr->config = config;
6073
return 0;

tools/perf/util/parse-events.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "util/parse-events-hybrid.h"
2929
#include "util/pmu-hybrid.h"
3030
#include "tracepoint.h"
31+
#include "thread_map.h"
3132

3233
#define MAX_NAME_LEN 100
3334

@@ -157,6 +158,44 @@ struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
157158
#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
158159
#define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT)
159160

161+
bool is_event_supported(u8 type, u64 config)
162+
{
163+
bool ret = true;
164+
int open_return;
165+
struct evsel *evsel;
166+
struct perf_event_attr attr = {
167+
.type = type,
168+
.config = config,
169+
.disabled = 1,
170+
};
171+
struct perf_thread_map *tmap = thread_map__new_by_tid(0);
172+
173+
if (tmap == NULL)
174+
return false;
175+
176+
evsel = evsel__new(&attr);
177+
if (evsel) {
178+
open_return = evsel__open(evsel, NULL, tmap);
179+
ret = open_return >= 0;
180+
181+
if (open_return == -EACCES) {
182+
/*
183+
* This happens if the paranoid value
184+
* /proc/sys/kernel/perf_event_paranoid is set to 2
185+
* Re-run with exclude_kernel set; we don't do that
186+
* by default as some ARM machines do not support it.
187+
*
188+
*/
189+
evsel->core.attr.exclude_kernel = 1;
190+
ret = evsel__open(evsel, NULL, tmap) >= 0;
191+
}
192+
evsel__delete(evsel);
193+
}
194+
195+
perf_thread_map__put(tmap);
196+
return ret;
197+
}
198+
160199
const char *event_type(int type)
161200
{
162201
switch (type) {

tools/perf/util/parse-events.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ struct option;
1919
struct perf_pmu;
2020

2121
bool have_tracepoints(struct list_head *evlist);
22+
bool is_event_supported(u8 type, u64 config);
2223

2324
const char *event_type(int type);
2425

tools/perf/util/print-events.c

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include "probe-file.h"
2323
#include "string2.h"
2424
#include "strlist.h"
25-
#include "thread_map.h"
2625
#include "tracepoint.h"
2726
#include "pfm.h"
2827
#include "pmu-hybrid.h"
@@ -239,44 +238,6 @@ void print_sdt_events(const char *subsys_glob, const char *event_glob,
239238
strlist__delete(sdtlist);
240239
}
241240

242-
static bool is_event_supported(u8 type, u64 config)
243-
{
244-
bool ret = true;
245-
int open_return;
246-
struct evsel *evsel;
247-
struct perf_event_attr attr = {
248-
.type = type,
249-
.config = config,
250-
.disabled = 1,
251-
};
252-
struct perf_thread_map *tmap = thread_map__new_by_tid(0);
253-
254-
if (tmap == NULL)
255-
return false;
256-
257-
evsel = evsel__new(&attr);
258-
if (evsel) {
259-
open_return = evsel__open(evsel, NULL, tmap);
260-
ret = open_return >= 0;
261-
262-
if (open_return == -EACCES) {
263-
/*
264-
* This happens if the paranoid value
265-
* /proc/sys/kernel/perf_event_paranoid is set to 2
266-
* Re-run with exclude_kernel set; we don't do that
267-
* by default as some ARM machines do not support it.
268-
*
269-
*/
270-
evsel->core.attr.exclude_kernel = 1;
271-
ret = evsel__open(evsel, NULL, tmap) >= 0;
272-
}
273-
evsel__delete(evsel);
274-
}
275-
276-
perf_thread_map__put(tmap);
277-
return ret;
278-
}
279-
280241
int print_hwcache_events(const char *event_glob, bool name_only)
281242
{
282243
unsigned int type, op, i, evt_i = 0, evt_num = 0, npmus = 0;

0 commit comments

Comments
 (0)