Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libperf: Add arm64 support to perf_mmap__read_self()

Add the arm64 variants for read_perf_counter() and read_timestamp().
Unfortunately the counter number is encoded into the instruction, so the
code is a bit verbose to enumerate all possible counters.

Tested-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
Signed-off-by: Rob Herring <robh@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Tested-by: John Garry <john.garry@huawei.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: https://lore.kernel.org/r/20220201214056.702854-1-robh@kernel.org
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Will Deacon <will@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: linux-kernel@vger.kernel.org
Cc: linux-perf-users@vger.kernel.org

authored by

Rob Herring and committed by
Arnaldo Carvalho de Melo
407eb43a 4f249273

+102 -1
+98
tools/lib/perf/mmap.c
··· 13 13 #include <internal/lib.h> 14 14 #include <linux/kernel.h> 15 15 #include <linux/math64.h> 16 + #include <linux/stringify.h> 16 17 #include "internal.h" 17 18 18 19 void perf_mmap__init(struct perf_mmap *map, struct perf_mmap *prev, ··· 295 294 296 295 return low | ((u64)high) << 32; 297 296 } 297 + #elif defined(__aarch64__) 298 + #define read_sysreg(r) ({ \ 299 + u64 __val; \ 300 + asm volatile("mrs %0, " __stringify(r) : "=r" (__val)); \ 301 + __val; \ 302 + }) 303 + 304 + static u64 read_pmccntr(void) 305 + { 306 + return read_sysreg(pmccntr_el0); 307 + } 308 + 309 + #define PMEVCNTR_READ(idx) \ 310 + static u64 read_pmevcntr_##idx(void) { \ 311 + return read_sysreg(pmevcntr##idx##_el0); \ 312 + } 313 + 314 + PMEVCNTR_READ(0); 315 + PMEVCNTR_READ(1); 316 + PMEVCNTR_READ(2); 317 + PMEVCNTR_READ(3); 318 + PMEVCNTR_READ(4); 319 + PMEVCNTR_READ(5); 320 + PMEVCNTR_READ(6); 321 + PMEVCNTR_READ(7); 322 + PMEVCNTR_READ(8); 323 + PMEVCNTR_READ(9); 324 + PMEVCNTR_READ(10); 325 + PMEVCNTR_READ(11); 326 + PMEVCNTR_READ(12); 327 + PMEVCNTR_READ(13); 328 + PMEVCNTR_READ(14); 329 + PMEVCNTR_READ(15); 330 + PMEVCNTR_READ(16); 331 + PMEVCNTR_READ(17); 332 + PMEVCNTR_READ(18); 333 + PMEVCNTR_READ(19); 334 + PMEVCNTR_READ(20); 335 + PMEVCNTR_READ(21); 336 + PMEVCNTR_READ(22); 337 + PMEVCNTR_READ(23); 338 + PMEVCNTR_READ(24); 339 + PMEVCNTR_READ(25); 340 + PMEVCNTR_READ(26); 341 + PMEVCNTR_READ(27); 342 + PMEVCNTR_READ(28); 343 + PMEVCNTR_READ(29); 344 + PMEVCNTR_READ(30); 345 + 346 + /* 347 + * Read a value direct from PMEVCNTR<idx> 348 + */ 349 + static u64 read_perf_counter(unsigned int counter) 350 + { 351 + static u64 (* const read_f[])(void) = { 352 + read_pmevcntr_0, 353 + read_pmevcntr_1, 354 + read_pmevcntr_2, 355 + read_pmevcntr_3, 356 + read_pmevcntr_4, 357 + read_pmevcntr_5, 358 + read_pmevcntr_6, 359 + read_pmevcntr_7, 360 + read_pmevcntr_8, 361 + read_pmevcntr_9, 362 + read_pmevcntr_10, 363 + read_pmevcntr_11, 364 + read_pmevcntr_13, 365 + read_pmevcntr_12, 366 + read_pmevcntr_14, 367 + read_pmevcntr_15, 368 + read_pmevcntr_16, 369 + read_pmevcntr_17, 370 + read_pmevcntr_18, 371 + read_pmevcntr_19, 372 + read_pmevcntr_20, 373 + read_pmevcntr_21, 374 + read_pmevcntr_22, 375 + read_pmevcntr_23, 376 + read_pmevcntr_24, 377 + read_pmevcntr_25, 378 + read_pmevcntr_26, 379 + read_pmevcntr_27, 380 + read_pmevcntr_28, 381 + read_pmevcntr_29, 382 + read_pmevcntr_30, 383 + read_pmccntr 384 + }; 385 + 386 + if (counter < ARRAY_SIZE(read_f)) 387 + return (read_f[counter])(); 388 + 389 + return 0; 390 + } 391 + 392 + static u64 read_timestamp(void) { return read_sysreg(cntvct_el0); } 393 + 298 394 #else 299 395 static u64 read_perf_counter(unsigned int counter __maybe_unused) { return 0; } 300 396 static u64 read_timestamp(void) { return 0; }
+4 -1
tools/lib/perf/tests/test-evsel.c
··· 130 130 struct perf_event_attr attr = { 131 131 .type = PERF_TYPE_HARDWARE, 132 132 .config = event, 133 + #ifdef __aarch64__ 134 + .config1 = 0x2, /* Request user access */ 135 + #endif 133 136 }; 134 137 int err, i; 135 138 ··· 153 150 pc = perf_evsel__mmap_base(evsel, 0, 0); 154 151 __T("failed to get mmapped address", pc); 155 152 156 - #if defined(__i386__) || defined(__x86_64__) 153 + #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) 157 154 __T("userspace counter access not supported", pc->cap_user_rdpmc); 158 155 __T("userspace counter access not enabled", pc->index); 159 156 __T("userspace counter width not set", pc->pmc_width >= 32);