Skip to content

Commit c1a515d

Browse files
committed
Merge tag 'perf-tools-fixes-for-v6.5-2-2023-08-03' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools
Pull perf tools fixes from Arnaldo Carvalho de Melo: - Fix segfault in the powerpc specific arch_skip_callchain_idx function. The patch doing the reference count init/exit that went into 6.5 missed this function. - Fix regression reading the arm64 PMU cpu slots in sysfs, a patch removing some code duplication ended up duplicating the /sysfs prefix for these files. - Fix grouping of events related to topdown, addressing a regression on the CSV output produced by 'perf stat' noticed on the downstream tool toplev. - Fix the uprobe_from_different_cu 'perf test' entry, it is failing when gcc isn't available, so we need to check that and skip the test if it is not installed. * tag 'perf-tools-fixes-for-v6.5-2-2023-08-03' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools: perf test parse-events: Test complex name has required event format perf pmus: Create placholder regardless of scanning core_only perf test uprobe_from_different_cu: Skip if there is no gcc perf parse-events: Only move force grouped evsels when sorting perf parse-events: When fixing group leaders always set the leader perf parse-events: Extra care around force grouped events perf callchain powerpc: Fix addr location init during arch_skip_callchain_idx function perf pmu arm64: Fix reading the PMU cpu slots in sysfs
2 parents 638c191 + 07d2b82 commit c1a515d

File tree

8 files changed

+81
-36
lines changed

8 files changed

+81
-36
lines changed

tools/perf/arch/arm64/util/pmu.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,11 @@ double perf_pmu__cpu_slots_per_cycle(void)
5454
perf_pmu__pathname_scnprintf(path, sizeof(path),
5555
pmu->name, "caps/slots");
5656
/*
57-
* The value of slots is not greater than 32 bits, but sysfs__read_int
58-
* can't read value with 0x prefix, so use sysfs__read_ull instead.
57+
* The value of slots is not greater than 32 bits, but
58+
* filename__read_int can't read value with 0x prefix,
59+
* so use filename__read_ull instead.
5960
*/
60-
sysfs__read_ull(path, &slots);
61+
filename__read_ull(path, &slots);
6162
}
6263

6364
return slots ? (double)slots : NAN;

tools/perf/arch/powerpc/util/skip-callchain-idx.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
250250
if (!chain || chain->nr < 3)
251251
return skip_slot;
252252

253+
addr_location__init(&al);
253254
ip = chain->ips[1];
254255

255256
thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al);
@@ -259,6 +260,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
259260

260261
if (!dso) {
261262
pr_debug("%" PRIx64 " dso is NULL\n", ip);
263+
addr_location__exit(&al);
262264
return skip_slot;
263265
}
264266

@@ -279,5 +281,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
279281
*/
280282
skip_slot = 3;
281283
}
284+
285+
addr_location__exit(&al);
282286
return skip_slot;
283287
}

tools/perf/tests/parse-events.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1631,6 +1631,16 @@ static bool test__pmu_cpu_valid(void)
16311631
return !!perf_pmus__find("cpu");
16321632
}
16331633

