Skip to content

Commit

Permalink
cpu: support darwin/arm64 CPU feature detection
Browse files Browse the repository at this point in the history
Support ARM64 features detection. The CPU features which are supported by
Apple Silicon M1 are assumed as the minimal set of features for Go programs
running on darwin/arm64.

The ARM64 supporting features are referred to
https://en.wikichip.org/wiki/arm/armv8#ARMv8_Extensions_and_Processor_Features
  • Loading branch information
howjmay committed Jul 10, 2021
1 parent 0f9fa26 commit 7942793
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 4 deletions.
2 changes: 1 addition & 1 deletion cpu/cpu_arm64.go
Expand Up @@ -41,7 +41,7 @@ func archInit() {
switch runtime.GOOS {
case "freebsd":
readARM64Registers()
case "linux", "netbsd":
case "linux", "netbsd", "darwin":
doinit()
default:
// Most platforms don't seem to allow reading these registers.
Expand Down
56 changes: 56 additions & 0 deletions cpu/cpu_darwin_arm64.go
@@ -0,0 +1,56 @@
// Copyright 2021 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.

// +build arm64
// +build darwin
// +build !ios

package cpu

const (
commpageHasNeonFP16 = 0x00000008 // ARM v8.2 NEON FP16 supported
commpageHasNeon = 0x00000100 // Advanced SIMD is supported
commpageHasNeonHPFP = 0x00000200 // Advanced SIMD half-precision
commpageHasVfp = 0x00000400 // VFP is supported
commpageHasEvent = 0x00001000 // WFE/SVE and period event wakeup
commpageHasARMv82FHM = 0x00004000 // Optional ARMv8.2 FMLAL/FMLSL instructions (required in ARMv8.4)
commpageHasARMv8Crypto = 0x01000000 // Optional ARMv8 Crypto extensions
commpageHasARMv81Atomics = 0x02000000 // ARMv8.1 Atomic instructions supported
commpageHasARMv8Crc32 = 0x04000000 // Optional ARMv8 crc32 instructions (required in ARMv8.1)
commpageHasARMv82SHA512 = 0x80000000 // Optional ARMv8.2 SHA512 instructions
commpageHasARMv82SHA3 = 0x0000000100000000 // Optional ARMv8.2 SHA3 instructions
)

func doinit() {
ARM64.HasFP = darwinCheckFeatureEnabled(commpageHasVfp)
ARM64.HasASIMD = darwinCheckFeatureEnabled(commpageHasNeon)
ARM64.HasCRC32 = darwinCheckFeatureEnabled(commpageHasARMv8Crc32)
ARM64.HasATOMICS = darwinCheckFeatureEnabled(commpageHasARMv81Atomics)
ARM64.HasFPHP = darwinCheckFeatureEnabled(commpageHasNeonFP16)
ARM64.HasASIMDHP = darwinCheckFeatureEnabled(commpageHasNeonHPFP)
ARM64.HasSHA3 = darwinCheckFeatureEnabled(commpageHasARMv82SHA3)
ARM64.HasSHA512 = darwinCheckFeatureEnabled(commpageHasARMv82SHA512)
ARM64.HasASIMDFHM = darwinCheckFeatureEnabled(commpageHasARMv82FHM)
ARM64.HasSVE = darwinCheckFeatureEnabled(commpageHasEvent)

// There are no hw.optional sysctl values for the below features on Mac OS 11.0
// to detect their supported state dynamically. Assume the CPU features that
// Apple Silicon M1 supports to be available as a minimal set of features
// to all Go programs running on darwin/arm64.
ARM64.HasEVTSTRM = true
ARM64.HasAES = true
ARM64.HasPMULL = true
ARM64.HasSHA1 = true
ARM64.HasSHA2 = true
ARM64.HasCPUID = true
ARM64.HasASIMDRDM = true
ARM64.HasJSCVT = true
ARM64.HasLRCPC = true
ARM64.HasDCPOP = true
ARM64.HasSM3 = true
ARM64.HasSM4 = true
ARM64.HasASIMDDP = true
}

func darwinCheckFeatureEnabled(feature_vec uint64) bool
29 changes: 29 additions & 0 deletions cpu/cpu_darwin_arm64.s
@@ -0,0 +1,29 @@
//go:build arm64 && gc
// +build arm64
// +build gc

#include "textflag.h"

// func darwinCheckFeatureEnabled(feature_vec uint64) bool
TEXT ·darwinCheckFeatureEnabled(SB), NOSPLIT, $0-8
MOVD feature_vec+0(FP), R0
MOVD $0, ret+0(FP) // default to false
MOVD $1, R2 // set R2 as true boolean constan

#ifdef GOOS_darwin // return if not darwin
#ifdef GOARCH_arm64 // return if not arm64
// These values from:
// https://github.com/apple/darwin-xnu/blob/main/osfmk/arm/cpu_capabilities.h
#define arm_commpage64_base_address 0x0000000fffffc000
#define arm_commpage64_cpu_capabilities64 (arm_commpage64_base_address+0x010)
MOVD $0xffffc000, R1
MOVK $(0xf<<32), R1
MOVD (R1), R1
AND R1, R0
CBZ R0, no_feature
MOVD R2, ret+8(FP)

no_feature:
#endif
#endif
RET
4 changes: 2 additions & 2 deletions cpu/cpu_other_arm64.go
Expand Up @@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build !linux && !netbsd && arm64
// +build !linux,!netbsd,arm64
//go:build !linux && !netbsd && !darwin && arm64
// +build !linux,!netbsd,!darwin,arm64

package cpu

Expand Down
2 changes: 1 addition & 1 deletion cpu/cpu_test.go
Expand Up @@ -42,7 +42,7 @@ func TestAVX512HasAVX2AndAVX(t *testing.T) {
}

func TestARM64minimalFeatures(t *testing.T) {
if runtime.GOARCH != "arm64" || (runtime.GOOS == "darwin" || runtime.GOOS == "ios") {
if runtime.GOARCH != "arm64" || runtime.GOOS == "ios" {
return
}
if !cpu.ARM64.HasASIMD {
Expand Down

0 comments on commit 7942793

Please sign in to comment.