@@ -8,17 +8,154 @@ package runtime
8
8
9
9
import "internal/cpu"
10
10
11
+ func getisar0 () uint64
12
+ func getisar1 () uint64
13
+ func getpfr0 () uint64
14
+
15
+ const (
16
+ hwcap_FP = 1 << 0
17
+ hwcap_ASIMD = 1 << 1
18
+ hwcap_EVTSTRM = 1 << 2
19
+ hwcap_AES = 1 << 3
20
+ hwcap_PMULL = 1 << 4
21
+ hwcap_SHA1 = 1 << 5
22
+ hwcap_SHA2 = 1 << 6
23
+ hwcap_CRC32 = 1 << 7
24
+ hwcap_ATOMICS = 1 << 8
25
+ hwcap_FPHP = 1 << 9
26
+ hwcap_ASIMDHP = 1 << 10
27
+ hwcap_CPUID = 1 << 11
28
+ hwcap_ASIMDRDM = 1 << 12
29
+ hwcap_JSCVT = 1 << 13
30
+ hwcap_FCMA = 1 << 14
31
+ hwcap_LRCPC = 1 << 15
32
+ hwcap_DCPOP = 1 << 16
33
+ hwcap_SHA3 = 1 << 17
34
+ hwcap_SM3 = 1 << 18
35
+ hwcap_SM4 = 1 << 19
36
+ hwcap_ASIMDDP = 1 << 20
37
+ hwcap_SHA512 = 1 << 21
38
+ hwcap_SVE = 1 << 22
39
+ hwcap_ASIMDFHM = 1 << 23
40
+ )
41
+
11
42
func archauxv (tag , val uintptr ) {
12
43
switch tag {
13
44
case _AT_HWCAP :
14
45
// arm64 doesn't have a 'cpuid' instruction equivalent and relies on
15
46
// HWCAP/HWCAP2 bits for hardware capabilities.
16
- cpu .HWCap = uint (val )
47
+ // detection. See issue #31746.
48
+ var isar0 , isar1 , pfr0 uint64
49
+
50
+ isar0 = getisar0 ()
51
+ isar1 = getisar1 ()
52
+ pfr0 = getpfr0 ()
53
+
54
+ // ID_AA64ISAR0_EL1
55
+ switch extract_bits (isar0 , 4 , 7 ) {
56
+ case 1 :
57
+ cpu .HWCap |= hwcap_AES
58
+ case 2 :
59
+ cpu .HWCap |= hwcap_PMULL | hwcap_AES
60
+ }
61
+
62
+ switch extract_bits (isar0 , 8 , 11 ) {
63
+ case 1 :
64
+ cpu .HWCap |= hwcap_SHA1
65
+ }
66
+
67
+ switch extract_bits (isar0 , 12 , 15 ) {
68
+ case 1 :
69
+ cpu .HWCap |= hwcap_SHA2
70
+ case 2 :
71
+ cpu .HWCap |= hwcap_SHA2 | hwcap_SHA512
72
+ }
73
+
74
+ switch extract_bits (isar0 , 16 , 19 ) {
75
+ case 1 :
76
+ cpu .HWCap |= hwcap_CRC32
77
+ }
78
+
79
+ switch extract_bits (isar0 , 20 , 23 ) {
80
+ case 2 :
81
+ cpu .HWCap |= hwcap_ATOMICS
82
+ }
83
+
84
+ switch extract_bits (isar0 , 28 , 31 ) {
85
+ case 1 :
86
+ cpu .HWCap |= hwcap_ASIMDRDM
87
+ }
88
+
89
+ switch extract_bits (isar0 , 32 , 35 ) {
90
+ case 1 :
91
+ cpu .HWCap |= hwcap_SHA3
92
+ }
93
+
94
+ switch extract_bits (isar0 , 36 , 39 ) {
95
+ case 1 :
96
+ cpu .HWCap |= hwcap_SM3
97
+ }
98
+
99
+ switch extract_bits (isar0 , 40 , 43 ) {
100
+ case 1 :
101
+ cpu .HWCap |= hwcap_SM4
102
+ }
103
+
104
+ switch extract_bits (isar0 , 44 , 47 ) {
105
+ case 1 :
106
+ cpu .HWCap |= hwcap_ASIMDDP
107
+ }
108
+
109
+ // ID_AA64ISAR1_EL1
110
+ switch extract_bits (isar1 , 0 , 3 ) {
111
+ case 1 :
112
+ cpu .HWCap |= hwcap_DCPOP
113
+ }
114
+
115
+ switch extract_bits (isar1 , 12 , 15 ) {
116
+ case 1 :
117
+ cpu .HWCap |= hwcap_JSCVT
118
+ }
119
+
120
+ switch extract_bits (isar1 , 16 , 19 ) {
121
+ case 1 :
122
+ cpu .HWCap |= hwcap_FCMA
123
+ }
124
+
125
+ switch extract_bits (isar1 , 20 , 23 ) {
126
+ case 1 :
127
+ cpu .HWCap |= hwcap_LRCPC
128
+ }
129
+
130
+ // ID_AA64PFR0_EL1
131
+ switch extract_bits (pfr0 , 16 , 19 ) {
132
+ case 0 :
133
+ cpu .HWCap |= hwcap_FP
134
+ case 1 :
135
+ cpu .HWCap |= hwcap_FP | hwcap_FPHP
136
+ }
137
+
138
+ switch extract_bits (pfr0 , 20 , 23 ) {
139
+ case 0 :
140
+ cpu .HWCap |= hwcap_ASIMD
141
+ case 1 :
142
+ cpu .HWCap |= hwcap_ASIMD | hwcap_ASIMDHP
143
+ }
144
+
145
+ switch extract_bits (pfr0 , 32 , 35 ) {
146
+ case 1 :
147
+ cpu .HWCap |= hwcap_SVE
148
+ }
149
+
17
150
case _AT_HWCAP2 :
18
151
cpu .HWCap2 = uint (val )
19
152
}
20
153
}
21
154
155
+ func extract_bits (data uint64 , start , end uint ) uint {
156
+ return (uint )(data >> start ) & ((1 << (end - start + 1 )) - 1 )
157
+ }
158
+
22
159
//go:nosplit
23
160
func cputicks () int64 {
24
161
// Currently cputicks() is used in blocking profiler and to seed runtime·fastrand().
0 commit comments