summaryrefslogtreecommitdiff
path: root/0009-Get-CPU-cycles-on-RISC-V.patch
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2024-08-15 02:12:35 +0000
committerCoprDistGit <infra@openeuler.org>2024-08-15 02:12:35 +0000
commitc8b7d4c0da0ad5a112a5108256cf100dab067c0b (patch)
treec7a557e7cf6d53256bed0e4c4775666d55af7e4c /0009-Get-CPU-cycles-on-RISC-V.patch
parent8dc494bd8fd232458f8945b3ba64769dddbd44d9 (diff)
automatic import of perftestopeneuler24.03_LTS
Diffstat (limited to '0009-Get-CPU-cycles-on-RISC-V.patch')
-rw-r--r--0009-Get-CPU-cycles-on-RISC-V.patch116
1 files changed, 116 insertions, 0 deletions
diff --git a/0009-Get-CPU-cycles-on-RISC-V.patch b/0009-Get-CPU-cycles-on-RISC-V.patch
new file mode 100644
index 0000000..1137b45
--- /dev/null
+++ b/0009-Get-CPU-cycles-on-RISC-V.patch
@@ -0,0 +1,116 @@
+From df20eb17a10aa4c930887c92a4d5a3832402a096 Mon Sep 17 00:00:00 2001
+From: "v.v.mitrofanov" <v.v.mitrofanov@yadro.com>
+Date: Mon, 31 Jan 2022 13:41:30 +0300
+Subject: [PATCH 2/2] Get CPU cycles on RISC-V
+
+This test acquires CPU cycles to perform output calculations
+and get timestamps. There is no cpu_cycles() implementation on RISC-V arch.
+
+This patch gets cycles using perf events.
+One of the most notable reasons to use perf event instead of
+reading counter registers is to avoid modifying MUCOUNTEREN
+register. Due to the RISC-V ISA specification (riscv-privileged-v1.9)
+before getting any access to counter registers it is necessary to enable it in MUCOUNTEREN in a privileged mode. On the other hand,
+perf events are free to use.
+
+This patch is tested on the SiFive HiFive Unmatched board.
+
+Signed-off-by: v.v.mitrofanov <v.v.mitrofanov@yadro.com>
+---
+ src/get_clock.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++
+ src/get_clock.h | 9 +++++++
+ 2 files changed, 71 insertions(+)
+
+diff --git a/src/get_clock.c b/src/get_clock.c
+index 78ad865..c6adbdc 100755
+--- a/src/get_clock.c
++++ b/src/get_clock.c
+@@ -237,3 +237,65 @@ double get_cpu_mhz(int no_cpu_freq_warn)
+ return proc;
+ #endif
+ }
++
++#if defined(__riscv)
++#include <stdlib.h>
++#include <stdio.h>
++#include <unistd.h>
++#include <string.h>
++#include <sys/syscall.h>
++#include <linux/perf_event.h>
++#include <asm/unistd.h>
++
++static long perf_event_open(struct perf_event_attr *hw_event,
++ pid_t pid, int cpu, int group_fd,
++ unsigned long flags)
++{
++ return syscall(__NR_perf_event_open, hw_event, pid,
++ cpu, group_fd, flags);
++}
++
++cycles_t perf_get_cycles()
++{
++ cycles_t cycles = 0;
++ struct perf_event_attr pe;
++ const pid_t pid = 0; // Current task
++ const int cpu = -1; // On any CPU
++ const int group_fd = -1; // Use leader group
++ const unsigned long flags = 0;
++ /* Use this variable just to open perf event here and once.
++ It is appropriate because it touches only this function and
++ not fix other code */
++ static int is_open = 0;
++ /* Make file discriptor static just to keep it valid during
++ programm execution. It will be closed automatically when
++ test finishes. It is a hack just not to fix other part of test */
++ static int fd = -1;
++
++ if (!is_open) {
++ memset(&pe, 0, sizeof(pe));
++
++ pe.type = PERF_TYPE_HARDWARE;
++ pe.size = sizeof(pe);
++ pe.config = PERF_COUNT_HW_CPU_CYCLES;
++ pe.disabled = 0;
++ pe.exclude_kernel = 0;
++ pe.exclude_hv = 0;
++
++ fd = perf_event_open(&pe, pid, cpu, group_fd, flags);
++ if (fd == -1) {
++ fprintf(stderr, "Error opening perf event (%llx)\n", pe.config);
++ exit(EXIT_FAILURE);
++ }
++
++ is_open = 1;
++ }
++
++ if(read(fd, &cycles, sizeof(cycles)) < 0) {
++ fprintf(stderr, "Error reading perf event (%llx)\n", pe.config);
++ exit(EXIT_FAILURE);
++ }
++
++ return cycles;
++}
++#endif
+diff --git a/src/get_clock.h b/src/get_clock.h
+index dacbcd0..97c3500 100755
+--- a/src/get_clock.h
++++ b/src/get_clock.h
+@@ -104,6 +104,15 @@ static inline cycles_t get_cycles()
+ asm volatile("mrs %0, cntvct_el0" : "=r" (cval));
+ return cval;
+ }
++#elif defined(__riscv)
++typedef unsigned long cycles_t;
++
++cycles_t perf_get_cycles();
++
++static inline cycles_t get_cycles()
++{
++ return perf_get_cycles();
++}
+
+ #elif defined(__loongarch64)
+ typedef unsigned long cycles_t;
+--
+2.40.1
+