101 lines
3.9 KiB
Diff
101 lines
3.9 KiB
Diff
From 841bfb4641f4cbad16a3aeb07fa462dcd4449cac Mon Sep 17 00:00:00 2001
|
|
From: IZUMI-Zu <binshuo.oerv@isrc.iscas.ac.cn>
|
|
Date: Fri, 23 Aug 2024 00:00:12 +0800
|
|
Subject: [PATCH] RISC-V: use RDTIME for cycle timer and disable __builtin_readcyclecounter
|
|
|
|
This commit backports and extends the fixes from MariaDB/server PRs #1981
|
|
and #2980 to address the RISC-V RDCYCLE privileged instruction issue.
|
|
|
|
Key changes:
|
|
1. Use RDTIME instead of RDCYCLE for cycle timer on RISC-V
|
|
2. Disable __builtin_readcyclecounter() for RISC-V as LLVM generates RDCYCLE
|
|
|
|
Starting with Linux 6.6 [1], RDCYCLE is a privileged instruction on RISC-V and can't be used directly from userland.
|
|
There is a sysctl option to change that as a transition period, but it will eventually disappear.
|
|
|
|
Use RDTIME instead, which while less accurate has the advantage of being synchronized between CPU (and thus monotonic)
|
|
and of constant frequency.
|
|
|
|
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cc4c07c89aada16229084eeb93895c95b7eabaa3
|
|
|
|
Backported-from: https://github.com/MariaDB/server/pull/1981
|
|
https://github.com/MariaDB/server/pull/2980
|
|
---
|
|
include/my_rdtsc.h | 26 +++++++++++++++++++++++++-
|
|
mysys/my_rdtsc.c | 2 ++
|
|
2 files changed, 27 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/include/my_rdtsc.h b/include/my_rdtsc.h
|
|
index e8101516..880625fa 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
|
|
guaranteed to be active.
|
|
+ On RISC-V, we use the rdtime instruction to read from mtime register.
|
|
|
|
Sadly, we have nothing for the Digital Alpha, MIPS, Motorola m68k,
|
|
HP PA-RISC or other non-mainstream (or obsolete) processors.
|
|
@@ -128,7 +129,7 @@ C_MODE_START
|
|
*/
|
|
static inline ulonglong my_timer_cycles(void)
|
|
{
|
|
-# if __has_builtin(__builtin_readcyclecounter) && !defined (__aarch64__)
|
|
+# if __has_builtin(__builtin_readcyclecounter) && !defined(__aarch64__) && !defined(__riscv)
|
|
return __builtin_readcyclecounter();
|
|
# elif defined _WIN32 || defined __i386__ || defined __x86_64__
|
|
return __rdtsc();
|
|
@@ -173,6 +174,28 @@ static inline ulonglong my_timer_cycles(void)
|
|
__asm __volatile("mrs %0, CNTVCT_EL0" : "=&r" (result));
|
|
return result;
|
|
}
|
|
+#elif defined(__riscv)
|
|
+ /* Use RDTIME (and RDTIMEH on riscv32) */
|
|
+ {
|
|
+# if __riscv_xlen == 32
|
|
+ ulong result_lo, result_hi0, result_hi1;
|
|
+ /* Implemented in assembly because Clang insisted on branching. */
|
|
+ __asm __volatile__(
|
|
+ "rdtimeh %0\n"
|
|
+ "rdtime %1\n"
|
|
+ "rdtimeh %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__("rdtime %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();
|
|
@@ -231,6 +254,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 1503a5db..ffd81602 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
|
|
--
|
|
2.46.0
|