1634+
static bool test__pmu_cpu_event_valid(void)
1635+
{
1636+
struct perf_pmu *pmu = perf_pmus__find("cpu");
1637+
1638+
if (!pmu)
1639+
return false;
1640+
1641+
return perf_pmu__has_format(pmu, "event");
1642+
}
1643+
16341644
static bool test__intel_pt_valid(void)
16351645
{
16361646
return !!perf_pmus__find("intel_pt");
@@ -2179,7 +2189,7 @@ static const struct evlist_test test__events_pmu[] = {
21792189
},
21802190
{
21812191
.name = "cpu/name='COMPLEX_CYCLES_NAME:orig=cycles,desc=chip-clock-ticks',period=0x1,event=0x2/ukp",
2182-
.valid = test__pmu_cpu_valid,
2192+
.valid = test__pmu_cpu_event_valid,
21832193
.check = test__checkevent_complex_name,
21842194
/* 3 */
21852195
},

tools/perf/tests/shell/test_uprobe_from_different_cu.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,20 @@
44

55
set -e
66

7+
# skip if there's no gcc
8+
if ! [ -x "$(command -v gcc)" ]; then
9+
echo "failed: no gcc compiler"
10+
exit 2
11+
fi
12+
713
temp_dir=$(mktemp -d /tmp/perf-uprobe-different-cu-sh.XXXXXXXXXX)
814

915
cleanup()
1016
{
1117
trap - EXIT TERM INT
1218
if [[ "${temp_dir}" =~ ^/tmp/perf-uprobe-different-cu-sh.*$ ]]; then
1319
echo "--- Cleaning up ---"
14-
perf probe -x ${temp_dir}/testfile -d foo
20+
perf probe -x ${temp_dir}/testfile -d foo || true
1521
rm -f "${temp_dir}/"*
1622
rmdir "${temp_dir}"
1723
fi

tools/perf/util/parse-events.c

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2100,16 +2100,16 @@ __weak int arch_evlist__cmp(const struct evsel *lhs, const struct evsel *rhs)
21002100
return lhs->core.idx - rhs->core.idx;
21012101
}
21022102

2103-
static int evlist__cmp(void *state, const struct list_head *l, const struct list_head *r)
2103+
static int evlist__cmp(void *_fg_idx, const struct list_head *l, const struct list_head *r)
21042104
{
21052105
const struct perf_evsel *lhs_core = container_of(l, struct perf_evsel, node);
21062106
const struct evsel *lhs = container_of(lhs_core, struct evsel, core);
21072107
const struct perf_evsel *rhs_core = container_of(r, struct perf_evsel, node);
21082108
const struct evsel *rhs = container_of(rhs_core, struct evsel, core);
2109-
int *leader_idx = state;
2110-
int lhs_leader_idx = *leader_idx, rhs_leader_idx = *leader_idx, ret;
2109+
int *force_grouped_idx = _fg_idx;
2110+
int lhs_sort_idx, rhs_sort_idx, ret;
21112111
const char *lhs_pmu_name, *rhs_pmu_name;
2112-
bool lhs_has_group = false, rhs_has_group = false;
2112+
bool lhs_has_group, rhs_has_group;
21132113

21142114
/*
21152115
* First sort by grouping/leader. Read the leader idx only if the evsel
@@ -2121,15 +2121,25 @@ static int evlist__cmp(void *state, const struct list_head *l, const struct list
21212121
*/
21222122
if (lhs_core->leader != lhs_core || lhs_core->nr_members > 1) {
21232123
lhs_has_group = true;
2124-
lhs_leader_idx = lhs_core->leader->idx;
2124+
lhs_sort_idx = lhs_core->leader->idx;
2125+
} else {
2126+
lhs_has_group = false;
2127+
lhs_sort_idx = *force_grouped_idx != -1 && arch_evsel__must_be_in_group(lhs)
2128+
? *force_grouped_idx
2129+
: lhs_core->idx;
21252130
}
21262131
if (rhs_core->leader != rhs_core || rhs_core->nr_members > 1) {
21272132
rhs_has_group = true;
2128-
rhs_leader_idx = rhs_core->leader->idx;
2133+
rhs_sort_idx = rhs_core->leader->idx;
2134+
} else {
2135+
rhs_has_group = false;
2136+
rhs_sort_idx = *force_grouped_idx != -1 && arch_evsel__must_be_in_group(rhs)
2137+
? *force_grouped_idx
2138+
: rhs_core->idx;
21292139
}
21302140

2131-
if (lhs_leader_idx != rhs_leader_idx)
2132-
return lhs_leader_idx - rhs_leader_idx;
2141+
if (lhs_sort_idx != rhs_sort_idx)
2142+
return lhs_sort_idx - rhs_sort_idx;
21332143

21342144
/* Group by PMU if there is a group. Groups can't span PMUs. */
21352145
if (lhs_has_group && rhs_has_group) {
@@ -2146,10 +2156,10 @@ static int evlist__cmp(void *state, const struct list_head *l, const struct list
21462156

21472157
static int parse_events__sort_events_and_fix_groups(struct list_head *list)
21482158
{
2149-
int idx = 0, unsorted_idx = -1;
2159+
int idx = 0, force_grouped_idx = -1;
21502160
struct evsel *pos, *cur_leader = NULL;
21512161
struct perf_evsel *cur_leaders_grp = NULL;
2152-
bool idx_changed = false;
2162+
bool idx_changed = false, cur_leader_force_grouped = false;
21532163
int orig_num_leaders = 0, num_leaders = 0;
21542164
int ret;
21552165

@@ -2174,12 +2184,14 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list)
21742184
*/
21752185
pos->core.idx = idx++;
21762186

2177-
if (unsorted_idx == -1 && pos == pos_leader && pos->core.nr_members < 2)
2178-
unsorted_idx = pos->core.idx;
2187+
/* Remember an index to sort all forced grouped events together to. */
2188+
if (force_grouped_idx == -1 && pos == pos_leader && pos->core.nr_members < 2 &&
2189+
arch_evsel__must_be_in_group(pos))
2190+
force_grouped_idx = pos->core.idx;
21792191
}
21802192

21812193
/* Sort events. */
2182-
list_sort(&unsorted_idx, list, evlist__cmp);
2194+
list_sort(&force_grouped_idx, list, evlist__cmp);
21832195

21842196
/*
21852197
* Recompute groups, splitting for PMUs and adding groups for events
@@ -2189,8 +2201,9 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list)
21892201
list_for_each_entry(pos, list, core.node) {
21902202
const struct evsel *pos_leader = evsel__leader(pos);
21912203
const char *pos_pmu_name = pos->group_pmu_name;
2192-
const char *cur_leader_pmu_name, *pos_leader_pmu_name;
2193-
bool force_grouped = arch_evsel__must_be_in_group(pos);
2204+
const char *cur_leader_pmu_name;
2205+
bool pos_force_grouped = force_grouped_idx != -1 &&
2206+
arch_evsel__must_be_in_group(pos);
21942207

21952208
/* Reset index and nr_members. */
21962209
if (pos->core.idx != idx)
@@ -2206,7 +2219,8 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list)
22062219
cur_leader = pos;
22072220

22082221
cur_leader_pmu_name = cur_leader->group_pmu_name;
2209-
if ((cur_leaders_grp != pos->core.leader && !force_grouped) ||
2222+
if ((cur_leaders_grp != pos->core.leader &&
2223+
(!pos_force_grouped || !cur_leader_force_grouped)) ||
22102224
strcmp(cur_leader_pmu_name, pos_pmu_name)) {
22112225
/* Event is for a different group/PMU than last. */
22122226
cur_leader = pos;
@@ -2216,14 +2230,14 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list)
22162230
* group.
22172231
*/
22182232
cur_leaders_grp = pos->core.leader;
2219-
}
2220-
pos_leader_pmu_name = pos_leader->group_pmu_name;
2221-
if (strcmp(pos_leader_pmu_name, pos_pmu_name) || force_grouped) {
22222233
/*
2223-
* Event's PMU differs from its leader's. Groups can't
2224-
* span PMUs, so update leader from the group/PMU
2225-
* tracker.
2234+
* Avoid forcing events into groups with events that
2235+
* don't need to be in the group.
22262236
*/
2237+
cur_leader_force_grouped = pos_force_grouped;
2238+
}
2239+
if (pos_leader != cur_leader) {
2240+
/* The leader changed so update it. */
22272241
evsel__set_leader(pos, cur_leader);
22282242
}
22292243
}

tools/perf/util/pmu.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,17 @@ void perf_pmu__del_formats(struct list_head *formats)
14401440
}
14411441
}
14421442

