From 15f51f7fcd6a65eeaea27e49cd70cd75bde6e35d Mon Sep 17 00:00:00 2001
From: Thomas Munro
Date: Wed, 2 May 2018 21:48:40 +1200
Subject: [PATCH] Use a portable way to detect ARMv8 CRC32 hardware.
Commit f044d71e introduced support for ARMv8 CRC32 compiler intrinsics, but
used a non-portable Linux-only interface to detect the capability at runtime.
Switch to a simple probing scheme where we try it and see if SIGILL is raised.
Thomas Munro
Reviewed-By: Tom Lane
Discussion: https://postgr.es/m/CAEepm%3D02Run-Pk3xyt%2BRV3p1N%2B7cKZxN95_MamaJw8Cnw%2BDwjQ%40mail.gmail.com
---
configure | 45 ++-----------------------------
configure.in | 21 ++-------------
src/port/pg_crc32c_armv8_choose.c | 30 ++++++++++++++-------
3 files changed, 25 insertions(+), 71 deletions(-)
diff --git a/configure b/configure
index 56f18dfbc26..0aafd9c8c06 100755
--- a/configure
+++ b/configure
@@ -17344,46 +17344,6 @@ fi
fi
-# In order to detect at runtime, if the ARM CRC Extension is available,
-# we will do "getauxval(AT_HWCAP) & HWCAP_CRC32". Check if we have
-# everything we need for that.
-for ac_func in getauxval
-do :
- ac_fn_c_check_func "$LINENO" "getauxval" "ac_cv_func_getauxval"
-if test "x$ac_cv_func_getauxval" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_GETAUXVAL 1
-_ACEOF
-
-fi
-done
-
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#include
-#include
-
-int
-main ()
-{
-
-#ifndef AT_HWCAP
-#error AT_HWCAP not defined
-#endif
-#ifndef HWCAP_CRC32
-#error HWCAP_CRC32 not defined
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- HAVE_HWCAP_CRC32=1
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
# Select CRC-32C implementation.
#
# If we are targeting a processor that has Intel SSE 4.2 instructions, we can
@@ -17414,9 +17374,8 @@ if test x"$USE_SLICING_BY_8_CRC32C" = x"" && test x"$USE_SSE42_CRC32C" = x"" &&
if test x"$pgac_armv8_crc32c_intrinsics" = x"yes" && test x"$CFLAGS_ARMV8_CRC32C" = x""; then
USE_ARMV8_CRC32C=1
else
- # ARM CRC Extension, with runtime check? The getauxval() function and
- # HWCAP_CRC32 are needed for the runtime check.
- if test x"$pgac_armv8_crc32c_intrinsics" = x"yes" && test x"$ac_cv_func_getauxval" = x"yes" && test x"$HAVE_HWCAP_CRC32" = x"1"; then
+ # ARM CRC Extension, with runtime check?
+ if test x"$pgac_armv8_crc32c_intrinsics" = x"yes"; then
USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK=1
else
# fall back to slicing-by-8 algorithm, which doesn't require any
diff --git a/configure.in b/configure.in
index da02a56ec66..c3841d5b07f 100644
--- a/configure.in
+++ b/configure.in
@@ -2014,22 +2014,6 @@ if test x"$pgac_armv8_crc32c_intrinsics" != x"yes"; then
fi
AC_SUBST(CFLAGS_ARMV8_CRC32C)
-# In order to detect at runtime, if the ARM CRC Extension is available,
-# we will do "getauxval(AT_HWCAP) & HWCAP_CRC32". Check if we have
-# everything we need for that.
-AC_CHECK_FUNCS([getauxval])
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
-#include
-#include
-], [
-#ifndef AT_HWCAP
-#error AT_HWCAP not defined
-#endif
-#ifndef HWCAP_CRC32
-#error HWCAP_CRC32 not defined
-#endif
-])], [HAVE_HWCAP_CRC32=1])
-
# Select CRC-32C implementation.
#
# If we are targeting a processor that has Intel SSE 4.2 instructions, we can
@@ -2060,9 +2044,8 @@ if test x"$USE_SLICING_BY_8_CRC32C" = x"" && test x"$USE_SSE42_CRC32C" = x"" &&
if test x"$pgac_armv8_crc32c_intrinsics" = x"yes" && test x"$CFLAGS_ARMV8_CRC32C" = x""; then
USE_ARMV8_CRC32C=1
else
- # ARM CRC Extension, with runtime check? The getauxval() function and
- # HWCAP_CRC32 are needed for the runtime check.
- if test x"$pgac_armv8_crc32c_intrinsics" = x"yes" && test x"$ac_cv_func_getauxval" = x"yes" && test x"$HAVE_HWCAP_CRC32" = x"1"; then
+ # ARM CRC Extension, with runtime check?
+ if test x"$pgac_armv8_crc32c_intrinsics" = x"yes"; then
USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK=1
else
# fall back to slicing-by-8 algorithm, which doesn't require any
diff --git a/src/port/pg_crc32c_armv8_choose.c b/src/port/pg_crc32c_armv8_choose.c
index f21a8243e9a..de775dab3e5 100644
--- a/src/port/pg_crc32c_armv8_choose.c
+++ b/src/port/pg_crc32c_armv8_choose.c
@@ -8,10 +8,6 @@
* computation. Otherwise, fall back to the pure software implementation
* (slicing-by-8).
*
- * XXX: The glibc-specific getauxval() function, with the HWCAP_CRC32
- * flag, is used to determine if the CRC Extension is available on the
- * current platform. Is there a more portable way to determine that?
- *
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
@@ -24,17 +20,33 @@
#include "c.h"
-#include
-#include
-
+#include "libpq/pqsignal.h"
#include "port/pg_crc32c.h"
+#include
+
+static sigjmp_buf illegal_instruction_jump;
+
+static void
+illegal_instruction_handler(int signo)
+{
+ siglongjmp(illegal_instruction_jump, 1);
+}
+
static bool
pg_crc32c_armv8_available(void)
{
- unsigned long auxv = getauxval(AT_HWCAP);
+ uint64 data = 42;
+ bool result;
+
+ pqsignal(SIGILL, illegal_instruction_handler);
+ if (sigsetjmp(illegal_instruction_jump, 1) == 0)
+ result = (pg_comp_crc32c_armv8(0, &data, sizeof(data)) == 0xdd439b0d);
+ else
+ result = false;
+ pqsignal(SIGILL, SIG_DFL);
- return (auxv & HWCAP_CRC32) != 0;
+ return result;
}
/*
--
2.17.0