diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index e0c3b30375035..d9654813adbc2 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -35,15 +35,28 @@ uint32_t VM_Version::_initial_vector_length = 0; -#define DEF_RV_FEATURE(NAME, PRETTY, BIT, FSTRING, FLAGF) \ -VM_Version::NAME##RVFeatureValue VM_Version::NAME(PRETTY, BIT, FSTRING); -RV_FEATURE_FLAGS(DEF_RV_FEATURE) - -#define ADD_RV_FEATURE_IN_LIST(NAME, PRETTY, BIT, FSTRING, FLAGF) \ - &VM_Version::NAME, -VM_Version::RVFeatureValue* VM_Version::_feature_list[] = { -RV_FEATURE_FLAGS(ADD_RV_FEATURE_IN_LIST) +#define DEF_RV_EXT_FEATURE(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \ +VM_Version::NAME##RVExtFeatureValue VM_Version::NAME; +RV_EXT_FEATURE_FLAGS(DEF_RV_EXT_FEATURE) +#undef DEF_RV_EXT_FEATURE + +#define DEF_RV_NON_EXT_FEATURE(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \ +VM_Version::NAME##RVNonExtFeatureValue VM_Version::NAME; +RV_NON_EXT_FEATURE_FLAGS(DEF_RV_NON_EXT_FEATURE) +#undef DEF_RV_NON_EXT_FEATURE + +#define ADD_RV_EXT_FEATURE_IN_LIST(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \ + &VM_Version::NAME, +#define ADD_RV_NON_EXT_FEATURE_IN_LIST(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \ + &VM_Version::NAME, + VM_Version::RVFeatureValue* VM_Version::_feature_list[] = { + RV_EXT_FEATURE_FLAGS(ADD_RV_EXT_FEATURE_IN_LIST) + RV_NON_EXT_FEATURE_FLAGS(ADD_RV_NON_EXT_FEATURE_IN_LIST) nullptr}; +#undef ADD_RV_NON_EXT_FEATURE_IN_LIST +#undef ADD_RV_EXT_FEATURE_IN_LIST + +VM_Version::RVExtFeatures* VM_Version::_rv_ext_features = new VM_Version::RVExtFeatures(); void VM_Version::useRVA20U64Profile() { RV_USE_RVA20U64; diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index d94385cd8ac1f..aec975d27bef3 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -46,30 +46,29 @@ class VM_Version : public Abstract_VM_Version { RIVOS = 0x6cf, // JEDEC: 0x4f, Bank: 14 }; + class RVExtFeatures; + class RVFeatureValue { const char* const _pretty; const bool _feature_string; - const uint64_t _feature_bit; - bool _enabled; + const uint64_t _linux_feature_bit; int64_t _value; public: - RVFeatureValue(const char* pretty, int bit_num, bool fstring) : - _pretty(pretty), _feature_string(fstring), _feature_bit(nth_bit(bit_num)), - _enabled(false), _value(-1) { + RVFeatureValue(const char* pretty, int linux_bit_num, bool fstring) : + _pretty(pretty), _feature_string(fstring), _linux_feature_bit(nth_bit(linux_bit_num)), + _value(-1) { } - void enable_feature(int64_t value = 0) { - _enabled = true; + virtual void enable_feature(int64_t value = 0) { _value = value; } - void disable_feature() { - _enabled = false; + virtual void disable_feature() { _value = -1; } const char* pretty() { return _pretty; } - uint64_t feature_bit() { return _feature_bit; } + uint64_t feature_bit() { return _linux_feature_bit; } bool feature_string() { return _feature_string; } - bool enabled() { return _enabled; } int64_t value() { return _value; } + virtual bool enabled() = 0; virtual void update_flag() = 0; }; @@ -111,6 +110,45 @@ class VM_Version : public Abstract_VM_Version { #define NO_UPDATE_DEFAULT \ void update_flag() {} \ + + class RVExtFeatureValue : public RVFeatureValue { + const uint32_t _cpu_feature_index; + public: + RVExtFeatureValue(const char* pretty, int linux_bit_num, uint32_t cpu_feature_index, bool fstring) : + RVFeatureValue(pretty, linux_bit_num, fstring), + _cpu_feature_index(cpu_feature_index) { + } + bool enabled() { + return RVExtFeatures::current()->support_feature(_cpu_feature_index); + } + void enable_feature(int64_t value = 0) { + RVFeatureValue::enable_feature(value); + RVExtFeatures::current()->set_feature(_cpu_feature_index); + } + void disable_feature() { + RVFeatureValue::disable_feature(); + RVExtFeatures::current()->clear_feature(_cpu_feature_index); + } + }; + + class RVNonExtFeatureValue : public RVFeatureValue { + bool _enabled; + public: + RVNonExtFeatureValue(const char* pretty, int linux_bit_num, bool fstring) : + RVFeatureValue(pretty, linux_bit_num, fstring), + _enabled(false) { + } + bool enabled() { return _enabled; } + void enable_feature(int64_t value = 0) { + RVFeatureValue::enable_feature(value); + _enabled = true; + } + void disable_feature() { + RVFeatureValue::disable_feature(); + _enabled = false; + } + }; + // Frozen standard extensions // I RV64I // M Integer Multiplication and Division @@ -161,58 +199,140 @@ class VM_Version : public Abstract_VM_Version { #define RV_NO_FLAG_BIT (BitsPerWord+1) // nth_bit will return 0 on values larger than BitsPerWord // Note: the order matters, depender should be after their dependee. E.g. ext_V before ext_Zvbb. - // declaration name , extension name, bit pos ,in str, mapped flag) - #define RV_FEATURE_FLAGS(decl) \ - decl(ext_I , "i" , ('I' - 'A'), true , NO_UPDATE_DEFAULT) \ - decl(ext_M , "m" , ('M' - 'A'), true , NO_UPDATE_DEFAULT) \ - decl(ext_A , "a" , ('A' - 'A'), true , NO_UPDATE_DEFAULT) \ - decl(ext_F , "f" , ('F' - 'A'), true , NO_UPDATE_DEFAULT) \ - decl(ext_D , "d" , ('D' - 'A'), true , NO_UPDATE_DEFAULT) \ - decl(ext_C , "c" , ('C' - 'A'), true , UPDATE_DEFAULT(UseRVC)) \ - decl(ext_Q , "q" , ('Q' - 'A'), true , NO_UPDATE_DEFAULT) \ - decl(ext_H , "h" , ('H' - 'A'), true , NO_UPDATE_DEFAULT) \ - decl(ext_V , "v" , ('V' - 'A'), true , UPDATE_DEFAULT(UseRVV)) \ - decl(ext_Zicbom , "Zicbom" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbom)) \ - decl(ext_Zicboz , "Zicboz" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicboz)) \ - decl(ext_Zicbop , "Zicbop" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbop)) \ - decl(ext_Zba , "Zba" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZba)) \ - decl(ext_Zbb , "Zbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbb)) \ - decl(ext_Zbc , "Zbc" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ - decl(ext_Zbs , "Zbs" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbs)) \ - decl(ext_Zbkb , "Zbkb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbkb)) \ - decl(ext_Zcb , "Zcb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZcb)) \ - decl(ext_Zfa , "Zfa" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfa)) \ - decl(ext_Zfh , "Zfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfh)) \ - decl(ext_Zfhmin , "Zfhmin" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfhmin)) \ - decl(ext_Zicsr , "Zicsr" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ - decl(ext_Zicntr , "Zicntr" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ - decl(ext_Zifencei , "Zifencei" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ - decl(ext_Zic64b , "Zic64b" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZic64b)) \ - decl(ext_Ztso , "Ztso" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZtso)) \ - decl(ext_Zihintpause , "Zihintpause" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \ - decl(ext_Zacas , "Zacas" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZacas)) \ - decl(ext_Zvbb , "Zvbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbb, ext_V)) \ - decl(ext_Zvbc , "Zvbc" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbc, ext_V)) \ - decl(ext_Zvfh , "Zvfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvfh, ext_V)) \ - decl(ext_Zvkn , "Zvkn" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkn, ext_V)) \ - decl(ext_Zicond , "Zicond" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicond)) \ - decl(mvendorid , "VendorId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ - decl(marchid , "ArchId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ - decl(mimpid , "ImpId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ - decl(unaligned_access , "Unaligned" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ - decl(satp_mode , "SATP" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ - decl(zicboz_block_size, "ZicbozBlockSize", RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ - - #define DECLARE_RV_FEATURE(NAME, PRETTY, BIT, FSTRING, FLAGF) \ - struct NAME##RVFeatureValue : public RVFeatureValue { \ - NAME##RVFeatureValue(const char* pretty, int bit, bool fstring) : \ - RVFeatureValue(pretty, bit, fstring) {} \ - FLAGF; \ - }; \ - static NAME##RVFeatureValue NAME; \ - - RV_FEATURE_FLAGS(DECLARE_RV_FEATURE) - #undef DECLARE_RV_FEATURE + // + // Fields description in `decl`: + // declaration name, extension name, bit value from linux, feature string?, mapped flag) + #define RV_EXT_FEATURE_FLAGS(decl) \ + decl(ext_I , i , ('I' - 'A'), true , NO_UPDATE_DEFAULT) \ + decl(ext_M , m , ('M' - 'A'), true , NO_UPDATE_DEFAULT) \ + decl(ext_A , a , ('A' - 'A'), true , NO_UPDATE_DEFAULT) \ + decl(ext_F , f , ('F' - 'A'), true , NO_UPDATE_DEFAULT) \ + decl(ext_D , d , ('D' - 'A'), true , NO_UPDATE_DEFAULT) \ + decl(ext_C , c , ('C' - 'A'), true , UPDATE_DEFAULT(UseRVC)) \ + decl(ext_Q , q , ('Q' - 'A'), true , NO_UPDATE_DEFAULT) \ + decl(ext_H , h , ('H' - 'A'), true , NO_UPDATE_DEFAULT) \ + decl(ext_V , v , ('V' - 'A'), true , UPDATE_DEFAULT(UseRVV)) \ + decl(ext_Zicbom , Zicbom , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbom)) \ + decl(ext_Zicboz , Zicboz , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicboz)) \ + decl(ext_Zicbop , Zicbop , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbop)) \ + decl(ext_Zba , Zba , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZba)) \ + decl(ext_Zbb , Zbb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbb)) \ + decl(ext_Zbc , Zbc , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ + decl(ext_Zbs , Zbs , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbs)) \ + decl(ext_Zbkb , Zbkb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbkb)) \ + decl(ext_Zcb , Zcb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZcb)) \ + decl(ext_Zfa , Zfa , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfa)) \ + decl(ext_Zfh , Zfh , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfh)) \ + decl(ext_Zfhmin , Zfhmin , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfhmin)) \ + decl(ext_Zicsr , Zicsr , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ + decl(ext_Zicntr , Zicntr , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ + decl(ext_Zifencei , Zifencei , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ + decl(ext_Zic64b , Zic64b , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZic64b)) \ + decl(ext_Ztso , Ztso , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZtso)) \ + decl(ext_Zihintpause , Zihintpause , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \ + decl(ext_Zacas , Zacas , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZacas)) \ + decl(ext_Zvbb , Zvbb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbb, ext_V)) \ + decl(ext_Zvbc , Zvbc , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbc, ext_V)) \ + decl(ext_Zvfh , Zvfh , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvfh, ext_V)) \ + decl(ext_Zvkn , Zvkn , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkn, ext_V)) \ + decl(ext_Zicond , Zicond , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicond)) \ + + #define DECLARE_RV_EXT_FEATURE(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \ + struct NAME##RVExtFeatureValue : public RVExtFeatureValue { \ + NAME##RVExtFeatureValue() : \ + RVExtFeatureValue(#PRETTY, LINUX_BIT, RVExtFeatures::CPU_##NAME, FSTRING) {} \ + FLAGF; \ + }; \ + static NAME##RVExtFeatureValue NAME; \ + + RV_EXT_FEATURE_FLAGS(DECLARE_RV_EXT_FEATURE) + #undef DECLARE_RV_EXT_FEATURE + + // Non-extension features + // + #define RV_NON_EXT_FEATURE_FLAGS(decl) \ + decl(unaligned_access , Unaligned , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ + decl(mvendorid , VendorId , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ + decl(marchid , ArchId , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ + decl(mimpid , ImpId , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ + decl(satp_mode , SATP , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ + decl(zicboz_block_size, ZicbozBlockSize , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ + + #define DECLARE_RV_NON_EXT_FEATURE(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \ + struct NAME##RVNonExtFeatureValue : public RVNonExtFeatureValue { \ + NAME##RVNonExtFeatureValue() : \ + RVNonExtFeatureValue(#PRETTY, LINUX_BIT, FSTRING) {} \ + FLAGF; \ + }; \ + static NAME##RVNonExtFeatureValue NAME; \ + + RV_NON_EXT_FEATURE_FLAGS(DECLARE_RV_NON_EXT_FEATURE) + #undef DECLARE_RV_NON_EXT_FEATURE + +private: + // Utility for AOT CPU feature store/check. + class RVExtFeatures : public CHeapObj { + public: + enum RVFeatureIndex { + #define DECLARE_RV_FEATURE_ENUM(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) CPU_##NAME, + + RV_EXT_FEATURE_FLAGS(DECLARE_RV_FEATURE_ENUM) + MAX_CPU_FEATURE_INDEX + #undef DECLARE_RV_FEATURE_ENUM + }; + private: + uint64_t _features_bitmap[(MAX_CPU_FEATURE_INDEX / BitsPerLong) + 1]; + STATIC_ASSERT(sizeof(_features_bitmap) * BitsPerByte >= MAX_CPU_FEATURE_INDEX); + + // Number of 8-byte elements in _features_bitmap. + constexpr static int element_count() { + return sizeof(_features_bitmap) / sizeof(uint64_t); + } + + static int element_index(RVFeatureIndex feature) { + int idx = feature / BitsPerLong; + assert(idx < element_count(), "Features array index out of bounds"); + return idx; + } + + static uint64_t feature_bit(RVFeatureIndex feature) { + return (1ULL << (feature % BitsPerLong)); + } + + static RVFeatureIndex convert(uint32_t index) { + assert(index < MAX_CPU_FEATURE_INDEX, "must"); + return (RVFeatureIndex)index; + } + + public: + static RVExtFeatures* current() { + return _rv_ext_features; + } + + RVExtFeatures() { + for (int i = 0; i < element_count(); i++) { + _features_bitmap[i] = 0; + } + } + + void set_feature(uint32_t feature) { + RVFeatureIndex f = convert(feature); + int idx = element_index(f); + _features_bitmap[idx] |= feature_bit(f); + } + + void clear_feature(uint32_t feature) { + RVFeatureIndex f = convert(feature); + int idx = element_index(f); + _features_bitmap[idx] &= ~feature_bit(f); + } + + bool support_feature(uint32_t feature) { + RVFeatureIndex f = convert(feature); + int idx = element_index(f); + return (_features_bitmap[idx] & feature_bit(f)) != 0; + } + }; // enable extensions based on profile, current supported profiles: // RVA20U64 @@ -286,6 +406,7 @@ class VM_Version : public Abstract_VM_Version { // Null terminated list static RVFeatureValue* _feature_list[]; + static RVExtFeatures* _rv_ext_features; // Enables features in _feature_list static void setup_cpu_available_features();