• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 Google Inc.
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 "internal/filesystem.h"
18 #include "internal/hwcaps.h"
19 #include "internal/stack_line_reader.h"
20 #include "internal/string_view.h"
21 #include "internal/unix_features_aggregator.h"
22 
23 #include <assert.h>
24 #include <ctype.h>
25 
26 DECLARE_SETTER(Aarch64Features, fp)
27 DECLARE_SETTER(Aarch64Features, asimd)
28 DECLARE_SETTER(Aarch64Features, aes)
29 DECLARE_SETTER(Aarch64Features, pmull)
30 DECLARE_SETTER(Aarch64Features, sha1)
31 DECLARE_SETTER(Aarch64Features, sha2)
32 DECLARE_SETTER(Aarch64Features, crc32)
33 
34 static const CapabilityConfig kConfigs[] = {
35   [AARCH64_FP] = {{AARCH64_HWCAP_FP, 0}, "fp", &set_fp},              //
36   [AARCH64_ASIMD] = {{AARCH64_HWCAP_ASIMD, 0}, "asimd", &set_asimd},  //
37   [AARCH64_AES] = {{AARCH64_HWCAP_AES, 0}, "aes", &set_aes},          //
38   [AARCH64_PMULL] = {{AARCH64_HWCAP_PMULL, 0}, "pmull", &set_pmull},  //
39   [AARCH64_SHA1] = {{AARCH64_HWCAP_SHA1, 0}, "sha1", &set_sha1},      //
40   [AARCH64_SHA2] = {{AARCH64_HWCAP_SHA2, 0}, "sha2", &set_sha2},      //
41   [AARCH64_CRC32] {{AARCH64_HWCAP_CRC32, 0}, "crc32", &set_crc32},    //
42 };
43 
44 static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
45 
HandleAarch64Line(const LineResult result,Aarch64Info * const info)46 static bool HandleAarch64Line(const LineResult result,
47                               Aarch64Info* const info) {
48   StringView line = result.line;
49   StringView key, value;
50   if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
51     if (CpuFeatures_StringView_IsEquals(key, str("Features"))) {
52       CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, &info->features);
53     } else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) {
54       info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
55     } else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) {
56       info->variant = CpuFeatures_StringView_ParsePositiveNumber(value);
57     } else if (CpuFeatures_StringView_IsEquals(key, str("CPU part"))) {
58       info->part = CpuFeatures_StringView_ParsePositiveNumber(value);
59     } else if (CpuFeatures_StringView_IsEquals(key, str("CPU revision"))) {
60       info->revision = CpuFeatures_StringView_ParsePositiveNumber(value);
61     }
62   }
63   return !result.eof;
64 }
65 
FillProcCpuInfoData(Aarch64Info * const info)66 static void FillProcCpuInfoData(Aarch64Info* const info) {
67   const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
68   if (fd >= 0) {
69     StackLineReader reader;
70     StackLineReader_Initialize(&reader, fd);
71     for (;;) {
72       if (!HandleAarch64Line(StackLineReader_NextLine(&reader), info)) {
73         break;
74       }
75     }
76     CpuFeatures_CloseFile(fd);
77   }
78 }
79 
80 static const Aarch64Info kEmptyAarch64Info;
81 
GetAarch64Info(void)82 Aarch64Info GetAarch64Info(void) {
83   assert(kConfigsSize == AARCH64_LAST_);
84 
85   // capabilities are fetched from both getauxval and /proc/cpuinfo so we can
86   // have some information if the executable is sandboxed (aka no access to
87   // /proc/cpuinfo).
88   Aarch64Info info = kEmptyAarch64Info;
89 
90   FillProcCpuInfoData(&info);
91   CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
92                                  CpuFeatures_GetHardwareCapabilities(),
93                                  &info.features);
94 
95   return info;
96 }
97 
98 ////////////////////////////////////////////////////////////////////////////////
99 // Introspection functions
100 
GetAarch64FeaturesEnumValue(const Aarch64Features * features,Aarch64FeaturesEnum value)101 int GetAarch64FeaturesEnumValue(const Aarch64Features* features,
102                                 Aarch64FeaturesEnum value) {
103   switch (value) {
104     case AARCH64_FP:
105       return features->fp;
106     case AARCH64_ASIMD:
107       return features->asimd;
108     case AARCH64_AES:
109       return features->aes;
110     case AARCH64_PMULL:
111       return features->pmull;
112     case AARCH64_SHA1:
113       return features->sha1;
114     case AARCH64_SHA2:
115       return features->sha2;
116     case AARCH64_CRC32:
117       return features->crc32;
118     case AARCH64_LAST_:
119       break;
120   }
121   return false;
122 }
123 
GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value)124 const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value) {
125   if(value >= kConfigsSize)
126     return "unknown feature";
127   return kConfigs[value].proc_cpuinfo_flag;
128 }
129