Skip to content

Commit 4570b22

Browse files
committed
Support runtime CRC feature probing on NetBSD/ARM using sysctl().
Commit aac831c left this as a to-do; here's code to do it. Like the previous patch, this is HEAD-only for now. Discussion: https://postgr.es/m/4496616.iHFcN1HehY@portable-bastien
1 parent 32a2aa7 commit 4570b22

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

src/port/pg_crc32c_armv8_choose.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@
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

3643
static 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

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy