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 "cpu_features_macros.h"
16
17 #ifdef CPU_FEATURES_ARCH_AARCH64
18 #if defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
19
20 #include "impl_aarch64__base_implementation.inl"
21
HandleAarch64Line(const LineResult result,Aarch64Info * const info)22 static bool HandleAarch64Line(const LineResult result,
23 Aarch64Info* const info) {
24 StringView line = result.line;
25 StringView key, value;
26 if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
27 if (CpuFeatures_StringView_IsEquals(key, str("Features"))) {
28 for (size_t i = 0; i < AARCH64_LAST_; ++i) {
29 kSetters[i](&info->features, CpuFeatures_StringView_HasWord(
30 value, kCpuInfoFlags[i], ' '));
31 }
32 } else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) {
33 info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
34 } else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) {
35 info->variant = CpuFeatures_StringView_ParsePositiveNumber(value);
36 } else if (CpuFeatures_StringView_IsEquals(key, str("CPU part"))) {
37 info->part = CpuFeatures_StringView_ParsePositiveNumber(value);
38 } else if (CpuFeatures_StringView_IsEquals(key, str("CPU revision"))) {
39 info->revision = CpuFeatures_StringView_ParsePositiveNumber(value);
40 }
41 }
42 return !result.eof;
43 }
44
FillProcCpuInfoData(Aarch64Info * const info)45 static void FillProcCpuInfoData(Aarch64Info* const info) {
46 const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
47 if (fd >= 0) {
48 StackLineReader reader;
49 StackLineReader_Initialize(&reader, fd);
50 for (;;) {
51 if (!HandleAarch64Line(StackLineReader_NextLine(&reader), info)) {
52 break;
53 }
54 }
55 CpuFeatures_CloseFile(fd);
56 }
57 }
58
59 static const Aarch64Info kEmptyAarch64Info;
60
GetAarch64Info(void)61 Aarch64Info GetAarch64Info(void) {
62 // capabilities are fetched from both getauxval and /proc/cpuinfo so we can
63 // have some information if the executable is sandboxed (aka no access to
64 // /proc/cpuinfo).
65 Aarch64Info info = kEmptyAarch64Info;
66
67 FillProcCpuInfoData(&info);
68 const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
69 for (size_t i = 0; i < AARCH64_LAST_; ++i) {
70 if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
71 kSetters[i](&info.features, true);
72 }
73 }
74
75 return info;
76 }
77
78 #endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
79 #endif // CPU_FEATURES_ARCH_AARCH64
80