Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/perf/arch/x86/util/topdown.c
51282 views
1
// SPDX-License-Identifier: GPL-2.0
2
#include <errno.h>
3
#include "util/evlist.h"
4
#include "util/pmu.h"
5
#include "util/pmus.h"
6
#include "util/topdown.h"
7
#include "topdown.h"
8
#include "evsel.h"
9
10
// cmask=0, inv=0, pc=0, edge=0, umask=4, event=0
11
#define TOPDOWN_SLOTS 0x0400
12
13
/* Check whether there is a PMU which supports the perf metrics. */
14
bool topdown_sys_has_perf_metrics(void)
15
{
16
static bool has_perf_metrics;
17
static bool cached;
18
struct perf_pmu *pmu;
19
20
if (cached)
21
return has_perf_metrics;
22
23
/*
24
* The perf metrics feature is a core PMU feature.
25
* The PERF_TYPE_RAW type is the type of a core PMU.
26
* The slots event is only available when the core PMU
27
* supports the perf metrics feature.
28
*/
29
pmu = perf_pmus__find_by_type(PERF_TYPE_RAW);
30
if (pmu && perf_pmu__have_event(pmu, "slots"))
31
has_perf_metrics = true;
32
33
cached = true;
34
return has_perf_metrics;
35
}
36
37
bool arch_is_topdown_slots(const struct evsel *evsel)
38
{
39
return evsel->core.attr.type == PERF_TYPE_RAW &&
40
evsel->core.attr.config == TOPDOWN_SLOTS &&
41
evsel->core.attr.config1 == 0;
42
}
43
44
bool arch_is_topdown_metrics(const struct evsel *evsel)
45
{
46
// cmask=0, inv=0, pc=0, edge=0, umask=0x80-0x87, event=0
47
return evsel->core.attr.type == PERF_TYPE_RAW &&
48
(evsel->core.attr.config & 0xFFFFF8FF) == 0x8000 &&
49
evsel->core.attr.config1 == 0;
50
}
51
52
/*
53
* Check whether a topdown group supports sample-read.
54
*
55
* Only Topdown metric supports sample-read. The slots
56
* event must be the leader of the topdown group.
57
*/
58
bool arch_topdown_sample_read(struct evsel *leader)
59
{
60
struct evsel *evsel;
61
62
if (!evsel__sys_has_perf_metrics(leader))
63
return false;
64
65
if (!arch_is_topdown_slots(leader))
66
return false;
67
68
/*
69
* If slots event as leader event but no topdown metric events
70
* in group, slots event should still sample as leader.
71
*/
72
evlist__for_each_entry(leader->evlist, evsel) {
73
if (evsel->core.leader != leader->core.leader)
74
continue;
75
if (evsel != leader && arch_is_topdown_metrics(evsel))
76
return true;
77
}
78
79
return false;
80
}
81
82
/*
83
* Make a copy of the topdown metric event metric_event with the given index but
84
* change its configuration to be a topdown slots event. Copying from
85
* metric_event ensures modifiers are the same.
86
*/
87
int topdown_insert_slots_event(struct list_head *list, int idx, struct evsel *metric_event)
88
{
89
struct evsel *evsel = evsel__new_idx(&metric_event->core.attr, idx);
90
91
if (!evsel)
92
return -ENOMEM;
93
94
evsel->core.attr.config = TOPDOWN_SLOTS;
95
evsel->core.cpus = perf_cpu_map__get(metric_event->core.cpus);
96
evsel->core.pmu_cpus = perf_cpu_map__get(metric_event->core.pmu_cpus);
97
evsel->core.is_pmu_core = true;
98
evsel->pmu = metric_event->pmu;
99
evsel->name = strdup("slots");
100
evsel->precise_max = metric_event->precise_max;
101
evsel->sample_read = metric_event->sample_read;
102
evsel->weak_group = metric_event->weak_group;
103
evsel->bpf_counter = metric_event->bpf_counter;
104
evsel->retire_lat = metric_event->retire_lat;
105
evsel__set_leader(evsel, evsel__leader(metric_event));
106
list_add_tail(&evsel->core.node, list);
107
return 0;
108
}
109
110