Skip to content

Commit

Permalink
MDEV-27429: Support RISC-V cycle timer
Browse files Browse the repository at this point in the history
Adapted from google/benchmark#833
authored by Sam Elliot at lowRISC.

This requires the RISCV kernel to set the CY bit of the mcountern register
which is done on Linux, but documenting here in case another OS hits
a SIGILL here.

When CY bit of the mcounteren register is unset, reading the cycle register
will cause illegal instruction exception in the next privilege level ( user
mode or supervisor mode ). See the privileged isa manual section 3.1.11 in
https://github.com/riscv/riscv-isa-manual/releases/latest
  • Loading branch information
alexfanqi authored and grooverdan committed Jan 5, 2022
1 parent b0d632a commit c0fd8fd
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 0 deletions.
24 changes: 24 additions & 0 deletions include/my_rdtsc.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ C_MODE_START
On AARCH64, we use the generic timer base register. We override clang
implementation for aarch64 as it access a PMU register which is not
guarenteed to be active.
On RISC-V, we use the rdcycle instruction to read from mcycle register.
Sadly, we have nothing for the Digital Alpha, MIPS, Motorola m68k,
HP PA-RISC or other non-mainstream (or obsolete) processors.
Expand Down Expand Up @@ -175,6 +176,28 @@ static inline ulonglong my_timer_cycles(void)
__asm __volatile("mrs %0, CNTVCT_EL0" : "=&r" (result));
return result;
}
#elif defined(__riscv)
/* Use RDCYCLE (and RDCYCLEH on riscv32) */
{
# if __riscv_xlen == 32
ulong result_lo, result_hi0, result_hi1;
/* Implemented in assembly because Clang insisted on branching. */
__asm __volatile__(
"rdcycleh %0\n"
"rdcycle %1\n"
"rdcycleh %2\n"
"sub %0, %0, %2\n"
"seqz %0, %0\n"
"sub %0, zero, %0\n"
"and %1, %1, %0\n"
: "=r"(result_hi0), "=r"(result_lo), "=r"(result_hi1));
return (static_cast<ulonglong>(result_hi1) << 32) | result_lo;
# else
ulonglong result;
__asm __volatile__("rdcycle %0" : "=r"(result));
return result;
}
# endif
#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME)
/* gethrtime may appear as either cycle or nanosecond counter */
return (ulonglong) gethrtime();
Expand Down Expand Up @@ -233,6 +256,7 @@ C_MODE_END
#define MY_TIMER_ROUTINE_GETSYSTEMTIMEASFILETIME 26
#define MY_TIMER_ROUTINE_ASM_S390 28
#define MY_TIMER_ROUTINE_AARCH64 29
#define MY_TIMER_ROUTINE_RISCV 30

#endif

2 changes: 2 additions & 0 deletions mysys/my_rdtsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,8 @@ void my_timer_init(MY_TIMER_INFO *mti)
mti->cycles.routine= MY_TIMER_ROUTINE_ASM_S390;
#elif defined(__GNUC__) && defined (__aarch64__)
mti->cycles.routine= MY_TIMER_ROUTINE_AARCH64;
#elif defined(__GNUC__) && defined (__riscv)
mti->cycles.routine= MY_TIMER_ROUTINE_RISCV;
#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME)
mti->cycles.routine= MY_TIMER_ROUTINE_GETHRTIME;
#else
Expand Down

0 comments on commit c0fd8fd

Please sign in to comment.