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
+}
 
+++ /dev/null
-// 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
 
+++ /dev/null
-// 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
 
--- /dev/null
+// 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
+}
 
                }
        }
 }
+
+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")
+               }
+       }
+}
 
 
 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)
        }
 }