aboutsummaryrefslogtreecommitdiff
path: root/src/internal
diff options
context:
space:
mode:
authorMartin Möhrmann <moehrmann@google.com>2020-10-13 22:30:23 +0200
committerMartin Möhrmann <moehrmann@google.com>2020-10-20 11:09:52 +0000
commitde932da453f68b8fc04e9c2ab25136748173c806 (patch)
treed657dab40079de391135dffc4fab9fc159a1d005 /src/internal
parent55b2d479d774d9887a6ec32b34e2c413f7c84f78 (diff)
downloadgo-de932da453f68b8fc04e9c2ab25136748173c806.tar.gz
go-de932da453f68b8fc04e9c2ab25136748173c806.zip
internal/cpu: consolidate arm64 feature detection
Move code to detect and mask arm64 CPU features from runtime to internal/cpu. Change-Id: Ib784e2ff056e8def125d68827b852f07a3eff0db Reviewed-on: https://go-review.googlesource.com/c/go/+/261878 Trust: Martin Möhrmann <moehrmann@google.com> Trust: Tobias Klauser <tobias.klauser@gmail.com> Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com> Reviewed-by: Benny Siegert <bsiegert@gmail.com>
Diffstat (limited to 'src/internal')
-rw-r--r--src/internal/cpu/cpu_android.go7
-rw-r--r--src/internal/cpu/cpu_arm64.go73
-rw-r--r--src/internal/cpu/cpu_arm64.s12
-rw-r--r--src/internal/cpu/cpu_freebsd.go7
-rw-r--r--src/internal/cpu/cpu_linux.go9
-rw-r--r--src/internal/cpu/cpu_other.go11
6 files changed, 107 insertions, 12 deletions
diff --git a/src/internal/cpu/cpu_android.go b/src/internal/cpu/cpu_android.go
new file mode 100644
index 0000000000..d995e8d5a7
--- /dev/null
+++ b/src/internal/cpu/cpu_android.go
@@ -0,0 +1,7 @@
+// Copyright 2020 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.
+
+package cpu
+
+const GOOS = "android"
diff --git a/src/internal/cpu/cpu_arm64.go b/src/internal/cpu/cpu_arm64.go
index d9e0c98ca6..533bea2470 100644
--- a/src/internal/cpu/cpu_arm64.go
+++ b/src/internal/cpu/cpu_arm64.go
@@ -6,13 +6,11 @@ package cpu
const CacheLinePadSize = 64
-// arm64 doesn't have a 'cpuid' equivalent, so we rely on HWCAP/HWCAP2.
-// These are initialized by archauxv and should not be changed after they are
-// initialized.
+// HWCap may be initialized by archauxv and
+// should not be changed after it was initialized.
var HWCap uint
-var HWCap2 uint
-// HWCAP/HWCAP2 bits. These are exposed by Linux.
+// HWCAP bits. These are exposed by Linux.
const (
hwcap_AES = 1 << 3
hwcap_PMULL = 1 << 4
@@ -32,15 +30,66 @@ func doinit() {
{Name: "atomics", Feature: &ARM64.HasATOMICS},
}
- // HWCAP feature bits
- 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)
+ switch GOOS {
+ case "linux", "android":
+ // HWCap was populated by the runtime from the auxillary vector.
+ // Use HWCap information since reading aarch64 system registers
+ // is not supported in user space on older linux kernels.
+ 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)
+
+ // The Samsung S9+ kernel reports support for atomics, but not all cores
+ // actually support them, resulting in SIGILL. See issue #28431.
+ // TODO(elias.naur): Only disable the optimization on bad chipsets on android.
+ ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS) && GOOS != "android"
+
+ case "freebsd":
+ // Retrieve info from system register ID_AA64ISAR0_EL1.
+ isar0 := getisar0()
+
+ // ID_AA64ISAR0_EL1
+ switch extractBits(isar0, 4, 7) {
+ case 1:
+ ARM64.HasAES = true
+ case 2:
+ ARM64.HasAES = true
+ ARM64.HasPMULL = true
+ }
+
+ switch extractBits(isar0, 8, 11) {
+ case 1:
+ ARM64.HasSHA1 = true
+ }
+
+ switch extractBits(isar0, 12, 15) {
+ case 1, 2:
+ ARM64.HasSHA2 = true
+ }
+
+ switch extractBits(isar0, 16, 19) {
+ case 1:
+ ARM64.HasCRC32 = true
+ }
+
+ switch extractBits(isar0, 20, 23) {
+ case 2:
+ ARM64.HasATOMICS = true
+ }
+ default:
+ // Other operating systems do not support reading HWCap from auxillary vector
+ // or reading privileged aarch64 system registers in user space.
+ }
+}
+
+func extractBits(data uint64, start, end uint) uint {
+ return (uint)(data>>start) & ((1 << (end - start + 1)) - 1)
}
func isSet(hwc uint, value uint) bool {
return hwc&value != 0
}
+
+func getisar0() uint64
diff --git a/src/internal/cpu/cpu_arm64.s b/src/internal/cpu/cpu_arm64.s
new file mode 100644
index 0000000000..d85914973f
--- /dev/null
+++ b/src/internal/cpu/cpu_arm64.s
@@ -0,0 +1,12 @@
+// Copyright 2020 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.
+
+#include "textflag.h"
+
+// func getisar0() uint64
+TEXT ·getisar0(SB),NOSPLIT,$0
+ // get Instruction Set Attributes 0 into R0
+ MRS ID_AA64ISAR0_EL1, R0
+ MOVD R0, ret+0(FP)
+ RET
diff --git a/src/internal/cpu/cpu_freebsd.go b/src/internal/cpu/cpu_freebsd.go
new file mode 100644
index 0000000000..dc37173dac
--- /dev/null
+++ b/src/internal/cpu/cpu_freebsd.go
@@ -0,0 +1,7 @@
+// Copyright 2020 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.
+
+package cpu
+
+const GOOS = "freebsd"
diff --git a/src/internal/cpu/cpu_linux.go b/src/internal/cpu/cpu_linux.go
new file mode 100644
index 0000000000..ec0b84c510
--- /dev/null
+++ b/src/internal/cpu/cpu_linux.go
@@ -0,0 +1,9 @@
+// Copyright 2020 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 !android
+
+package cpu
+
+const GOOS = "linux"
diff --git a/src/internal/cpu/cpu_other.go b/src/internal/cpu/cpu_other.go
new file mode 100644
index 0000000000..8a15fbe79d
--- /dev/null
+++ b/src/internal/cpu/cpu_other.go
@@ -0,0 +1,11 @@
+// Copyright 2020 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 !linux
+// +build !freebsd
+// +build !android
+
+package cpu
+
+const GOOS = "other"