From: Tan En De <ende.tan@xxxxxxxxxxxxxxxx> This commit is to support running oslat on riscv. Ported frc() to use rdcycle instruction to get CPU cycles. NOTE: Run this before running oslat on riscv. echo 2 > /proc/sys/kernel/perf_user_access See https://docs.kernel.org/admin-guide/sysctl/kernel.html#riscv Signed-off-by: Tan En De <ende.tan@xxxxxxxxxxxxxxxx> --- src/oslat/oslat.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/oslat/oslat.c b/src/oslat/oslat.c index 0863297..460f102 100644 --- a/src/oslat/oslat.c +++ b/src/oslat/oslat.c @@ -43,6 +43,11 @@ #include <linux/unistd.h> +#ifdef __riscv +#include <linux/perf_event.h> +#include <sys/ioctl.h> +#endif + #include "rt-utils.h" #include "rt-numa.h" #include "rt-error.h" @@ -101,6 +106,24 @@ static inline void frc(uint64_t *pval) __asm__ __volatile__("isb" : : : "memory"); } +#elif defined(__riscv) +#define relax() __asm__ __volatile__("nop") + +static long perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu, + int group_fd, unsigned long flags) +{ + return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags); +} + +/* + * NOTE: Due to the use of rdcycle instruction, before running oslat, + * Please run this command first: + * echo 2 > /proc/sys/kernel/perf_user_access + */ +static inline void frc(uint64_t *pval) +{ + asm volatile("rdcycle %0" : "=r" (*pval)); +} # else # define relax() do { } while (0) # define frc(x) @@ -176,6 +199,11 @@ struct thread { /* These variables are calculated after the test */ double average; + +#ifdef __riscv + /* File descriptor for cycles perf event */ + int fd_cycles; +#endif }; struct global { @@ -299,6 +327,26 @@ static unsigned int measure_counter_mhz(void) static void thread_init(struct thread *t) { +#ifdef __riscv + struct perf_event_attr pe_cycles; + int fd_cycles; + + memset(&pe_cycles, 0, sizeof(pe_cycles)); + pe_cycles.type = PERF_TYPE_HARDWARE; + pe_cycles.size = sizeof(pe_cycles); + pe_cycles.config = PERF_COUNT_HW_CPU_CYCLES; + pe_cycles.disabled = 1; + + fd_cycles = perf_event_open(&pe_cycles, 0, -1, -1, 0); + if (fd_cycles == -1) { + fprintf(stderr, "Error opening leader %#llx\n", pe_cycles.config); + exit(EXIT_FAILURE); + } + t->fd_cycles = fd_cycles; + + ioctl(fd_cycles, PERF_EVENT_IOC_ENABLE, 0); +#endif + t->counter_mhz = measure_counter_mhz(); t->maxlat = 0; t->overflow_sum = 0; @@ -449,6 +497,11 @@ static void *thread_main(void *arg) while (g.n_threads_finished != g.n_threads) relax(); +#ifdef __riscv + ioctl(t->fd_cycles, PERF_EVENT_IOC_DISABLE, 0); + close(t->fd_cycles); +#endif + return NULL; } -- 2.34.1