2019-07-21 13:25:03 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2019-09-02 10:33:09 +02:00
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
2022-08-18 17:36:43 -07:00
|
|
|
#include <string.h>
|
2019-07-21 13:25:03 +02:00
|
|
|
#include <linux/perf_event.h>
|
2022-08-18 17:36:43 -07:00
|
|
|
#include <linux/kernel.h>
|
2019-07-21 13:25:03 +02:00
|
|
|
#include <perf/cpumap.h>
|
|
|
|
#include <perf/threadmap.h>
|
|
|
|
#include <perf/evsel.h>
|
2022-08-18 17:36:43 -07:00
|
|
|
#include <internal/evsel.h>
|
2019-07-21 13:25:03 +02:00
|
|
|
#include <internal/tests.h>
|
2021-07-06 17:16:58 +02:00
|
|
|
#include "tests.h"
|
2019-07-21 13:25:03 +02:00
|
|
|
|
2019-09-02 10:33:09 +02:00
|
|
|
static int libperf_print(enum libperf_print_level level,
|
|
|
|
const char *fmt, va_list ap)
|
|
|
|
{
|
|
|
|
return vfprintf(stderr, fmt, ap);
|
|
|
|
}
|
|
|
|
|
2019-07-21 13:25:03 +02:00
|
|
|
static int test_stat_cpu(void)
|
|
|
|
{
|
|
|
|
struct perf_cpu_map *cpus;
|
|
|
|
struct perf_evsel *evsel;
|
|
|
|
struct perf_event_attr attr = {
|
|
|
|
.type = PERF_TYPE_SOFTWARE,
|
|
|
|
.config = PERF_COUNT_SW_CPU_CLOCK,
|
|
|
|
};
|
2021-10-11 17:37:04 +09:00
|
|
|
int err, idx;
|
2019-07-21 13:25:03 +02:00
|
|
|
|
2023-11-28 22:02:01 -08:00
|
|
|
cpus = perf_cpu_map__new_online_cpus();
|
2019-07-21 13:25:03 +02:00
|
|
|
__T("failed to create cpus", cpus);
|
|
|
|
|
|
|
|
evsel = perf_evsel__new(&attr);
|
|
|
|
__T("failed to create evsel", evsel);
|
|
|
|
|
|
|
|
err = perf_evsel__open(evsel, cpus, NULL);
|
|
|
|
__T("failed to open evsel", err == 0);
|
|
|
|
|
2021-10-11 17:37:04 +09:00
|
|
|
for (idx = 0; idx < perf_cpu_map__nr(cpus); idx++) {
|
2019-07-21 13:25:03 +02:00
|
|
|
struct perf_counts_values counts = { .val = 0 };
|
|
|
|
|
2021-10-11 17:37:04 +09:00
|
|
|
perf_evsel__read(evsel, idx, 0, &counts);
|
2019-07-21 13:25:03 +02:00
|
|
|
__T("failed to read value for evsel", counts.val != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
perf_evsel__close(evsel);
|
|
|
|
perf_evsel__delete(evsel);
|
|
|
|
|
|
|
|
perf_cpu_map__put(cpus);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int test_stat_thread(void)
|
|
|
|
{
|
|
|
|
struct perf_counts_values counts = { .val = 0 };
|
|
|
|
struct perf_thread_map *threads;
|
|
|
|
struct perf_evsel *evsel;
|
|
|
|
struct perf_event_attr attr = {
|
|
|
|
.type = PERF_TYPE_SOFTWARE,
|
|
|
|
.config = PERF_COUNT_SW_TASK_CLOCK,
|
|
|
|
};
|
|
|
|
int err;
|
|
|
|
|
|
|
|
threads = perf_thread_map__new_dummy();
|
|
|
|
__T("failed to create threads", threads);
|
|
|
|
|
|
|
|
perf_thread_map__set_pid(threads, 0, 0);
|
|
|
|
|
|
|
|
evsel = perf_evsel__new(&attr);
|
|
|
|
__T("failed to create evsel", evsel);
|
|
|
|
|
|
|
|
err = perf_evsel__open(evsel, NULL, threads);
|
|
|
|
__T("failed to open evsel", err == 0);
|
|
|
|
|
|
|
|
perf_evsel__read(evsel, 0, 0, &counts);
|
|
|
|
__T("failed to read value for evsel", counts.val != 0);
|
|
|
|
|
|
|
|
perf_evsel__close(evsel);
|
|
|
|
perf_evsel__delete(evsel);
|
|
|
|
|
|
|
|
perf_thread_map__put(threads);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-07-21 13:25:05 +02:00
|
|
|
static int test_stat_thread_enable(void)
|
|
|
|
{
|
|
|
|
struct perf_counts_values counts = { .val = 0 };
|
|
|
|
struct perf_thread_map *threads;
|
|
|
|
struct perf_evsel *evsel;
|
|
|
|
struct perf_event_attr attr = {
|
|
|
|
.type = PERF_TYPE_SOFTWARE,
|
|
|
|
.config = PERF_COUNT_SW_TASK_CLOCK,
|
|
|
|
.disabled = 1,
|
|
|
|
};
|
|
|
|
int err;
|
|
|
|
|
|
|
|
threads = perf_thread_map__new_dummy();
|
|
|
|
__T("failed to create threads", threads);
|
|
|
|
|
|
|
|
perf_thread_map__set_pid(threads, 0, 0);
|
|
|
|
|
|
|
|
evsel = perf_evsel__new(&attr);
|
|
|
|
__T("failed to create evsel", evsel);
|
|
|
|
|
|
|
|
err = perf_evsel__open(evsel, NULL, threads);
|
|
|
|
__T("failed to open evsel", err == 0);
|
|
|
|
|
|
|
|
perf_evsel__read(evsel, 0, 0, &counts);
|
|
|
|
__T("failed to read value for evsel", counts.val == 0);
|
|
|
|
|
|
|
|
err = perf_evsel__enable(evsel);
|
|
|
|
__T("failed to enable evsel", err == 0);
|
|
|
|
|
|
|
|
perf_evsel__read(evsel, 0, 0, &counts);
|
|
|
|
__T("failed to read value for evsel", counts.val != 0);
|
|
|
|
|
|
|
|
err = perf_evsel__disable(evsel);
|
|
|
|
__T("failed to enable evsel", err == 0);
|
|
|
|
|
|
|
|
perf_evsel__close(evsel);
|
|
|
|
perf_evsel__delete(evsel);
|
|
|
|
|
|
|
|
perf_thread_map__put(threads);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
libperf: Add support for user space counter access
x86 and arm64 can both support direct access of event counters in
userspace. The access sequence is less than trivial and currently exists
in perf test code (tools/perf/arch/x86/tests/rdpmc.c) with copies in
projects such as PAPI and libpfm4.
In order to support userspace access, an event must be mmapped first
with perf_evsel__mmap(). Then subsequent calls to perf_evsel__read()
will use the fast path (assuming the arch supports it).
Committer notes:
Added a '__maybe_unused' attribute to the read_perf_counter() argument
to fix the build on arches other than x86_64 and arm.
Committer testing:
Building and running the libperf tests in verbose mode (V=1) now shows
those "loop = N, count = N" extra lines, testing user space counter
access.
# make V=1 -C tools/lib/perf tests
make: Entering directory '/home/acme/git/perf/tools/lib/perf'
make -f /home/acme/git/perf/tools/build/Makefile.build dir=. obj=libperf
make -C /home/acme/git/perf/tools/lib/api/ O= libapi.a
make -f /home/acme/git/perf/tools/build/Makefile.build dir=./fd obj=libapi
make -f /home/acme/git/perf/tools/build/Makefile.build dir=./fs obj=libapi
make -C tests
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-cpumap-a test-cpumap.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-threadmap-a test-threadmap.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-evlist-a test-evlist.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-evsel-a test-evsel.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-cpumap-so test-cpumap.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-threadmap-so test-threadmap.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-evlist-so test-evlist.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-evsel-so test-evsel.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
make -C tests run
running static:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...OK
- running test-evsel.c...
loop = 65536, count = 333926
loop = 131072, count = 655781
loop = 262144, count = 1311141
loop = 524288, count = 2630126
loop = 1048576, count = 5256955
loop = 65536, count = 524594
loop = 131072, count = 1058916
loop = 262144, count = 2097458
loop = 524288, count = 4205429
loop = 1048576, count = 8406606
OK
running dynamic:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...OK
- running test-evsel.c...
loop = 65536, count = 328102
loop = 131072, count = 655782
loop = 262144, count = 1317494
loop = 524288, count = 2627851
loop = 1048576, count = 5255187
loop = 65536, count = 524601
loop = 131072, count = 1048923
loop = 262144, count = 2107917
loop = 524288, count = 4194606
loop = 1048576, count = 8409322
OK
make: Leaving directory '/home/acme/git/perf/tools/lib/perf'
#
Signed-off-by: Rob Herring <robh@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Itaru Kitayama <itaru.kitayama@gmail.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will@kernel.org>
Link: http://lore.kernel.org/lkml/20210414155412.3697605-4-robh@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-04-14 11:07:39 -05:00
|
|
|
static int test_stat_user_read(int event)
|
|
|
|
{
|
|
|
|
struct perf_counts_values counts = { .val = 0 };
|
|
|
|
struct perf_thread_map *threads;
|
|
|
|
struct perf_evsel *evsel;
|
|
|
|
struct perf_event_mmap_page *pc;
|
|
|
|
struct perf_event_attr attr = {
|
|
|
|
.type = PERF_TYPE_HARDWARE,
|
|
|
|
.config = event,
|
2022-02-01 15:40:56 -06:00
|
|
|
#ifdef __aarch64__
|
|
|
|
.config1 = 0x2, /* Request user access */
|
|
|
|
#endif
|
libperf: Add support for user space counter access
x86 and arm64 can both support direct access of event counters in
userspace. The access sequence is less than trivial and currently exists
in perf test code (tools/perf/arch/x86/tests/rdpmc.c) with copies in
projects such as PAPI and libpfm4.
In order to support userspace access, an event must be mmapped first
with perf_evsel__mmap(). Then subsequent calls to perf_evsel__read()
will use the fast path (assuming the arch supports it).
Committer notes:
Added a '__maybe_unused' attribute to the read_perf_counter() argument
to fix the build on arches other than x86_64 and arm.
Committer testing:
Building and running the libperf tests in verbose mode (V=1) now shows
those "loop = N, count = N" extra lines, testing user space counter
access.
# make V=1 -C tools/lib/perf tests
make: Entering directory '/home/acme/git/perf/tools/lib/perf'
make -f /home/acme/git/perf/tools/build/Makefile.build dir=. obj=libperf
make -C /home/acme/git/perf/tools/lib/api/ O= libapi.a
make -f /home/acme/git/perf/tools/build/Makefile.build dir=./fd obj=libapi
make -f /home/acme/git/perf/tools/build/Makefile.build dir=./fs obj=libapi
make -C tests
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-cpumap-a test-cpumap.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-threadmap-a test-threadmap.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-evlist-a test-evlist.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-evsel-a test-evsel.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-cpumap-so test-cpumap.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-threadmap-so test-threadmap.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-evlist-so test-evlist.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-evsel-so test-evsel.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
make -C tests run
running static:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...OK
- running test-evsel.c...
loop = 65536, count = 333926
loop = 131072, count = 655781
loop = 262144, count = 1311141
loop = 524288, count = 2630126
loop = 1048576, count = 5256955
loop = 65536, count = 524594
loop = 131072, count = 1058916
loop = 262144, count = 2097458
loop = 524288, count = 4205429
loop = 1048576, count = 8406606
OK
running dynamic:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...OK
- running test-evsel.c...
loop = 65536, count = 328102
loop = 131072, count = 655782
loop = 262144, count = 1317494
loop = 524288, count = 2627851
loop = 1048576, count = 5255187
loop = 65536, count = 524601
loop = 131072, count = 1048923
loop = 262144, count = 2107917
loop = 524288, count = 4194606
loop = 1048576, count = 8409322
OK
make: Leaving directory '/home/acme/git/perf/tools/lib/perf'
#
Signed-off-by: Rob Herring <robh@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Itaru Kitayama <itaru.kitayama@gmail.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will@kernel.org>
Link: http://lore.kernel.org/lkml/20210414155412.3697605-4-robh@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-04-14 11:07:39 -05:00
|
|
|
};
|
|
|
|
int err, i;
|
|
|
|
|
|
|
|
threads = perf_thread_map__new_dummy();
|
|
|
|
__T("failed to create threads", threads);
|
|
|
|
|
|
|
|
perf_thread_map__set_pid(threads, 0, 0);
|
|
|
|
|
|
|
|
evsel = perf_evsel__new(&attr);
|
|
|
|
__T("failed to create evsel", evsel);
|
|
|
|
|
|
|
|
err = perf_evsel__open(evsel, NULL, threads);
|
|
|
|
__T("failed to open evsel", err == 0);
|
|
|
|
|
|
|
|
err = perf_evsel__mmap(evsel, 0);
|
|
|
|
__T("failed to mmap evsel", err == 0);
|
|
|
|
|
|
|
|
pc = perf_evsel__mmap_base(evsel, 0, 0);
|
2021-10-06 18:57:03 +09:00
|
|
|
__T("failed to get mmapped address", pc);
|
libperf: Add support for user space counter access
x86 and arm64 can both support direct access of event counters in
userspace. The access sequence is less than trivial and currently exists
in perf test code (tools/perf/arch/x86/tests/rdpmc.c) with copies in
projects such as PAPI and libpfm4.
In order to support userspace access, an event must be mmapped first
with perf_evsel__mmap(). Then subsequent calls to perf_evsel__read()
will use the fast path (assuming the arch supports it).
Committer notes:
Added a '__maybe_unused' attribute to the read_perf_counter() argument
to fix the build on arches other than x86_64 and arm.
Committer testing:
Building and running the libperf tests in verbose mode (V=1) now shows
those "loop = N, count = N" extra lines, testing user space counter
access.
# make V=1 -C tools/lib/perf tests
make: Entering directory '/home/acme/git/perf/tools/lib/perf'
make -f /home/acme/git/perf/tools/build/Makefile.build dir=. obj=libperf
make -C /home/acme/git/perf/tools/lib/api/ O= libapi.a
make -f /home/acme/git/perf/tools/build/Makefile.build dir=./fd obj=libapi
make -f /home/acme/git/perf/tools/build/Makefile.build dir=./fs obj=libapi
make -C tests
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-cpumap-a test-cpumap.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-threadmap-a test-threadmap.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-evlist-a test-evlist.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-evsel-a test-evsel.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-cpumap-so test-cpumap.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-threadmap-so test-threadmap.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-evlist-so test-evlist.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-evsel-so test-evsel.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
make -C tests run
running static:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...OK
- running test-evsel.c...
loop = 65536, count = 333926
loop = 131072, count = 655781
loop = 262144, count = 1311141
loop = 524288, count = 2630126
loop = 1048576, count = 5256955
loop = 65536, count = 524594
loop = 131072, count = 1058916
loop = 262144, count = 2097458
loop = 524288, count = 4205429
loop = 1048576, count = 8406606
OK
running dynamic:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...OK
- running test-evsel.c...
loop = 65536, count = 328102
loop = 131072, count = 655782
loop = 262144, count = 1317494
loop = 524288, count = 2627851
loop = 1048576, count = 5255187
loop = 65536, count = 524601
loop = 131072, count = 1048923
loop = 262144, count = 2107917
loop = 524288, count = 4194606
loop = 1048576, count = 8409322
OK
make: Leaving directory '/home/acme/git/perf/tools/lib/perf'
#
Signed-off-by: Rob Herring <robh@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Itaru Kitayama <itaru.kitayama@gmail.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will@kernel.org>
Link: http://lore.kernel.org/lkml/20210414155412.3697605-4-robh@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-04-14 11:07:39 -05:00
|
|
|
|
2022-02-01 15:40:56 -06:00
|
|
|
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
|
libperf: Add support for user space counter access
x86 and arm64 can both support direct access of event counters in
userspace. The access sequence is less than trivial and currently exists
in perf test code (tools/perf/arch/x86/tests/rdpmc.c) with copies in
projects such as PAPI and libpfm4.
In order to support userspace access, an event must be mmapped first
with perf_evsel__mmap(). Then subsequent calls to perf_evsel__read()
will use the fast path (assuming the arch supports it).
Committer notes:
Added a '__maybe_unused' attribute to the read_perf_counter() argument
to fix the build on arches other than x86_64 and arm.
Committer testing:
Building and running the libperf tests in verbose mode (V=1) now shows
those "loop = N, count = N" extra lines, testing user space counter
access.
# make V=1 -C tools/lib/perf tests
make: Entering directory '/home/acme/git/perf/tools/lib/perf'
make -f /home/acme/git/perf/tools/build/Makefile.build dir=. obj=libperf
make -C /home/acme/git/perf/tools/lib/api/ O= libapi.a
make -f /home/acme/git/perf/tools/build/Makefile.build dir=./fd obj=libapi
make -f /home/acme/git/perf/tools/build/Makefile.build dir=./fs obj=libapi
make -C tests
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-cpumap-a test-cpumap.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-threadmap-a test-threadmap.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-evlist-a test-evlist.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-evsel-a test-evsel.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-cpumap-so test-cpumap.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-threadmap-so test-threadmap.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-evlist-so test-evlist.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-evsel-so test-evsel.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
make -C tests run
running static:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...OK
- running test-evsel.c...
loop = 65536, count = 333926
loop = 131072, count = 655781
loop = 262144, count = 1311141
loop = 524288, count = 2630126
loop = 1048576, count = 5256955
loop = 65536, count = 524594
loop = 131072, count = 1058916
loop = 262144, count = 2097458
loop = 524288, count = 4205429
loop = 1048576, count = 8406606
OK
running dynamic:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...OK
- running test-evsel.c...
loop = 65536, count = 328102
loop = 131072, count = 655782
loop = 262144, count = 1317494
loop = 524288, count = 2627851
loop = 1048576, count = 5255187
loop = 65536, count = 524601
loop = 131072, count = 1048923
loop = 262144, count = 2107917
loop = 524288, count = 4194606
loop = 1048576, count = 8409322
OK
make: Leaving directory '/home/acme/git/perf/tools/lib/perf'
#
Signed-off-by: Rob Herring <robh@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Itaru Kitayama <itaru.kitayama@gmail.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will@kernel.org>
Link: http://lore.kernel.org/lkml/20210414155412.3697605-4-robh@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-04-14 11:07:39 -05:00
|
|
|
__T("userspace counter access not supported", pc->cap_user_rdpmc);
|
|
|
|
__T("userspace counter access not enabled", pc->index);
|
|
|
|
__T("userspace counter width not set", pc->pmc_width >= 32);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
perf_evsel__read(evsel, 0, 0, &counts);
|
|
|
|
__T("failed to read value for evsel", counts.val != 0);
|
|
|
|
|
|
|
|
for (i = 0; i < 5; i++) {
|
|
|
|
volatile int count = 0x10000 << i;
|
|
|
|
__u64 start, end, last = 0;
|
|
|
|
|
|
|
|
__T_VERBOSE("\tloop = %u, ", count);
|
|
|
|
|
|
|
|
perf_evsel__read(evsel, 0, 0, &counts);
|
|
|
|
start = counts.val;
|
|
|
|
|
|
|
|
while (count--) ;
|
|
|
|
|
|
|
|
perf_evsel__read(evsel, 0, 0, &counts);
|
|
|
|
end = counts.val;
|
|
|
|
|
|
|
|
__T("invalid counter data", (end - start) > last);
|
|
|
|
last = end - start;
|
|
|
|
__T_VERBOSE("count = %llu\n", end - start);
|
|
|
|
}
|
|
|
|
|
|
|
|
perf_evsel__munmap(evsel);
|
|
|
|
perf_evsel__close(evsel);
|
|
|
|
perf_evsel__delete(evsel);
|
|
|
|
|
|
|
|
perf_thread_map__put(threads);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-08-18 17:36:43 -07:00
|
|
|
static int test_stat_read_format_single(struct perf_event_attr *attr, struct perf_thread_map *threads)
|
|
|
|
{
|
|
|
|
struct perf_evsel *evsel;
|
|
|
|
struct perf_counts_values counts;
|
|
|
|
volatile int count = 0x100000;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
evsel = perf_evsel__new(attr);
|
|
|
|
__T("failed to create evsel", evsel);
|
|
|
|
|
|
|
|
/* skip old kernels that don't support the format */
|
|
|
|
err = perf_evsel__open(evsel, NULL, threads);
|
|
|
|
if (err < 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
while (count--) ;
|
|
|
|
|
|
|
|
memset(&counts, -1, sizeof(counts));
|
|
|
|
perf_evsel__read(evsel, 0, 0, &counts);
|
|
|
|
|
|
|
|
__T("failed to read value", counts.val);
|
|
|
|
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
|
|
|
|
__T("failed to read TOTAL_TIME_ENABLED", counts.ena);
|
|
|
|
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
|
|
|
|
__T("failed to read TOTAL_TIME_RUNNING", counts.run);
|
|
|
|
if (attr->read_format & PERF_FORMAT_ID)
|
|
|
|
__T("failed to read ID", counts.id);
|
|
|
|
if (attr->read_format & PERF_FORMAT_LOST)
|
|
|
|
__T("failed to read LOST", counts.lost == 0);
|
|
|
|
|
|
|
|
perf_evsel__close(evsel);
|
|
|
|
perf_evsel__delete(evsel);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int test_stat_read_format_group(struct perf_event_attr *attr, struct perf_thread_map *threads)
|
|
|
|
{
|
|
|
|
struct perf_evsel *leader, *member;
|
|
|
|
struct perf_counts_values counts;
|
|
|
|
volatile int count = 0x100000;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
attr->read_format |= PERF_FORMAT_GROUP;
|
|
|
|
leader = perf_evsel__new(attr);
|
|
|
|
__T("failed to create leader", leader);
|
|
|
|
|
|
|
|
attr->read_format &= ~PERF_FORMAT_GROUP;
|
|
|
|
member = perf_evsel__new(attr);
|
|
|
|
__T("failed to create member", member);
|
|
|
|
|
|
|
|
member->leader = leader;
|
|
|
|
leader->nr_members = 2;
|
|
|
|
|
|
|
|
/* skip old kernels that don't support the format */
|
|
|
|
err = perf_evsel__open(leader, NULL, threads);
|
|
|
|
if (err < 0)
|
|
|
|
return 0;
|
|
|
|
err = perf_evsel__open(member, NULL, threads);
|
|
|
|
if (err < 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
while (count--) ;
|
|
|
|
|
|
|
|
memset(&counts, -1, sizeof(counts));
|
|
|
|
perf_evsel__read(leader, 0, 0, &counts);
|
|
|
|
|
|
|
|
__T("failed to read leader value", counts.val);
|
|
|
|
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
|
|
|
|
__T("failed to read leader TOTAL_TIME_ENABLED", counts.ena);
|
|
|
|
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
|
|
|
|
__T("failed to read leader TOTAL_TIME_RUNNING", counts.run);
|
|
|
|
if (attr->read_format & PERF_FORMAT_ID)
|
|
|
|
__T("failed to read leader ID", counts.id);
|
|
|
|
if (attr->read_format & PERF_FORMAT_LOST)
|
|
|
|
__T("failed to read leader LOST", counts.lost == 0);
|
|
|
|
|
|
|
|
memset(&counts, -1, sizeof(counts));
|
|
|
|
perf_evsel__read(member, 0, 0, &counts);
|
|
|
|
|
|
|
|
__T("failed to read member value", counts.val);
|
|
|
|
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
|
|
|
|
__T("failed to read member TOTAL_TIME_ENABLED", counts.ena);
|
|
|
|
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
|
|
|
|
__T("failed to read member TOTAL_TIME_RUNNING", counts.run);
|
|
|
|
if (attr->read_format & PERF_FORMAT_ID)
|
|
|
|
__T("failed to read member ID", counts.id);
|
|
|
|
if (attr->read_format & PERF_FORMAT_LOST)
|
|
|
|
__T("failed to read member LOST", counts.lost == 0);
|
|
|
|
|
|
|
|
perf_evsel__close(member);
|
|
|
|
perf_evsel__close(leader);
|
|
|
|
perf_evsel__delete(member);
|
|
|
|
perf_evsel__delete(leader);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int test_stat_read_format(void)
|
|
|
|
{
|
|
|
|
struct perf_thread_map *threads;
|
|
|
|
struct perf_event_attr attr = {
|
|
|
|
.type = PERF_TYPE_SOFTWARE,
|
|
|
|
.config = PERF_COUNT_SW_TASK_CLOCK,
|
|
|
|
};
|
|
|
|
int err, i;
|
|
|
|
|
|
|
|
#define FMT(_fmt) PERF_FORMAT_ ## _fmt
|
|
|
|
#define FMT_TIME (FMT(TOTAL_TIME_ENABLED) | FMT(TOTAL_TIME_RUNNING))
|
|
|
|
|
|
|
|
uint64_t test_formats [] = {
|
|
|
|
0,
|
|
|
|
FMT_TIME,
|
|
|
|
FMT(ID),
|
|
|
|
FMT(LOST),
|
|
|
|
FMT_TIME | FMT(ID),
|
|
|
|
FMT_TIME | FMT(LOST),
|
|
|
|
FMT_TIME | FMT(ID) | FMT(LOST),
|
|
|
|
FMT(ID) | FMT(LOST),
|
|
|
|
};
|
|
|
|
|
|
|
|
#undef FMT
|
|
|
|
#undef FMT_TIME
|
|
|
|
|
|
|
|
threads = perf_thread_map__new_dummy();
|
|
|
|
__T("failed to create threads", threads);
|
|
|
|
|
|
|
|
perf_thread_map__set_pid(threads, 0, 0);
|
|
|
|
|
|
|
|
for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) {
|
|
|
|
attr.read_format = test_formats[i];
|
|
|
|
__T_VERBOSE("testing single read with read_format: %lx\n",
|
|
|
|
(unsigned long)test_formats[i]);
|
|
|
|
|
|
|
|
err = test_stat_read_format_single(&attr, threads);
|
|
|
|
__T("failed to read single format", err == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
perf_thread_map__put(threads);
|
|
|
|
|
|
|
|
threads = perf_thread_map__new_array(2, NULL);
|
|
|
|
__T("failed to create threads", threads);
|
|
|
|
|
|
|
|
perf_thread_map__set_pid(threads, 0, 0);
|
|
|
|
perf_thread_map__set_pid(threads, 1, 0);
|
|
|
|
|
|
|
|
for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) {
|
|
|
|
attr.read_format = test_formats[i];
|
|
|
|
__T_VERBOSE("testing group read with read_format: %lx\n",
|
|
|
|
(unsigned long)test_formats[i]);
|
|
|
|
|
|
|
|
err = test_stat_read_format_group(&attr, threads);
|
|
|
|
__T("failed to read group format", err == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
perf_thread_map__put(threads);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:16:58 +02:00
|
|
|
int test_evsel(int argc, char **argv)
|
2019-07-21 13:25:03 +02:00
|
|
|
{
|
|
|
|
__T_START;
|
|
|
|
|
2019-09-02 10:33:09 +02:00
|
|
|
libperf_init(libperf_print);
|
|
|
|
|
2019-07-21 13:25:03 +02:00
|
|
|
test_stat_cpu();
|
|
|
|
test_stat_thread();
|
2019-07-21 13:25:05 +02:00
|
|
|
test_stat_thread_enable();
|
libperf: Add support for user space counter access
x86 and arm64 can both support direct access of event counters in
userspace. The access sequence is less than trivial and currently exists
in perf test code (tools/perf/arch/x86/tests/rdpmc.c) with copies in
projects such as PAPI and libpfm4.
In order to support userspace access, an event must be mmapped first
with perf_evsel__mmap(). Then subsequent calls to perf_evsel__read()
will use the fast path (assuming the arch supports it).
Committer notes:
Added a '__maybe_unused' attribute to the read_perf_counter() argument
to fix the build on arches other than x86_64 and arm.
Committer testing:
Building and running the libperf tests in verbose mode (V=1) now shows
those "loop = N, count = N" extra lines, testing user space counter
access.
# make V=1 -C tools/lib/perf tests
make: Entering directory '/home/acme/git/perf/tools/lib/perf'
make -f /home/acme/git/perf/tools/build/Makefile.build dir=. obj=libperf
make -C /home/acme/git/perf/tools/lib/api/ O= libapi.a
make -f /home/acme/git/perf/tools/build/Makefile.build dir=./fd obj=libapi
make -f /home/acme/git/perf/tools/build/Makefile.build dir=./fs obj=libapi
make -C tests
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-cpumap-a test-cpumap.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-threadmap-a test-threadmap.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-evlist-a test-evlist.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -o test-evsel-a test-evsel.c ../libperf.a /home/acme/git/perf/tools/lib/api/libapi.a
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-cpumap-so test-cpumap.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-threadmap-so test-threadmap.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-evlist-so test-evlist.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
gcc -I/home/acme/git/perf/tools/lib/perf/include -I/home/acme/git/perf/tools/include -I/home/acme/git/perf/tools/lib -g -Wall -L.. -o test-evsel-so test-evsel.c /home/acme/git/perf/tools/lib/api/libapi.a -lperf
make -C tests run
running static:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...OK
- running test-evsel.c...
loop = 65536, count = 333926
loop = 131072, count = 655781
loop = 262144, count = 1311141
loop = 524288, count = 2630126
loop = 1048576, count = 5256955
loop = 65536, count = 524594
loop = 131072, count = 1058916
loop = 262144, count = 2097458
loop = 524288, count = 4205429
loop = 1048576, count = 8406606
OK
running dynamic:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...OK
- running test-evsel.c...
loop = 65536, count = 328102
loop = 131072, count = 655782
loop = 262144, count = 1317494
loop = 524288, count = 2627851
loop = 1048576, count = 5255187
loop = 65536, count = 524601
loop = 131072, count = 1048923
loop = 262144, count = 2107917
loop = 524288, count = 4194606
loop = 1048576, count = 8409322
OK
make: Leaving directory '/home/acme/git/perf/tools/lib/perf'
#
Signed-off-by: Rob Herring <robh@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Itaru Kitayama <itaru.kitayama@gmail.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will@kernel.org>
Link: http://lore.kernel.org/lkml/20210414155412.3697605-4-robh@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-04-14 11:07:39 -05:00
|
|
|
test_stat_user_read(PERF_COUNT_HW_INSTRUCTIONS);
|
|
|
|
test_stat_user_read(PERF_COUNT_HW_CPU_CYCLES);
|
2022-08-18 17:36:43 -07:00
|
|
|
test_stat_read_format();
|
2019-07-21 13:25:03 +02:00
|
|
|
|
2019-10-17 12:59:16 +02:00
|
|
|
__T_END;
|
2021-01-14 10:02:49 -08:00
|
|
|
return tests_failed == 0 ? 0 : -1;
|
2019-07-21 13:25:03 +02:00
|
|
|
}
|