perf tools fixes for v6.6: 2nd batch

- Fix regression in reading scale and unit files from sysfs for PMU
   events, so that we can use that info to pretty print instead of
   printing raw numbers:
 
   # perf stat -e power/energy-ram/,power/energy-gpu/ sleep 2
 
    Performance counter stats for 'system wide':
 
               1.64 Joules power/energy-ram/
               0.20 Joules power/energy-gpu/
 
        2.001228914 seconds time elapsed
   #
   # grep -m1 "model name" /proc/cpuinfo
   model name	: Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz
   #
 
 - The small llvm.cpp file used to check if the llvm devel files are present was
   incorrectly deleted when removing the BPF event in 'perf trace', put it back
   as it is also used by tools/bpf/bpftool, that uses llvm routines to do
   disassembly of BPF object files.
 
 - Fix use of addr_location__exit() in dlfilter__object_code(), making sure that
   it is only used to pair a previous addr_location__init() call.
 
 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQR2GiIUctdOfX2qHhGyPKLppCJ+JwUCZTKh5AAKCRCyPKLppCJ+
 J/g/AP0f6SNyHJz21JzDTzyjXAeSdMzKwic0LXv+kATQy31HJAD+Kf7UKQieUeZB
 fxvp60aKyFN8IVIgpYiAjZMS3k9XPAY=
 =N7Gv
 -----END PGP SIGNATURE-----

Merge tag 'perf-tools-fixes-for-v6.6-2-2023-10-20' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools

Pull perf tools fixes from Arnaldo Carvalho de Melo:

 - Fix regression in reading scale and unit files from sysfs for PMU
   events, so that we can use that info to pretty print instead of
   printing raw numbers:

     # perf stat -e power/energy-ram/,power/energy-gpu/ sleep 2

      Performance counter stats for 'system wide':

                 1.64 Joules power/energy-ram/
                 0.20 Joules power/energy-gpu/

          2.001228914 seconds time elapsed
     #
     # grep -m1 "model name" /proc/cpuinfo
     model name	: Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz
     #

 - The small llvm.cpp file used to check if the llvm devel files are
   present was incorrectly deleted when removing the BPF event in 'perf
   trace', put it back as it is also used by tools/bpf/bpftool, that
   uses llvm routines to do disassembly of BPF object files.

 - Fix use of addr_location__exit() in dlfilter__object_code(), making
   sure that it is only used to pair a previous addr_location__init()
   call.

* tag 'perf-tools-fixes-for-v6.6-2-2023-10-20' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools:
  tools build: Fix llvm feature detection, still used by bpftool
  perf dlfilter: Add a test for object_code()
  perf dlfilter: Fix use of addr_location__exit() in dlfilter__object_code()
  perf pmu: Fix perf stat output with correct scale and unit
This commit is contained in:
Linus Torvalds 2023-10-20 14:49:24 -07:00
commit 9c5d00cb7b
5 changed files with 56 additions and 24 deletions

View file

@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-2.0
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
#define NUM_VERSION (((LLVM_VERSION_MAJOR) << 16) + (LLVM_VERSION_MINOR << 8) + LLVM_VERSION_PATCH)
#if NUM_VERSION < 0x030900
# error "LLVM version too low"
#endif
int main()
{
llvm::errs() << "Hello World!\n";
llvm::llvm_shutdown();
return 0;
}

View file

