Use inline asm to read cntvct_el0 to accommodate GCC

The safer instrinsics-based pattern isn't GCC-compatible, because GCC
added the intrisc some 8 years later than Clang did.

Bug: 440670941
Change-Id: I3db3ef2393b21aae8427457a3c26b62993b75eaa
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/81607
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
diff --git a/crypto/fipsmodule/entropy/jitter.cc.inc b/crypto/fipsmodule/entropy/jitter.cc.inc
index bc7ed26..af9993b 100644
--- a/crypto/fipsmodule/entropy/jitter.cc.inc
+++ b/crypto/fipsmodule/entropy/jitter.cc.inc
@@ -37,8 +37,6 @@
 
 #if defined(__x86_64__)
 #include <x86intrin.h>
-#elif defined(__aarch64__)
-#include <arm_acle.h>
 #endif
 
 
@@ -49,7 +47,15 @@
 #if defined(__x86_64__)
 static inline uint64_t GetTimestamp() { return _rdtsc(); }
 #elif defined(__aarch64__)
-static inline uint64_t GetTimestamp() { return __arm_rsr64("cntvct_el0"); }
+static inline uint64_t GetTimestamp() {
+  // Ideally this would use __arm_rsr64 from <arm_acle.h>. Clang has supported
+  // it Clang 3.7 (2016), but GCC did not add it until GCC 14.1.0 (2024). See
+  // https://crbug.com/440670941. When our minimum GCC is past that point,
+  // switch this back to __arm_rsr64.
+  uint64_t ret;
+  __asm__ volatile("mrs %0, cntvct_el0" : "=r"(ret));
+  return ret;
+}
 #else
 static inline uint64_t GetTimestamp() {
   struct timespec ts;