cpu: add linux/arm64

Port from Go internal/cpu

Updates golang/go#25185

Change-Id: I8390980e38b61f6c428fafa0665a03952e7b00bb
Reviewed-on: https://go-review.googlesource.com/c/150718
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Martin Möhrmann <moehrmann@google.com>
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
diff --git a/cpu/cpu_linux.go b/cpu/cpu_linux.go
new file mode 100644
index 0000000..126bb68
--- /dev/null
+++ b/cpu/cpu_linux.go
@@ -0,0 +1,55 @@
+// Copyright 2018 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 !amd64,!amd64p32,!386
+
+package cpu
+
+import (
+	"encoding/binary"
+	"io/ioutil"
+)
+
+const (
+	_AT_HWCAP  = 16
+	_AT_HWCAP2 = 26
+
+	procAuxv = "/proc/self/auxv"
+
+	uintSize uint = 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 {
+		panic("read proc auxv failed: " + err.Error())
+	}
+
+	pb := int(uintSize / 8)
+
+	for i := 0; i < len(buf)-pb*2; i += pb * 2 {
+		var tag, val uint
+		switch uintSize {
+		case 32:
+			tag = uint(binary.LittleEndian.Uint32(buf[i:]))
+			val = uint(binary.LittleEndian.Uint32(buf[i+pb:]))
+		case 64:
+			tag = uint(binary.LittleEndian.Uint64(buf[i:]))
+			val = uint(binary.LittleEndian.Uint64(buf[i+pb:]))
+		}
+		switch tag {
+		case _AT_HWCAP:
+			HWCap = val
+		case _AT_HWCAP2:
+			HWCap2 = val
+		}
+	}
+	doinit()
+}