]> Cypherpunks repositories - gostls13.git/commitdiff
runtime, internal/cpu: CPU capabilities detection for ppc64x
authorCarlos Eduardo Seo <cseo@linux.vnet.ibm.com>
Mon, 10 Jul 2017 18:28:27 +0000 (15:28 -0300)
committerLynn Boger <laboger@linux.vnet.ibm.com>
Mon, 14 Aug 2017 12:16:42 +0000 (12:16 +0000)
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>
src/internal/cpu/cpu.go
src/internal/cpu/cpu_ppc64.go [deleted file]
src/internal/cpu/cpu_ppc64le.go [deleted file]
src/internal/cpu/cpu_ppc64x.go [new file with mode: 0644]
src/internal/cpu/cpu_test.go
src/runtime/os_linux_ppc64x.go

index 2226b777e2397744a8d7b48bb154c24110cf880e..6a8e23d4257a2e61410a5d9279f5a63433d2e0ce 100644 (file)
@@ -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 (file)
index 5b15150..0000000
+++ /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 (file)
index 5b15150..0000000
+++ /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 (file)
index 0000000..7f09372
--- /dev/null
@@ -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
+}
index ab9836ac2f67675885d0ddb8fb03a6e12b6af380..07b0243f3060492e816c14155a6ee05c8057f356 100644 (file)
@@ -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")
+               }
+       }
+}
index b0da98b0bd90249762cae72338535c82610ddf3d..e37bfc453a9d6ae7f0b2fb2c774c577f8b83c532 100644 (file)
@@ -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)
        }
 }