8317697: refactor-encapsulate x86 VM_Version::CpuidInfo

Reviewed-by: dholmes, kvn
This commit is contained in:
Jan Kratochvil 2024-02-17 16:37:56 +00:00 committed by Vladimir Kozlov
parent 3b76372254
commit cf13086efe
2 changed files with 102 additions and 95 deletions

View File

@ -809,7 +809,7 @@ void VM_Version::get_processor_features() {
_stepping = cpu_stepping();
if (cpu_family() > 4) { // it supports CPUID
_features = feature_flags(); // These can be changed by VM settings
_features = _cpuid_info.feature_flags(); // These can be changed by VM settings
_cpu_features = _features; // Preserve features
// Logical processors are only available on P4s and above,
// and only if hyperthreading is available.
@ -2891,13 +2891,13 @@ int64_t VM_Version::maximum_qualified_cpu_frequency(void) {
return _max_qualified_cpu_frequency;
}
uint64_t VM_Version::feature_flags() {
uint64_t VM_Version::CpuidInfo::feature_flags() const {
uint64_t result = 0;
if (_cpuid_info.std_cpuid1_edx.bits.cmpxchg8 != 0)
if (std_cpuid1_edx.bits.cmpxchg8 != 0)
result |= CPU_CX8;
if (_cpuid_info.std_cpuid1_edx.bits.cmov != 0)
if (std_cpuid1_edx.bits.cmov != 0)
result |= CPU_CMOV;
if (_cpuid_info.std_cpuid1_edx.bits.clflush != 0)
if (std_cpuid1_edx.bits.clflush != 0)
result |= CPU_FLUSH;
#ifdef _LP64
// clflush should always be available on x86_64
@ -2905,158 +2905,158 @@ uint64_t VM_Version::feature_flags() {
// to flush the code cache.
assert ((result & CPU_FLUSH) != 0, "clflush should be available");
#endif
if (_cpuid_info.std_cpuid1_edx.bits.fxsr != 0 || (is_amd_family() &&
_cpuid_info.ext_cpuid1_edx.bits.fxsr != 0))
if (std_cpuid1_edx.bits.fxsr != 0 || (is_amd_family() &&
ext_cpuid1_edx.bits.fxsr != 0))
result |= CPU_FXSR;
// HT flag is set for multi-core processors also.
if (threads_per_core() > 1)
result |= CPU_HT;
if (_cpuid_info.std_cpuid1_edx.bits.mmx != 0 || (is_amd_family() &&
_cpuid_info.ext_cpuid1_edx.bits.mmx != 0))
if (std_cpuid1_edx.bits.mmx != 0 || (is_amd_family() &&
ext_cpuid1_edx.bits.mmx != 0))
result |= CPU_MMX;
if (_cpuid_info.std_cpuid1_edx.bits.sse != 0)
if (std_cpuid1_edx.bits.sse != 0)
result |= CPU_SSE;
if (_cpuid_info.std_cpuid1_edx.bits.sse2 != 0)
if (std_cpuid1_edx.bits.sse2 != 0)
result |= CPU_SSE2;
if (_cpuid_info.std_cpuid1_ecx.bits.sse3 != 0)
if (std_cpuid1_ecx.bits.sse3 != 0)
result |= CPU_SSE3;
if (_cpuid_info.std_cpuid1_ecx.bits.ssse3 != 0)
if (std_cpuid1_ecx.bits.ssse3 != 0)
result |= CPU_SSSE3;
if (_cpuid_info.std_cpuid1_ecx.bits.sse4_1 != 0)
if (std_cpuid1_ecx.bits.sse4_1 != 0)
result |= CPU_SSE4_1;
if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0)
if (std_cpuid1_ecx.bits.sse4_2 != 0)
result |= CPU_SSE4_2;
if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0)
if (std_cpuid1_ecx.bits.popcnt != 0)
result |= CPU_POPCNT;
if (_cpuid_info.std_cpuid1_ecx.bits.avx != 0 &&
_cpuid_info.std_cpuid1_ecx.bits.osxsave != 0 &&
_cpuid_info.xem_xcr0_eax.bits.sse != 0 &&
_cpuid_info.xem_xcr0_eax.bits.ymm != 0) {
if (std_cpuid1_ecx.bits.avx != 0 &&
std_cpuid1_ecx.bits.osxsave != 0 &&
xem_xcr0_eax.bits.sse != 0 &&
xem_xcr0_eax.bits.ymm != 0) {
result |= CPU_AVX;
result |= CPU_VZEROUPPER;
if (_cpuid_info.std_cpuid1_ecx.bits.f16c != 0)
if (std_cpuid1_ecx.bits.f16c != 0)
result |= CPU_F16C;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx2 != 0)
if (sef_cpuid7_ebx.bits.avx2 != 0)
result |= CPU_AVX2;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx512f != 0 &&
_cpuid_info.xem_xcr0_eax.bits.opmask != 0 &&
_cpuid_info.xem_xcr0_eax.bits.zmm512 != 0 &&
_cpuid_info.xem_xcr0_eax.bits.zmm32 != 0) {
if (sef_cpuid7_ebx.bits.avx512f != 0 &&
xem_xcr0_eax.bits.opmask != 0 &&
xem_xcr0_eax.bits.zmm512 != 0 &&
xem_xcr0_eax.bits.zmm32 != 0) {
result |= CPU_AVX512F;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx512cd != 0)
if (sef_cpuid7_ebx.bits.avx512cd != 0)
result |= CPU_AVX512CD;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx512dq != 0)
if (sef_cpuid7_ebx.bits.avx512dq != 0)
result |= CPU_AVX512DQ;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx512ifma != 0)
if (sef_cpuid7_ebx.bits.avx512ifma != 0)
result |= CPU_AVX512_IFMA;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx512pf != 0)
if (sef_cpuid7_ebx.bits.avx512pf != 0)
result |= CPU_AVX512PF;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx512er != 0)
if (sef_cpuid7_ebx.bits.avx512er != 0)
result |= CPU_AVX512ER;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx512bw != 0)
if (sef_cpuid7_ebx.bits.avx512bw != 0)
result |= CPU_AVX512BW;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx512vl != 0)
if (sef_cpuid7_ebx.bits.avx512vl != 0)
result |= CPU_AVX512VL;
if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vpopcntdq != 0)
if (sef_cpuid7_ecx.bits.avx512_vpopcntdq != 0)
result |= CPU_AVX512_VPOPCNTDQ;
if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vpclmulqdq != 0)
if (sef_cpuid7_ecx.bits.avx512_vpclmulqdq != 0)
result |= CPU_AVX512_VPCLMULQDQ;
if (_cpuid_info.sef_cpuid7_ecx.bits.vaes != 0)
if (sef_cpuid7_ecx.bits.vaes != 0)
result |= CPU_AVX512_VAES;
if (_cpuid_info.sef_cpuid7_ecx.bits.gfni != 0)
if (sef_cpuid7_ecx.bits.gfni != 0)
result |= CPU_GFNI;
if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vnni != 0)
if (sef_cpuid7_ecx.bits.avx512_vnni != 0)
result |= CPU_AVX512_VNNI;
if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_bitalg != 0)
if (sef_cpuid7_ecx.bits.avx512_bitalg != 0)
result |= CPU_AVX512_BITALG;
if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vbmi != 0)
if (sef_cpuid7_ecx.bits.avx512_vbmi != 0)
result |= CPU_AVX512_VBMI;
if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vbmi2 != 0)
if (sef_cpuid7_ecx.bits.avx512_vbmi2 != 0)
result |= CPU_AVX512_VBMI2;
}
}
if (_cpuid_info.std_cpuid1_ecx.bits.hv != 0)
if (std_cpuid1_ecx.bits.hv != 0)
result |= CPU_HV;
if (_cpuid_info.sef_cpuid7_ebx.bits.bmi1 != 0)
if (sef_cpuid7_ebx.bits.bmi1 != 0)
result |= CPU_BMI1;
if (_cpuid_info.std_cpuid1_edx.bits.tsc != 0)
if (std_cpuid1_edx.bits.tsc != 0)
result |= CPU_TSC;
if (_cpuid_info.ext_cpuid7_edx.bits.tsc_invariance != 0)
if (ext_cpuid7_edx.bits.tsc_invariance != 0)
result |= CPU_TSCINV_BIT;
if (_cpuid_info.std_cpuid1_ecx.bits.aes != 0)
if (std_cpuid1_ecx.bits.aes != 0)
result |= CPU_AES;
if (_cpuid_info.sef_cpuid7_ebx.bits.erms != 0)
if (sef_cpuid7_ebx.bits.erms != 0)
result |= CPU_ERMS;
if (_cpuid_info.sef_cpuid7_edx.bits.fast_short_rep_mov != 0)
if (sef_cpuid7_edx.bits.fast_short_rep_mov != 0)
result |= CPU_FSRM;
if (_cpuid_info.std_cpuid1_ecx.bits.clmul != 0)
if (std_cpuid1_ecx.bits.clmul != 0)
result |= CPU_CLMUL;
if (_cpuid_info.sef_cpuid7_ebx.bits.rtm != 0)
if (sef_cpuid7_ebx.bits.rtm != 0)
result |= CPU_RTM;
if (_cpuid_info.sef_cpuid7_ebx.bits.adx != 0)
if (sef_cpuid7_ebx.bits.adx != 0)
result |= CPU_ADX;
if (_cpuid_info.sef_cpuid7_ebx.bits.bmi2 != 0)
if (sef_cpuid7_ebx.bits.bmi2 != 0)
result |= CPU_BMI2;
if (_cpuid_info.sef_cpuid7_ebx.bits.sha != 0)
if (sef_cpuid7_ebx.bits.sha != 0)
result |= CPU_SHA;
if (_cpuid_info.std_cpuid1_ecx.bits.fma != 0)
if (std_cpuid1_ecx.bits.fma != 0)
result |= CPU_FMA;
if (_cpuid_info.sef_cpuid7_ebx.bits.clflushopt != 0)
if (sef_cpuid7_ebx.bits.clflushopt != 0)
result |= CPU_FLUSHOPT;
if (_cpuid_info.ext_cpuid1_edx.bits.rdtscp != 0)
if (ext_cpuid1_edx.bits.rdtscp != 0)
result |= CPU_RDTSCP;
if (_cpuid_info.sef_cpuid7_ecx.bits.rdpid != 0)
if (sef_cpuid7_ecx.bits.rdpid != 0)
result |= CPU_RDPID;
// AMD|Hygon features.
if (is_amd_family()) {
if ((_cpuid_info.ext_cpuid1_edx.bits.tdnow != 0) ||
(_cpuid_info.ext_cpuid1_ecx.bits.prefetchw != 0))
if ((ext_cpuid1_edx.bits.tdnow != 0) ||
(ext_cpuid1_ecx.bits.prefetchw != 0))
result |= CPU_3DNOW_PREFETCH;
if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0)
if (ext_cpuid1_ecx.bits.lzcnt != 0)
result |= CPU_LZCNT;
if (_cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0)
if (ext_cpuid1_ecx.bits.sse4a != 0)
result |= CPU_SSE4A;
}
// Intel features.
if (is_intel()) {
if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0) {
if (ext_cpuid1_ecx.bits.lzcnt != 0) {
result |= CPU_LZCNT;
}
if (_cpuid_info.ext_cpuid1_ecx.bits.prefetchw != 0) {
if (ext_cpuid1_ecx.bits.prefetchw != 0) {
result |= CPU_3DNOW_PREFETCH;
}
if (_cpuid_info.sef_cpuid7_ebx.bits.clwb != 0) {
if (sef_cpuid7_ebx.bits.clwb != 0) {
result |= CPU_CLWB;
}
if (_cpuid_info.sef_cpuid7_edx.bits.serialize != 0)
if (sef_cpuid7_edx.bits.serialize != 0)
result |= CPU_SERIALIZE;
}
// ZX features.
if (is_zx()) {
if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0) {
if (ext_cpuid1_ecx.bits.lzcnt != 0) {
result |= CPU_LZCNT;
}
if (_cpuid_info.ext_cpuid1_ecx.bits.prefetchw != 0) {
if (ext_cpuid1_ecx.bits.prefetchw != 0) {
result |= CPU_3DNOW_PREFETCH;
}
}
// Protection key features.
if (_cpuid_info.sef_cpuid7_ecx.bits.pku != 0) {
if (sef_cpuid7_ecx.bits.pku != 0) {
result |= CPU_PKU;
}
if (_cpuid_info.sef_cpuid7_ecx.bits.ospke != 0) {
if (sef_cpuid7_ecx.bits.ospke != 0) {
result |= CPU_OSPKE;
}
// Control flow enforcement (CET) features.
if (_cpuid_info.sef_cpuid7_ecx.bits.cet_ss != 0) {
if (sef_cpuid7_ecx.bits.cet_ss != 0) {
result |= CPU_CET_SS;
}
if (_cpuid_info.sef_cpuid7_edx.bits.cet_ibt != 0) {
if (sef_cpuid7_edx.bits.cet_ibt != 0) {
result |= CPU_CET_IBT;
}

View File

@ -428,7 +428,8 @@ protected:
//
// The info block is laid out in subblocks of 4 dwords corresponding to
// eax, ebx, ecx and edx, whether or not they contain anything useful.
struct CpuidInfo {
class CpuidInfo {
public:
// cpuid function 0
uint32_t std_max_function;
uint32_t std_vendor_name_0;
@ -522,6 +523,31 @@ protected:
// Space to save zmm registers after signal handle
int zmm_save[16*4]; // Save zmm0, zmm7, zmm8, zmm31
uint64_t feature_flags() const;
// Asserts
void assert_is_initialized() const {
assert(std_cpuid1_eax.bits.family != 0, "VM_Version not initialized");
}
// Extractors
uint32_t extended_cpu_family() const {
uint32_t result = std_cpuid1_eax.bits.family;
result += std_cpuid1_eax.bits.ext_family;
return result;
}
uint32_t extended_cpu_model() const {
uint32_t result = std_cpuid1_eax.bits.model;
result |= std_cpuid1_eax.bits.ext_model << 4;
return result;
}
uint32_t cpu_stepping() const {
uint32_t result = std_cpuid1_eax.bits.stepping;
return result;
}
};
private:
@ -529,23 +555,6 @@ private:
static CpuidInfo _cpuid_info;
// Extractors and predicates
static uint32_t extended_cpu_family() {
uint32_t result = _cpuid_info.std_cpuid1_eax.bits.family;
result += _cpuid_info.std_cpuid1_eax.bits.ext_family;
return result;
}
static uint32_t extended_cpu_model() {
uint32_t result = _cpuid_info.std_cpuid1_eax.bits.model;
result |= _cpuid_info.std_cpuid1_eax.bits.ext_model << 4;
return result;
}
static uint32_t cpu_stepping() {
uint32_t result = _cpuid_info.std_cpuid1_eax.bits.stepping;
return result;
}
static uint logical_processor_count() {
uint result = threads_per_core();
return result;
@ -553,7 +562,6 @@ private:
static bool compute_has_intel_jcc_erratum();
static uint64_t feature_flags();
static bool os_supports_avx_vectors();
static void get_processor_features();
@ -594,11 +602,6 @@ public:
// Override Abstract_VM_Version implementation
static void print_platform_virtualization_info(outputStream*);
// Asserts
static void assert_is_initialized() {
assert(_cpuid_info.std_cpuid1_eax.bits.family != 0, "VM_Version not initialized");
}
//
// Processor family:
// 3 - 386
@ -614,6 +617,10 @@ public:
// processors. Use the feature test functions below to
// determine whether a particular instruction is supported.
//
static void assert_is_initialized() { _cpuid_info.assert_is_initialized(); }
static uint32_t extended_cpu_family() { return _cpuid_info.extended_cpu_family(); }
static uint32_t extended_cpu_model() { return _cpuid_info.extended_cpu_model(); }
static uint32_t cpu_stepping() { return _cpuid_info.cpu_stepping(); }
static int cpu_family() { return _cpu;}
static bool is_P6() { return cpu_family() >= 6; }
static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA'