xref: /aosp_15_r20/external/cpu_features/test/cpuinfo_aarch64_test.cc (revision eca53ba6d2e951e174b64682eaf56a36b8204c89)
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_aarch64.h"
16 
17 #include <set>
18 
19 #include "filesystem_for_testing.h"
20 #include "gtest/gtest.h"
21 #include "hwcaps_for_testing.h"
22 #if defined(CPU_FEATURES_OS_WINDOWS)
23 #include "internal/windows_utils.h"
24 #endif  // CPU_FEATURES_OS_WINDOWS
25 
26 namespace cpu_features {
27 class FakeCpuAarch64 {
28 #if defined(CPU_FEATURES_OS_LINUX)
29   // No particular implementation for Linux as we use /proc/cpuinfo
30 #elif defined(CPU_FEATURES_OS_MACOS)
31   std::set<std::string> darwin_sysctlbyname_;
32   std::map<std::string, int> darwin_sysctlbynamevalue_;
33 
34  public:
35   bool GetDarwinSysCtlByName(std::string name) const {
36     return darwin_sysctlbyname_.count(name);
37   }
38 
39   int GetDarwinSysCtlByNameValue(std::string name) const {
40     const auto iter = darwin_sysctlbynamevalue_.find(name);
41     if (iter != darwin_sysctlbynamevalue_.end()) return iter->second;
42     return 0;
43   }
44 
45   void SetDarwinSysCtlByName(std::string name) {
46     darwin_sysctlbyname_.insert(name);
47   }
48 
49   void SetDarwinSysCtlByNameValue(std::string name, int value) {
50     darwin_sysctlbynamevalue_[name] = value;
51   }
52 #elif defined(CPU_FEATURES_OS_WINDOWS)
53   std::set<DWORD> windows_isprocessorfeaturepresent_;
54   WORD processor_revision_{};
55 
56  public:
57   bool GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) {
58     return windows_isprocessorfeaturepresent_.count(dwProcessorFeature);
59   }
60 
61   void SetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) {
62     windows_isprocessorfeaturepresent_.insert(dwProcessorFeature);
63   }
64 
65   WORD GetWindowsNativeSystemInfoProcessorRevision() const {
66     return processor_revision_;
67   }
68 
69   void SetWindowsNativeSystemInfoProcessorRevision(WORD wProcessorRevision) {
70     processor_revision_ = wProcessorRevision;
71   }
72 #endif
73 };
74 
75 static FakeCpuAarch64* g_fake_cpu_instance = nullptr;
76 
cpu()77 static FakeCpuAarch64& cpu() {
78   assert(g_fake_cpu_instance != nullptr);
79   return *g_fake_cpu_instance;
80 }
81 
82 // Define OS dependent mock functions
83 #if defined(CPU_FEATURES_OS_LINUX)
84 // No particular functions to implement for Linux as we use /proc/cpuinfo
85 #elif defined(CPU_FEATURES_OS_MACOS)
GetDarwinSysCtlByName(const char * name)86 extern "C" bool GetDarwinSysCtlByName(const char* name) {
87   return cpu().GetDarwinSysCtlByName(name);
88 }
89 
GetDarwinSysCtlByNameValue(const char * name)90 extern "C" int GetDarwinSysCtlByNameValue(const char* name) {
91   return cpu().GetDarwinSysCtlByNameValue(name);
92 }
93 #elif defined(CPU_FEATURES_OS_WINDOWS)
GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature)94 extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) {
95   return cpu().GetWindowsIsProcessorFeaturePresent(dwProcessorFeature);
96 }
97 
GetWindowsNativeSystemInfoProcessorRevision()98 extern "C" WORD GetWindowsNativeSystemInfoProcessorRevision() {
99   return cpu().GetWindowsNativeSystemInfoProcessorRevision();
100 }
101 #endif
102 
103 namespace {
104 
105 class CpuidAarch64Test : public ::testing::Test {
106  protected:
SetUp()107   void SetUp() override {
108     assert(g_fake_cpu_instance == nullptr);
109     g_fake_cpu_instance = new FakeCpuAarch64();
110   }
TearDown()111   void TearDown() override {
112     delete g_fake_cpu_instance;
113     g_fake_cpu_instance = nullptr;
114   }
115 };
116 
TEST_F(CpuidAarch64Test,Aarch64FeaturesEnum)117 TEST_F(CpuidAarch64Test, Aarch64FeaturesEnum) {
118   const char* last_name = GetAarch64FeaturesEnumName(AARCH64_LAST_);
119   EXPECT_STREQ(last_name, "unknown_feature");
120   for (int i = static_cast<int>(AARCH64_FP);
121        i != static_cast<int>(AARCH64_LAST_); ++i) {
122     const auto feature = static_cast<Aarch64FeaturesEnum>(i);
123     const char* name = GetAarch64FeaturesEnumName(feature);
124     ASSERT_FALSE(name == nullptr);
125     EXPECT_STRNE(name, "");
126     EXPECT_STRNE(name, last_name);
127   }
128 }
129 
130 // OS dependent tests
131 #if defined(CPU_FEATURES_OS_LINUX)
TEST_F(CpuidAarch64Test,FromHardwareCap)132 TEST_F(CpuidAarch64Test, FromHardwareCap) {
133   ResetHwcaps();
134   SetHardwareCapabilities(AARCH64_HWCAP_FP | AARCH64_HWCAP_AES, 0);
135   GetEmptyFilesystem();  // disabling /proc/cpuinfo
136   const auto info = GetAarch64Info();
137   EXPECT_TRUE(info.features.fp);
138   EXPECT_FALSE(info.features.asimd);
139   EXPECT_FALSE(info.features.evtstrm);
140   EXPECT_TRUE(info.features.aes);
141   EXPECT_FALSE(info.features.pmull);
142   EXPECT_FALSE(info.features.sha1);
143   EXPECT_FALSE(info.features.sha2);
144   EXPECT_FALSE(info.features.crc32);
145   EXPECT_FALSE(info.features.atomics);
146   EXPECT_FALSE(info.features.fphp);
147   EXPECT_FALSE(info.features.asimdhp);
148   EXPECT_FALSE(info.features.cpuid);
149   EXPECT_FALSE(info.features.asimdrdm);
150   EXPECT_FALSE(info.features.jscvt);
151   EXPECT_FALSE(info.features.fcma);
152   EXPECT_FALSE(info.features.lrcpc);
153   EXPECT_FALSE(info.features.dcpop);
154   EXPECT_FALSE(info.features.sha3);
155   EXPECT_FALSE(info.features.sm3);
156   EXPECT_FALSE(info.features.sm4);
157   EXPECT_FALSE(info.features.asimddp);
158   EXPECT_FALSE(info.features.sha512);
159   EXPECT_FALSE(info.features.sve);
160   EXPECT_FALSE(info.features.asimdfhm);
161   EXPECT_FALSE(info.features.dit);
162   EXPECT_FALSE(info.features.uscat);
163   EXPECT_FALSE(info.features.ilrcpc);
164   EXPECT_FALSE(info.features.flagm);
165   EXPECT_FALSE(info.features.ssbs);
166   EXPECT_FALSE(info.features.sb);
167   EXPECT_FALSE(info.features.paca);
168   EXPECT_FALSE(info.features.pacg);
169 }
170 
TEST_F(CpuidAarch64Test,FromHardwareCap2)171 TEST_F(CpuidAarch64Test, FromHardwareCap2) {
172   ResetHwcaps();
173   SetHardwareCapabilities(AARCH64_HWCAP_FP,
174                           AARCH64_HWCAP2_SVE2 | AARCH64_HWCAP2_BTI);
175   GetEmptyFilesystem();  // disabling /proc/cpuinfo
176   const auto info = GetAarch64Info();
177   EXPECT_TRUE(info.features.fp);
178 
179   EXPECT_TRUE(info.features.sve2);
180   EXPECT_TRUE(info.features.bti);
181 
182   EXPECT_FALSE(info.features.dcpodp);
183   EXPECT_FALSE(info.features.sveaes);
184   EXPECT_FALSE(info.features.svepmull);
185   EXPECT_FALSE(info.features.svebitperm);
186   EXPECT_FALSE(info.features.svesha3);
187   EXPECT_FALSE(info.features.svesm4);
188   EXPECT_FALSE(info.features.flagm2);
189   EXPECT_FALSE(info.features.frint);
190   EXPECT_FALSE(info.features.svei8mm);
191   EXPECT_FALSE(info.features.svef32mm);
192   EXPECT_FALSE(info.features.svef64mm);
193   EXPECT_FALSE(info.features.svebf16);
194   EXPECT_FALSE(info.features.i8mm);
195   EXPECT_FALSE(info.features.bf16);
196   EXPECT_FALSE(info.features.dgh);
197   EXPECT_FALSE(info.features.rng);
198 }
199 
TEST_F(CpuidAarch64Test,ARMCortexA53)200 TEST_F(CpuidAarch64Test, ARMCortexA53) {
201   ResetHwcaps();
202   auto& fs = GetEmptyFilesystem();
203   fs.CreateFile("/proc/cpuinfo",
204                 R"(Processor   : AArch64 Processor rev 3 (aarch64)
205 processor   : 0
206 processor   : 1
207 processor   : 2
208 processor   : 3
209 processor   : 4
210 processor   : 5
211 processor   : 6
212 processor   : 7
213 Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32
214 CPU implementer : 0x41
215 CPU architecture: AArch64
216 CPU variant : 0x0
217 CPU part    : 0xd03
218 CPU revision    : 3)");
219   const auto info = GetAarch64Info();
220   EXPECT_EQ(info.implementer, 0x41);
221   EXPECT_EQ(info.variant, 0x0);
222   EXPECT_EQ(info.part, 0xd03);
223   EXPECT_EQ(info.revision, 3);
224 
225   EXPECT_TRUE(info.features.fp);
226   EXPECT_TRUE(info.features.asimd);
227   EXPECT_TRUE(info.features.evtstrm);
228   EXPECT_TRUE(info.features.aes);
229   EXPECT_TRUE(info.features.pmull);
230   EXPECT_TRUE(info.features.sha1);
231   EXPECT_TRUE(info.features.sha2);
232   EXPECT_TRUE(info.features.crc32);
233 
234   EXPECT_FALSE(info.features.atomics);
235   EXPECT_FALSE(info.features.fphp);
236   EXPECT_FALSE(info.features.asimdhp);
237   EXPECT_FALSE(info.features.cpuid);
238   EXPECT_FALSE(info.features.asimdrdm);
239   EXPECT_FALSE(info.features.jscvt);
240   EXPECT_FALSE(info.features.fcma);
241   EXPECT_FALSE(info.features.lrcpc);
242   EXPECT_FALSE(info.features.dcpop);
243   EXPECT_FALSE(info.features.sha3);
244   EXPECT_FALSE(info.features.sm3);
245   EXPECT_FALSE(info.features.sm4);
246   EXPECT_FALSE(info.features.asimddp);
247   EXPECT_FALSE(info.features.sha512);
248   EXPECT_FALSE(info.features.sve);
249   EXPECT_FALSE(info.features.asimdfhm);
250   EXPECT_FALSE(info.features.dit);
251   EXPECT_FALSE(info.features.uscat);
252   EXPECT_FALSE(info.features.ilrcpc);
253   EXPECT_FALSE(info.features.flagm);
254   EXPECT_FALSE(info.features.ssbs);
255   EXPECT_FALSE(info.features.sb);
256   EXPECT_FALSE(info.features.paca);
257   EXPECT_FALSE(info.features.pacg);
258   EXPECT_FALSE(info.features.dcpodp);
259   EXPECT_FALSE(info.features.sve2);
260   EXPECT_FALSE(info.features.sveaes);
261   EXPECT_FALSE(info.features.svepmull);
262   EXPECT_FALSE(info.features.svebitperm);
263   EXPECT_FALSE(info.features.svesha3);
264   EXPECT_FALSE(info.features.svesm4);
265   EXPECT_FALSE(info.features.flagm2);
266   EXPECT_FALSE(info.features.frint);
267   EXPECT_FALSE(info.features.svei8mm);
268   EXPECT_FALSE(info.features.svef32mm);
269   EXPECT_FALSE(info.features.svef64mm);
270   EXPECT_FALSE(info.features.svebf16);
271   EXPECT_FALSE(info.features.i8mm);
272   EXPECT_FALSE(info.features.bf16);
273   EXPECT_FALSE(info.features.dgh);
274   EXPECT_FALSE(info.features.rng);
275   EXPECT_FALSE(info.features.bti);
276   EXPECT_FALSE(info.features.mte);
277   EXPECT_FALSE(info.features.ecv);
278   EXPECT_FALSE(info.features.afp);
279   EXPECT_FALSE(info.features.rpres);
280   EXPECT_FALSE(info.features.mte3);
281   EXPECT_FALSE(info.features.sme);
282   EXPECT_FALSE(info.features.smei16i64);
283   EXPECT_FALSE(info.features.smef64f64);
284   EXPECT_FALSE(info.features.smei8i32);
285   EXPECT_FALSE(info.features.smef16f32);
286   EXPECT_FALSE(info.features.smeb16f32);
287   EXPECT_FALSE(info.features.smef32f32);
288   EXPECT_FALSE(info.features.smefa64);
289   EXPECT_FALSE(info.features.wfxt);
290   EXPECT_FALSE(info.features.ebf16);
291   EXPECT_FALSE(info.features.sveebf16);
292   EXPECT_FALSE(info.features.cssc);
293   EXPECT_FALSE(info.features.rprfm);
294   EXPECT_FALSE(info.features.sve2p1);
295   EXPECT_FALSE(info.features.sme2);
296   EXPECT_FALSE(info.features.sme2p1);
297   EXPECT_FALSE(info.features.smei16i32);
298   EXPECT_FALSE(info.features.smebi32i32);
299   EXPECT_FALSE(info.features.smeb16b16);
300   EXPECT_FALSE(info.features.smef16f16);
301 }
302 #elif defined(CPU_FEATURES_OS_MACOS)
TEST_F(CpuidAarch64Test,FromDarwinSysctlFromName)303 TEST_F(CpuidAarch64Test, FromDarwinSysctlFromName) {
304   cpu().SetDarwinSysCtlByName("hw.optional.floatingpoint");
305   cpu().SetDarwinSysCtlByName("hw.optional.neon");
306   cpu().SetDarwinSysCtlByName("hw.optional.AdvSIMD_HPFPCvt");
307   cpu().SetDarwinSysCtlByName("hw.optional.arm.FEAT_FP16");
308   cpu().SetDarwinSysCtlByName("hw.optional.arm.FEAT_LSE");
309   cpu().SetDarwinSysCtlByName("hw.optional.armv8_crc32");
310   cpu().SetDarwinSysCtlByName("hw.optional.arm.FEAT_FHM");
311   cpu().SetDarwinSysCtlByName("hw.optional.arm.FEAT_SHA512");
312   cpu().SetDarwinSysCtlByName("hw.optional.arm.FEAT_SHA3");
313   cpu().SetDarwinSysCtlByName("hw.optional.amx_version");
314   cpu().SetDarwinSysCtlByName("hw.optional.ucnormal_mem");
315   cpu().SetDarwinSysCtlByName("hw.optional.arm64");
316 
317   cpu().SetDarwinSysCtlByNameValue("hw.cputype", 16777228);
318   cpu().SetDarwinSysCtlByNameValue("hw.cpusubtype", 2);
319   cpu().SetDarwinSysCtlByNameValue("hw.cpu64bit", 1);
320   cpu().SetDarwinSysCtlByNameValue("hw.cpufamily", 458787763);
321   cpu().SetDarwinSysCtlByNameValue("hw.cpusubfamily", 2);
322 
323   const auto info = GetAarch64Info();
324 
325   EXPECT_EQ(info.implementer, 0x100000C);
326   EXPECT_EQ(info.variant, 2);
327   EXPECT_EQ(info.part, 0x1B588BB3);
328   EXPECT_EQ(info.revision, 2);
329 
330   EXPECT_TRUE(info.features.fp);
331   EXPECT_FALSE(info.features.asimd);
332   EXPECT_FALSE(info.features.evtstrm);
333   EXPECT_FALSE(info.features.aes);
334   EXPECT_FALSE(info.features.pmull);
335   EXPECT_FALSE(info.features.sha1);
336   EXPECT_FALSE(info.features.sha2);
337   EXPECT_TRUE(info.features.crc32);
338   EXPECT_TRUE(info.features.atomics);
339   EXPECT_TRUE(info.features.fphp);
340   EXPECT_FALSE(info.features.asimdhp);
341   EXPECT_FALSE(info.features.cpuid);
342   EXPECT_FALSE(info.features.asimdrdm);
343   EXPECT_FALSE(info.features.jscvt);
344   EXPECT_FALSE(info.features.fcma);
345   EXPECT_FALSE(info.features.lrcpc);
346   EXPECT_FALSE(info.features.dcpop);
347   EXPECT_TRUE(info.features.sha3);
348   EXPECT_FALSE(info.features.sm3);
349   EXPECT_FALSE(info.features.sm4);
350   EXPECT_FALSE(info.features.asimddp);
351   EXPECT_TRUE(info.features.sha512);
352   EXPECT_FALSE(info.features.sve);
353   EXPECT_TRUE(info.features.asimdfhm);
354   EXPECT_FALSE(info.features.dit);
355   EXPECT_FALSE(info.features.uscat);
356   EXPECT_FALSE(info.features.ilrcpc);
357   EXPECT_FALSE(info.features.flagm);
358   EXPECT_FALSE(info.features.ssbs);
359   EXPECT_FALSE(info.features.sb);
360   EXPECT_FALSE(info.features.paca);
361   EXPECT_FALSE(info.features.pacg);
362 }
363 #elif defined(CPU_FEATURES_OS_WINDOWS)
TEST_F(CpuidAarch64Test,WINDOWS_AARCH64_RPI4)364 TEST_F(CpuidAarch64Test, WINDOWS_AARCH64_RPI4) {
365   cpu().SetWindowsNativeSystemInfoProcessorRevision(0x03);
366   cpu().SetWindowsIsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE);
367   cpu().SetWindowsIsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE);
368   cpu().SetWindowsIsProcessorFeaturePresent(
369       PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE);
370 
371   const auto info = GetAarch64Info();
372 
373   EXPECT_EQ(info.revision, 0x03);
374   EXPECT_TRUE(info.features.fp);
375   EXPECT_TRUE(info.features.asimd);
376   EXPECT_TRUE(info.features.crc32);
377   EXPECT_FALSE(info.features.aes);
378   EXPECT_FALSE(info.features.sha1);
379   EXPECT_FALSE(info.features.sha2);
380   EXPECT_FALSE(info.features.pmull);
381   EXPECT_FALSE(info.features.atomics);
382   EXPECT_FALSE(info.features.asimddp);
383   EXPECT_FALSE(info.features.jscvt);
384   EXPECT_FALSE(info.features.lrcpc);
385 }
386 #endif  // CPU_FEATURES_OS_WINDOWS
387 }  // namespace
388 }  // namespace cpu_features
389