cpu: add mips64x feature detection

Follow CL 200579

Change-Id: Ibedd6569bda3d7836ccb77a7746ed0e5df13c633
Reviewed-on: https://go-review.googlesource.com/c/sys/+/221698
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/cpu/cpu.go b/cpu/cpu.go
index b4e6ecb..e44deb7 100644
--- a/cpu/cpu.go
+++ b/cpu/cpu.go
@@ -114,6 +114,15 @@
 	_           CacheLinePad
 }
 
+// MIPS64X contains the supported CPU features of the current mips64/mips64le
+// platforms. If the current platform is not mips64/mips64le or the current
+// operating system is not Linux then all feature flags are false.
+var MIPS64X struct {
+	_      CacheLinePad
+	HasMSA bool // MIPS SIMD architecture
+	_      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.
 //
diff --git a/cpu/cpu_linux_mips64x.go b/cpu/cpu_linux_mips64x.go
new file mode 100644
index 0000000..eb24e50
--- /dev/null
+++ b/cpu/cpu_linux_mips64x.go
@@ -0,0 +1,22 @@
+// Copyright 2020 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 mips64 mips64le
+
+package cpu
+
+// HWCAP bits. These are exposed by the Linux kernel 5.4.
+const (
+	// CPU features
+	hwcap_MIPS_MSA = 1 << 1
+)
+
+func doinit() {
+	// HWCAP feature bits
+	MIPS64X.HasMSA = isSet(hwCap, hwcap_MIPS_MSA)
+}
+
+func isSet(hwc uint, value uint) bool {
+	return hwc&value != 0
+}
diff --git a/cpu/cpu_linux_noinit.go b/cpu/cpu_linux_noinit.go
index f65134f..42b5d33 100644
--- a/cpu/cpu_linux_noinit.go
+++ b/cpu/cpu_linux_noinit.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build linux,!arm,!arm64,!ppc64,!ppc64le,!s390x
+// +build linux,!arm,!arm64,!mips64,!mips64le,!ppc64,!ppc64le,!s390x
 
 package cpu
 
diff --git a/cpu/cpu_test.go b/cpu/cpu_test.go
index d37f097..83fa5ef 100644
--- a/cpu/cpu_test.go
+++ b/cpu/cpu_test.go
@@ -42,6 +42,14 @@
 	}
 }
 
+func TestMIPS64Initialized(t *testing.T) {
+	if runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" {
+		if !cpu.Initialized {
+			t.Fatal("Initialized 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