1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 5 package cpu
6 7 import (
8 "os"
9 )
10 11 const (
12 _AT_HWCAP = 16
13 _AT_HWCAP2 = 26
14 15 procAuxv = "/proc/self/auxv"
16 17 uintSize = int(32 << (^uint(0) >> 63))
18 )
19 20 // For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2
21 // These are initialized in cpu_$GOARCH.go
22 // and should not be changed after they are initialized.
23 var hwCap uint
24 var hwCap2 uint
25 26 func readHWCAP() error {
27 // For Go 1.21+, get auxv from the Go runtime.
28 if a := getAuxv(); len(a) > 0 {
29 for len(a) >= 2 {
30 tag, val := a[0], uint(a[1])
31 a = a[2:]
32 switch tag {
33 case _AT_HWCAP:
34 hwCap = val
35 case _AT_HWCAP2:
36 hwCap2 = val
37 }
38 }
39 return nil
40 }
41 42 buf, err := os.ReadFile(procAuxv)
43 if err != nil {
44 // e.g. on android /proc/self/auxv is not accessible, so silently
45 // ignore the error and leave Initialized = false. On some
46 // architectures (e.g. arm64) doinit() implements a fallback
47 // readout and will set Initialized = true again.
48 return err
49 }
50 bo := hostByteOrder()
51 for len(buf) >= 2*(uintSize/8) {
52 var tag, val uint
53 switch uintSize {
54 case 32:
55 tag = uint(bo.Uint32(buf[0:]))
56 val = uint(bo.Uint32(buf[4:]))
57 buf = buf[8:]
58 case 64:
59 tag = uint(bo.Uint64(buf[0:]))
60 val = uint(bo.Uint64(buf[8:]))
61 buf = buf[16:]
62 }
63 switch tag {
64 case _AT_HWCAP:
65 hwCap = val
66 case _AT_HWCAP2:
67 hwCap2 = val
68 }
69 }
70 return nil
71 }
72