summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralexfanqi <alex.fan.q@gmail.com>2022-01-04 13:59:59 +1100
committerDaniel Black <daniel@mariadb.org>2022-01-06 10:36:55 +1100
commitd18f6f263119b9d2f533373fb5130d9043a8f904 (patch)
tree2d183b30f52c02963855a7257778450cc7ffb765
parentb0d632a8409364e5a539a75e06fb994037ebde36 (diff)
downloadmariadb-git-d18f6f263119b9d2f533373fb5130d9043a8f904.tar.gz
MDEV-27429: Support RISC-V cycle timer
Adapted from https://github.com/google/benchmark/pull/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
-rw-r--r--include/my_rdtsc.h24
-rw-r--r--mysys/my_rdtsc.c2
2 files changed, 26 insertions, 0 deletions
diff --git a/include/my_rdtsc.h b/include/my_rdtsc.h
index 5a6f4a87012..10b69567336 100644
--- a/include/my_rdtsc.h
+++ b/include/my_rdtsc.h
@@ -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.
@@ -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();
@@ -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
diff --git a/mysys/my_rdtsc.c b/mysys/my_rdtsc.c
index 1503a5db442..ffd816024e5 100644
--- a/mysys/my_rdtsc.c
+++ b/mysys/my_rdtsc.c
@@ -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