Skip to content

Commit 9cbfa2f

Browse files
Jin Yaoacmel
authored andcommitted
perf parse-events: Create two hybrid hardware events
Current hardware events has special perf types PERF_TYPE_HARDWARE. But it doesn't pass the PMU type in the user interface. For a hybrid system, the perf kernel doesn't know which PMU the events belong to. So now this type is extended to be PMU aware type. The PMU type ID is stored at attr.config[63:32]. PMU type ID is retrieved from sysfs. root@lkp-adl-d01:/sys/devices/cpu_atom# cat type 8 root@lkp-adl-d01:/sys/devices/cpu_core# cat type 4 When enabling a hybrid hardware event without specified pmu, such as, 'perf stat -e cycles -a', two events are created automatically. One is for atom, the other is for core. # perf stat -e cycles -a -vv -- sleep 1 Control descriptor is not initialized ------------------------------------------------------------ perf_event_attr: size 120 config 0x400000000 sample_type IDENTIFIER read_format TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING disabled 1 inherit 1 exclude_guest 1 ------------------------------------------------------------ sys_perf_event_open: pid -1 cpu 0 group_fd -1 flags 0x8 = 3 ------------------------------------------------------------ ... ------------------------------------------------------------ perf_event_attr: size 120 config 0x400000000 sample_type IDENTIFIER read_format TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING disabled 1 inherit 1 exclude_guest 1 ------------------------------------------------------------ sys_perf_event_open: pid -1 cpu 15 group_fd -1 flags 0x8 = 19 ------------------------------------------------------------ perf_event_attr: size 120 config 0x800000000 sample_type IDENTIFIER read_format TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING disabled 1 inherit 1 exclude_guest 1 ------------------------------------------------------------ sys_perf_event_open: pid -1 cpu 16 group_fd -1 flags 0x8 = 20 ------------------------------------------------------------ ... ------------------------------------------------------------ perf_event_attr: size 120 config 0x800000000 sample_type IDENTIFIER read_format TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING disabled 1 inherit 1 exclude_guest 1 ------------------------------------------------------------ sys_perf_event_open: pid -1 cpu 23 group_fd -1 flags 0x8 = 27 cycles: 0: 836272 1001525722 1001525722 cycles: 1: 628564 1001580453 1001580453 cycles: 2: 872693 1001605997 1001605997 cycles: 3: 70417 1001641369 1001641369 cycles: 4: 88593 1001726722 1001726722 cycles: 5: 470495 1001752993 1001752993 cycles: 6: 484733 1001840440 1001840440 cycles: 7: 1272477 1001593105 1001593105 cycles: 8: 209185 1001608616 1001608616 cycles: 9: 204391 1001633962 1001633962 cycles: 10: 264121 1001661745 1001661745 cycles: 11: 826104 1001689904 1001689904 cycles: 12: 89935 1001728861 1001728861 cycles: 13: 70639 1001756757 1001756757 cycles: 14: 185266 1001784810 1001784810 cycles: 15: 171094 1001825466 1001825466 cycles: 0: 129624 1001854843 1001854843 cycles: 1: 122533 1001840421 1001840421 cycles: 2: 90055 1001882506 1001882506 cycles: 3: 139607 1001896463 1001896463 cycles: 4: 141791 1001907838 1001907838 cycles: 5: 530927 1001883880 1001883880 cycles: 6: 143246 1001852529 1001852529 cycles: 7: 667769 1001872626 1001872626 cycles: 6744979 16026956922 16026956922 cycles: 1965552 8014991106 8014991106 Performance counter stats for 'system wide': 6,744,979 cpu_core/cycles/ 1,965,552 cpu_atom/cycles/ 1.001882711 seconds time elapsed 0x4 in 0x400000000 indicates the cpu_core pmu. 0x8 in 0x800000000 indicates the cpu_atom pmu. Signed-off-by: Jin Yao <[email protected]> Reviewed-by: Jiri Olsa <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Kan Liang <[email protected]> Cc: Peter Zijlstra <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 1227942 commit 9cbfa2f

File tree

5 files changed

+141
-0
lines changed

5 files changed

+141
-0
lines changed

