From 54c2df71cfc6a81e617bce95b48e924e5e6e0d60 Mon Sep 17 00:00:00 2001 From: HowJMay Date: Thu, 8 Jul 2021 00:02:54 +0800 Subject: [PATCH] cpu: support darwin/arm64 CPU feature detection 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 --- cpu/cpu_arm64.go | 2 +- cpu/cpu_darwin_arm64.go | 56 +++++++++++++++++++++++++++++++++++++++++ cpu/cpu_darwin_arm64.s | 29 +++++++++++++++++++++ cpu/cpu_other_arm64.go | 4 +-- cpu/cpu_test.go | 2 +- 5 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 cpu/cpu_darwin_arm64.go create mode 100644 cpu/cpu_darwin_arm64.s diff --git a/cpu/cpu_arm64.go b/cpu/cpu_arm64.go index 87dd5e3021..ebab2662ee 100644 --- a/cpu/cpu_arm64.go +++ b/cpu/cpu_arm64.go @@ -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. diff --git a/cpu/cpu_darwin_arm64.go b/cpu/cpu_darwin_arm64.go new file mode 100644 index 0000000000..e1ec145d1d --- /dev/null +++ b/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 diff --git a/cpu/cpu_darwin_arm64.s b/cpu/cpu_darwin_arm64.s new file mode 100644 index 0000000000..0de3e54e06 --- /dev/null +++ b/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 amd64 +// 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 diff --git a/cpu/cpu_other_arm64.go b/cpu/cpu_other_arm64.go index f8c484f589..836f8ae19d 100644 --- a/cpu/cpu_other_arm64.go +++ b/cpu/cpu_other_arm64.go @@ -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 diff --git a/cpu/cpu_test.go b/cpu/cpu_test.go index 5f7f843fe4..ba25551509 100644 --- a/cpu/cpu_test.go +++ b/cpu/cpu_test.go @@ -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 {