libperf: Implement riscv mmap support
authorAlexandre Ghiti <alexghiti@rivosinc.com>
Wed, 2 Aug 2023 08:03:27 +0000 (10:03 +0200)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 16 Aug 2023 11:52:47 +0000 (08:52 -0300)
riscv now supports mmaping hardware counters so add what's needed to
take advantage of that in libperf.

Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Anup Patel <anup@brainfault.org>
Cc: Atish Patra <atishp@atishpatra.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Paul Walmsley <paul.walmsley@sifive.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rob Herring <robh@kernel.org>
Cc: RĂ©mi Denis-Courmont <remi@remlab.net>
Cc: Will Deacon <will@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-doc@vger.kernel.org
Cc: linux-riscv@lists.infradead.org
Link: https://lore.kernel.org/r/20230802080328.1213905-10-alexghiti@rivosinc.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/lib/perf/mmap.c

index 0d1634c..2184814 100644 (file)
@@ -392,6 +392,72 @@ static u64 read_perf_counter(unsigned int counter)
 
 static u64 read_timestamp(void) { return read_sysreg(cntvct_el0); }
 
+/* __riscv_xlen contains the witdh of the native base integer, here 64-bit */
+#elif defined(__riscv) && __riscv_xlen == 64
+
+/* TODO: implement rv32 support */
+
+#define CSR_CYCLE      0xc00
+#define CSR_TIME       0xc01
+
+#define csr_read(csr)                                          \
+({                                                             \
+       register unsigned long __v;                             \
+               __asm__ __volatile__ ("csrr %0, %1"             \
+                : "=r" (__v)                                   \
+                : "i" (csr) : );                               \
+                __v;                                           \
+})
+
+static unsigned long csr_read_num(int csr_num)
+{
+#define switchcase_csr_read(__csr_num, __val)           {\
+       case __csr_num:                                 \
+               __val = csr_read(__csr_num);            \
+               break; }
+#define switchcase_csr_read_2(__csr_num, __val)         {\
+       switchcase_csr_read(__csr_num + 0, __val)        \
+       switchcase_csr_read(__csr_num + 1, __val)}
+#define switchcase_csr_read_4(__csr_num, __val)         {\
+       switchcase_csr_read_2(__csr_num + 0, __val)      \
+       switchcase_csr_read_2(__csr_num + 2, __val)}
+#define switchcase_csr_read_8(__csr_num, __val)         {\
+       switchcase_csr_read_4(__csr_num + 0, __val)      \
+       switchcase_csr_read_4(__csr_num + 4, __val)}
+#define switchcase_csr_read_16(__csr_num, __val)        {\
+       switchcase_csr_read_8(__csr_num + 0, __val)      \
+       switchcase_csr_read_8(__csr_num + 8, __val)}
+#define switchcase_csr_read_32(__csr_num, __val)        {\
+       switchcase_csr_read_16(__csr_num + 0, __val)     \
+       switchcase_csr_read_16(__csr_num + 16, __val)}
+
+       unsigned long ret = 0;
+
+       switch (csr_num) {
+       switchcase_csr_read_32(CSR_CYCLE, ret)
+       default:
+               break;
+       }
+
+       return ret;
+#undef switchcase_csr_read_32
+#undef switchcase_csr_read_16
+#undef switchcase_csr_read_8
+#undef switchcase_csr_read_4
+#undef switchcase_csr_read_2
+#undef switchcase_csr_read
+}
+
+static u64 read_perf_counter(unsigned int counter)
+{
+       return csr_read_num(CSR_CYCLE + counter);
+}
+
+static u64 read_timestamp(void)
+{
+       return csr_read_num(CSR_TIME);
+}
+
 #else
 static u64 read_perf_counter(unsigned int counter __maybe_unused) { return 0; }
 static u64 read_timestamp(void) { return 0; }