cpu: add linux/arm64
Port from Go internal/cpu
Updates golang/go#25185
Change-Id: I8390980e38b61f6c428fafa0665a03952e7b00bb
Reviewed-on: https://go-review.googlesource.com/c/150718
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Martin Möhrmann <moehrmann@google.com>
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
diff --git a/cpu/cpu.go b/cpu/cpu.go
index 3d88f86..11e8fb9 100644
--- a/cpu/cpu.go
+++ b/cpu/cpu.go
@@ -36,3 +36,35 @@
HasSSE42 bool // Streaming SIMD extension 4 and 4.2
_ CacheLinePad
}
+
+// ARM64 contains the supported CPU features of the
+// current ARMv8(aarch64) platform. If the current platform
+// is not arm64 then all feature flags are false.
+var ARM64 struct {
+ _ CacheLinePad
+ HasFP bool // Floating-point instruction set (always available)
+ HasASIMD bool // Advanced SIMD (always available)
+ HasEVTSTRM bool // Event stream support
+ HasAES bool // AES hardware implementation
+ HasPMULL bool // Polynomial multiplication instruction set
+ HasSHA1 bool // SHA1 hardware implementation
+ HasSHA2 bool // SHA2 hardware implementation
+ HasCRC32 bool // CRC32 hardware implementation
+ HasATOMICS bool // Atomic memory operation instruction set
+ HasFPHP bool // Half precision floating-point instruction set
+ HasASIMDHP bool // Advanced SIMD half precision instruction set
+ HasCPUID bool // CPUID identification scheme registers
+ HasASIMDRDM bool // Rounding double multiply add/subtract instruction set
+ HasJSCVT bool // Javascript conversion from floating-point to integer
+ HasFCMA bool // Floating-point multiplication and addition of complex numbers
+ HasLRCPC bool // Release Consistent processor consistent support
+ HasDCPOP bool // Persistent memory support
+ HasSHA3 bool // SHA3 hardware implementation
+ HasSM3 bool // SM3 hardware implementation
+ HasSM4 bool // SM4 hardware implementation
+ HasASIMDDP bool // Advanced SIMD double precision instruction set
+ HasSHA512 bool // SHA512 hardware implementation
+ HasSVE bool // Scalable Vector Extensions
+ HasASIMDFHM bool // Advanced SIMD multiplication FP16 to FP32
+ _ CacheLinePad
+}
diff --git a/cpu/cpu_arm.go b/cpu/cpu_arm.go
index d93036f..7f2348b 100644
--- a/cpu/cpu_arm.go
+++ b/cpu/cpu_arm.go
@@ -5,3 +5,5 @@
package cpu
const cacheLineSize = 32
+
+func doinit() {}
diff --git a/cpu/cpu_arm64.go b/cpu/cpu_arm64.go
index 1d2ab29..02ed58b 100644
--- a/cpu/cpu_arm64.go
+++ b/cpu/cpu_arm64.go
@@ -5,3 +5,63 @@
package cpu
const cacheLineSize = 64
+
+// HWCAP/HWCAP2 bits. These are exposed by Linux.
+const (
+ hwcap_FP = 1 << 0
+ hwcap_ASIMD = 1 << 1
+ hwcap_EVTSTRM = 1 << 2
+ hwcap_AES = 1 << 3
+ hwcap_PMULL = 1 << 4
+ hwcap_SHA1 = 1 << 5
+ hwcap_SHA2 = 1 << 6
+ hwcap_CRC32 = 1 << 7
+ hwcap_ATOMICS = 1 << 8
+ hwcap_FPHP = 1 << 9
+ hwcap_ASIMDHP = 1 << 10
+ hwcap_CPUID = 1 << 11
+ hwcap_ASIMDRDM = 1 << 12
+ hwcap_JSCVT = 1 << 13
+ hwcap_FCMA = 1 << 14
+ hwcap_LRCPC = 1 << 15
+ hwcap_DCPOP = 1 << 16
+ hwcap_SHA3 = 1 << 17
+ hwcap_SM3 = 1 << 18
+ hwcap_SM4 = 1 << 19
+ hwcap_ASIMDDP = 1 << 20
+ hwcap_SHA512 = 1 << 21
+ hwcap_SVE = 1 << 22
+ hwcap_ASIMDFHM = 1 << 23
+)
+
+func doinit() {
+ // HWCAP feature bits
+ ARM64.HasFP = isSet(HWCap, hwcap_FP)
+ ARM64.HasASIMD = isSet(HWCap, hwcap_ASIMD)
+ ARM64.HasEVTSTRM = isSet(HWCap, hwcap_EVTSTRM)
+ ARM64.HasAES = isSet(HWCap, hwcap_AES)
+ ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL)
+ ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1)
+ ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2)
+ ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32)
+ ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS)
+ ARM64.HasFPHP = isSet(HWCap, hwcap_FPHP)
+ ARM64.HasASIMDHP = isSet(HWCap, hwcap_ASIMDHP)
+ ARM64.HasCPUID = isSet(HWCap, hwcap_CPUID)
+ ARM64.HasASIMDRDM = isSet(HWCap, hwcap_ASIMDRDM)
+ ARM64.HasJSCVT = isSet(HWCap, hwcap_JSCVT)
+ ARM64.HasFCMA = isSet(HWCap, hwcap_FCMA)
+ ARM64.HasLRCPC = isSet(HWCap, hwcap_LRCPC)
+ ARM64.HasDCPOP = isSet(HWCap, hwcap_DCPOP)
+ ARM64.HasSHA3 = isSet(HWCap, hwcap_SHA3)
+ ARM64.HasSM3 = isSet(HWCap, hwcap_SM3)
+ ARM64.HasSM4 = isSet(HWCap, hwcap_SM4)
+ ARM64.HasASIMDDP = isSet(HWCap, hwcap_ASIMDDP)
+ ARM64.HasSHA512 = isSet(HWCap, hwcap_SHA512)
+ ARM64.HasSVE = isSet(HWCap, hwcap_SVE)
+ ARM64.HasASIMDFHM = isSet(HWCap, hwcap_ASIMDFHM)
+}
+
+func isSet(hwc uint, value uint) bool {
+ return hwc&value != 0
+}
diff --git a/cpu/cpu_linux.go b/cpu/cpu_linux.go
new file mode 100644
index 0000000..126bb68
--- /dev/null
+++ b/cpu/cpu_linux.go
@@ -0,0 +1,55 @@
+// Copyright 2018 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 !amd64,!amd64p32,!386
+
+package cpu
+
+import (
+ "encoding/binary"
+ "io/ioutil"
+)
+
+const (
+ _AT_HWCAP = 16
+ _AT_HWCAP2 = 26
+
+ procAuxv = "/proc/self/auxv"
+
+ uintSize uint = 32 << (^uint(0) >> 63)
+)
+
+// For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2
+// These are initialized in cpu_$GOARCH.go
+// and should not be changed after they are initialized.
+var HWCap uint
+var HWCap2 uint
+
+func init() {
+ buf, err := ioutil.ReadFile(procAuxv)
+ if err != nil {
+ panic("read proc auxv failed: " + err.Error())
+ }
+
+ pb := int(uintSize / 8)
+
+ for i := 0; i < len(buf)-pb*2; i += pb * 2 {
+ var tag, val uint
+ switch uintSize {
+ case 32:
+ tag = uint(binary.LittleEndian.Uint32(buf[i:]))
+ val = uint(binary.LittleEndian.Uint32(buf[i+pb:]))
+ case 64:
+ tag = uint(binary.LittleEndian.Uint64(buf[i:]))
+ val = uint(binary.LittleEndian.Uint64(buf[i+pb:]))
+ }
+ switch tag {
+ case _AT_HWCAP:
+ HWCap = val
+ case _AT_HWCAP2:
+ HWCap2 = val
+ }
+ }
+ doinit()
+}
diff --git a/cpu/cpu_mips64x.go b/cpu/cpu_mips64x.go
index 6165f12..f55e0c8 100644
--- a/cpu/cpu_mips64x.go
+++ b/cpu/cpu_mips64x.go
@@ -7,3 +7,5 @@
package cpu
const cacheLineSize = 32
+
+func doinit() {}
diff --git a/cpu/cpu_mipsx.go b/cpu/cpu_mipsx.go
index 1269eee..cda87b1 100644
--- a/cpu/cpu_mipsx.go
+++ b/cpu/cpu_mipsx.go
@@ -7,3 +7,5 @@
package cpu
const cacheLineSize = 32
+
+func doinit() {}
diff --git a/cpu/cpu_ppc64x.go b/cpu/cpu_ppc64x.go
index d10759a..70c959b 100644
--- a/cpu/cpu_ppc64x.go
+++ b/cpu/cpu_ppc64x.go
@@ -7,3 +7,5 @@
package cpu
const cacheLineSize = 128
+
+func doinit() {}
diff --git a/cpu/cpu_s390x.go b/cpu/cpu_s390x.go
index 684c4f0..ce8a228 100644
--- a/cpu/cpu_s390x.go
+++ b/cpu/cpu_s390x.go
@@ -5,3 +5,5 @@
package cpu
const cacheLineSize = 256
+
+func doinit() {}
diff --git a/cpu/cpu_test.go b/cpu/cpu_test.go
index baf4b87..0c8cc83 100644
--- a/cpu/cpu_test.go
+++ b/cpu/cpu_test.go
@@ -26,3 +26,15 @@
}
}
}
+
+func TestARM64minimalFeatures(t *testing.T) {
+ if runtime.GOARCH != "arm64" || runtime.GOOS != "linux" {
+ return
+ }
+ if !cpu.ARM64.HasASIMD {
+ t.Fatal("HasASIMD expected true, got false")
+ }
+ if !cpu.ARM64.HasFP {
+ t.Fatal("HasFP expected true, got false")
+ }
+}