Skip to content

Commit aac831c

Browse files
committed
Use auxv to check for CRC32 instructions on ARM.
Previously we probed for CRC32 instructions by testing if they caused SIGILL. Some have expressed doubts about that technique, the Linux documentation advises not to use it, and it's not exactly beautiful. Now that more operating systems expose CPU features to userspace via the ELF loader in approximately the same way, let's use that instead. This is expected to work on Linux, FreeBSD and recent OpenBSD. OpenBSD/ARM has not been tested and is not present in our build farm, but the API matches FreeBSD. On macOS, compilers use a more recent baseline ISA so the runtime test mechanism isn't reached. (A similar situation is expected for Windows/ARM when that port lands.) On NetBSD, runtime feature probing is lost for armv8-a builds. It looks potentially doable with sysctl following the example of the cpuctl program; patches are welcome. No back-patch for now, since we don't have any evidence of actual breakage from the previous technique. Suggested-by: Bastien Roucariès <[email protected]> Discussion: https://postgr.es/m/4496616.iHFcN1HehY%40portable-bastien
1 parent ea15816 commit aac831c

File tree

5 files changed

+34
-44
lines changed

5 files changed

+34
-44
lines changed

configure

+1-1
Original file line numberDiff line numberDiff line change
@@ -15144,7 +15144,7 @@ fi
1514415144
LIBS_including_readline="$LIBS"
1514515145
LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
1514615146

15147-
for ac_func in backtrace_symbols copyfile copy_file_range getifaddrs getpeerucred inet_pton kqueue mbstowcs_l memset_s posix_fallocate ppoll pthread_is_threaded_np setproctitle setproctitle_fast strchrnul strsignal syncfs sync_file_range uselocale wcstombs_l
15147+
for ac_func in backtrace_symbols copyfile copy_file_range elf_aux_info getauxval getifaddrs getpeerucred inet_pton kqueue mbstowcs_l memset_s posix_fallocate ppoll pthread_is_threaded_np setproctitle setproctitle_fast strchrnul strsignal syncfs sync_file_range uselocale wcstombs_l
1514815148
do :
1514915149
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
1515015150
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"

configure.ac

+2
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,8 @@ AC_CHECK_FUNCS(m4_normalize([
17231723
backtrace_symbols
17241724
copyfile
17251725
copy_file_range
1726+
elf_aux_info
1727+
getauxval
17261728
getifaddrs
17271729
getpeerucred
17281730
inet_pton

meson.build

+2
Original file line numberDiff line numberDiff line change
@@ -2623,7 +2623,9 @@ func_checks = [
26232623
# when enabling asan the dlopen check doesn't notice that -ldl is actually
26242624
# required. Just checking for dlsym() ought to suffice.
26252625
['dlsym', {'dependencies': [dl_dep], 'define': false}],
2626+
['elf_aux_info'],
26262627
['explicit_bzero'],
2628+
['getauxval'],
26272629
['getifaddrs'],
26282630
['getopt', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt}],
26292631
['getopt_long', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt_long}],

src/include/pg_config.h.in

+6
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@
125125
/* Define to 1 if you have the <editline/readline.h> header file. */
126126
#undef HAVE_EDITLINE_READLINE_H
127127

128+
/* Define to 1 if you have the `elf_aux_info' function. */
129+
#undef HAVE_ELF_AUX_INFO
130+
128131
/* Define to 1 if you have the <execinfo.h> header file. */
129132
#undef HAVE_EXECINFO_H
130133

@@ -154,6 +157,9 @@
154157
*/
155158
#undef HAVE_GCC__SYNC_INT64_CAS
156159

160+
/* Define to 1 if you have the `getauxval' function. */
161+
#undef HAVE_GETAUXVAL
162+
157163
/* Define to 1 if you have the `getifaddrs' function. */
158164
#undef HAVE_GETIFADDRS
159165

src/port/pg_crc32c_armv8_choose.c

+23-43
Original file line numberDiff line numberDiff line change
@@ -24,57 +24,37 @@
2424
#include "postgres_fe.h"
2525
#endif
2626

27-
#include <setjmp.h>
28-
#include <signal.h>
27+
#if defined(HAVE_ELF_AUX_INFO) || defined(HAVE_GETAUXVAL)
28+
#include <sys/auxv.h>
29+
#if defined(__linux__) && !defined(__aarch64__) && !defined(HWCAP2_CRC32)
30+
#include <asm/hwcap.h>
31+
#endif
32+
#endif
2933

3034
#include "port/pg_crc32c.h"
3135

32-
33-
static sigjmp_buf illegal_instruction_jump;
34-
35-
/*
36-
* Probe by trying to execute pg_comp_crc32c_armv8(). If the instruction
37-
* isn't available, we expect to get SIGILL, which we can trap.
38-
*/
39-
static void
40-
illegal_instruction_handler(SIGNAL_ARGS)
41-
{
42-
siglongjmp(illegal_instruction_jump, 1);
43-
}
44-
4536
static bool
4637
pg_crc32c_armv8_available(void)
4738
{
48-
uint64 data = 42;
49-
int result;
39+
#if defined(HAVE_ELF_AUX_INFO)
40+
unsigned long value;
5041

51-
/*
52-
* Be careful not to do anything that might throw an error while we have
53-
* the SIGILL handler set to a nonstandard value.
54-
*/
55-
pqsignal(SIGILL, illegal_instruction_handler);
56-
if (sigsetjmp(illegal_instruction_jump, 1) == 0)
57-
{
58-
/* Rather than hard-wiring an expected result, compare to SB8 code */
59-
result = (pg_comp_crc32c_armv8(0, &data, sizeof(data)) ==
60-
pg_comp_crc32c_sb8(0, &data, sizeof(data)));
61-
}
62-
else
63-
{
64-
/* We got the SIGILL trap */
65-
result = -1;
66-
}
67-
pqsignal(SIGILL, SIG_DFL);
68-
69-
#ifndef FRONTEND
70-
/* We don't expect this case, so complain loudly */
71-
if (result == 0)
72-
elog(ERROR, "crc32 hardware and software results disagree");
73-
74-
elog(DEBUG1, "using armv8 crc32 hardware = %d", (result > 0));
42+
#ifdef __aarch64__
43+
return elf_aux_info(AT_HWCAP, &value, sizeof(value)) == 0 &&
44+
(value & HWCAP_CRC32) != 0;
45+
#else
46+
return elf_aux_info(AT_HWCAP2, &value, sizeof(value)) == 0 &&
47+
(value & HWCAP2_CRC32) != 0;
48+
#endif
49+
#elif defined(HAVE_GETAUXVAL)
50+
#ifdef __aarch64__
51+
return (getauxval(AT_HWCAP) & HWCAP_CRC32) != 0;
52+
#else
53+
return (getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0;
54+
#endif
55+
#else
56+
return false;
7557
#endif
76-
77-
return (result > 0);
7858
}
7959

8060
/*

0 commit comments

Comments
 (0)