1443+
bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name)
1444+
{
1445+
struct perf_pmu_format *format;
1446+
1447+
list_for_each_entry(format, &pmu->format, list) {
1448+
if (!strcmp(format->name, name))
1449+
return true;
1450+
}
1451+
return false;
1452+
}
1453+
14431454
bool is_pmu_core(const char *name)
14441455
{
14451456
return !strcmp(name, "cpu") || !strcmp(name, "cpum_cf") || is_sysfs_pmu_core(name);

tools/perf/util/pmu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ int perf_pmu__new_format(struct list_head *list, char *name,
234234
void perf_pmu__set_format(unsigned long *bits, long from, long to);
235235
int perf_pmu__format_parse(int dirfd, struct list_head *head);
236236
void perf_pmu__del_formats(struct list_head *formats);
237+
bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name);
237238

238239
bool is_pmu_core(const char *name);
239240
bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu);

tools/perf/util/pmus.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -152,16 +152,14 @@ static void pmu_read_sysfs(bool core_only)
152152
}
153153

154154
closedir(dir);
155-
if (core_only) {
156-
if (!list_empty(&core_pmus))
157-
read_sysfs_core_pmus = true;
158-
else {
159-
if (perf_pmu__create_placeholder_core_pmu(&core_pmus))
160-
read_sysfs_core_pmus = true;
161-
}
162-
} else {
155+
if (list_empty(&core_pmus)) {
156+
if (!perf_pmu__create_placeholder_core_pmu(&core_pmus))
157+
pr_err("Failure to set up any core PMUs\n");
158+
}
159+
if (!list_empty(&core_pmus)) {
163160
read_sysfs_core_pmus = true;
164-
read_sysfs_all_pmus = true;
161+
if (!core_only)
162+
read_sysfs_all_pmus = true;
165163
}
166164
}
167165

0 commit comments

Comments
 (0)