tools/perf/util/Build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ perf-y += llvm-utils.o
2323
perf-y += mmap.o
2424
perf-y += memswap.o
2525
perf-y += parse-events.o
26+
perf-y += parse-events-hybrid.o
2627
perf-y += perf_regs.o
2728
perf-y += path.o
2829
perf-y += print_binary.o
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <linux/err.h>
3+
#include <linux/zalloc.h>
4+
#include <errno.h>
5+
#include <sys/types.h>
6+
#include <sys/stat.h>
7+
#include <fcntl.h>
8+
#include <sys/param.h>
9+
#include "evlist.h"
10+
#include "evsel.h"
11+
#include "parse-events.h"
12+
#include "parse-events-hybrid.h"
13+
#include "debug.h"
14+
#include "pmu.h"
15+
#include "pmu-hybrid.h"
16+
#include "perf.h"
17+
18+
static void config_hybrid_attr(struct perf_event_attr *attr,
19+
int type, int pmu_type)
20+
{
21+
/*
22+
* attr.config layout for type PERF_TYPE_HARDWARE and
23+
* PERF_TYPE_HW_CACHE
24+
*
25+
* PERF_TYPE_HARDWARE: 0xEEEEEEEE000000AA
26+
* AA: hardware event ID
27+
* EEEEEEEE: PMU type ID
28+
* PERF_TYPE_HW_CACHE: 0xEEEEEEEE00DDCCBB
29+
* BB: hardware cache ID
30+
* CC: hardware cache op ID
31+
* DD: hardware cache op result ID
32+
* EEEEEEEE: PMU type ID
33+
* If the PMU type ID is 0, the PERF_TYPE_RAW will be applied.
34+
*/
35+
attr->type = type;
36+
attr->config = attr->config | ((__u64)pmu_type << PERF_PMU_TYPE_SHIFT);
37+
}
38+
39+
static int create_event_hybrid(__u32 config_type, int *idx,
40+
struct list_head *list,
41+
struct perf_event_attr *attr, char *name,
42+
struct list_head *config_terms,
43+
struct perf_pmu *pmu)
44+
{
45+
struct evsel *evsel;
46+
__u32 type = attr->type;
47+
__u64 config = attr->config;
48+
49+
config_hybrid_attr(attr, config_type, pmu->type);
50+
evsel = parse_events__add_event_hybrid(list, idx, attr, name,
51+
pmu, config_terms);
52+
if (evsel)
53+
evsel->pmu_name = strdup(pmu->name);
54+
else
55+
return -ENOMEM;
56+
57+
attr->type = type;
58+
attr->config = config;
59+
return 0;
60+
}
61+
62+
static int add_hw_hybrid(struct parse_events_state *parse_state,
63+
struct list_head *list, struct perf_event_attr *attr,
64+
char *name, struct list_head *config_terms)
65+
{
66+
struct perf_pmu *pmu;
67+
int ret;
68+
69+
perf_pmu__for_each_hybrid_pmu(pmu) {
70+
ret = create_event_hybrid(PERF_TYPE_HARDWARE,
71+
&parse_state->idx, list, attr, name,
72+
config_terms, pmu);
73+
if (ret)
74+
return ret;
75+
}
76+
77+
return 0;
78+
}
79+
80+
int parse_events__add_numeric_hybrid(struct parse_events_state *parse_state,
81+
struct list_head *list,
82+
struct perf_event_attr *attr,
83+
char *name, struct list_head *config_terms,
84+
bool *hybrid)
85+
{
86+
*hybrid = false;
87+
if (attr->type == PERF_TYPE_SOFTWARE)
88+
return 0;
89+
90+
if (!perf_pmu__has_hybrid())
91+
return 0;
92+
93+
*hybrid = true;
94+
if (attr->type != PERF_TYPE_RAW) {
95+
return add_hw_hybrid(parse_state, list, attr, name,
96+
config_terms);
97+
}
98+
99+
return -1;
100+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef __PERF_PARSE_EVENTS_HYBRID_H
3+
#define __PERF_PARSE_EVENTS_HYBRID_H
4+
5+
#include <linux/list.h>
6+
#include <stdbool.h>
7+
#include <linux/types.h>
8+
#include <linux/perf_event.h>
9+
#include <string.h>
10+
11+
int parse_events__add_numeric_hybrid(struct parse_events_state *parse_state,
12+
struct list_head *list,
13+
struct perf_event_attr *attr,
14+
char *name, struct list_head *config_terms,
15+
bool *hybrid);
16+
17+
#endif /* __PERF_PARSE_EVENTS_HYBRID_H */

tools/perf/util/parse-events.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "util/evsel_config.h"
3838
#include "util/event.h"
3939
#include "util/pfm.h"
40+
#include "util/parse-events-hybrid.h"
4041
#include "perf.h"
4142

4243
#define MAX_NAME_LEN 100
@@ -1419,6 +1420,8 @@ int parse_events_add_numeric(struct parse_events_state *parse_state,
14191420
{
14201421
struct perf_event_attr attr;
14211422
LIST_HEAD(config_terms);
1423+
bool hybrid;
1424+
int ret;
14221425

14231426
memset(&attr, 0, sizeof(attr));
14241427
attr.type = type;
@@ -1433,6 +1436,12 @@ int parse_events_add_numeric(struct parse_events_state *parse_state,
14331436
return -ENOMEM;
14341437
}
14351438

1439+
ret = parse_events__add_numeric_hybrid(parse_state, list, &attr,
1440+
get_config_name(head_config),
1441+
&config_terms, &hybrid);
1442+
if (hybrid)
1443+
return ret;
1444+
14361445
return add_event(list, &parse_state->idx, &attr,
14371446
get_config_name(head_config), &config_terms);
14381447
}
@@ -3194,3 +3203,12 @@ char *parse_events_formats_error_string(char *additional_terms)
31943203
fail:
31953204
return NULL;
31963205
}
3206+
3207+
struct evsel *parse_events__add_event_hybrid(struct list_head *list, int *idx,
3208+
struct perf_event_attr *attr,
3209+
char *name, struct perf_pmu *pmu,
3210+
struct list_head *config_terms)
3211+
{
3212+
return __add_event(list, idx, attr, true, name, pmu,
3213+
config_terms, false, NULL);
3214+
}

tools/perf/util/parse-events.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,4 +263,9 @@ static inline bool is_sdt_event(char *str __maybe_unused)
263263

264264
int perf_pmu__test_parse_init(void);
265265

266+
struct evsel *parse_events__add_event_hybrid(struct list_head *list, int *idx,
267+
struct perf_event_attr *attr,
268+
char *name, struct perf_pmu *pmu,
269+
struct list_head *config_terms);
270+
266271
#endif /* __PERF_PARSE_EVENTS_H */

0 commit comments

Comments
 (0)