cpu: support reading arm64 CPU feature registers

This allows to detect ARM64 CPU features on non-Linux systems. On Linux,
this is used in case /proc/self/auxv cannot be read.

Change-Id: I67d55e989f2beda0c05a97ca5e55781840a8e01c
Reviewed-on: https://go-review.googlesource.com/c/sys/+/209478
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_linux.go b/cpu/cpu_linux.go
index 10e712d..fe13918 100644
--- a/cpu/cpu_linux.go
+++ b/cpu/cpu_linux.go
@@ -2,58 +2,14 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !amd64,!amd64p32,!386
+// +build !386,!amd64,!amd64p32,!arm64
 
 package cpu
 
-import (
-	"io/ioutil"
-)
-
-const (
-	_AT_HWCAP  = 16
-	_AT_HWCAP2 = 26
-
-	procAuxv = "/proc/self/auxv"
-
-	uintSize = int(32 << (^uint(0) >> 63))
-)
-
-// For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2
-// These are initialized in cpu_$GOARCH.go
-// and should not be changed after they are initialized.
-var hwCap uint
-var hwCap2 uint
-
 func init() {
-	buf, err := ioutil.ReadFile(procAuxv)
-	if err != nil {
-		// e.g. on android /proc/self/auxv is not accessible, so silently
-		// ignore the error and leave Initialized = false
+	if err := readHWCAP(); err != nil {
 		return
 	}
-
-	bo := hostByteOrder()
-	for len(buf) >= 2*(uintSize/8) {
-		var tag, val uint
-		switch uintSize {
-		case 32:
-			tag = uint(bo.Uint32(buf[0:]))
-			val = uint(bo.Uint32(buf[4:]))
-			buf = buf[8:]
-		case 64:
-			tag = uint(bo.Uint64(buf[0:]))
-			val = uint(bo.Uint64(buf[8:]))
-			buf = buf[16:]
-		}
-		switch tag {
-		case _AT_HWCAP:
-			hwCap = val
-		case _AT_HWCAP2:
-			hwCap2 = val
-		}
-	}
 	doinit()
-
 	Initialized = true
 }