Commit 6661cf6d authored by Carlos Eduardo Seo's avatar Carlos Eduardo Seo Committed by Lynn Boger

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/53830Reviewed-by: default avatarMartin Möhrmann <moehrmann@google.com>
parent 01385b1b
......@@ -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
}
// 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
// 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
// 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)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment