@@ -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;
}