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
TEST(CpuinfoArmTest,ArmFeaturesEnum)24 TEST(CpuinfoArmTest, ArmFeaturesEnum) {
25 const char *last_name = GetArmFeaturesEnumName(ARM_LAST_);
26 EXPECT_STREQ(last_name, "unknown_feature");
27 for (int i = static_cast<int>(ARM_SWP); i != static_cast<int>(ARM_LAST_); ++i) {
28 const auto feature = static_cast<ArmFeaturesEnum>(i);
29 const char *name = GetArmFeaturesEnumName(feature);
30 ASSERT_FALSE(name == nullptr);
31 EXPECT_STRNE(name, "");
32 EXPECT_STRNE(name, last_name);
33 }
34 }
35
TEST(CpuinfoArmTest,FromHardwareCap)36 TEST(CpuinfoArmTest, FromHardwareCap) {
37 ResetHwcaps();
38 SetHardwareCapabilities(ARM_HWCAP_NEON, ARM_HWCAP2_AES | ARM_HWCAP2_CRC32);
39 GetEmptyFilesystem(); // disabling /proc/cpuinfo
40 const auto info = GetArmInfo();
41 EXPECT_TRUE(info.features.vfp); // triggered by vfpv3
42 EXPECT_TRUE(info.features.vfpv3); // triggered by neon
43 EXPECT_TRUE(info.features.neon);
44 EXPECT_TRUE(info.features.aes);
45 EXPECT_TRUE(info.features.crc32);
46
47 EXPECT_FALSE(info.features.vfpv4);
48 EXPECT_FALSE(info.features.iwmmxt);
49 EXPECT_FALSE(info.features.crunch);
50 EXPECT_FALSE(info.features.thumbee);
51 EXPECT_FALSE(info.features.vfpv3d16);
52 EXPECT_FALSE(info.features.idiva);
53 EXPECT_FALSE(info.features.idivt);
54 EXPECT_FALSE(info.features.pmull);
55 EXPECT_FALSE(info.features.sha1);
56 EXPECT_FALSE(info.features.sha2);
57
58 // check some random features with EnumValue():
59 EXPECT_TRUE(GetArmFeaturesEnumValue(&info.features, ARM_VFP));
60 EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, ARM_VFPV4));
61 // out of bound EnumValue() check
62 EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, (ArmFeaturesEnum)~0x0));
63 }
64
TEST(CpuinfoArmTest,ODroidFromCpuInfo)65 TEST(CpuinfoArmTest, ODroidFromCpuInfo) {
66 ResetHwcaps();
67 auto& fs = GetEmptyFilesystem();
68 fs.CreateFile("/proc/cpuinfo", R"(processor : 0
69 model name : ARMv7 Processor rev 3 (v71)
70 BogoMIPS : 120.00
71 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae
72 CPU implementer : 0x41
73 CPU architecture: 7
74 CPU variant : 0x2
75 CPU part : 0xc0f
76 CPU revision : 3)");
77 const auto info = GetArmInfo();
78 EXPECT_EQ(info.implementer, 0x41);
79 EXPECT_EQ(info.variant, 0x2);
80 EXPECT_EQ(info.part, 0xc0f);
81 EXPECT_EQ(info.revision, 3);
82 EXPECT_EQ(info.architecture, 7);
83
84 EXPECT_FALSE(info.features.swp);
85 EXPECT_TRUE(info.features.half);
86 EXPECT_TRUE(info.features.thumb);
87 EXPECT_FALSE(info.features._26bit);
88 EXPECT_TRUE(info.features.fastmult);
89 EXPECT_FALSE(info.features.fpa);
90 EXPECT_TRUE(info.features.vfp);
91 EXPECT_TRUE(info.features.edsp);
92 EXPECT_FALSE(info.features.java);
93 EXPECT_FALSE(info.features.iwmmxt);
94 EXPECT_FALSE(info.features.crunch);
95 EXPECT_FALSE(info.features.thumbee);
96 EXPECT_TRUE(info.features.neon);
97 EXPECT_TRUE(info.features.vfpv3);
98 EXPECT_FALSE(info.features.vfpv3d16);
99 EXPECT_TRUE(info.features.tls);
100 EXPECT_TRUE(info.features.vfpv4);
101 EXPECT_TRUE(info.features.idiva);
102 EXPECT_TRUE(info.features.idivt);
103 EXPECT_TRUE(info.features.vfpd32);
104 EXPECT_TRUE(info.features.lpae);
105 EXPECT_FALSE(info.features.evtstrm);
106 EXPECT_FALSE(info.features.aes);
107 EXPECT_FALSE(info.features.pmull);
108 EXPECT_FALSE(info.features.sha1);
109 EXPECT_FALSE(info.features.sha2);
110 EXPECT_FALSE(info.features.crc32);
111 }
112
113 // Linux test-case
TEST(CpuinfoArmTest,RaspberryPiZeroFromCpuInfo)114 TEST(CpuinfoArmTest, RaspberryPiZeroFromCpuInfo) {
115 ResetHwcaps();
116 auto& fs = GetEmptyFilesystem();
117 fs.CreateFile("/proc/cpuinfo", R"(processor : 0
118 model name : ARMv6-compatible processor rev 7 (v6l)
119 BogoMIPS : 697.95
120 Features : half thumb fastmult vfp edsp java tls
121 CPU implementer : 0x41
122 CPU architecture: 7
123 CPU variant : 0x0
124 CPU part : 0xb76
125 CPU revision : 7
126
127 Hardware : BCM2835
128 Revision : 9000c1
129 Serial : 000000006cd946f3)");
130 const auto info = GetArmInfo();
131 EXPECT_EQ(info.implementer, 0x41);
132 EXPECT_EQ(info.variant, 0x0);
133 EXPECT_EQ(info.part, 0xb76);
134 EXPECT_EQ(info.revision, 7);
135 EXPECT_EQ(info.architecture, 6);
136
137 EXPECT_FALSE(info.features.swp);
138 EXPECT_TRUE(info.features.half);
139 EXPECT_TRUE(info.features.thumb);
140 EXPECT_FALSE(info.features._26bit);
141 EXPECT_TRUE(info.features.fastmult);
142 EXPECT_FALSE(info.features.fpa);
143 EXPECT_TRUE(info.features.vfp);
144 EXPECT_TRUE(info.features.edsp);
145 EXPECT_TRUE(info.features.java);
146 EXPECT_FALSE(info.features.iwmmxt);
147 EXPECT_FALSE(info.features.crunch);
148 EXPECT_FALSE(info.features.thumbee);
149 EXPECT_FALSE(info.features.neon);
150 EXPECT_FALSE(info.features.vfpv3);
151 EXPECT_FALSE(info.features.vfpv3d16);
152 EXPECT_TRUE(info.features.tls);
153 EXPECT_FALSE(info.features.vfpv4);
154 EXPECT_FALSE(info.features.idiva);
155 EXPECT_FALSE(info.features.idivt);
156 EXPECT_FALSE(info.features.vfpd32);
157 EXPECT_FALSE(info.features.lpae);
158 EXPECT_FALSE(info.features.evtstrm);
159 EXPECT_FALSE(info.features.aes);
160 EXPECT_FALSE(info.features.pmull);
161 EXPECT_FALSE(info.features.sha1);
162 EXPECT_FALSE(info.features.sha2);
163 EXPECT_FALSE(info.features.crc32);
164 }
165
TEST(CpuinfoArmTest,MarvellArmadaFromCpuInfo)166 TEST(CpuinfoArmTest, MarvellArmadaFromCpuInfo) {
167 ResetHwcaps();
168 auto& fs = GetEmptyFilesystem();
169 fs.CreateFile("/proc/cpuinfo", R"(processor : 0
170 model name : ARMv7 Processor rev 1 (v7l)
171 BogoMIPS : 50.00
172 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
173 CPU implementer : 0x41
174 CPU architecture: 7
175 CPU variant : 0x4
176 CPU part : 0xc09
177 CPU revision : 1
178
179 processor : 1
180 model name : ARMv7 Processor rev 1 (v7l)
181 BogoMIPS : 50.00
182 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
183 CPU implementer : 0x41
184 CPU architecture: 7
185 CPU variant : 0x4
186 CPU part : 0xc09
187 CPU revision : 1
188
189 Hardware : Marvell Armada 380/385 (Device Tree)
190 Revision : 0000
191 Serial : 0000000000000000)");
192 const auto info = GetArmInfo();
193 EXPECT_EQ(info.implementer, 0x41);
194 EXPECT_EQ(info.variant, 0x4);
195 EXPECT_EQ(info.part, 0xc09);
196 EXPECT_EQ(info.revision, 1);
197 EXPECT_EQ(info.architecture, 7);
198
199 EXPECT_FALSE(info.features.swp);
200 EXPECT_TRUE(info.features.half);
201 EXPECT_TRUE(info.features.thumb);
202 EXPECT_FALSE(info.features._26bit);
203 EXPECT_TRUE(info.features.fastmult);
204 EXPECT_FALSE(info.features.fpa);
205 EXPECT_TRUE(info.features.vfp);
206 EXPECT_TRUE(info.features.edsp);
207 EXPECT_FALSE(info.features.java);
208 EXPECT_FALSE(info.features.iwmmxt);
209 EXPECT_FALSE(info.features.crunch);
210 EXPECT_FALSE(info.features.thumbee);
211 EXPECT_TRUE(info.features.neon);
212 EXPECT_TRUE(info.features.vfpv3);
213 EXPECT_FALSE(info.features.vfpv3d16);
214 EXPECT_TRUE(info.features.tls);
215 EXPECT_FALSE(info.features.vfpv4);
216 EXPECT_FALSE(info.features.idiva);
217 EXPECT_FALSE(info.features.idivt);
218 EXPECT_TRUE(info.features.vfpd32);
219 EXPECT_FALSE(info.features.lpae);
220 EXPECT_FALSE(info.features.evtstrm);
221 EXPECT_FALSE(info.features.aes);
222 EXPECT_FALSE(info.features.pmull);
223 EXPECT_FALSE(info.features.sha1);
224 EXPECT_FALSE(info.features.sha2);
225 EXPECT_FALSE(info.features.crc32);
226 }
227
228 // Android test-case
229 // http://code.google.com/p/android/issues/detail?id=10812
TEST(CpuinfoArmTest,InvalidArmv7)230 TEST(CpuinfoArmTest, InvalidArmv7) {
231 ResetHwcaps();
232 auto& fs = GetEmptyFilesystem();
233 fs.CreateFile("/proc/cpuinfo",
234 R"(Processor : ARMv6-compatible processor rev 6 (v6l)
235 BogoMIPS : 199.47
236 Features : swp half thumb fastmult vfp edsp java
237 CPU implementer : 0x41
238 CPU architecture: 7
239 CPU variant : 0x0
240 CPU part : 0xb76
241 CPU revision : 6
242
243 Hardware : SPICA
244 Revision : 0020
245 Serial : 33323613546d00ec )");
246 const auto info = GetArmInfo();
247 EXPECT_EQ(info.architecture, 6);
248
249 EXPECT_TRUE(info.features.swp);
250 EXPECT_TRUE(info.features.half);
251 EXPECT_TRUE(info.features.thumb);
252 EXPECT_FALSE(info.features._26bit);
253 EXPECT_TRUE(info.features.fastmult);
254 EXPECT_FALSE(info.features.fpa);
255 EXPECT_TRUE(info.features.vfp);
256 EXPECT_TRUE(info.features.edsp);
257 EXPECT_TRUE(info.features.java);
258 EXPECT_FALSE(info.features.iwmmxt);
259 EXPECT_FALSE(info.features.crunch);
260 EXPECT_FALSE(info.features.thumbee);
261 EXPECT_FALSE(info.features.neon);
262 EXPECT_FALSE(info.features.vfpv3);
263 EXPECT_FALSE(info.features.vfpv3d16);
264 EXPECT_FALSE(info.features.tls);
265 EXPECT_FALSE(info.features.vfpv4);
266 EXPECT_FALSE(info.features.idiva);
267 EXPECT_FALSE(info.features.idivt);
268 EXPECT_FALSE(info.features.vfpd32);
269 EXPECT_FALSE(info.features.lpae);
270 EXPECT_FALSE(info.features.evtstrm);
271 EXPECT_FALSE(info.features.aes);
272 EXPECT_FALSE(info.features.pmull);
273 EXPECT_FALSE(info.features.sha1);
274 EXPECT_FALSE(info.features.sha2);
275 EXPECT_FALSE(info.features.crc32);
276 }
277
278 // Android test-case
279 // https://crbug.com/341598.
TEST(CpuinfoArmTest,InvalidNeon)280 TEST(CpuinfoArmTest, InvalidNeon) {
281 ResetHwcaps();
282 auto& fs = GetEmptyFilesystem();
283 fs.CreateFile("/proc/cpuinfo",
284 R"(Processor: ARMv7 Processory rev 0 (v71)
285 processor: 0
286 BogoMIPS: 13.50
287
288 Processor: 1
289 BogoMIPS: 13.50
290
291 Features: swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
292 CPU implementer : 0x51
293 CPU architecture: 7
294 CPU variant: 0x1
295 CPU part: 0x04d
296 CPU revision: 0
297
298 Hardware: SAMSUNG M2
299 Revision: 0010
300 Serial: 00001e030000354e)");
301 const auto info = GetArmInfo();
302 EXPECT_TRUE(info.features.swp);
303 EXPECT_FALSE(info.features.neon);
304 }
305
306 // The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV
307 // support.
TEST(CpuinfoArmTest,Nexus4_0x510006f2)308 TEST(CpuinfoArmTest, Nexus4_0x510006f2) {
309 ResetHwcaps();
310 auto& fs = GetEmptyFilesystem();
311 fs.CreateFile("/proc/cpuinfo",
312 R"(CPU implementer : 0x51
313 CPU architecture: 7
314 CPU variant : 0x0
315 CPU part : 0x6f
316 CPU revision : 2)");
317 const auto info = GetArmInfo();
318 EXPECT_TRUE(info.features.idiva);
319 EXPECT_TRUE(info.features.idivt);
320
321 EXPECT_EQ(GetArmCpuId(&info), 0x510006f2);
322 }
323
324 // The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV
325 // support.
TEST(CpuinfoArmTest,Nexus4_0x510006f3)326 TEST(CpuinfoArmTest, Nexus4_0x510006f3) {
327 ResetHwcaps();
328 auto& fs = GetEmptyFilesystem();
329 fs.CreateFile("/proc/cpuinfo",
330 R"(CPU implementer : 0x51
331 CPU architecture: 7
332 CPU variant : 0x0
333 CPU part : 0x6f
334 CPU revision : 3)");
335 const auto info = GetArmInfo();
336 EXPECT_TRUE(info.features.idiva);
337 EXPECT_TRUE(info.features.idivt);
338
339 EXPECT_EQ(GetArmCpuId(&info), 0x510006f3);
340 }
341
342 // The 2013 Nexus 7 (Qualcomm Krait) kernel configuration forgets to report IDIV
343 // support.
TEST(CpuinfoArmTest,Nexus7_2013_0x511006f0)344 TEST(CpuinfoArmTest, Nexus7_2013_0x511006f0) {
345 ResetHwcaps();
346 auto& fs = GetEmptyFilesystem();
347 fs.CreateFile("/proc/cpuinfo",
348 R"(CPU implementer : 0x51
349 CPU architecture: 7
350 CPU variant : 0x1
351 CPU part : 0x06f
352 CPU revision : 0)");
353 const auto info = GetArmInfo();
354 EXPECT_TRUE(info.features.idiva);
355 EXPECT_TRUE(info.features.idivt);
356
357 EXPECT_EQ(GetArmCpuId(&info), 0x511006f0);
358 }
359
360 // The emulator-specific Android 4.2 kernel fails to report support for the
361 // 32-bit ARM IDIV instruction. Technically, this is a feature of the virtual
362 // CPU implemented by the emulator.
TEST(CpuinfoArmTest,EmulatorSpecificIdiv)363 TEST(CpuinfoArmTest, EmulatorSpecificIdiv) {
364 ResetHwcaps();
365 auto& fs = GetEmptyFilesystem();
366 fs.CreateFile("/proc/cpuinfo",
367 R"(Processor : ARMv7 Processor rev 0 (v7l)
368 BogoMIPS : 629.14
369 Features : swp half thumb fastmult vfp edsp neon vfpv3
370 CPU implementer : 0x41
371 CPU architecture: 7
372 CPU variant : 0x0
373 CPU part : 0xc08
374 CPU revision : 0
375
376 Hardware : Goldfish
377 Revision : 0000
378 Serial : 0000000000000000)");
379 const auto info = GetArmInfo();
380 EXPECT_TRUE(info.features.idiva);
381 }
382
383 } // namespace
384 } // namespace cpu_features
385