8309258: RISC-V: Add riscv_hwprobe syscall
Reviewed-by: fjiang, stuefe, fyang, luhenry
This commit is contained in:
parent
4a9cc8a000
commit
31b6fd775f
src/hotspot
cpu/riscv
os_cpu/linux_riscv
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2023, Rivos Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,10 +31,20 @@
|
||||
#include "utilities/formatBuffer.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
const char* VM_Version::_uarch = "";
|
||||
const char* VM_Version::_vm_mode = "";
|
||||
#include <ctype.h>
|
||||
|
||||
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)
|
||||
nullptr};
|
||||
|
||||
void VM_Version::initialize() {
|
||||
_supports_cx8 = true;
|
||||
_supports_atomic_getset4 = true;
|
||||
@ -41,13 +52,14 @@ void VM_Version::initialize() {
|
||||
_supports_atomic_getset8 = true;
|
||||
_supports_atomic_getadd8 = true;
|
||||
|
||||
get_os_cpu_info();
|
||||
setup_cpu_available_features();
|
||||
|
||||
// check if satp.mode is supported, currently supports up to SV48(RV64)
|
||||
if (get_satp_mode() > VM_SV48) {
|
||||
if (satp_mode.value() > VM_SV48 || satp_mode.value() < VM_MBARE) {
|
||||
vm_exit_during_initialization(
|
||||
err_msg("Unsupported satp mode: %s. Only satp modes up to sv48 are supported for now.",
|
||||
_vm_mode));
|
||||
err_msg(
|
||||
"Unsupported satp mode: SV%d. Only satp modes up to sv48 are supported for now.",
|
||||
(int)satp_mode.value()));
|
||||
}
|
||||
|
||||
// https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc#rva20-profiles
|
||||
@ -165,16 +177,16 @@ void VM_Version::initialize() {
|
||||
}
|
||||
|
||||
if (UseRVV) {
|
||||
if (!(_features & CPU_V)) {
|
||||
if (!ext_V.enabled()) {
|
||||
warning("RVV is not supported on this CPU");
|
||||
FLAG_SET_DEFAULT(UseRVV, false);
|
||||
} else {
|
||||
// read vector length from vector CSR vlenb
|
||||
_initial_vector_length = get_current_vector_length();
|
||||
_initial_vector_length = cpu_vector_length();
|
||||
}
|
||||
}
|
||||
|
||||
if (UseRVC && !(_features & CPU_C)) {
|
||||
if (UseRVC && !ext_C.enabled()) {
|
||||
warning("RVC is not supported on this CPU");
|
||||
FLAG_SET_DEFAULT(UseRVC, false);
|
||||
|
||||
@ -185,7 +197,11 @@ void VM_Version::initialize() {
|
||||
}
|
||||
|
||||
if (FLAG_IS_DEFAULT(AvoidUnalignedAccesses)) {
|
||||
FLAG_SET_DEFAULT(AvoidUnalignedAccesses, true);
|
||||
if (unaligned_access.value() != MISALIGNED_FAST) {
|
||||
FLAG_SET_DEFAULT(AvoidUnalignedAccesses, true);
|
||||
} else {
|
||||
FLAG_SET_DEFAULT(AvoidUnalignedAccesses, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (UseZbb) {
|
||||
@ -208,16 +224,6 @@ void VM_Version::initialize() {
|
||||
FLAG_SET_DEFAULT(UseBlockZeroing, false);
|
||||
}
|
||||
|
||||
char buf[512];
|
||||
buf[0] = '\0';
|
||||
if (_uarch != nullptr && strcmp(_uarch, "") != 0) snprintf(buf, sizeof(buf), "%s,", _uarch);
|
||||
strcat(buf, "rv64");
|
||||
#define ADD_FEATURE_IF_SUPPORTED(id, name, bit) if (_features & CPU_##id) strcat(buf, name);
|
||||
CPU_FEATURE_FLAGS(ADD_FEATURE_IF_SUPPORTED)
|
||||
#undef ADD_FEATURE_IF_SUPPORTED
|
||||
|
||||
_features_string = os::strdup(buf);
|
||||
|
||||
#ifdef COMPILER2
|
||||
c2_initialize();
|
||||
#endif // COMPILER2
|
||||
@ -333,6 +339,6 @@ void VM_Version::initialize_cpu_information(void) {
|
||||
_no_of_threads = _no_of_cores;
|
||||
_no_of_sockets = _no_of_cores;
|
||||
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "RISCV64");
|
||||
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "RISCV64 %s", _features_string);
|
||||
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "RISCV64 %s", features_string());
|
||||
_initialized = true;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
|
||||
* Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2023, Rivos Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,55 +31,176 @@
|
||||
#include "runtime/abstract_vm_version.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/globals_extension.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/sizes.hpp"
|
||||
|
||||
class RiscvHwprobe;
|
||||
|
||||
class VM_Version : public Abstract_VM_Version {
|
||||
friend RiscvHwprobe;
|
||||
private:
|
||||
class RVFeatureValue {
|
||||
const char* const _pretty;
|
||||
const bool _feature_string;
|
||||
const uint64_t _feature_bit;
|
||||
bool _enabled;
|
||||
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) {
|
||||
}
|
||||
void enable_feature(int64_t value = 0) {
|
||||
_enabled = true;
|
||||
_value = value;
|
||||
}
|
||||
const char* const pretty() { return _pretty; }
|
||||
const uint64_t feature_bit() { return _feature_bit; }
|
||||
const bool feature_string() { return _feature_string; }
|
||||
bool enabled() { return _enabled; }
|
||||
int64_t value() { return _value; }
|
||||
virtual void update_flag() = 0;
|
||||
};
|
||||
|
||||
#define UPDATE_DEFAULT(flag) \
|
||||
void update_flag() { \
|
||||
assert(enabled(), "Must be."); \
|
||||
if (FLAG_IS_DEFAULT(flag)) { \
|
||||
FLAG_SET_DEFAULT(flag, true); \
|
||||
} \
|
||||
} \
|
||||
|
||||
#define NO_UPDATE_DEFAULT \
|
||||
void update_flag() {} \
|
||||
|
||||
// Frozen standard extensions
|
||||
// I RV64I
|
||||
// M Integer Multiplication and Division
|
||||
// A Atomic Instructions
|
||||
// F Single-Precision Floating-Point
|
||||
// D Single-Precision Floating-Point
|
||||
// (G = M + A + F + D)
|
||||
// Q Quad-Precision Floating-Point
|
||||
// C Compressed Instructions
|
||||
// H Hypervisor
|
||||
//
|
||||
// Others, open and non-standard
|
||||
// V Vector
|
||||
//
|
||||
// Cache Management Operations
|
||||
// Zicbom Cache Block Management Operations
|
||||
// Zicboz Cache Block Zero Operations
|
||||
// Zicbop Cache Block Prefetch Operations
|
||||
//
|
||||
// Bit-manipulation
|
||||
// Zba Address generation instructions
|
||||
// Zbb Basic bit-manipulation
|
||||
// Zbc Carry-less multiplication
|
||||
// Zbs Single-bit instructions
|
||||
//
|
||||
// Zicsr Control and Status Register (CSR) Instructions
|
||||
// Zifencei Instruction-Fetch Fence
|
||||
// Zic64b Cache blocks must be 64 bytes in size, naturally aligned in the address space.
|
||||
// Zihintpause Pause instruction HINT
|
||||
//
|
||||
// Other features and settings
|
||||
// mvendorid Manufactory JEDEC id encoded, ISA vol 2 3.1.2..
|
||||
// marchid Id for microarch. Mvendorid plus marchid uniquely identify the microarch.
|
||||
// mimpid A unique encoding of the version of the processor implementation.
|
||||
// unaligned_access Unaligned memory accesses (unknown, unspported, emulated, slow, firmware, fast)
|
||||
// satp mode SATP bits (number of virtual addr bits) mbare, sv39, sv48, sv57, sv64
|
||||
|
||||
#define RV_NO_FLAG_BIT (BitsPerWord+1) // nth_bit will return 0 on values larger than BitsPerWord
|
||||
|
||||
// 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_Zicsr , "Zicsr" , 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_Zihintpause , "Zihintpause" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \
|
||||
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) \
|
||||
|
||||
#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
|
||||
|
||||
// VM modes (satp.mode) privileged ISA 1.10
|
||||
enum VM_MODE : int {
|
||||
VM_NOTSET = -1,
|
||||
VM_MBARE = 0,
|
||||
VM_SV39 = 39,
|
||||
VM_SV48 = 48,
|
||||
VM_SV57 = 57,
|
||||
VM_SV64 = 64
|
||||
};
|
||||
|
||||
static VM_MODE parse_satp_mode(const char* vm_mode);
|
||||
|
||||
// Values from riscv_hwprobe()
|
||||
enum UNALIGNED_ACCESS : int {
|
||||
MISALIGNED_UNKNOWN = 0,
|
||||
MISALIGNED_EMULATED = 1,
|
||||
MISALIGNED_SLOW = 2,
|
||||
MISALIGNED_FAST = 3,
|
||||
MISALIGNED_UNSUPPORTED = 4
|
||||
};
|
||||
|
||||
// Null terminated list
|
||||
static RVFeatureValue* _feature_list[];
|
||||
|
||||
// Enables features in _feature_list
|
||||
static void setup_cpu_available_features();
|
||||
// Helper for specific queries
|
||||
static void os_aux_features();
|
||||
static char* os_uarch_additional_features();
|
||||
static void vendor_features();
|
||||
// Vendors specific features
|
||||
static void rivos_features();
|
||||
|
||||
// Determine vector length iff ext_V/UseRVV
|
||||
static uint32_t cpu_vector_length();
|
||||
static uint32_t _initial_vector_length;
|
||||
|
||||
#ifdef COMPILER2
|
||||
private:
|
||||
static void c2_initialize();
|
||||
#endif // COMPILER2
|
||||
|
||||
// VM modes (satp.mode) privileged ISA 1.10
|
||||
enum VM_MODE {
|
||||
VM_MBARE = 0,
|
||||
VM_SV39 = 8,
|
||||
VM_SV48 = 9,
|
||||
VM_SV57 = 10,
|
||||
VM_SV64 = 11
|
||||
};
|
||||
|
||||
protected:
|
||||
static const char* _uarch;
|
||||
static const char* _vm_mode;
|
||||
static uint32_t _initial_vector_length;
|
||||
static void get_os_cpu_info();
|
||||
static uint32_t get_current_vector_length();
|
||||
static VM_MODE get_satp_mode();
|
||||
|
||||
public:
|
||||
public:
|
||||
// Initialization
|
||||
static void initialize();
|
||||
static void initialize_cpu_information();
|
||||
|
||||
constexpr static bool supports_stack_watermark_barrier() { return true; }
|
||||
|
||||
static bool supports_on_spin_wait() { return UseZihintpause; }
|
||||
|
||||
enum Feature_Flag {
|
||||
#define CPU_FEATURE_FLAGS(decl) \
|
||||
decl(I, "i", 8) \
|
||||
decl(M, "m", 12) \
|
||||
decl(A, "a", 0) \
|
||||
decl(F, "f", 5) \
|
||||
decl(D, "d", 3) \
|
||||
decl(C, "c", 2) \
|
||||
decl(V, "v", 21)
|
||||
|
||||
#define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = (1 << bit),
|
||||
CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_FLAG)
|
||||
#undef DECLARE_CPU_FEATURE_FLAG
|
||||
};
|
||||
|
||||
static void initialize_cpu_information(void);
|
||||
};
|
||||
|
||||
#endif // CPU_RISCV_VM_VERSION_RISCV_HPP
|
||||
|
136
src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp
Normal file
136
src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, Rivos Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "riscv_hwprobe.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/vm_version.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
#include <sched.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// Syscall defined in kernel 6.4 and the defines will be in asm/hwprobe.h
|
||||
#define RISCV_HWPROBE_KEY_MVENDORID 0
|
||||
#define RISCV_HWPROBE_KEY_MARCHID 1
|
||||
#define RISCV_HWPROBE_KEY_MIMPID 2
|
||||
|
||||
#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3
|
||||
#define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1 << 0)
|
||||
|
||||
#define RISCV_HWPROBE_KEY_IMA_EXT_0 4
|
||||
#define RISCV_HWPROBE_IMA_FD (1 << 0)
|
||||
#define RISCV_HWPROBE_IMA_C (1 << 1)
|
||||
|
||||
#define RISCV_HWPROBE_KEY_CPUPERF_0 5
|
||||
#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
|
||||
#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)
|
||||
#define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0)
|
||||
#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0)
|
||||
#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0)
|
||||
#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0)
|
||||
|
||||
#ifndef NR_riscv_hwprobe
|
||||
#ifndef NR_arch_specific_syscall
|
||||
#define NR_arch_specific_syscall 244
|
||||
#endif
|
||||
#define NR_riscv_hwprobe (NR_arch_specific_syscall + 14)
|
||||
#endif
|
||||
|
||||
struct riscv_hwprobe {
|
||||
int64_t key;
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
long sys_riscv_hwprobe(struct riscv_hwprobe *pairs, size_t pairc,
|
||||
size_t cpuc, cpu_set_t *cpus,
|
||||
unsigned int flags) {
|
||||
return syscall(NR_riscv_hwprobe, pairs, pairc, cpuc, cpus, 0 /* flags*/);
|
||||
}
|
||||
|
||||
static bool rw_hwprobe_completed = false;
|
||||
|
||||
static struct riscv_hwprobe query[] = {{RISCV_HWPROBE_KEY_MVENDORID, 0},
|
||||
{RISCV_HWPROBE_KEY_MARCHID, 0},
|
||||
{RISCV_HWPROBE_KEY_MIMPID, 0},
|
||||
{RISCV_HWPROBE_KEY_BASE_BEHAVIOR, 0},
|
||||
{RISCV_HWPROBE_KEY_IMA_EXT_0, 0},
|
||||
{RISCV_HWPROBE_KEY_CPUPERF_0, 0}};
|
||||
|
||||
bool RiscvHwprobe::probe_features() {
|
||||
assert(!rw_hwprobe_completed, "Called twice.");
|
||||
int ret = sys_riscv_hwprobe(&query[0], sizeof(query) / sizeof(query[0]), 0, nullptr, 0);
|
||||
rw_hwprobe_completed = true;
|
||||
if (ret != 0) {
|
||||
log_debug(os, cpu)("riscv_hwprobe unsupported");
|
||||
return false;
|
||||
}
|
||||
log_debug(os, cpu)("riscv_hwprobe supported");
|
||||
add_features_from_query_result();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_valid(int64_t key) {
|
||||
return query[key].key != -1;
|
||||
}
|
||||
|
||||
static bool is_set(int64_t key, uint64_t value_mask) {
|
||||
if (is_valid(key)) {
|
||||
return query[key].value & value_mask != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RiscvHwprobe::add_features_from_query_result() {
|
||||
assert(rw_hwprobe_completed, "hwprobe not init yet.");
|
||||
|
||||
if (is_valid(RISCV_HWPROBE_KEY_MVENDORID)) {
|
||||
VM_Version::mvendorid.enable_feature(query[RISCV_HWPROBE_KEY_MVENDORID].value);
|
||||
}
|
||||
if (is_valid(RISCV_HWPROBE_KEY_MARCHID)) {
|
||||
VM_Version::marchid.enable_feature(query[RISCV_HWPROBE_KEY_MARCHID].value);
|
||||
}
|
||||
if (is_valid(RISCV_HWPROBE_KEY_MIMPID)) {
|
||||
VM_Version::mimpid.enable_feature(query[RISCV_HWPROBE_KEY_MIMPID].value);
|
||||
}
|
||||
if (is_set(RISCV_HWPROBE_KEY_BASE_BEHAVIOR, RISCV_HWPROBE_BASE_BEHAVIOR_IMA)) {
|
||||
VM_Version::ext_I.enable_feature();
|
||||
VM_Version::ext_M.enable_feature();
|
||||
VM_Version::ext_A.enable_feature();
|
||||
}
|
||||
if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_IMA_FD)) {
|
||||
VM_Version::ext_F.enable_feature();
|
||||
VM_Version::ext_D.enable_feature();
|
||||
}
|
||||
if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_IMA_C)) {
|
||||
VM_Version::ext_C.enable_feature();
|
||||
}
|
||||
if (is_valid(RISCV_HWPROBE_KEY_CPUPERF_0)) {
|
||||
VM_Version::unaligned_access.enable_feature(
|
||||
query[RISCV_HWPROBE_KEY_CPUPERF_0].value & RISCV_HWPROBE_MISALIGNED_MASK);
|
||||
}
|
||||
}
|
39
src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.hpp
Normal file
39
src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, Rivos Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OS_LINUX_RISCV_HWPROBE_LINUX_HPP
|
||||
#define OS_LINUX_RISCV_HWPROBE_LINUX_HPP
|
||||
|
||||
#include "memory/allStatic.hpp"
|
||||
#include "runtime/vm_version.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
|
||||
class RiscvHwprobe: public AllStatic {
|
||||
static void add_features_from_query_result();
|
||||
public:
|
||||
static bool probe_features();
|
||||
};
|
||||
|
||||
#endif // OS_LINUX_RISCV_HWPROBE_LINUX_HPP
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2023, Rivos Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,39 +26,50 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "asm/register.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "riscv_hwprobe.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/os.inline.hpp"
|
||||
#include "runtime/vm_version.hpp"
|
||||
|
||||
#include <asm/hwcap.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/auxv.h>
|
||||
|
||||
#ifndef HWCAP_ISA_I
|
||||
#define HWCAP_ISA_I (1 << ('I' - 'A'))
|
||||
#define HWCAP_ISA_I nth_bit('I' - 'A')
|
||||
#endif
|
||||
|
||||
#ifndef HWCAP_ISA_M
|
||||
#define HWCAP_ISA_M (1 << ('M' - 'A'))
|
||||
#define HWCAP_ISA_M nth_bit('M' - 'A')
|
||||
#endif
|
||||
|
||||
#ifndef HWCAP_ISA_A
|
||||
#define HWCAP_ISA_A (1 << ('A' - 'A'))
|
||||
#define HWCAP_ISA_A nth_bit('A' - 'A')
|
||||
#endif
|
||||
|
||||
#ifndef HWCAP_ISA_F
|
||||
#define HWCAP_ISA_F (1 << ('F' - 'A'))
|
||||
#define HWCAP_ISA_F nth_bit('F' - 'A')
|
||||
#endif
|
||||
|
||||
#ifndef HWCAP_ISA_D
|
||||
#define HWCAP_ISA_D (1 << ('D' - 'A'))
|
||||
#define HWCAP_ISA_D nth_bit('D' - 'A')
|
||||
#endif
|
||||
|
||||
#ifndef HWCAP_ISA_C
|
||||
#define HWCAP_ISA_C (1 << ('C' - 'A'))
|
||||
#define HWCAP_ISA_C nth_bit('C' - 'A')
|
||||
#endif
|
||||
|
||||
#ifndef HWCAP_ISA_Q
|
||||
#define HWCAP_ISA_Q nth_bit('Q' - 'A')
|
||||
#endif
|
||||
|
||||
#ifndef HWCAP_ISA_H
|
||||
#define HWCAP_ISA_H nth_bit('H' - 'A')
|
||||
#endif
|
||||
|
||||
#ifndef HWCAP_ISA_V
|
||||
#define HWCAP_ISA_V (1 << ('V' - 'A'))
|
||||
#define HWCAP_ISA_V nth_bit('V' - 'A')
|
||||
#endif
|
||||
|
||||
#define read_csr(csr) \
|
||||
@ -70,68 +82,173 @@
|
||||
__v; \
|
||||
})
|
||||
|
||||
uint32_t VM_Version::get_current_vector_length() {
|
||||
assert(_features & CPU_V, "should not call this");
|
||||
uint32_t VM_Version::cpu_vector_length() {
|
||||
assert(ext_V.enabled(), "should not call this");
|
||||
return (uint32_t)read_csr(CSR_VLENB);
|
||||
}
|
||||
|
||||
VM_Version::VM_MODE VM_Version::get_satp_mode() {
|
||||
if (!strcmp(_vm_mode, "sv39")) {
|
||||
void VM_Version::setup_cpu_available_features() {
|
||||
|
||||
assert(ext_I.feature_bit() == HWCAP_ISA_I, "Bit for I must follow Linux HWCAP");
|
||||
assert(ext_M.feature_bit() == HWCAP_ISA_M, "Bit for M must follow Linux HWCAP");
|
||||
assert(ext_A.feature_bit() == HWCAP_ISA_A, "Bit for A must follow Linux HWCAP");
|
||||
assert(ext_F.feature_bit() == HWCAP_ISA_F, "Bit for F must follow Linux HWCAP");
|
||||
assert(ext_D.feature_bit() == HWCAP_ISA_D, "Bit for D must follow Linux HWCAP");
|
||||
assert(ext_C.feature_bit() == HWCAP_ISA_C, "Bit for C must follow Linux HWCAP");
|
||||
assert(ext_Q.feature_bit() == HWCAP_ISA_Q, "Bit for Q must follow Linux HWCAP");
|
||||
assert(ext_H.feature_bit() == HWCAP_ISA_H, "Bit for H must follow Linux HWCAP");
|
||||
assert(ext_V.feature_bit() == HWCAP_ISA_V, "Bit for V must follow Linux HWCAP");
|
||||
|
||||
if (!RiscvHwprobe::probe_features()) {
|
||||
os_aux_features();
|
||||
}
|
||||
char* uarch = os_uarch_additional_features();
|
||||
vendor_features();
|
||||
|
||||
char buf[1024] = {};
|
||||
if (uarch != nullptr && strcmp(uarch, "") != 0) {
|
||||
// Use at max half the buffer.
|
||||
snprintf(buf, sizeof(buf)/2, "%s,", uarch);
|
||||
}
|
||||
os::free((void*) uarch);
|
||||
strcat(buf, "rv64");
|
||||
int i = 0;
|
||||
while (_feature_list[i] != nullptr) {
|
||||
if (_feature_list[i]->enabled()) {
|
||||
log_debug(os, cpu)("Enabled RV64 feature \"%s\" (%ld)",
|
||||
_feature_list[i]->pretty(),
|
||||
_feature_list[i]->value());
|
||||
// The feature string
|
||||
if (_feature_list[i]->feature_string()) {
|
||||
const char* tmp = _feature_list[i]->pretty();
|
||||
if (strlen(tmp) == 1) {
|
||||
strcat(buf, tmp);
|
||||
} else {
|
||||
// Feature string is expected to be lower case.
|
||||
// Turn Zxxx into zxxx
|
||||
char prebuf[3] = {};
|
||||
assert(strlen(tmp) > 1, "Must be");
|
||||
prebuf[0] = '_';
|
||||
prebuf[1] = (char)tolower(tmp[0]);
|
||||
strcat(buf, prebuf);
|
||||
strcat(buf, &tmp[1]);
|
||||
}
|
||||
}
|
||||
// Feature bit
|
||||
if (_feature_list[i]->feature_bit() != 0) {
|
||||
_features |= _feature_list[i]->feature_bit();
|
||||
}
|
||||
// Change flag default
|
||||
_feature_list[i]->update_flag();
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
_features_string = os::strdup(buf);
|
||||
}
|
||||
|
||||
void VM_Version::os_aux_features() {
|
||||
uint64_t auxv = getauxval(AT_HWCAP);
|
||||
int i = 0;
|
||||
while (_feature_list[i] != nullptr) {
|
||||
if ((_feature_list[i]->feature_bit() & auxv) != 0) {
|
||||
_feature_list[i]->enable_feature();
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
VM_Version::VM_MODE VM_Version::parse_satp_mode(const char* vm_mode) {
|
||||
if (!strcmp(vm_mode, "sv39")) {
|
||||
return VM_SV39;
|
||||
} else if (!strcmp(_vm_mode, "sv48")) {
|
||||
} else if (!strcmp(vm_mode, "sv48")) {
|
||||
return VM_SV48;
|
||||
} else if (!strcmp(_vm_mode, "sv57")) {
|
||||
} else if (!strcmp(vm_mode, "sv57")) {
|
||||
return VM_SV57;
|
||||
} else if (!strcmp(_vm_mode, "sv64")) {
|
||||
} else if (!strcmp(vm_mode, "sv64")) {
|
||||
return VM_SV64;
|
||||
} else {
|
||||
return VM_MBARE;
|
||||
}
|
||||
}
|
||||
|
||||
void VM_Version::get_os_cpu_info() {
|
||||
char* VM_Version::os_uarch_additional_features() {
|
||||
char* ret = nullptr;
|
||||
VM_MODE mode = VM_NOTSET;
|
||||
|
||||
uint64_t auxv = getauxval(AT_HWCAP);
|
||||
FILE *f = fopen("/proc/cpuinfo", "r");
|
||||
if (f == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static_assert(CPU_I == HWCAP_ISA_I, "Flag CPU_I must follow Linux HWCAP");
|
||||
static_assert(CPU_M == HWCAP_ISA_M, "Flag CPU_M must follow Linux HWCAP");
|
||||
static_assert(CPU_A == HWCAP_ISA_A, "Flag CPU_A must follow Linux HWCAP");
|
||||
static_assert(CPU_F == HWCAP_ISA_F, "Flag CPU_F must follow Linux HWCAP");
|
||||
static_assert(CPU_D == HWCAP_ISA_D, "Flag CPU_D must follow Linux HWCAP");
|
||||
static_assert(CPU_C == HWCAP_ISA_C, "Flag CPU_C must follow Linux HWCAP");
|
||||
static_assert(CPU_V == HWCAP_ISA_V, "Flag CPU_V must follow Linux HWCAP");
|
||||
|
||||
// RISC-V has four bit-manipulation ISA-extensions: Zba/Zbb/Zbc/Zbs.
|
||||
// Availability for those extensions could not be queried from HWCAP.
|
||||
// TODO: Add proper detection for those extensions.
|
||||
_features = auxv & (
|
||||
HWCAP_ISA_I |
|
||||
HWCAP_ISA_M |
|
||||
HWCAP_ISA_A |
|
||||
HWCAP_ISA_F |
|
||||
HWCAP_ISA_D |
|
||||
HWCAP_ISA_C |
|
||||
HWCAP_ISA_V);
|
||||
|
||||
if (FILE *f = fopen("/proc/cpuinfo", "r")) {
|
||||
char buf[512], *p;
|
||||
while (fgets(buf, sizeof (buf), f) != nullptr) {
|
||||
if ((p = strchr(buf, ':')) != nullptr) {
|
||||
char buf[512], *p;
|
||||
while (fgets(buf, sizeof (buf), f) != nullptr &&
|
||||
(mode == VM_NOTSET || ret == nullptr)) {
|
||||
if ((p = strchr(buf, ':')) != nullptr) {
|
||||
if (mode == VM_NOTSET) {
|
||||
if (strncmp(buf, "mmu", sizeof "mmu" - 1) == 0) {
|
||||
if (_vm_mode[0] != '\0') {
|
||||
continue;
|
||||
}
|
||||
char* vm_mode = os::strdup(p + 2);
|
||||
vm_mode[strcspn(vm_mode, "\n")] = '\0';
|
||||
_vm_mode = vm_mode;
|
||||
} else if (strncmp(buf, "uarch", sizeof "uarch" - 1) == 0) {
|
||||
char* uarch = os::strdup(p + 2);
|
||||
uarch[strcspn(uarch, "\n")] = '\0';
|
||||
_uarch = uarch;
|
||||
break;
|
||||
mode = VM_Version::parse_satp_mode(p);
|
||||
}
|
||||
}
|
||||
if (ret == nullptr) {
|
||||
if (strncmp(buf, "uarch", sizeof "uarch" - 1) == 0) {
|
||||
ret = os::strdup(p + 2);
|
||||
ret[strcspn(ret, "\n")] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
if (mode == VM_NOTSET) {
|
||||
mode = VM_MBARE;
|
||||
}
|
||||
fclose(f);
|
||||
satp_mode.enable_feature(mode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void VM_Version::vendor_features() {
|
||||
// JEDEC encoded as ((bank - 1) << 7) | (0x7f & JEDEC)
|
||||
static constexpr int RIVOS_MVENDORID = 0x6cf; // JEDEC: 0x4f, Bank: 14
|
||||
|
||||
if (!mvendorid.enabled()) {
|
||||
return;
|
||||
}
|
||||
switch (mvendorid.value()) {
|
||||
case RIVOS_MVENDORID:
|
||||
rivos_features();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VM_Version::rivos_features() {
|
||||
// Enable common features not dependent on marchid/mimpid.
|
||||
ext_I.enable_feature();
|
||||
ext_M.enable_feature();
|
||||
ext_A.enable_feature();
|
||||
ext_F.enable_feature();
|
||||
ext_D.enable_feature();
|
||||
ext_C.enable_feature();
|
||||
ext_H.enable_feature();
|
||||
ext_V.enable_feature();
|
||||
|
||||
ext_Zicbom.enable_feature();
|
||||
ext_Zicboz.enable_feature();
|
||||
ext_Zicbop.enable_feature();
|
||||
|
||||
ext_Zba.enable_feature();
|
||||
ext_Zbb.enable_feature();
|
||||
ext_Zbs.enable_feature();
|
||||
|
||||
ext_Zicsr.enable_feature();
|
||||
ext_Zifencei.enable_feature();
|
||||
ext_Zic64b.enable_feature();
|
||||
ext_Zihintpause.enable_feature();
|
||||
|
||||
unaligned_access.enable_feature(MISALIGNED_FAST);
|
||||
satp_mode.enable_feature(VM_SV48);
|
||||
|
||||
// Features dependent on march/mimpid.
|
||||
// I.e. march.value() and mimplid.value()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user