Forráskód Böngészése

cpu: add linux/ppc64x

Port from Go internal/cpu.

Fixes golang/go#25185

Change-Id: Id3cac18da6ffec9d10df755c4032ce3068ab634d
Reviewed-on: https://go-review.googlesource.com/c/152938
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Carlos Eduardo Seo 7 éve
szülő
commit
20be8e55dc
4 módosított fájl, 61 hozzáadás és 3 törlés
  1. 17 0
      cpu/cpu.go
  2. 8 2
      cpu/cpu_linux.go
  3. 22 1
      cpu/cpu_ppc64x.go
  4. 14 0
      cpu/cpu_test.go

+ 17 - 0
cpu/cpu.go

@@ -68,3 +68,20 @@ var ARM64 struct {
 	HasASIMDFHM bool // Advanced SIMD multiplication FP16 to FP32
 	HasASIMDFHM bool // Advanced SIMD multiplication FP16 to FP32
 	_           CacheLinePad
 	_           CacheLinePad
 }
 }
+
+// PPC64 contains the supported CPU features of the current ppc64/ppc64le platforms.
+// If the current platform is not ppc64/ppc64le then all feature flags are false.
+//
+// For ppc64/ppc64le, 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 feature bits for
+// those as well. The minimum processor requirement is POWER8 (ISA 2.07).
+// The struct is padded to avoid false sharing.
+var PPC64 struct {
+	_        CacheLinePad
+	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)
+	_        CacheLinePad
+}

+ 8 - 2
cpu/cpu_linux.go

@@ -9,6 +9,7 @@ package cpu
 import (
 import (
 	"encoding/binary"
 	"encoding/binary"
 	"io/ioutil"
 	"io/ioutil"
+	"runtime"
 )
 )
 
 
 const (
 const (
@@ -41,8 +42,13 @@ func init() {
 			tag = uint(binary.LittleEndian.Uint32(buf[i:]))
 			tag = uint(binary.LittleEndian.Uint32(buf[i:]))
 			val = uint(binary.LittleEndian.Uint32(buf[i+pb:]))
 			val = uint(binary.LittleEndian.Uint32(buf[i+pb:]))
 		case 64:
 		case 64:
-			tag = uint(binary.LittleEndian.Uint64(buf[i:]))
-			val = uint(binary.LittleEndian.Uint64(buf[i+pb:]))
+			if runtime.GOARCH == "ppc64" {
+				tag = uint(binary.BigEndian.Uint64(buf[i:]))
+				val = uint(binary.BigEndian.Uint64(buf[i+pb:]))
+			} else {
+				tag = uint(binary.LittleEndian.Uint64(buf[i:]))
+				val = uint(binary.LittleEndian.Uint64(buf[i+pb:]))
+			}
 		}
 		}
 		switch tag {
 		switch tag {
 		case _AT_HWCAP:
 		case _AT_HWCAP:

+ 22 - 1
cpu/cpu_ppc64x.go

@@ -8,4 +8,25 @@ package cpu
 
 
 const cacheLineSize = 128
 const cacheLineSize = 128
 
 
-func doinit() {}
+// 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_FEATURE2_DARN = 0x00200000
+	_PPC_FEATURE2_SCV  = 0x00100000
+)
+
+func doinit() {
+	// HWCAP2 feature bits
+	PPC64.IsPOWER8 = isSet(HWCap2, _PPC_FEATURE2_ARCH_2_07)
+	PPC64.IsPOWER9 = isSet(HWCap2, _PPC_FEATURE2_ARCH_3_00)
+	PPC64.HasDARN = isSet(HWCap2, _PPC_FEATURE2_DARN)
+	PPC64.HasSCV = isSet(HWCap2, _PPC_FEATURE2_SCV)
+}
+
+func isSet(hwc uint, value uint) bool {
+	return hwc&value != 0
+}

+ 14 - 0
cpu/cpu_test.go

@@ -38,3 +38,17 @@ func TestARM64minimalFeatures(t *testing.T) {
 		t.Fatal("HasFP expected true, got false")
 		t.Fatal("HasFP expected true, got false")
 	}
 	}
 }
 }
+
+// On ppc64x, the ISA bit for POWER8 should always be set on POWER8 and beyond.
+func TestPPC64minimalFeatures(t *testing.T) {
+	// Do not run this with gccgo on ppc64, as it doesn't have POWER8 as a minimum
+	// requirement.
+	if runtime.Compiler == "gccgo" && runtime.GOARCH == "ppc64" {
+		t.Skip("gccgo does not require POWER8 on ppc64; skipping")
+	}
+	if runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" {
+		if !cpu.PPC64.IsPOWER8 {
+			t.Fatal("IsPOWER8 expected true, got false")
+		}
+	}
+}