3131#endif
3232#endif
3333
34+ #if defined(__NetBSD__ )
35+ #include <sys/sysctl.h>
36+ #if defined(__aarch64__ )
37+ #include <aarch64/armreg.h>
38+ #endif
39+ #endif
40+
3441#include "port/pg_crc32c.h"
3542
3643static bool
@@ -52,6 +59,49 @@ pg_crc32c_armv8_available(void)
5259#else
5360 return (getauxval (AT_HWCAP2 ) & HWCAP2_CRC32 ) != 0 ;
5461#endif
62+ #elif defined(__NetBSD__ )
63+ /*
64+ * On NetBSD we can read the Instruction Set Attribute Registers via
65+ * sysctl. For doubtless-historical reasons the sysctl interface is
66+ * completely different on 64-bit than 32-bit, but the underlying
67+ * registers contain the same fields.
68+ */
69+ #define ISAR0_CRC32_BITPOS 16
70+ #define ISAR0_CRC32_BITWIDTH 4
71+ #define WIDTHMASK (w ) ((1 << (w)) - 1)
72+ #define SYSCTL_CPU_ID_MAXSIZE 64
73+
74+ size_t len ;
75+ uint64 sysctlbuf [SYSCTL_CPU_ID_MAXSIZE ];
76+ #if defined(__aarch64__ )
77+ /* We assume cpu0 is representative of all the machine's CPUs. */
78+ const char * path = "machdep.cpu0.cpu_id" ;
79+ size_t expected_len = sizeof (struct aarch64_sysctl_cpu_id );
80+ #define ISAR0 ((struct aarch64_sysctl_cpu_id *) sysctlbuf)->ac_aa64isar0
81+ #else
82+ const char * path = "machdep.id_isar" ;
83+ size_t expected_len = 6 * sizeof (int );
84+ #define ISAR0 ((int *) sysctlbuf)[5]
85+ #endif
86+ uint64 fld ;
87+
88+ /* Fetch the appropriate set of register values. */
89+ len = sizeof (sysctlbuf );
90+ memset (sysctlbuf , 0 , len );
91+ if (sysctlbyname (path , sysctlbuf , & len , NULL , 0 ) != 0 )
92+ return false; /* perhaps kernel is 64-bit and we aren't? */
93+ if (len != expected_len )
94+ return false; /* kernel API change? */
95+
96+ /* Fetch the CRC32 field from ISAR0. */
97+ fld = (ISAR0 >> ISAR0_CRC32_BITPOS ) & WIDTHMASK (ISAR0_CRC32_BITWIDTH );
98+
99+ /*
100+ * Current documentation defines only the field values 0 (No CRC32) and 1
101+ * (CRC32B/CRC32H/CRC32W/CRC32X/CRC32CB/CRC32CH/CRC32CW/CRC32CX). Assume
102+ * that any future nonzero value will be a superset of 1.
103+ */
104+ return (fld != 0 );
55105#else
56106 return false;
57107#endif
0 commit comments