1 // Copyright 2017 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "cpuinfo_arm.h"
16
17 #include "filesystem_for_testing.h"
18 #include "gtest/gtest.h"
19 #include "hwcaps_for_testing.h"
20
21 namespace cpu_features {
22 namespace {
23
DisableHardwareCapabilities()24 void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); }
25
TEST(CpuinfoArmTest,FromHardwareCap)26 TEST(CpuinfoArmTest, FromHardwareCap) {
27 SetHardwareCapabilities(ARM_HWCAP_NEON, ARM_HWCAP2_AES | ARM_HWCAP2_CRC32);
28 GetEmptyFilesystem(); // disabling /proc/cpuinfo
29 const auto info = GetArmInfo();
30 EXPECT_TRUE(info.features.vfp); // triggered by vfpv3
31 EXPECT_TRUE(info.features.vfpv3); // triggered by neon
32 EXPECT_TRUE(info.features.neon);
33 EXPECT_TRUE(info.features.aes);
34 EXPECT_TRUE(info.features.crc32);
35
36 EXPECT_FALSE(info.features.vfpv4);
37 EXPECT_FALSE(info.features.iwmmxt);
38 EXPECT_FALSE(info.features.crunch);
39 EXPECT_FALSE(info.features.thumbee);
40 EXPECT_FALSE(info.features.vfpv3d16);
41 EXPECT_FALSE(info.features.idiva);
42 EXPECT_FALSE(info.features.idivt);
43 EXPECT_FALSE(info.features.pmull);
44 EXPECT_FALSE(info.features.sha1);
45 EXPECT_FALSE(info.features.sha2);
46
47 // check some random features with EnumValue():
48 EXPECT_TRUE(GetArmFeaturesEnumValue(&info.features, ARM_VFP));
49 EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, ARM_VFPV4));
50 // out of bound EnumValue() check
51 EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, (ArmFeaturesEnum)~0x0));
52 }
53
TEST(CpuinfoArmTest,ODroidFromCpuInfo)54 TEST(CpuinfoArmTest, ODroidFromCpuInfo) {
55 DisableHardwareCapabilities();
56 auto& fs = GetEmptyFilesystem();
57 fs.CreateFile("/proc/cpuinfo", R"(processor : 0
58 model name : ARMv7 Processor rev 3 (v71)
59 BogoMIPS : 120.00
60 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae
61 CPU implementer : 0x41
62 CPU architecture: 7
63 CPU variant : 0x2
64 CPU part : 0xc0f
65 CPU revision : 3)");
66 const auto info = GetArmInfo();
67 EXPECT_EQ(info.implementer, 0x41);
68 EXPECT_EQ(info.variant, 0x2);
69 EXPECT_EQ(info.part, 0xc0f);
70 EXPECT_EQ(info.revision, 3);
71 EXPECT_EQ(info.architecture, 7);
72
73 EXPECT_FALSE(info.features.swp);
74 EXPECT_TRUE(info.features.half);
75 EXPECT_TRUE(info.features.thumb);
76 EXPECT_FALSE(info.features._26bit);
77 EXPECT_TRUE(info.features.fastmult);
78 EXPECT_FALSE(info.features.fpa);
79 EXPECT_TRUE(info.features.vfp);
80 EXPECT_TRUE(info.features.edsp);
81 EXPECT_FALSE(info.features.java);
82 EXPECT_FALSE(info.features.iwmmxt);
83 EXPECT_FALSE(info.features.crunch);
84 EXPECT_FALSE(info.features.thumbee);
85 EXPECT_TRUE(info.features.neon);
86 EXPECT_TRUE(info.features.vfpv3);
87 EXPECT_FALSE(info.features.vfpv3d16);
88 EXPECT_TRUE(info.features.tls);
89 EXPECT_TRUE(info.features.vfpv4);
90 EXPECT_TRUE(info.features.idiva);
91 EXPECT_TRUE(info.features.idivt);
92 EXPECT_TRUE(info.features.vfpd32);
93 EXPECT_TRUE(info.features.lpae);
94 EXPECT_FALSE(info.features.evtstrm);
95 EXPECT_FALSE(info.features.aes);
96 EXPECT_FALSE(info.features.pmull);
97 EXPECT_FALSE(info.features.sha1);
98 EXPECT_FALSE(info.features.sha2);
99 EXPECT_FALSE(info.features.crc32);
100 }
101
102 // Linux test-case
TEST(CpuinfoArmTest,RaspberryPiZeroFromCpuInfo)103 TEST(CpuinfoArmTest, RaspberryPiZeroFromCpuInfo) {
104 DisableHardwareCapabilities();
105 auto& fs = GetEmptyFilesystem();
106 fs.CreateFile("/proc/cpuinfo", R"(processor : 0
107 model name : ARMv6-compatible processor rev 7 (v6l)
108 BogoMIPS : 697.95
109 Features : half thumb fastmult vfp edsp java tls
110 CPU implementer : 0x41
111 CPU architecture: 7
112 CPU variant : 0x0
113 CPU part : 0xb76
114 CPU revision : 7
115
116 Hardware : BCM2835
117 Revision : 9000c1
118 Serial : 000000006cd946f3)");
119 const auto info = GetArmInfo();
120 EXPECT_EQ(info.implementer, 0x41);
121 EXPECT_EQ(info.variant, 0x0);
122 EXPECT_EQ(info.part, 0xb76);
123 EXPECT_EQ(info.revision, 7);
124 EXPECT_EQ(info.architecture, 6);
125
126 EXPECT_FALSE(info.features.swp);
127 EXPECT_TRUE(info.features.half);
128 EXPECT_TRUE(info.features.thumb);
129 EXPECT_FALSE(info.features._26bit);
130 EXPECT_TRUE(info.features.fastmult);
131 EXPECT_FALSE(info.features.fpa);
132 EXPECT_TRUE(info.features.vfp);
133 EXPECT_TRUE(info.features.edsp);
134 EXPECT_TRUE(info.features.java);
135 EXPECT_FALSE(info.features.iwmmxt);
136 EXPECT_FALSE(info.features.crunch);
137 EXPECT_FALSE(info.features.thumbee);
138 EXPECT_FALSE(info.features.neon);
139 EXPECT_FALSE(info.features.vfpv3);
140 EXPECT_FALSE(info.features.vfpv3d16);
141 EXPECT_TRUE(info.features.tls);
142 EXPECT_FALSE(info.features.vfpv4);
143 EXPECT_FALSE(info.features.idiva);
144 EXPECT_FALSE(info.features.idivt);
145 EXPECT_FALSE(info.features.vfpd32);
146 EXPECT_FALSE(info.features.lpae);
147 EXPECT_FALSE(info.features.evtstrm);
148 EXPECT_FALSE(info.features.aes);
149 EXPECT_FALSE(info.features.pmull);
150 EXPECT_FALSE(info.features.sha1);
151 EXPECT_FALSE(info.features.sha2);
152 EXPECT_FALSE(info.features.crc32);
153 }
154
TEST(CpuinfoArmTest,MarvellArmadaFromCpuInfo)155 TEST(CpuinfoArmTest, MarvellArmadaFromCpuInfo) {
156 DisableHardwareCapabilities();
157 auto& fs = GetEmptyFilesystem();
158 fs.CreateFile("/proc/cpuinfo", R"(processor : 0
159 model name : ARMv7 Processor rev 1 (v7l)
160 BogoMIPS : 50.00
161 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
162 CPU implementer : 0x41
163 CPU architecture: 7
164 CPU variant : 0x4
165 CPU part : 0xc09
166 CPU revision : 1
167
168 processor : 1
169 model name : ARMv7 Processor rev 1 (v7l)
170 BogoMIPS : 50.00
171 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
172 CPU implementer : 0x41
173 CPU architecture: 7
174 CPU variant : 0x4
175 CPU part : 0xc09
176 CPU revision : 1
177
178 Hardware : Marvell Armada 380/385 (Device Tree)
179 Revision : 0000
180 Serial : 0000000000000000)");
181 const auto info = GetArmInfo();
182 EXPECT_EQ(info.implementer, 0x41);
183 EXPECT_EQ(info.variant, 0x4);
184 EXPECT_EQ(info.part, 0xc09);
185 EXPECT_EQ(info.revision, 1);
186 EXPECT_EQ(info.architecture, 7);
187
188 EXPECT_FALSE(info.features.swp);
189 EXPECT_TRUE(info.features.half);
190 EXPECT_TRUE(info.features.thumb);
191 EXPECT_FALSE(info.features._26bit);
192 EXPECT_TRUE(info.features.fastmult);
193 EXPECT_FALSE(info.features.fpa);
194 EXPECT_TRUE(info.features.vfp);
195 EXPECT_TRUE(info.features.edsp);
196 EXPECT_FALSE(info.features.java);
197 EXPECT_FALSE(info.features.iwmmxt);
198 EXPECT_FALSE(info.features.crunch);
199 EXPECT_FALSE(info.features.thumbee);
200 EXPECT_TRUE(info.features.neon);
201 EXPECT_TRUE(info.features.vfpv3);
202 EXPECT_FALSE(info.features.vfpv3d16);
203 EXPECT_TRUE(info.features.tls);
204 EXPECT_FALSE(info.features.vfpv4);
205 EXPECT_FALSE(info.features.idiva);
206 EXPECT_FALSE(info.features.idivt);
207 EXPECT_TRUE(info.features.vfpd32);
208 EXPECT_FALSE(info.features.lpae);
209 EXPECT_FALSE(info.features.evtstrm);
210 EXPECT_FALSE(info.features.aes);
211 EXPECT_FALSE(info.features.pmull);
212 EXPECT_FALSE(info.features.sha1);
213 EXPECT_FALSE(info.features.sha2);
214 EXPECT_FALSE(info.features.crc32);
215 }
216
217 // Android test-case
218 // http://code.google.com/p/android/issues/detail?id=10812
TEST(CpuinfoArmTest,InvalidArmv7)219 TEST(CpuinfoArmTest, InvalidArmv7) {
220 DisableHardwareCapabilities();
221 auto& fs = GetEmptyFilesystem();
222 fs.CreateFile("/proc/cpuinfo",
223 R"(Processor : ARMv6-compatible processor rev 6 (v6l)
224 BogoMIPS : 199.47
225 Features : swp half thumb fastmult vfp edsp java
226 CPU implementer : 0x41
227 CPU architecture: 7
228 CPU variant : 0x0
229 CPU part : 0xb76
230 CPU revision : 6
231
232 Hardware : SPICA
233 Revision : 0020
234 Serial : 33323613546d00ec )");
235 const auto info = GetArmInfo();
236 EXPECT_EQ(info.architecture, 6);
237
238 EXPECT_TRUE(info.features.swp);
239 EXPECT_TRUE(info.features.half);
240 EXPECT_TRUE(info.features.thumb);
241 EXPECT_FALSE(info.features._26bit);
242 EXPECT_TRUE(info.features.fastmult);
243 EXPECT_FALSE(info.features.fpa);
244 EXPECT_TRUE(info.features.vfp);
245 EXPECT_TRUE(info.features.edsp);
246 EXPECT_TRUE(info.features.java);
247 EXPECT_FALSE(info.features.iwmmxt);
248 EXPECT_FALSE(info.features.crunch);
249 EXPECT_FALSE(info.features.thumbee);
250 EXPECT_FALSE(info.features.neon);
251 EXPECT_FALSE(info.features.vfpv3);
252 EXPECT_FALSE(info.features.vfpv3d16);
253 EXPECT_FALSE(info.features.tls);
254 EXPECT_FALSE(info.features.vfpv4);
255 EXPECT_FALSE(info.features.idiva);
256 EXPECT_FALSE(info.features.idivt);
257 EXPECT_FALSE(info.features.vfpd32);
258 EXPECT_FALSE(info.features.lpae);
259 EXPECT_FALSE(info.features.evtstrm);
260 EXPECT_FALSE(info.features.aes);
261 EXPECT_FALSE(info.features.pmull);
262 EXPECT_FALSE(info.features.sha1);
263 EXPECT_FALSE(info.features.sha2);
264 EXPECT_FALSE(info.features.crc32);
265 }
266
267 // Android test-case
268 // https://crbug.com/341598.
TEST(CpuinfoArmTest,InvalidNeon)269 TEST(CpuinfoArmTest, InvalidNeon) {
270 auto& fs = GetEmptyFilesystem();
271 fs.CreateFile("/proc/cpuinfo",
272 R"(Processor: ARMv7 Processory rev 0 (v71)
273 processor: 0
274 BogoMIPS: 13.50
275
276 Processor: 1
277 BogoMIPS: 13.50
278
279 Features: swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
280 CPU implementer : 0x51
281 CPU architecture: 7
282 CPU variant: 0x1
283 CPU part: 0x04d
284 CPU revision: 0
285
286 Hardware: SAMSUNG M2
287 Revision: 0010
288 Serial: 00001e030000354e)");
289 const auto info = GetArmInfo();
290 EXPECT_TRUE(info.features.swp);
291 EXPECT_FALSE(info.features.neon);
292 }
293
294 // The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV
295 // support.
TEST(CpuinfoArmTest,Nexus4_0x510006f2)296 TEST(CpuinfoArmTest, Nexus4_0x510006f2) {
297 DisableHardwareCapabilities();
298 auto& fs = GetEmptyFilesystem();
299 fs.CreateFile("/proc/cpuinfo",
300 R"(CPU implementer : 0x51
301 CPU architecture: 7
302 CPU variant : 0x0
303 CPU part : 0x6f
304 CPU revision : 2)");
305 const auto info = GetArmInfo();
306 EXPECT_TRUE(info.features.idiva);
307 EXPECT_TRUE(info.features.idivt);
308
309 EXPECT_EQ(GetArmCpuId(&info), 0x510006f2);
310 }
311
312 // The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV
313 // support.
TEST(CpuinfoArmTest,Nexus4_0x510006f3)314 TEST(CpuinfoArmTest, Nexus4_0x510006f3) {
315 DisableHardwareCapabilities();
316 auto& fs = GetEmptyFilesystem();
317 fs.CreateFile("/proc/cpuinfo",
318 R"(CPU implementer : 0x51
319 CPU architecture: 7
320 CPU variant : 0x0
321 CPU part : 0x6f
322 CPU revision : 3)");
323 const auto info = GetArmInfo();
324 EXPECT_TRUE(info.features.idiva);
325 EXPECT_TRUE(info.features.idivt);
326
327 EXPECT_EQ(GetArmCpuId(&info), 0x510006f3);
328 }
329
330 // The emulator-specific Android 4.2 kernel fails to report support for the
331 // 32-bit ARM IDIV instruction. Technically, this is a feature of the virtual
332 // CPU implemented by the emulator.
TEST(CpuinfoArmTest,EmulatorSpecificIdiv)333 TEST(CpuinfoArmTest, EmulatorSpecificIdiv) {
334 DisableHardwareCapabilities();
335 auto& fs = GetEmptyFilesystem();
336 fs.CreateFile("/proc/cpuinfo",
337 R"(Processor : ARMv7 Processor rev 0 (v7l)
338 BogoMIPS : 629.14
339 Features : swp half thumb fastmult vfp edsp neon vfpv3
340 CPU implementer : 0x41
341 CPU architecture: 7
342 CPU variant : 0x0
343 CPU part : 0xc08
344 CPU revision : 0
345
346 Hardware : Goldfish
347 Revision : 0000
348 Serial : 0000000000000000)");
349 const auto info = GetArmInfo();
350 EXPECT_TRUE(info.features.idiva);
351 }
352
353 } // namespace
354 } // namespace cpu_features
355