[sys] cpu: darwin/arm64 feature detection

0 views
Skip to first unread message

Egon Elbre (Gerrit)

unread,
8:38 AM (10 hours ago) 8:38 AM
to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

Egon Elbre has uploaded the change for review

Commit message

cpu: darwin/arm64 feature detection

The ARM64 flags were not being correctly set for Mac M series laptops.

Fixes golang/go#43046
Change-Id: I1d884dccd3f3a0a010ad7babbab26b73731ab583

Change diff

diff --git a/cpu/asm_darwin_arm64_gc.s b/cpu/asm_darwin_arm64_gc.s
new file mode 100644
index 0000000..eb57a3d
--- /dev/null
+++ b/cpu/asm_darwin_arm64_gc.s
@@ -0,0 +1,17 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build darwin && arm64 && gc
+
+#include "textflag.h"
+
+TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0
+ JMP libc_sysctl(SB)
+GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8
+DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB)
+
+TEXT libc_sysctlbyname_trampoline<>(SB),NOSPLIT,$0-0
+ JMP libc_sysctlbyname(SB)
+GLOBL ·libc_sysctlbyname_trampoline_addr(SB), RODATA, $8
+DATA ·libc_sysctlbyname_trampoline_addr(SB)/8, $libc_sysctlbyname_trampoline<>(SB)
diff --git a/cpu/cpu_arm64.go b/cpu/cpu_arm64.go
index af2aa99..b3b7651 100644
--- a/cpu/cpu_arm64.go
+++ b/cpu/cpu_arm64.go
@@ -47,7 +47,7 @@
switch runtime.GOOS {
case "freebsd":
readARM64Registers()
- case "linux", "netbsd", "openbsd":
+ case "linux", "netbsd", "openbsd", "darwin":
doinit()
default:
// Many platforms don't seem to allow reading these registers.
diff --git a/cpu/cpu_darwin_arm64.go b/cpu/cpu_darwin_arm64.go
new file mode 100644
index 0000000..9316a53
--- /dev/null
+++ b/cpu/cpu_darwin_arm64.go
@@ -0,0 +1,60 @@
+// Copyright 2026 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build arm64 && darwin
+
+package cpu
+
+func doinit() {
+ setMinimalFeatures()
+
+ // The feature flags are explained in [Instruction Set Detection].
+ //
+ // There are some differences between MacOS versions:
+ //
+ // MacOS 11 does not have "hw.optional" sysctl values for some of the features.
+ //
+ // MacOS 13 changed some of the naming conventions to align with ARM Architecture Reference Manual.
+ // For example "hw.optional.armv8_2_sha512" became "hw.optional.arm.FEAT_SHA512".
+ // The current flags will use the older naming convention to stay backwards compatible
+ // with MacOS 11 and 12. The code has commented out the new naming convention
+ // that can be used once MacOS 12 is no longer supported.
+
+ // Encryption capabilities
+
+ // For the following flags there are no MacOS 11 sysctl flags.
+ ARM64.HasAES = true // darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_AES\x00"))
+ ARM64.HasPMULL = true // darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_PMULL\x00"))
+ ARM64.HasSHA1 = true // darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_SHA1\x00"))
+ ARM64.HasSHA2 = true // darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_SHA256\x00"))
+
+ // For these we can do a check similarly to internal/cpu.
+ ARM64.HasSHA3 = darwinSysctlEnabled([]byte("hw.optional.armv8_2_sha3\x00")) // darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_SHA3\x00"))
+ ARM64.HasSHA512 = darwinSysctlEnabled([]byte("hw.optional.armv8_2_sha512\x00")) // darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_SHA512\x00"))
+
+ // Atomic and memory ordering (FEAT_LSE)
+ ARM64.HasATOMICS = darwinSysctlEnabled([]byte("hw.optional.armv8_1_atomics\x00")) // darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_LSE\x00"))
+ ARM64.HasLRCPC = darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_LRCPC\x00"))
+
+ // CRC32
+ ARM64.HasCRC32 = darwinSysctlEnabled([]byte("hw.optional.armv8_crc32\x00"))
+
+ // SIMD and floating point capabilities
+ ARM64.HasFPHP = darwinSysctlEnabled([]byte("hw.optional.neon_fp16\x00")) // darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_FP16\x00"))
+ ARM64.HasASIMDHP = darwinSysctlEnabled([]byte("hw.optional.neon_hpfp\x00")) // darwinSysctlEnabled([]byte("hw.optional.AdvSIMD_HPFPCvt\x00"))
+ ARM64.HasASIMDRDM = darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_RDM\x00"))
+ ARM64.HasASIMDDP = darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_DotProd\x00"))
+ ARM64.HasASIMDFHM = darwinSysctlEnabled([]byte("hw.optional.armv8_2_fhm\x00")) // darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_FHM\x00"))
+ ARM64.HasI8MM = darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_I8MM\x00"))
+
+ // JavaScript and complex number instructions
+ ARM64.HasJSCVT = darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_JSCVT\x00"))
+ ARM64.HasFCMA = darwinSysctlEnabled([]byte("hw.optional.armv8_3_compnum\x00")) // darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_FCMA\x00"))
+
+ // Persistent memory support (DCPOP = DC CVAP instruction from FEAT_DPB)
+ ARM64.HasDCPOP = darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_DPB\x00"))
+
+ // Data Independent Timing
+ ARM64.HasDIT = darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_DIT\x00"))
+}
diff --git a/cpu/cpu_other_arm64.go b/cpu/cpu_other_arm64.go
index 5341e7f..0ad9b42 100644
--- a/cpu/cpu_other_arm64.go
+++ b/cpu/cpu_other_arm64.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

-//go:build !linux && !netbsd && !openbsd && arm64
+//go:build !linux && !netbsd && !openbsd && !darwin && arm64

package cpu

diff --git a/cpu/syscall_darwin_arm64_gc.go b/cpu/syscall_darwin_arm64_gc.go
new file mode 100644
index 0000000..811982a
--- /dev/null
+++ b/cpu/syscall_darwin_arm64_gc.go
@@ -0,0 +1,55 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Minimal copy of x/sys/unix so the cpu package can make a
+// system call on Darwin without depending on x/sys/unix.
+
+//go:build darwin && arm64 && gc
+
+package cpu
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+type Errno = syscall.Errno
+
+// adapted from internal/cpu/cpu_arm64_darwin.go
+func darwinSysctlEnabled(name []byte) bool {
+ out := int32(0)
+ nout := unsafe.Sizeof(out)
+ if ret := sysctlbyname(&name[0], (*byte)(unsafe.Pointer(&out)), &nout, nil, 0); ret != nil {
+ return false
+ }
+ return out > 0
+}
+
+//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
+
+var libc_sysctlbyname_trampoline_addr uintptr
+
+// adapted from runtime/sys_darwin.go in the pattern of sysctl() above, as defined in x/sys/unix
+func sysctlbyname(name *byte, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error {
+ if _, _, err := syscall_syscall6(
+ libc_sysctlbyname_trampoline_addr,
+ uintptr(unsafe.Pointer(name)),
+ uintptr(unsafe.Pointer(old)),
+ uintptr(unsafe.Pointer(oldlen)),
+ uintptr(unsafe.Pointer(new)),
+ uintptr(newlen),
+ 0,
+ ); err != 0 {
+ return err
+ }
+
+ return nil
+}
+
+//go:cgo_import_dynamic libc_sysctlbyname sysctlbyname "/usr/lib/libSystem.B.dylib"
+
+// Implemented in the runtime package (runtime/sys_darwin.go)
+func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
+
+//go:linkname syscall_syscall6 syscall.syscall6

Change information

Files:
  • A cpu/asm_darwin_arm64_gc.s
  • M cpu/cpu_arm64.go
  • A cpu/cpu_darwin_arm64.go
  • M cpu/cpu_other_arm64.go
  • A cpu/syscall_darwin_arm64_gc.go
Change size: M
Delta: 5 files changed, 134 insertions(+), 2 deletions(-)
Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newchange
Gerrit-Project: sys
Gerrit-Branch: master
Gerrit-Change-Id: I1d884dccd3f3a0a010ad7babbab26b73731ab583
Gerrit-Change-Number: 737260
Gerrit-PatchSet: 1
Gerrit-Owner: Egon Elbre <egon...@gmail.com>
unsatisfied_requirement
satisfied_requirement
open
diffy

Egon Elbre (Gerrit)

unread,
8:40 AM (10 hours ago) 8:40 AM
to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

Egon Elbre uploaded new patchset

Egon Elbre uploaded patch set #2 to this change.
Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newpatchset
Gerrit-Project: sys
Gerrit-Branch: master
Gerrit-Change-Id: I1d884dccd3f3a0a010ad7babbab26b73731ab583
Gerrit-Change-Number: 737260
Gerrit-PatchSet: 2
Gerrit-Owner: Egon Elbre <egon...@gmail.com>
unsatisfied_requirement
satisfied_requirement
open
diffy

Egon Elbre (Gerrit)

unread,
8:43 AM (10 hours ago) 8:43 AM
to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

Egon Elbre uploaded new patchset

Egon Elbre uploaded patch set #3 to this change.
Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newpatchset
Gerrit-Project: sys
Gerrit-Branch: master
Gerrit-Change-Id: I1d884dccd3f3a0a010ad7babbab26b73731ab583
Gerrit-Change-Number: 737260
Gerrit-PatchSet: 3
Gerrit-Owner: Egon Elbre <egon...@gmail.com>
unsatisfied_requirement
satisfied_requirement
open
diffy

Egon Elbre (Gerrit)

unread,
8:45 AM (10 hours ago) 8:45 AM
to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

Egon Elbre added 1 comment

Patchset-level comments
File-level comment, Patchset 3 (Latest):
Egon Elbre . resolved

There is prior work https://go-review.googlesource.com/c/sys/+/397754 and https://go-review.googlesource.com/c/sys/+/332729. These should no longer be necessary with this approach.

Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sys
Gerrit-Branch: master
Gerrit-Change-Id: I1d884dccd3f3a0a010ad7babbab26b73731ab583
Gerrit-Change-Number: 737260
Gerrit-PatchSet: 3
Gerrit-Owner: Egon Elbre <egon...@gmail.com>
Gerrit-Comment-Date: Sat, 17 Jan 2026 13:45:46 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
unsatisfied_requirement
satisfied_requirement
open
diffy
Reply all
Reply to author
Forward
0 new messages