mirror of https://github.com/golang/go.git
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>
This commit is contained in:
parent
01385b1bb6
commit
6661cf6dfd
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue