1 /*
  2  * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
  3  * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
  4  * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
  5  * Copyright (c) 2023, Rivos Inc. All rights reserved.
  6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  7  *
  8  * This code is free software; you can redistribute it and/or modify it
  9  * under the terms of the GNU General Public License version 2 only, as
 10  * published by the Free Software Foundation.
 11  *
 12  * This code is distributed in the hope that it will be useful, but WITHOUT
 13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 15  * version 2 for more details (a copy is included in the LICENSE file that
 16  * accompanied this code).
 17  *
 18  * You should have received a copy of the GNU General Public License version
 19  * 2 along with this work; if not, write to the Free Software Foundation,
 20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 21  *
 22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 23  * or visit www.oracle.com if you need additional information or have any
 24  * questions.
 25  *
 26  */
 27 
 28 #ifndef CPU_RISCV_VM_VERSION_RISCV_HPP
 29 #define CPU_RISCV_VM_VERSION_RISCV_HPP
 30 
 31 #include "runtime/abstract_vm_version.hpp"
 32 #include "runtime/arguments.hpp"
 33 #include "runtime/globals_extension.hpp"
 34 #include "utilities/globalDefinitions.hpp"
 35 #include "utilities/growableArray.hpp"
 36 #include "utilities/sizes.hpp"
 37 
 38 class RiscvHwprobe;
 39 
 40 class VM_Version : public Abstract_VM_Version {
 41   friend RiscvHwprobe;
 42  private:
 43 
 44   // JEDEC encoded as ((bank - 1) << 7) | (0x7f & JEDEC)
 45   enum VendorId {
 46     RIVOS = 0x6cf, // JEDEC: 0x4f, Bank: 14
 47   };
 48 
 49   class RVExtFeatures;
 50 
 51   class RVFeatureValue {
 52     const char* const _pretty;
 53     const bool        _feature_string;
 54     const uint64_t    _linux_feature_bit;
 55 
 56    public:
 57     RVFeatureValue(const char* pretty, int linux_bit_num, bool fstring) :
 58       _pretty(pretty), _feature_string(fstring), _linux_feature_bit(nth_bit<uint64_t>(linux_bit_num)) {
 59     }
 60     virtual void enable_feature(int64_t value = 0) = 0;
 61     virtual void disable_feature() = 0;
 62     const char* pretty()         { return _pretty; }
 63     uint64_t feature_bit()       { return _linux_feature_bit; }
 64     bool feature_string()        { return _feature_string; }
 65     virtual bool enabled() = 0;
 66     virtual void update_flag() = 0;
 67     virtual void log_enabled() = 0;
 68   };
 69 
 70   #define UPDATE_DEFAULT(flag)           \
 71   void update_flag() {                   \
 72     assert(enabled(), "Must be.");       \
 73     if (FLAG_IS_DEFAULT(flag)) {         \
 74       FLAG_SET_DEFAULT(flag, true);      \
 75     } else {                             \
 76       /* Sync CPU features with flags */ \
 77       if (!flag) {                       \
 78         disable_feature();               \
 79       }                                  \
 80     }                                    \
 81   }                                      \
 82 
 83   #define UPDATE_DEFAULT_DEP(flag, dep0, ...)                                                               \
 84   void update_flag() {                                                                                      \
 85       assert(enabled(), "Must be.");                                                                        \
 86       DEBUG_ONLY(verify_deps(dep0, ##__VA_ARGS__));                                                         \
 87       if (FLAG_IS_DEFAULT(flag)) {                                                                          \
 88         if (deps_all_enabled(dep0, ##__VA_ARGS__)) {                                                        \
 89           FLAG_SET_DEFAULT(flag, true);                                                                     \
 90         } else {                                                                                            \
 91           FLAG_SET_DEFAULT(flag, false);                                                                    \
 92           /* Sync CPU features with flags */                                                                \
 93           disable_feature();                                                                                \
 94           stringStream ss;                                                                                  \
 95           ss.print("missing dependent extension(s): ");                                                     \
 96           deps_string(ss, dep0, ##__VA_ARGS__);                                                             \
 97           log_disabled(ss.as_string(true));                                                                 \
 98         }                                                                                                   \
 99       } else {                                                                                              \
100         /* Sync CPU features with flags */                                                                  \
101         if (!flag) {                                                                                        \
102           disable_feature();                                                                                \
103         } else if (!deps_all_enabled(dep0, ##__VA_ARGS__)) {                                                \
104           FLAG_SET_DEFAULT(flag, false);                                                                    \
105           /* Sync CPU features with flags */                                                                \
106           disable_feature();                                                                                \
107           stringStream ss;                                                                                  \
108           ss.print("missing dependent extension(s): ");                                                     \
109           deps_string(ss, dep0, ##__VA_ARGS__);                                                             \
110           log_disabled(ss.as_string(true));                                                                 \
111         }                                                                                                   \
112       }                                                                                                     \
113   }                                                                                                         \
114 
115   #define NO_UPDATE_DEFAULT                \
116   void update_flag() {}                    \
117 
118 
119   class RVExtFeatureValue : public RVFeatureValue {
120     const uint32_t _cpu_feature_index;
121 
122    public:
123     RVExtFeatureValue(const char* pretty, int linux_bit_num, uint32_t cpu_feature_index, bool fstring) :
124       RVFeatureValue(pretty, linux_bit_num, fstring),
125       _cpu_feature_index(cpu_feature_index) {
126     }
127     int cpu_feature_index() {
128       // Can be used to check, for example, v is declared before Zvfh in RV_EXT_FEATURE_FLAGS.
129       return _cpu_feature_index;
130     }
131     bool enabled() {
132       return RVExtFeatures::current()->support_feature(_cpu_feature_index);
133     }
134     void enable_feature(int64_t value = 0) {
135       RVExtFeatures::current()->set_feature(_cpu_feature_index);
136     }
137     void disable_feature() {
138       RVExtFeatures::current()->clear_feature(_cpu_feature_index);
139     }
140     void log_enabled();
141     void log_disabled(const char* reason);
142 
143    protected:
144     bool deps_all_enabled(RVExtFeatureValue* dep0, ...) {
145       assert(dep0 != nullptr, "must not");
146 
147       va_list va;
148       va_start(va, dep0);
149       RVExtFeatureValue* next = dep0;
150       bool enabled = true;
151       while (next != nullptr && enabled) {
152         enabled = next->enabled();
153         next = va_arg(va, RVExtFeatureValue*);
154       }
155       va_end(va);
156       return enabled;
157     }
158 
159     void deps_string(stringStream& ss, RVExtFeatureValue* dep0, ...) {
160       assert(dep0 != nullptr, "must not");
161       ss.print("%s (%s)", dep0->pretty(), dep0->enabled() ? "enabled" : "disabled");
162 
163       va_list va;
164       va_start(va, dep0);
165       RVExtFeatureValue* next = nullptr;
166       while ((next = va_arg(va, RVExtFeatureValue*)) != nullptr) {
167         ss.print(", %s (%s)", next->pretty(), next->enabled() ? "enabled" : "disabled");
168       }
169       va_end(va);
170     }
171 
172 #ifdef ASSERT
173     void verify_deps(RVExtFeatureValue* dep0, ...) {
174       assert(dep0 != nullptr, "must not");
175       assert(cpu_feature_index() >= 0, "must");
176 
177       va_list va;
178       va_start(va, dep0);
179       RVExtFeatureValue* next = dep0;
180       while (next != nullptr) {
181         assert(next->cpu_feature_index() >= 0, "must");
182         // We only need to check depenency relationship for extension flags.
183         // The dependant ones must be declared before this, for example, v must be declared
184         // before Zvfh in RV_EXT_FEATURE_FLAGS. The reason is in setup_cpu_available_features
185         // we need to make sure v is `update_flag`ed before Zvfh, so Zvfh is `update_flag`ed
186         // based on v.
187         assert(cpu_feature_index() > next->cpu_feature_index(), "Invalid");
188         next = va_arg(va, RVExtFeatureValue*);
189       }
190       va_end(va);
191     }
192 #endif // ASSERT
193   };
194 
195   class RVNonExtFeatureValue : public RVFeatureValue {
196     static const int64_t DEFAULT_VALUE = -1;
197     int64_t _value;
198 
199    public:
200     RVNonExtFeatureValue(const char* pretty, int linux_bit_num, bool fstring) :
201       RVFeatureValue(pretty, linux_bit_num, fstring),
202       _value(DEFAULT_VALUE) {
203     }
204     bool enabled() { return _value != DEFAULT_VALUE; }
205     void enable_feature(int64_t value) {
206       assert(value != DEFAULT_VALUE, "Sanity");
207       _value = value;
208     }
209     void disable_feature() { _value = DEFAULT_VALUE; }
210     int64_t value() { return _value; }
211     void log_enabled();
212   };
213 
214  public:
215 
216   #define RV_NO_FLAG_BIT (BitsPerWord+1) // nth_bit will return 0 on values larger than BitsPerWord
217 
218   // Note: the order matters, depender should be after their dependee. E.g. ext_V before ext_Zvbb.
219   //
220   // Fields description in `decl`:
221   //    declaration name, extension name, bit value from linux, feature string?, mapped flag)
222   #define RV_EXT_FEATURE_FLAGS(decl)                                                                   \
223   /* A Atomic Instructions */                                                                          \
224   decl(a           ,     ('A' - 'A'),  true ,  NO_UPDATE_DEFAULT)                                      \
225   /* C Compressed Instructions */                                                                      \
226   decl(c           ,     ('C' - 'A'),  true ,  UPDATE_DEFAULT(UseRVC))                                 \
227   /* D Single-Precision Floating-Point */                                                              \
228   decl(d           ,     ('D' - 'A'),  true ,  NO_UPDATE_DEFAULT)                                      \
229   /* F Single-Precision Floating-Point */                                                              \
230   decl(f           ,     ('F' - 'A'),  true ,  NO_UPDATE_DEFAULT)                                      \
231   /* H Hypervisor */                                                                                   \
232   decl(h           ,     ('H' - 'A'),  true ,  NO_UPDATE_DEFAULT)                                      \
233   /* I RV64I */                                                                                        \
234   decl(i           ,     ('I' - 'A'),  true ,  NO_UPDATE_DEFAULT)                                      \
235   /* M Integer Multiplication and Division */                                                          \
236   decl(m           ,     ('M' - 'A'),  true ,  NO_UPDATE_DEFAULT)                                      \
237   /* Q Quad-Precision Floating-Point */                                                                \
238   decl(q           ,     ('Q' - 'A'),  true ,  NO_UPDATE_DEFAULT)                                      \
239   /* V Vector */                                                                                       \
240   decl(v           ,     ('V' - 'A'),  true ,  UPDATE_DEFAULT(UseRVV))                                 \
241                                                                                                        \
242   /* ----------------------- Other extensions ----------------------- */                               \
243                                                                                                        \
244   /* Atomic compare-and-swap (CAS) instructions */                                                     \
245   decl(Zacas       ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZacas))                               \
246   /* Zba Address generation instructions */                                                            \
247   decl(Zba         ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZba))                                 \
248   /* Zbb Basic bit-manipulation */                                                                     \
249   decl(Zbb         ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZbb))                                 \
250   /* Zbc Carry-less multiplication */                                                                  \
251   decl(Zbc         ,  RV_NO_FLAG_BIT,  true ,  NO_UPDATE_DEFAULT)                                      \
252   /* Bitmanip instructions for Cryptography */                                                         \
253   decl(Zbkb        ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZbkb))                                \
254   /* Zbs Single-bit instructions */                                                                    \
255   decl(Zbs         ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZbs))                                 \
256   /* Zcb Simple code-size saving instructions */                                                       \
257   decl(Zcb         ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZcb))                                 \
258   /* Additional Floating-Point instructions */                                                         \
259   decl(Zfa         ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZfa))                                 \
260   /* Zfh Half-Precision Floating-Point instructions */                                                 \
261   decl(Zfh         ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZfh))                                 \
262   /* Zfhmin Minimal Half-Precision Floating-Point instructions */                                      \
263   decl(Zfhmin      ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZfhmin))                              \
264   /* Zicbom Cache Block Management Operations */                                                       \
265   decl(Zicbom      ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZicbom))                              \
266   /* Zicbop Cache Block Prefetch Operations */                                                         \
267   decl(Zicbop      ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZicbop))                              \
268   /* Zicboz Cache Block Zero Operations */                                                             \
269   decl(Zicboz      ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZicboz))                              \
270   /* Base Counters and Timers */                                                                       \
271   decl(Zicntr      ,  RV_NO_FLAG_BIT,  true ,  NO_UPDATE_DEFAULT)                                      \
272   /* Zicond Conditional operations */                                                                  \
273   decl(Zicond      ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZicond))                              \
274   /* Zicsr Control and Status Register (CSR) Instructions */                                           \
275   decl(Zicsr       ,  RV_NO_FLAG_BIT,  true ,  NO_UPDATE_DEFAULT)                                      \
276   /* Zic64b Cache blocks must be 64 bytes in size, naturally aligned in the address space. */          \
277   decl(Zic64b      ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZic64b))                              \
278   /* Zifencei Instruction-Fetch Fence */                                                               \
279   decl(Zifencei    ,  RV_NO_FLAG_BIT,  true ,  NO_UPDATE_DEFAULT)                                      \
280   /* Zihintpause Pause instruction HINT */                                                             \
281   decl(Zihintpause ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZihintpause))                         \
282   /* Total Store Ordering */                                                                           \
283   decl(Ztso        ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT(UseZtso))                                \
284   /* Vector Basic Bit-manipulation */                                                                  \
285   decl(Zvbb        ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT_DEP(UseZvbb, &ext_v, nullptr))           \
286   /* Vector Carryless Multiplication */                                                                \
287   decl(Zvbc        ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT_DEP(UseZvbc, &ext_v, nullptr))           \
288   /* Vector Extension for Half-Precision Floating-Point */                                             \
289   decl(Zvfh        ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT_DEP(UseZvfh, &ext_v, &ext_Zfh, nullptr)) \
290   /* Shorthand for Zvkned + Zvknhb + Zvkb + Zvkt */                                                    \
291   decl(Zvkn        ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT_DEP(UseZvkn, &ext_v, nullptr))           \
292   /* Zvkg crypto extension for ghash and gcm */                                                        \
293   decl(Zvkg        ,  RV_NO_FLAG_BIT,  true ,  UPDATE_DEFAULT_DEP(UseZvkg, &ext_v, nullptr))           \
294 
295   #define DECLARE_RV_EXT_FEATURE(PRETTY, LINUX_BIT, FSTRING, FLAGF)                             \
296   struct ext_##PRETTY##RVExtFeatureValue : public RVExtFeatureValue {                           \
297     ext_##PRETTY##RVExtFeatureValue() :                                                         \
298       RVExtFeatureValue(#PRETTY, LINUX_BIT, RVExtFeatures::CPU_##ext_##PRETTY, FSTRING) {}      \
299     FLAGF;                                                                                      \
300   };                                                                                            \
301   static ext_##PRETTY##RVExtFeatureValue ext_##PRETTY;                                          \
302 
303   RV_EXT_FEATURE_FLAGS(DECLARE_RV_EXT_FEATURE)
304   #undef DECLARE_RV_EXT_FEATURE
305 
306   // Non-extension features
307   //
308   #define RV_NON_EXT_FEATURE_FLAGS(decl)                                                       \
309   /* Id for microarch. Mvendorid plus marchid uniquely identify the microarch. */              \
310   decl(marchid           ,  RV_NO_FLAG_BIT,  false,  NO_UPDATE_DEFAULT)                        \
311   /* A unique encoding of the version of the processor implementation. */                      \
312   decl(mimpid            ,  RV_NO_FLAG_BIT,  false,  NO_UPDATE_DEFAULT)                        \
313   /* Manufactory JEDEC id encoded, ISA vol 2 3.1.2.. */                                        \
314   decl(mvendorid         ,  RV_NO_FLAG_BIT,  false,  NO_UPDATE_DEFAULT)                        \
315   /* SATP bits (number of virtual addr bits) mbare, sv39, sv48, sv57, sv64 */                  \
316   decl(satp_mode         ,  RV_NO_FLAG_BIT,  false,  NO_UPDATE_DEFAULT)                        \
317   /* Performance of misaligned scalar accesses (unknown, emulated, slow, fast, unsupported) */ \
318   decl(unaligned_scalar  ,  RV_NO_FLAG_BIT,  false,  NO_UPDATE_DEFAULT)                        \
319   /* Performance of misaligned vector accesses (unknown, unspported, slow, fast) */            \
320   decl(unaligned_vector  ,  RV_NO_FLAG_BIT,  false,  NO_UPDATE_DEFAULT)                        \
321   decl(zicboz_block_size ,  RV_NO_FLAG_BIT,  false,  NO_UPDATE_DEFAULT)                        \
322 
323   #define DECLARE_RV_NON_EXT_FEATURE(PRETTY, LINUX_BIT, FSTRING, FLAGF)            \
324   struct PRETTY##RVNonExtFeatureValue : public RVNonExtFeatureValue {              \
325     PRETTY##RVNonExtFeatureValue() :                                               \
326       RVNonExtFeatureValue(#PRETTY, LINUX_BIT, FSTRING) {}                         \
327     FLAGF;                                                                         \
328   };                                                                               \
329   static PRETTY##RVNonExtFeatureValue PRETTY;                                      \
330 
331   RV_NON_EXT_FEATURE_FLAGS(DECLARE_RV_NON_EXT_FEATURE)
332   #undef DECLARE_RV_NON_EXT_FEATURE
333 
334 private:
335   // Utility for AOT CPU feature store/check.
336   class RVExtFeatures : public CHeapObj<mtCode> {
337    public:
338     enum RVFeatureIndex {
339       #define DECLARE_RV_FEATURE_ENUM(PRETTY, LINUX_BIT, FSTRING, FLAGF) CPU_##ext_##PRETTY,
340 
341       RV_EXT_FEATURE_FLAGS(DECLARE_RV_FEATURE_ENUM)
342       MAX_CPU_FEATURE_INDEX
343       #undef DECLARE_RV_FEATURE_ENUM
344     };
345    private:
346     uint64_t _features_bitmap[(MAX_CPU_FEATURE_INDEX / BitsPerLong) + 1];
347     STATIC_ASSERT(sizeof(_features_bitmap) * BitsPerByte >= MAX_CPU_FEATURE_INDEX);
348 
349     // Number of 8-byte elements in _features_bitmap.
350     constexpr static int element_count() {
351       return sizeof(_features_bitmap) / sizeof(uint64_t);
352     }
353 
354     static int element_index(RVFeatureIndex feature) {
355       int idx = feature / BitsPerLong;
356       assert(idx < element_count(), "Features array index out of bounds");
357       return idx;
358     }
359 
360     static uint64_t feature_bit(RVFeatureIndex feature) {
361       return (1ULL << (feature % BitsPerLong));
362     }
363 
364     static RVFeatureIndex convert(uint32_t index) {
365       assert(index < MAX_CPU_FEATURE_INDEX, "must");
366       return (RVFeatureIndex)index;
367     }
368 
369    public:
370     static RVExtFeatures* current() {
371       return _rv_ext_features;
372     }
373 
374     RVExtFeatures() {
375       for (int i = 0; i < element_count(); i++) {
376         _features_bitmap[i] = 0;
377       }
378     }
379 
380     void set_feature(uint32_t feature) {
381       RVFeatureIndex f = convert(feature);
382       int idx = element_index(f);
383       _features_bitmap[idx] |= feature_bit(f);
384     }
385 
386     void clear_feature(uint32_t feature) {
387       RVFeatureIndex f = convert(feature);
388       int idx = element_index(f);
389       _features_bitmap[idx] &= ~feature_bit(f);
390     }
391 
392     bool support_feature(uint32_t feature) {
393       RVFeatureIndex f = convert(feature);
394       int idx = element_index(f);
395       return (_features_bitmap[idx] & feature_bit(f)) != 0;
396     }
397   };
398 
399   // enable extensions based on profile, current supported profiles:
400   //  RVA20U64
401   //  RVA22U64
402   //  RVA23U64
403   // NOTE: we only enable the mandatory extensions, not optional extension.
404   #define RV_ENABLE_EXTENSION(UseExtension)     \
405     if (FLAG_IS_DEFAULT(UseExtension)) {        \
406       FLAG_SET_DEFAULT(UseExtension, true);     \
407     }                                           \
408 
409   // https://github.com/riscv/riscv-profiles/blob/main/src/profiles.adoc#rva20-profiles
410   #define RV_USE_RVA20U64                            \
411     RV_ENABLE_EXTENSION(UseRVC)                      \
412 
413   static void useRVA20U64Profile();
414 
415   // https://github.com/riscv/riscv-profiles/blob/main/src/profiles.adoc#rva22-profiles
416   #define RV_USE_RVA22U64                            \
417     RV_ENABLE_EXTENSION(UseRVC)                      \
418     RV_ENABLE_EXTENSION(UseZba)                      \
419     RV_ENABLE_EXTENSION(UseZbb)                      \
420     RV_ENABLE_EXTENSION(UseZbs)                      \
421     RV_ENABLE_EXTENSION(UseZic64b)                   \
422     RV_ENABLE_EXTENSION(UseZicbom)                   \
423     RV_ENABLE_EXTENSION(UseZicbop)                   \
424     RV_ENABLE_EXTENSION(UseZicboz)                   \
425     RV_ENABLE_EXTENSION(UseZihintpause)              \
426 
427   static void useRVA22U64Profile();
428 
429   // https://github.com/riscv/riscv-profiles/blob/main/src/rva23-profile.adoc#rva23u64-profile
430   #define RV_USE_RVA23U64                           \
431     RV_ENABLE_EXTENSION(UseRVC)                     \
432     RV_ENABLE_EXTENSION(UseRVV)                     \
433     RV_ENABLE_EXTENSION(UseZba)                     \
434     RV_ENABLE_EXTENSION(UseZbb)                     \
435     RV_ENABLE_EXTENSION(UseZbs)                     \
436     RV_ENABLE_EXTENSION(UseZcb)                     \
437     RV_ENABLE_EXTENSION(UseZfa)                     \
438     RV_ENABLE_EXTENSION(UseZfhmin)                  \
439     RV_ENABLE_EXTENSION(UseZic64b)                  \
440     RV_ENABLE_EXTENSION(UseZicbom)                  \
441     RV_ENABLE_EXTENSION(UseZicbop)                  \
442     RV_ENABLE_EXTENSION(UseZicboz)                  \
443     RV_ENABLE_EXTENSION(UseZicond)                  \
444     RV_ENABLE_EXTENSION(UseZihintpause)             \
445 
446   static void useRVA23U64Profile();
447 
448   // VM modes (satp.mode) privileged ISA 1.10
449   enum VM_MODE : int {
450     VM_NOTSET = -1,
451     VM_MBARE  = 0,
452     VM_SV39   = 39,
453     VM_SV48   = 48,
454     VM_SV57   = 57,
455     VM_SV64   = 64
456   };
457 
458   static VM_MODE parse_satp_mode(const char* vm_mode);
459 
460   // Values from riscv_hwprobe()
461   enum UNALIGNED_SCALAR_ACCESS : int {
462     MISALIGNED_SCALAR_UNKNOWN     = 0,
463     MISALIGNED_SCALAR_EMULATED    = 1,
464     MISALIGNED_SCALAR_SLOW        = 2,
465     MISALIGNED_SCALAR_FAST        = 3,
466     MISALIGNED_SCALAR_UNSUPPORTED = 4
467   };
468 
469   enum UNALIGNED_VECTOR_ACCESS : int {
470     MISALIGNED_VECTOR_UNKNOWN     = 0,
471     MISALIGNED_VECTOR_SLOW        = 2,
472     MISALIGNED_VECTOR_FAST        = 3,
473     MISALIGNED_VECTOR_UNSUPPORTED = 4
474   };
475 
476   // Null terminated list
477   static RVFeatureValue* _feature_list[];
478   static RVExtFeatures* _rv_ext_features;
479 
480   // Enables features in _feature_list
481   static void setup_cpu_available_features();
482   // Helper for specific queries
483   static void os_aux_features();
484   static char* os_uarch_additional_features();
485   static void vendor_features();
486   // Vendors specific features
487   static void rivos_features();
488 
489   // Determine vector length iff ext_V/UseRVV
490   static uint32_t cpu_vector_length();
491   static uint32_t _initial_vector_length;
492 
493   static void common_initialize();
494 
495 #ifdef COMPILER2
496   static void c2_initialize();
497 #endif // COMPILER2
498 
499  public:
500   // Initialization
501   static void initialize();
502   static void initialize_cpu_information();
503 
504   constexpr static bool supports_stack_watermark_barrier() { return true; }
505 
506   constexpr static bool supports_recursive_fast_locking() { return true; }
507 
508   constexpr static bool supports_secondary_supers_table() { return true; }
509 
510   static bool supports_on_spin_wait() { return UseZihintpause; }
511 
512   // RISCV64 supports fast class initialization checks
513   static bool supports_fast_class_init_checks() { return true; }
514   static bool supports_fencei_barrier() { return ext_Zifencei.enabled(); }
515 
516   static bool supports_float16_float_conversion() {
517     return UseZfh || UseZfhmin;
518   }
519 
520   // Check intrinsic support
521   static bool is_intrinsic_supported(vmIntrinsicID id);
522 };
523 
524 #endif // CPU_RISCV_VM_VERSION_RISCV_HPP