blob: 26a07d3ebd53c94ea0e01bb81d75910ccb82dd9e [file] [log] [blame]
Guillaume Chatelet439d3712018-02-01 10:03:09 +01001// 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"
Guillaume Chatelet439d3712018-02-01 10:03:09 +010019#include "internal/stack_line_reader.h"
20#include "internal/string_view.h"
Guillaume Chateletdfdac6a2019-01-17 18:00:21 +010021#include "internal/unix_features_aggregator.h"
Guillaume Chatelet439d3712018-02-01 10:03:09 +010022
Dr.-Ing. Patrick Siegl22c05ed2019-06-29 22:02:23 +020023#include <assert.h>
Guillaume Chatelet439d3712018-02-01 10:03:09 +010024#include <ctype.h>
25
26DECLARE_SETTER(Aarch64Features, fp)
27DECLARE_SETTER(Aarch64Features, asimd)
28DECLARE_SETTER(Aarch64Features, aes)
29DECLARE_SETTER(Aarch64Features, pmull)
30DECLARE_SETTER(Aarch64Features, sha1)
31DECLARE_SETTER(Aarch64Features, sha2)
32DECLARE_SETTER(Aarch64Features, crc32)
33
34static const CapabilityConfig kConfigs[] = {
Dr.-Ing. Patrick Siegl22c05ed2019-06-29 22:02:23 +020035 [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}, //
Guillaume Chatelet439d3712018-02-01 10:03:09 +010042};
43
44static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
45
46static bool HandleAarch64Line(const LineResult result,
47 Aarch64Info* const info) {
48 StringView line = result.line;
49 StringView key, value;
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +020050 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);
Guillaume Chatelet439d3712018-02-01 10:03:09 +010061 }
62 }
63 return !result.eof;
64}
65
66static void FillProcCpuInfoData(Aarch64Info* const info) {
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +020067 const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
Guillaume Chatelet439d3712018-02-01 10:03:09 +010068 if (fd >= 0) {
69 StackLineReader reader;
70 StackLineReader_Initialize(&reader, fd);
71 for (;;) {
72 if (!HandleAarch64Line(StackLineReader_NextLine(&reader), info)) {
73 break;
74 }
75 }
Arvid Gerstmanna1ffdcb2018-04-26 10:31:03 +020076 CpuFeatures_CloseFile(fd);
Guillaume Chatelet439d3712018-02-01 10:03:09 +010077 }
78}
79
80static const Aarch64Info kEmptyAarch64Info;
81
82Aarch64Info GetAarch64Info(void) {
Dr.-Ing. Patrick Siegl22c05ed2019-06-29 22:02:23 +020083 assert(kConfigsSize == AARCH64_LAST_);
84
Guillaume Chatelet439d3712018-02-01 10:03:09 +010085 // 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);
Arvid Gerstmannd9689912018-05-04 09:32:17 +020091 CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
92 CpuFeatures_GetHardwareCapabilities(),
93 &info.features);
Guillaume Chatelet439d3712018-02-01 10:03:09 +010094
95 return info;
96}
97
98////////////////////////////////////////////////////////////////////////////////
99// Introspection functions
100
101int 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
124const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value) {
Dr.-Ing. Patrick Siegl22c05ed2019-06-29 22:02:23 +0200125 if(value >= kConfigsSize)
126 return "unknown feature";
127 return kConfigs[value].proc_cpuinfo_flag;
Guillaume Chatelet439d3712018-02-01 10:03:09 +0100128}