]> Cypherpunks repositories - gostls13.git/commitdiff
internal/cpu: detect cpu features in internal/cpu package
authorFangming.Fang <fangming.fang@arm.com>
Wed, 8 Nov 2017 02:17:51 +0000 (02:17 +0000)
committerBrad Fitzpatrick <bradfitz@golang.org>
Tue, 14 Nov 2017 19:07:15 +0000 (19:07 +0000)
change hash/crc32 package to use cpu package instead of using
runtime internal variables to check crc32 instruction

Change-Id: I8f88d2351bde8ed4e256f9adf822a08b9a00f532
Reviewed-on: https://go-review.googlesource.com/76490
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>

src/hash/crc32/crc32_arm64.go
src/hash/crc32/crc32_arm64.s
src/internal/cpu/cpu.go
src/internal/cpu/cpu_arm64.go
src/runtime/os_darwin_arm64.go
src/runtime/os_linux_arm64.go

index 17044861c7f074942d3b1538bdc45828bf6ce61d..1f8779d506fc6bd55ca6ebbee49ce7228f92831a 100644 (file)
@@ -8,11 +8,12 @@
 
 package crc32
 
-func supportsCRC32() bool
+import "internal/cpu"
+
 func castagnoliUpdate(crc uint32, p []byte) uint32
 func ieeeUpdate(crc uint32, p []byte) uint32
 
-var hasCRC32 = supportsCRC32()
+var hasCRC32 = cpu.ARM64.HasCRC32
 
 func archAvailableCastagnoli() bool {
        return hasCRC32
index 26a86e4efa64dfe73642003c1403cb42cbb2c2f3..53274c56235ed04de0159ae64c77a2ed290cbf4e 100644 (file)
@@ -89,9 +89,3 @@ less_than_2:
 done:
        MOVWU   R9, ret+32(FP)
        RET
-
-// func supportsCRC32() bool
-TEXT ·supportsCRC32(SB),NOSPLIT,$0-1
-       MOVB    runtime·supportCRC32(SB), R0
-       MOVB    R0, ret+0(FP)
-       RET
index 38fedc4e2b4aacd7bc97d333db771124fee59fd7..22fc561002d8608624bcb56e286d804ca4f69e7e 100644 (file)
@@ -57,3 +57,21 @@ type ppc64 struct {
        IsPOWER9   bool // ISA v3.00 (POWER9)
        _          [CacheLineSize]byte
 }
+
+var ARM64 arm64
+
+// The booleans in arm64 contain the correspondingly named cpu feature bit.
+// The struct is padded to avoid false sharing.
+type arm64 struct {
+       _          [CacheLineSize]byte
+       HasFP      bool
+       HasASIMD   bool
+       HasEVTSTRM bool
+       HasAES     bool
+       HasPMULL   bool
+       HasSHA1    bool
+       HasSHA2    bool
+       HasCRC32   bool
+       HasATOMICS bool
+       _          [CacheLineSize]byte
+}
index 4d071b3a4e61e2d5e3d2eb8f764706bd853cffb7..e1278a147a1df48c18b0202dfdd3efb7eadc49d0 100644 (file)
@@ -2,13 +2,44 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build arm64
+
 package cpu
 
 const CacheLineSize = 64
 
-// TODO: delete this once https://go-review.googlesource.com/c/go/+/76490 lands.
-// These will just be false for now.
-var ARM64 struct {
-       HasSHA1 bool
-       HasSHA2 bool
+// arm64 doesn't have a 'cpuid' equivalent, so we rely on HWCAP/HWCAP2.
+// These are linknamed in runtime/os_linux_arm64.go and are initialized by
+// archauxv().
+var arm64_hwcap uint
+var arm64_hwcap2 uint
+
+// HWCAP/HWCAP2 bits. These are exposed by Linux.
+const (
+       _ARM64_FEATURE_HAS_FP      = (1 << 0)
+       _ARM64_FEATURE_HAS_ASIMD   = (1 << 1)
+       _ARM64_FEATURE_HAS_EVTSTRM = (1 << 2)
+       _ARM64_FEATURE_HAS_AES     = (1 << 3)
+       _ARM64_FEATURE_HAS_PMULL   = (1 << 4)
+       _ARM64_FEATURE_HAS_SHA1    = (1 << 5)
+       _ARM64_FEATURE_HAS_SHA2    = (1 << 6)
+       _ARM64_FEATURE_HAS_CRC32   = (1 << 7)
+       _ARM64_FEATURE_HAS_ATOMICS = (1 << 8)
+)
+
+func init() {
+       // HWCAP feature bits
+       ARM64.HasFP = isSet(arm64_hwcap, _ARM64_FEATURE_HAS_FP)
+       ARM64.HasASIMD = isSet(arm64_hwcap, _ARM64_FEATURE_HAS_ASIMD)
+       ARM64.HasEVTSTRM = isSet(arm64_hwcap, _ARM64_FEATURE_HAS_EVTSTRM)
+       ARM64.HasAES = isSet(arm64_hwcap, _ARM64_FEATURE_HAS_AES)
+       ARM64.HasPMULL = isSet(arm64_hwcap, _ARM64_FEATURE_HAS_PMULL)
+       ARM64.HasSHA1 = isSet(arm64_hwcap, _ARM64_FEATURE_HAS_SHA1)
+       ARM64.HasSHA2 = isSet(arm64_hwcap, _ARM64_FEATURE_HAS_SHA2)
+       ARM64.HasCRC32 = isSet(arm64_hwcap, _ARM64_FEATURE_HAS_CRC32)
+       ARM64.HasATOMICS = isSet(arm64_hwcap, _ARM64_FEATURE_HAS_ATOMICS)
+}
+
+func isSet(hwc uint, value uint) bool {
+       return hwc&value != 0
 }
index 01285afa190959b54efea59b9ab580461c9ede8a..8de132d8e2fab9419705cc1faefd250acb69d21f 100644 (file)
@@ -4,8 +4,6 @@
 
 package runtime
 
-var supportCRC32 = false
-
 //go:nosplit
 func cputicks() int64 {
        // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand().
index 986a34135e45c7788702c849da385382afdb5b55..96827e7c9f1492984014f0ed8ab9066057259cbb 100644 (file)
@@ -2,14 +2,22 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build arm64
+
 package runtime
 
-const (
-       _ARM64_FEATURE_HAS_CRC32 = 0x80
-)
+// For go:linkname
+import _ "unsafe"
 
 var randomNumber uint32
-var supportCRC32 bool
+
+// arm64 doesn't have a 'cpuid' instruction equivalent and relies on
+// HWCAP/HWCAP2 bits for hardware capabilities.
+
+//go:linkname cpu_hwcap internal/cpu.arm64_hwcap
+//go:linkname cpu_hwcap2 internal/cpu.arm64_hwcap2
+var cpu_hwcap uint
+var cpu_hwcap2 uint
 
 func archauxv(tag, val uintptr) {
        switch tag {
@@ -20,7 +28,9 @@ func archauxv(tag, val uintptr) {
                randomNumber = uint32(startupRandomData[4]) | uint32(startupRandomData[5])<<8 |
                        uint32(startupRandomData[6])<<16 | uint32(startupRandomData[7])<<24
        case _AT_HWCAP:
-               supportCRC32 = val&_ARM64_FEATURE_HAS_CRC32 != 0
+               cpu_hwcap = uint(val)
+       case _AT_HWCAP2:
+               cpu_hwcap2 = uint(val)
        }
 }