@ -289,6 +289,15 @@ static int check_attr(void *ctx)
return 0;
}
static int check_object_code(void *ctx, const struct perf_dlfilter_sample *sample)
{
__u8 buf[15];
CHECK(perf_dlfilter_fns.object_code(ctx, sample->ip, buf, sizeof(buf)) > 0);
return 0;
}
static int do_checks(void *data, const struct perf_dlfilter_sample *sample, void *ctx, bool early)
{
struct filter_data *d = data;
@ -314,7 +323,8 @@ static int do_checks(void *data, const struct perf_dlfilter_sample *sample, void
if (early && !d->do_early)
return 0;
if (check_al(ctx) || check_addr_al(ctx) || check_address_al(ctx, sample))
if (check_al(ctx) || check_addr_al(ctx) || check_address_al(ctx, sample) ||
check_object_code(ctx, sample))
return -1;
if (early)

View file

@ -308,6 +308,15 @@ static int check_attr(void *ctx)
return 0;
}
static int check_object_code(void *ctx, const struct perf_dlfilter_sample *sample)
{
__u8 buf[15];
CHECK(perf_dlfilter_fns.object_code(ctx, sample->ip, buf, sizeof(buf)) > 0);
return 0;
}
static int do_checks(void *data, const struct perf_dlfilter_sample *sample, void *ctx, bool early)
{
struct filter_data *d = data;
@ -333,7 +342,8 @@ static int do_checks(void *data, const struct perf_dlfilter_sample *sample, void
if (early && !d->do_early)
return 0;
if (check_al(ctx) || check_addr_al(ctx) || check_address_al(ctx, sample))
if (check_al(ctx) || check_addr_al(ctx) || check_address_al(ctx, sample) ||
check_object_code(ctx, sample))
return -1;
if (early)

View file

@ -282,13 +282,21 @@ static struct perf_event_attr *dlfilter__attr(void *ctx)
return &d->evsel->core.attr;
}
static __s32 code_read(__u64 ip, struct map *map, struct machine *machine, void *buf, __u32 len)
{
u64 offset = map__map_ip(map, ip);
if (ip + len >= map__end(map))
len = map__end(map) - ip;
return dso__data_read_offset(map__dso(map), machine, offset, buf, len);
}
static __s32 dlfilter__object_code(void *ctx, __u64 ip, void *buf, __u32 len)
{
struct dlfilter *d = (struct dlfilter *)ctx;
struct addr_location *al;
struct addr_location a;
struct map *map;
u64 offset;
__s32 ret;
if (!d->ctx_valid)
@ -298,27 +306,17 @@ static __s32 dlfilter__object_code(void *ctx, __u64 ip, void *buf, __u32 len)
if (!al)
return -1;
map = al->map;
if (map && ip >= map__start(map) && ip < map__end(map) &&
if (al->map && ip >= map__start(al->map) && ip < map__end(al->map) &&
machine__kernel_ip(d->machine, ip) == machine__kernel_ip(d->machine, d->sample->ip))
goto have_map;
return code_read(ip, al->map, d->machine, buf, len);
addr_location__init(&a);
thread__find_map_fb(al->thread, d->sample->cpumode, ip, &a);
if (!a.map) {
ret = -1;
goto out;
}
map = a.map;
have_map:
offset = map__map_ip(map, ip);
if (ip + len >= map__end(map))
len = map__end(map) - ip;
ret = dso__data_read_offset(map__dso(map), d->machine, offset, buf, len);
out:
thread__find_map_fb(al->thread, d->sample->cpumode, ip, &a);
ret = a.map ? code_read(ip, a.map, d->machine, buf, len) : -1;
addr_location__exit(&a);
return ret;
}

View file

@ -295,7 +295,7 @@ static int perf_pmu__parse_scale(struct perf_pmu *pmu, struct perf_pmu_alias *al
len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
if (!len)
return 0;
scnprintf(path + len, sizeof(path) - len, "%s/%s.scale", pmu->name, alias->name);
scnprintf(path + len, sizeof(path) - len, "%s/events/%s.scale", pmu->name, alias->name);
fd = open(path, O_RDONLY);
if (fd == -1)
@ -330,7 +330,7 @@ static int perf_pmu__parse_unit(struct perf_pmu *pmu, struct perf_pmu_alias *ali
len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
if (!len)
return 0;
scnprintf(path + len, sizeof(path) - len, "%s/%s.unit", pmu->name, alias->name);
scnprintf(path + len, sizeof(path) - len, "%s/events/%s.unit", pmu->name, alias->name);
fd = open(path, O_RDONLY);
if (fd == -1)
@ -364,7 +364,7 @@ perf_pmu__parse_per_pkg(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
if (!len)
return 0;
scnprintf(path + len, sizeof(path) - len, "%s/%s.per-pkg", pmu->name, alias->name);
scnprintf(path + len, sizeof(path) - len, "%s/events/%s.per-pkg", pmu->name, alias->name);
fd = open(path, O_RDONLY);
if (fd == -1)
@ -385,7 +385,7 @@ static int perf_pmu__parse_snapshot(struct perf_pmu *pmu, struct perf_pmu_alias
len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
if (!len)
return 0;
scnprintf(path + len, sizeof(path) - len, "%s/%s.snapshot", pmu->name, alias->name);
scnprintf(path + len, sizeof(path) - len, "%s/events/%s.snapshot", pmu->name, alias->name);
fd = open(path, O_RDONLY);
if (fd == -1)