aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarlos Eduardo Seo <cseo@linux.vnet.ibm.com>2017-07-10 15:28:27 -0300
committerLynn Boger <laboger@linux.vnet.ibm.com>2017-08-14 12:16:42 +0000
commit6661cf6dfd91dc3dd5d233e8bdb9f2d60829c68e (patch)
tree152e2e9bacdcc9f5814b449705e534c8fe9541ea /src
parent01385b1bb64328040cdd2ea32e3de9ce8d22386a (diff)
downloadgo-6661cf6dfd91dc3dd5d233e8bdb9f2d60829c68e.tar.xz
runtime, internal/cpu: CPU capabilities detection for ppc64x
This change replaces the current runtime capabilities check for ppc64x with the new internal/cpu package. It also adds support for the new POWER9 ISA and capabilities. Updates #15403 Change-Id: I5b64a79e782f8da3603e5529600434f602986292 Reviewed-on: https://go-review.googlesource.com/53830 Reviewed-by: Martin Möhrmann <moehrmann@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/internal/cpu/cpu.go25
-rw-r--r--src/internal/cpu/cpu_ppc64.go7
-rw-r--r--src/internal/cpu/cpu_ppc64le.go7
-rw-r--r--src/internal/cpu/cpu_ppc64x.go54
-rw-r--r--src/internal/cpu/cpu_test.go23
-rw-r--r--src/runtime/os_linux_ppc64x.go53
6 files changed, 112 insertions, 57 deletions
diff --git a/src/internal/cpu/cpu.go b/src/internal/cpu/cpu.go
index 2226b777e2..6a8e23d425 100644
--- a/src/internal/cpu/cpu.go
+++ b/src/internal/cpu/cpu.go
@@ -30,3 +30,28 @@ type x86 struct {
HasSSE42 bool
_ [CacheLineSize]byte
}
+
+var PPC64 ppc64
+
+// For ppc64x, it is safe to check only for ISA level starting on ISA v3.00,
+// since there are no optional categories. There are some exceptions that also
+// require kernel support to work (darn, scv), so there are capability bits for
+// those as well. The minimum processor requirement is POWER8 (ISA 2.07), so we
+// maintain some of the old capability checks for optional categories for
+// safety.
+// The struct is padded to avoid false sharing.
+type ppc64 struct {
+ _ [CacheLineSize]byte
+ HasVMX bool // Vector unit (Altivec)
+ HasDFP bool // Decimal Floating Point unit
+ HasVSX bool // Vector-scalar unit
+ HasHTM bool // Hardware Transactional Memory
+ HasISEL bool // Integer select
+ HasVCRYPTO bool // Vector cryptography
+ HasHTMNOSC bool // HTM: kernel-aborted transaction in syscalls
+ HasDARN bool // Hardware random number generator (requires kernel enablement)
+ HasSCV bool // Syscall vectored (requires kernel enablement)
+ IsPOWER8 bool // ISA v2.07 (POWER8)
+ IsPOWER9 bool // ISA v3.00 (POWER9)
+ _ [CacheLineSize]byte
+}
diff --git a/src/internal/cpu/cpu_ppc64.go b/src/internal/cpu/cpu_ppc64.go
deleted file mode 100644
index 5b15150847..0000000000
--- a/src/internal/cpu/cpu_ppc64.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2017 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 CacheLineSize = 128
diff --git a/src/internal/cpu/cpu_ppc64le.go b/src/internal/cpu/cpu_ppc64le.go
deleted file mode 100644
index 5b15150847..0000000000
--- a/src/internal/cpu/cpu_ppc64le.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2017 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 CacheLineSize = 128
diff --git a/src/internal/cpu/cpu_ppc64x.go b/src/internal/cpu/cpu_ppc64x.go
new file mode 100644
index 0000000000..7f093723b2
--- /dev/null
+++ b/src/internal/cpu/cpu_ppc64x.go
@@ -0,0 +1,54 @@
+// Copyright 2017 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 ppc64 ppc64le
+
+package cpu
+
+const CacheLineSize = 128
+
+// ppc64x doesn't have a 'cpuid' equivalent, so we rely on HWCAP/HWCAP2.
+// These are linknamed in runtime/os_linux_ppc64x.go and are initialized by
+// archauxv().
+var ppc64x_hwcap uint
+var ppc64x_hwcap2 uint
+
+// HWCAP/HWCAP2 bits. These are exposed by the kernel.
+const (
+ // ISA Level
+ _PPC_FEATURE2_ARCH_2_07 = 0x80000000
+ _PPC_FEATURE2_ARCH_3_00 = 0x00800000
+
+ // CPU features
+ _PPC_FEATURE_HAS_ALTIVEC = 0x10000000
+ _PPC_FEATURE_HAS_DFP = 0x00000400
+ _PPC_FEATURE_HAS_VSX = 0x00000080
+ _PPC_FEATURE2_HAS_HTM = 0x40000000
+ _PPC_FEATURE2_HAS_ISEL = 0x08000000
+ _PPC_FEATURE2_HAS_VEC_CRYPTO = 0x02000000
+ _PPC_FEATURE2_HTM_NOSC = 0x01000000
+ _PPC_FEATURE2_DARN = 0x00200000
+ _PPC_FEATURE2_SCV = 0x00100000
+)
+
+func init() {
+ // HWCAP feature bits
+ PPC64.HasVMX = isSet(ppc64x_hwcap, _PPC_FEATURE_HAS_ALTIVEC)
+ PPC64.HasDFP = isSet(ppc64x_hwcap, _PPC_FEATURE_HAS_DFP)
+ PPC64.HasVSX = isSet(ppc64x_hwcap, _PPC_FEATURE_HAS_VSX)
+
+ // HWCAP2 feature bits
+ PPC64.IsPOWER8 = isSet(ppc64x_hwcap2, _PPC_FEATURE2_ARCH_2_07)
+ PPC64.HasHTM = isSet(ppc64x_hwcap2, _PPC_FEATURE2_HAS_HTM)
+ PPC64.HasISEL = isSet(ppc64x_hwcap2, _PPC_FEATURE2_HAS_ISEL)
+ PPC64.HasVCRYPTO = isSet(ppc64x_hwcap2, _PPC_FEATURE2_HAS_VEC_CRYPTO)
+ PPC64.HasHTMNOSC = isSet(ppc64x_hwcap2, _PPC_FEATURE2_HTM_NOSC)
+ PPC64.IsPOWER9 = isSet(ppc64x_hwcap2, _PPC_FEATURE2_ARCH_3_00)
+ PPC64.HasDARN = isSet(ppc64x_hwcap2, _PPC_FEATURE2_DARN)
+ PPC64.HasSCV = isSet(ppc64x_hwcap2, _PPC_FEATURE2_SCV)
+}
+
+func isSet(hwc uint, value uint) bool {
+ return hwc&value != 0
+}
diff --git a/src/internal/cpu/cpu_test.go b/src/internal/cpu/cpu_test.go
index ab9836ac2f..07b0243f30 100644
--- a/src/internal/cpu/cpu_test.go
+++ b/src/internal/cpu/cpu_test.go
@@ -25,3 +25,26 @@ func TestAVX2hasAVX(t *testing.T) {
}
}
}
+
+func TestPPC64minimalFeatures(t *testing.T) {
+ if runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" {
+ if !cpu.PPC64.IsPOWER8 {
+ t.Fatalf("IsPOWER8 expected true, got false")
+ }
+ if !cpu.PPC64.HasVMX {
+ t.Fatalf("HasVMX expected true, got false")
+ }
+ if !cpu.PPC64.HasDFP {
+ t.Fatalf("HasDFP expected true, got false")
+ }
+ if !cpu.PPC64.HasVSX {
+ t.Fatalf("HasVSX expected true, got false")
+ }
+ if !cpu.PPC64.HasISEL {
+ t.Fatalf("HasISEL expected true, got false")
+ }
+ if !cpu.PPC64.HasVCRYPTO {
+ t.Fatalf("HasVCRYPTO expected true, got false")
+ }
+ }
+}
diff --git a/src/runtime/os_linux_ppc64x.go b/src/runtime/os_linux_ppc64x.go
index b0da98b0bd..e37bfc453a 100644
--- a/src/runtime/os_linux_ppc64x.go
+++ b/src/runtime/os_linux_ppc64x.go
@@ -6,55 +6,22 @@
package runtime
-import (
- "runtime/internal/sys"
-)
+// For go:linkname
+import _ "unsafe"
-const (
- // ISA level
- // Go currently requires POWER5 as a minimum for ppc64, so we need
- // to check for ISA 2.03 and beyond.
- _PPC_FEATURE_POWER5_PLUS = 0x00020000 // ISA 2.03 (POWER5+)
- _PPC_FEATURE_ARCH_2_05 = 0x00001000 // ISA 2.05 (POWER6)
- _PPC_FEATURE_POWER6_EXT = 0x00000200 // mffgpr/mftgpr extension (POWER6x)
- _PPC_FEATURE_ARCH_2_06 = 0x00000100 // ISA 2.06 (POWER7)
- _PPC_FEATURE2_ARCH_2_07 = 0x80000000 // ISA 2.07 (POWER8)
+// ppc64x doesn't have a 'cpuid' instruction equivalent and relies on
+// HWCAP/HWCAP2 bits for hardware capabilities.
- // Standalone capabilities
- _PPC_FEATURE_HAS_ALTIVEC = 0x10000000 // SIMD/Vector unit
- _PPC_FEATURE_HAS_VSX = 0x00000080 // Vector scalar unit
-)
-
-type facilities struct {
- _ [sys.CacheLineSize]byte
- isPOWER5x bool // ISA 2.03
- isPOWER6 bool // ISA 2.05
- isPOWER6x bool // ISA 2.05 + mffgpr/mftgpr extension
- isPOWER7 bool // ISA 2.06
- isPOWER8 bool // ISA 2.07
- hasVMX bool // Vector unit
- hasVSX bool // Vector scalar unit
- _ [sys.CacheLineSize]byte
-}
-
-// cpu can be tested at runtime in go assembler code to check for
-// a certain ISA level or hardware capability, for example:
-// ·cpu+facilities_hasVSX(SB) for checking the availability of VSX
-// or
-// ·cpu+facilities_isPOWER7(SB) for checking if the processor implements
-// ISA 2.06 instructions.
-var cpu facilities
+//go:linkname cpu_hwcap internal/cpu.ppc64x_hwcap
+//go:linkname cpu_hwcap2 internal/cpu.ppc64x_hwcap2
+var cpu_hwcap uint
+var cpu_hwcap2 uint
func archauxv(tag, val uintptr) {
switch tag {
case _AT_HWCAP:
- cpu.isPOWER5x = val&_PPC_FEATURE_POWER5_PLUS != 0
- cpu.isPOWER6 = val&_PPC_FEATURE_ARCH_2_05 != 0
- cpu.isPOWER6x = val&_PPC_FEATURE_POWER6_EXT != 0
- cpu.isPOWER7 = val&_PPC_FEATURE_ARCH_2_06 != 0
- cpu.hasVMX = val&_PPC_FEATURE_HAS_ALTIVEC != 0
- cpu.hasVSX = val&_PPC_FEATURE_HAS_VSX != 0
+ cpu_hwcap = uint(val)
case _AT_HWCAP2:
- cpu.isPOWER8 = val&_PPC_FEATURE2_ARCH_2_07 != 0
+ cpu_hwcap2 = uint(val)
}
}