1+ // Copyright 2022 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_RISCV
18+ #if defined(CPU_FEATURES_OS_LINUX )
19+
20+ #include "cpuinfo_riscv.h"
21+
22+ // According to
23+ // https://elixir.bootlin.com/linux/latest/source/Documentation/devicetree/bindings/riscv/cpus.yaml
24+ // isa string should match the following regex
25+ // ^rv(?:64|32)imaf?d?q?c?b?v?k?h?(?:_[hsxz](?:[a-z])+)*$
26+ //
27+ // This means we can test for features in this exact order except for Z
28+ // extensions.
29+
30+ ////////////////////////////////////////////////////////////////////////////////
31+ // Definitions for introspection.
32+ ////////////////////////////////////////////////////////////////////////////////
33+ #define INTROSPECTION_TABLE \
34+ LINE(RISCV_RV32I, RV32I, "rv32i", RISCV_HWCAP_32, 0) \
35+ LINE(RISCV_RV64I, RV64I, "rv64i", RISCV_HWCAP_64, 0) \
36+ LINE(RISCV_M, M, "m", RISCV_HWCAP_M, 0) \
37+ LINE(RISCV_A, A, "a", RISCV_HWCAP_A, 0) \
38+ LINE(RISCV_F, F, "f", RISCV_HWCAP_F, 0) \
39+ LINE(RISCV_D, D, "d", RISCV_HWCAP_D, 0) \
40+ LINE(RISCV_Q, Q, "q", RISCV_HWCAP_Q, 0) \
41+ LINE(RISCV_C, C, "c", RISCV_HWCAP_C, 0) \
42+ LINE(RISCV_V, V, "v", RISCV_HWCAP_V, 0) \
43+ LINE(RISCV_Zicsr, Zicsr, "_zicsr", 0, 0) \
44+ LINE(RISCV_Zifencei, Zifencei, "_zifencei", 0, 0)
45+ #define INTROSPECTION_PREFIX Riscv
46+ #define INTROSPECTION_ENUM_PREFIX RISCV
47+ #include "define_introspection_and_hwcaps.inl"
48+
49+ ////////////////////////////////////////////////////////////////////////////////
50+ // Implementation.
51+ ////////////////////////////////////////////////////////////////////////////////
52+
53+ #include <stdbool.h>
54+ #include <stdio.h>
55+
56+ #include "internal/filesystem.h"
57+ #include "internal/stack_line_reader.h"
58+
59+ static const RiscvInfo kEmptyRiscvInfo ;
60+
61+ static void HandleRiscVIsaLine (StringView line , RiscvFeatures * const features ) {
62+ for (size_t i = 0 ; i < RISCV_LAST_ ; ++ i ) {
63+ StringView flag = str (kCpuInfoFlags [i ]);
64+ int index_of_flag = CpuFeatures_StringView_IndexOf (line , flag );
65+ bool is_set = index_of_flag != -1 ;
66+ kSetters [i ](features , is_set );
67+ if (is_set )
68+ line = CpuFeatures_StringView_PopFront (line , index_of_flag + flag .size );
69+ }
70+ }
71+
72+ static bool HandleRiscVLine (const LineResult result , RiscvInfo * const info ) {
73+ StringView line = result .line ;
74+ StringView key , value ;
75+ if (CpuFeatures_StringView_GetAttributeKeyValue (line , & key , & value )) {
76+ if (CpuFeatures_StringView_IsEquals (key , str ("isa" ))) {
77+ HandleRiscVIsaLine (value , & info -> features );
78+ } else if (CpuFeatures_StringView_IsEquals (key , str ("uarch" ))) {
79+ int index = CpuFeatures_StringView_IndexOfChar (value , ',' );
80+ if (index == -1 ) return true;
81+ StringView vendor = CpuFeatures_StringView_KeepFront (value , index );
82+ StringView uarch = CpuFeatures_StringView_PopFront (value , index + 1 );
83+ CpuFeatures_StringView_CopyString (vendor , info -> vendor ,
84+ sizeof (info -> vendor ));
85+ CpuFeatures_StringView_CopyString (uarch , info -> uarch ,
86+ sizeof (info -> uarch ));
87+ }
88+ }
89+ return !result .eof ;
90+ }
91+
92+ static void FillProcCpuInfoData (RiscvInfo * const info ) {
93+ const int fd = CpuFeatures_OpenFile ("/proc/cpuinfo" );
94+ if (fd >= 0 ) {
95+ StackLineReader reader ;
96+ StackLineReader_Initialize (& reader , fd );
97+ for (;;) {
98+ if (!HandleRiscVLine (StackLineReader_NextLine (& reader ), info )) break ;
99+ }
100+ CpuFeatures_CloseFile (fd );
101+ }
102+ }
103+
104+ RiscvInfo GetRiscvInfo (void ) {
105+ RiscvInfo info = kEmptyRiscvInfo ;
106+ FillProcCpuInfoData (& info );
107+ return info ;
108+ }
109+
110+ #endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
111+ #endif // CPU_FEATURES_ARCH_RISCV
0 commit comments