8352675: Support Intel AVX10 converged vector ISA feature detection

Reviewed-by: sviswanathan, vlivanov, yzheng
This commit is contained in:
Jatin Bhateja 2025-05-09 23:33:32 +00:00
parent 0f2a6c266b
commit 3b336a9da0
15 changed files with 493 additions and 249 deletions

View File

@ -35,8 +35,7 @@
static_field(VM_Version, _rop_protection, bool) \ static_field(VM_Version, _rop_protection, bool) \
static_field(VM_Version, _pac_mask, uintptr_t) static_field(VM_Version, _pac_mask, uintptr_t)
#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) \ #define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type)
declare_toplevel_type(VM_Version)
#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) #define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant)

View File

@ -29,15 +29,20 @@
// constants required by the Serviceability Agent. This file is // constants required by the Serviceability Agent. This file is
// referenced by vmStructs.cpp. // referenced by vmStructs.cpp.
#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ #define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \
volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \
static_field(VM_Version, _features, VM_Version::VM_Features) \
nonstatic_field(VM_Version::VM_Features, _features_bitmap[0], uint64_t) \
static_field(VM_Version::VM_Features, _features_bitmap_size, int)
#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) \ #define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) \
declare_toplevel_type(VM_Version::VM_Features)
#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) \ #define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) \
LP64_ONLY(declare_constant(frame::arg_reg_save_area_bytes)) \ declare_constant(frame::arg_reg_save_area_bytes) \
declare_constant(frame::interpreter_frame_sender_sp_offset) \ declare_constant(frame::interpreter_frame_sender_sp_offset) \
declare_constant(frame::interpreter_frame_last_sp_offset) declare_constant(frame::interpreter_frame_last_sp_offset) \
declare_constant(frame::entry_frame_call_wrapper_offset)
#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant)

View File

@ -63,6 +63,11 @@ address VM_Version::_cpuinfo_cont_addr_apx = nullptr;
static BufferBlob* stub_blob; static BufferBlob* stub_blob;
static const int stub_size = 2000; static const int stub_size = 2000;
int VM_Version::VM_Features::_features_bitmap_size = sizeof(VM_Version::VM_Features::_features_bitmap) / BytesPerLong;
VM_Version::VM_Features VM_Version::_features;
VM_Version::VM_Features VM_Version::_cpu_features;
extern "C" { extern "C" {
typedef void (*get_cpu_info_stub_t)(void*); typedef void (*get_cpu_info_stub_t)(void*);
typedef void (*detect_virt_stub_t)(uint32_t, uint32_t*); typedef void (*detect_virt_stub_t)(uint32_t, uint32_t*);
@ -82,7 +87,7 @@ bool VM_Version::supports_clflush() {
// up. Assembler::flush calls this routine to check that clflush // up. Assembler::flush calls this routine to check that clflush
// is allowed. So, we give the caller a free pass if Universe init // is allowed. So, we give the caller a free pass if Universe init
// is still in progress. // is still in progress.
assert ((!Universe::is_fully_initialized() || (_features & CPU_FLUSH) != 0), "clflush should be available"); assert ((!Universe::is_fully_initialized() || _features.supports_feature(CPU_FLUSH)), "clflush should be available");
return true; return true;
} }
@ -133,7 +138,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT); const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT);
bool use_evex = FLAG_IS_DEFAULT(UseAVX) || (UseAVX > 2); bool use_evex = FLAG_IS_DEFAULT(UseAVX) || (UseAVX > 2);
Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4; Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4, std_cpuid24;
Label sef_cpuid, sefsl1_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7; Label sef_cpuid, sefsl1_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7;
Label ext_cpuid8, done, wrapup, vector_save_restore, apx_save_restore_warning; Label ext_cpuid8, done, wrapup, vector_save_restore, apx_save_restore_warning;
Label legacy_setup, save_restore_except, legacy_save_restore, start_simd_check; Label legacy_setup, save_restore_except, legacy_save_restore, start_simd_check;
@ -332,6 +337,17 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 0), rax);
__ movl(Address(rsi, 4), rdx); __ movl(Address(rsi, 4), rdx);
//
// cpuid(0x24) Converged Vector ISA Main Leaf (EAX = 24H, ECX = 0).
//
__ bind(std_cpuid24);
__ movl(rax, 0x24);
__ movl(rcx, 0);
__ cpuid();
__ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid24_offset())));
__ movl(Address(rsi, 0), rax);
__ movl(Address(rsi, 4), rbx);
// //
// Extended cpuid(0x80000000) // Extended cpuid(0x80000000)
// //
@ -418,13 +434,11 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ lea(rsi, Address(rbp, in_bytes(VM_Version::sefsl1_cpuid7_offset()))); __ lea(rsi, Address(rbp, in_bytes(VM_Version::sefsl1_cpuid7_offset())));
__ movl(rax, 0x200000); __ movl(rax, 0x200000);
__ andl(rax, Address(rsi, 4)); __ andl(rax, Address(rsi, 4));
__ cmpl(rax, 0x200000); __ jcc(Assembler::equal, vector_save_restore);
__ jcc(Assembler::notEqual, vector_save_restore);
// check _cpuid_info.xem_xcr0_eax.bits.apx_f // check _cpuid_info.xem_xcr0_eax.bits.apx_f
__ movl(rax, 0x80000); __ movl(rax, 0x80000);
__ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits apx_f __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits apx_f
__ cmpl(rax, 0x80000); __ jcc(Assembler::equal, vector_save_restore);
__ jcc(Assembler::notEqual, vector_save_restore);
#ifndef PRODUCT #ifndef PRODUCT
bool save_apx = UseAPX; bool save_apx = UseAPX;
@ -477,11 +491,15 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
// If UseAVX is uninitialized or is set by the user to include EVEX // If UseAVX is uninitialized or is set by the user to include EVEX
if (use_evex) { if (use_evex) {
// check _cpuid_info.sef_cpuid7_ebx.bits.avx512f // check _cpuid_info.sef_cpuid7_ebx.bits.avx512f
// OR check _cpuid_info.sefsl1_cpuid7_edx.bits.avx10
__ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset()))); __ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset())));
__ movl(rax, 0x10000); __ movl(rax, 0x10000);
__ andl(rax, Address(rsi, 4)); // xcr0 bits sse | ymm __ andl(rax, Address(rsi, 4));
__ cmpl(rax, 0x10000); __ lea(rsi, Address(rbp, in_bytes(VM_Version::sefsl1_cpuid7_offset())));
__ jccb(Assembler::notEqual, legacy_setup); // jump if EVEX is not supported __ movl(rbx, 0x80000);
__ andl(rbx, Address(rsi, 4));
__ orl(rax, rbx);
__ jccb(Assembler::equal, legacy_setup); // jump if EVEX is not supported
// check _cpuid_info.xem_xcr0_eax.bits.opmask // check _cpuid_info.xem_xcr0_eax.bits.opmask
// check _cpuid_info.xem_xcr0_eax.bits.zmm512 // check _cpuid_info.xem_xcr0_eax.bits.zmm512
// check _cpuid_info.xem_xcr0_eax.bits.zmm32 // check _cpuid_info.xem_xcr0_eax.bits.zmm32
@ -562,8 +580,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset()))); __ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset())));
__ movl(rax, 0x10000); __ movl(rax, 0x10000);
__ andl(rax, Address(rsi, 4)); __ andl(rax, Address(rsi, 4));
__ cmpl(rax, 0x10000); __ jcc(Assembler::equal, legacy_save_restore);
__ jcc(Assembler::notEqual, legacy_save_restore);
// check _cpuid_info.xem_xcr0_eax.bits.opmask // check _cpuid_info.xem_xcr0_eax.bits.opmask
// check _cpuid_info.xem_xcr0_eax.bits.zmm512 // check _cpuid_info.xem_xcr0_eax.bits.zmm512
// check _cpuid_info.xem_xcr0_eax.bits.zmm32 // check _cpuid_info.xem_xcr0_eax.bits.zmm32
@ -835,7 +852,6 @@ void VM_Version::get_processor_features() {
_cpu = 4; // 486 by default _cpu = 4; // 486 by default
_model = 0; _model = 0;
_stepping = 0; _stepping = 0;
_features = 0;
_logical_processors_per_package = 1; _logical_processors_per_package = 1;
// i486 internal cache is both I&D and has a 16-byte line size // i486 internal cache is both I&D and has a 16-byte line size
_L1_data_cache_line_size = 16; _L1_data_cache_line_size = 16;
@ -851,7 +867,7 @@ void VM_Version::get_processor_features() {
if (cpu_family() > 4) { // it supports CPUID if (cpu_family() > 4) { // it supports CPUID
_features = _cpuid_info.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 _cpu_features = _features; // Preserve features
// Logical processors are only available on P4s and above, // Logical processors are only available on P4s and above,
// and only if hyperthreading is available. // and only if hyperthreading is available.
_logical_processors_per_package = logical_processor_count(); _logical_processors_per_package = logical_processor_count();
@ -900,21 +916,21 @@ void VM_Version::get_processor_features() {
} }
if (UseSSE < 4) { if (UseSSE < 4) {
_features &= ~CPU_SSE4_1; _features.clear_feature(CPU_SSE4_1);
_features &= ~CPU_SSE4_2; _features.clear_feature(CPU_SSE4_2);
} }
if (UseSSE < 3) { if (UseSSE < 3) {
_features &= ~CPU_SSE3; _features.clear_feature(CPU_SSE3);
_features &= ~CPU_SSSE3; _features.clear_feature(CPU_SSSE3);
_features &= ~CPU_SSE4A; _features.clear_feature(CPU_SSE4A);
} }
if (UseSSE < 2) if (UseSSE < 2)
_features &= ~CPU_SSE2; _features.clear_feature(CPU_SSE2);
if (UseSSE < 1) if (UseSSE < 1)
_features &= ~CPU_SSE; _features.clear_feature(CPU_SSE);
//since AVX instructions is slower than SSE in some ZX cpus, force USEAVX=0. //since AVX instructions is slower than SSE in some ZX cpus, force USEAVX=0.
if (is_zx() && ((cpu_family() == 6) || (cpu_family() == 7))) { if (is_zx() && ((cpu_family() == 6) || (cpu_family() == 7))) {
@ -980,21 +996,25 @@ void VM_Version::get_processor_features() {
} }
if (UseAVX < 3) { if (UseAVX < 3) {
_features &= ~CPU_AVX512F; _features.clear_feature(CPU_AVX512F);
_features &= ~CPU_AVX512DQ; _features.clear_feature(CPU_AVX512DQ);
_features &= ~CPU_AVX512CD; _features.clear_feature(CPU_AVX512CD);
_features &= ~CPU_AVX512BW; _features.clear_feature(CPU_AVX512BW);
_features &= ~CPU_AVX512VL; _features.clear_feature(CPU_AVX512ER);
_features &= ~CPU_AVX512_VPOPCNTDQ; _features.clear_feature(CPU_AVX512PF);
_features &= ~CPU_AVX512_VPCLMULQDQ; _features.clear_feature(CPU_AVX512VL);
_features &= ~CPU_AVX512_VAES; _features.clear_feature(CPU_AVX512_VPOPCNTDQ);
_features &= ~CPU_AVX512_VNNI; _features.clear_feature(CPU_AVX512_VPCLMULQDQ);
_features &= ~CPU_AVX512_VBMI; _features.clear_feature(CPU_AVX512_VAES);
_features &= ~CPU_AVX512_VBMI2; _features.clear_feature(CPU_AVX512_VNNI);
_features &= ~CPU_AVX512_BITALG; _features.clear_feature(CPU_AVX512_VBMI);
_features &= ~CPU_AVX512_IFMA; _features.clear_feature(CPU_AVX512_VBMI2);
_features &= ~CPU_APX_F; _features.clear_feature(CPU_AVX512_BITALG);
_features &= ~CPU_AVX512_FP16; _features.clear_feature(CPU_AVX512_IFMA);
_features.clear_feature(CPU_APX_F);
_features.clear_feature(CPU_AVX512_FP16);
_features.clear_feature(CPU_AVX10_1);
_features.clear_feature(CPU_AVX10_2);
} }
// Currently APX support is only enabled for targets supporting AVX512VL feature. // Currently APX support is only enabled for targets supporting AVX512VL feature.
@ -1007,45 +1027,47 @@ void VM_Version::get_processor_features() {
} }
if (!UseAPX) { if (!UseAPX) {
_features &= ~CPU_APX_F; _features.clear_feature(CPU_APX_F);
} }
if (UseAVX < 2) { if (UseAVX < 2) {
_features &= ~CPU_AVX2; _features.clear_feature(CPU_AVX2);
_features &= ~CPU_AVX_IFMA; _features.clear_feature(CPU_AVX_IFMA);
} }
if (UseAVX < 1) { if (UseAVX < 1) {
_features &= ~CPU_AVX; _features.clear_feature(CPU_AVX);
_features &= ~CPU_VZEROUPPER; _features.clear_feature(CPU_VZEROUPPER);
_features &= ~CPU_F16C; _features.clear_feature(CPU_F16C);
_features &= ~CPU_SHA512; _features.clear_feature(CPU_SHA512);
} }
if (logical_processors_per_package() == 1) { if (logical_processors_per_package() == 1) {
// HT processor could be installed on a system which doesn't support HT. // HT processor could be installed on a system which doesn't support HT.
_features &= ~CPU_HT; _features.clear_feature(CPU_HT);
} }
if (is_intel()) { // Intel cpus specific settings if (is_intel()) { // Intel cpus specific settings
if (is_knights_family()) { if (is_knights_family()) {
_features &= ~CPU_VZEROUPPER; _features.clear_feature(CPU_VZEROUPPER);
_features &= ~CPU_AVX512BW; _features.clear_feature(CPU_AVX512BW);
_features &= ~CPU_AVX512VL; _features.clear_feature(CPU_AVX512VL);
_features &= ~CPU_AVX512DQ; _features.clear_feature(CPU_AVX512DQ);
_features &= ~CPU_AVX512_VNNI; _features.clear_feature(CPU_AVX512_VNNI);
_features &= ~CPU_AVX512_VAES; _features.clear_feature(CPU_AVX512_VAES);
_features &= ~CPU_AVX512_VPOPCNTDQ; _features.clear_feature(CPU_AVX512_VPOPCNTDQ);
_features &= ~CPU_AVX512_VPCLMULQDQ; _features.clear_feature(CPU_AVX512_VPCLMULQDQ);
_features &= ~CPU_AVX512_VBMI; _features.clear_feature(CPU_AVX512_VBMI);
_features &= ~CPU_AVX512_VBMI2; _features.clear_feature(CPU_AVX512_VBMI2);
_features &= ~CPU_CLWB; _features.clear_feature(CPU_CLWB);
_features &= ~CPU_FLUSHOPT; _features.clear_feature(CPU_FLUSHOPT);
_features &= ~CPU_GFNI; _features.clear_feature(CPU_GFNI);
_features &= ~CPU_AVX512_BITALG; _features.clear_feature(CPU_AVX512_BITALG);
_features &= ~CPU_AVX512_IFMA; _features.clear_feature(CPU_AVX512_IFMA);
_features &= ~CPU_AVX_IFMA; _features.clear_feature(CPU_AVX_IFMA);
_features &= ~CPU_AVX512_FP16; _features.clear_feature(CPU_AVX512_FP16);
_features.clear_feature(CPU_AVX10_1);
_features.clear_feature(CPU_AVX10_2);
} }
} }
@ -1055,7 +1077,6 @@ void VM_Version::get_processor_features() {
_has_intel_jcc_erratum = IntelJccErratumMitigation; _has_intel_jcc_erratum = IntelJccErratumMitigation;
} }
assert(supports_cpuid(), "Always present");
assert(supports_clflush(), "Always present"); assert(supports_clflush(), "Always present");
if (X86ICacheSync == -1) { if (X86ICacheSync == -1) {
// Auto-detect, choosing the best performant one that still flushes // Auto-detect, choosing the best performant one that still flushes
@ -1079,14 +1100,15 @@ void VM_Version::get_processor_features() {
} }
} }
char buf[1024]; char buf[2048];
int cpu_info_size = jio_snprintf( size_t cpu_info_size = jio_snprintf(
buf, sizeof(buf), buf, sizeof(buf),
"(%u cores per cpu, %u threads per core) family %d model %d stepping %d microcode 0x%x", "(%u cores per cpu, %u threads per core) family %d model %d stepping %d microcode 0x%x",
cores_per_cpu(), threads_per_core(), cores_per_cpu(), threads_per_core(),
cpu_family(), _model, _stepping, os::cpu_microcode_revision()); cpu_family(), _model, _stepping, os::cpu_microcode_revision());
assert(cpu_info_size > 0, "not enough temporary space allocated"); assert(cpu_info_size > 0, "not enough temporary space allocated");
insert_features_names(buf + cpu_info_size, sizeof(buf) - cpu_info_size, _features_names);
insert_features_names(_features, buf + cpu_info_size, sizeof(buf) - cpu_info_size);
_cpu_info_string = os::strdup(buf); _cpu_info_string = os::strdup(buf);
@ -2088,6 +2110,7 @@ static bool _vm_version_initialized = false;
void VM_Version::initialize() { void VM_Version::initialize() {
ResourceMark rm; ResourceMark rm;
// Making this stub must be FIRST use of assembler // Making this stub must be FIRST use of assembler
stub_blob = BufferBlob::create("VM_Version stub", stub_size); stub_blob = BufferBlob::create("VM_Version stub", stub_size);
if (stub_blob == nullptr) { if (stub_blob == nullptr) {
@ -2863,185 +2886,212 @@ int64_t VM_Version::maximum_qualified_cpu_frequency(void) {
return _max_qualified_cpu_frequency; return _max_qualified_cpu_frequency;
} }
uint64_t VM_Version::CpuidInfo::feature_flags() const { VM_Version::VM_Features VM_Version::CpuidInfo::feature_flags() const {
uint64_t result = 0; VM_Features vm_features;
if (std_cpuid1_edx.bits.cmpxchg8 != 0) if (std_cpuid1_edx.bits.cmpxchg8 != 0)
result |= CPU_CX8; vm_features.set_feature(CPU_CX8);
if (std_cpuid1_edx.bits.cmov != 0) if (std_cpuid1_edx.bits.cmov != 0)
result |= CPU_CMOV; vm_features.set_feature(CPU_CMOV);
if (std_cpuid1_edx.bits.clflush != 0) if (std_cpuid1_edx.bits.clflush != 0)
result |= CPU_FLUSH; vm_features.set_feature(CPU_FLUSH);
// clflush should always be available on x86_64 // clflush should always be available on x86_64
// if not we are in real trouble because we rely on it // if not we are in real trouble because we rely on it
// to flush the code cache. // to flush the code cache.
assert ((result & CPU_FLUSH) != 0, "clflush should be available"); assert (vm_features.supports_feature(CPU_FLUSH), "clflush should be available");
if (std_cpuid1_edx.bits.fxsr != 0 || (is_amd_family() && if (std_cpuid1_edx.bits.fxsr != 0 || (is_amd_family() &&
ext_cpuid1_edx.bits.fxsr != 0)) ext_cpuid1_edx.bits.fxsr != 0))
result |= CPU_FXSR; vm_features.set_feature(CPU_FXSR);
// HT flag is set for multi-core processors also. // HT flag is set for multi-core processors also.
if (threads_per_core() > 1) if (threads_per_core() > 1)
result |= CPU_HT; vm_features.set_feature(CPU_HT);
if (std_cpuid1_edx.bits.mmx != 0 || (is_amd_family() && if (std_cpuid1_edx.bits.mmx != 0 || (is_amd_family() &&
ext_cpuid1_edx.bits.mmx != 0)) ext_cpuid1_edx.bits.mmx != 0))
result |= CPU_MMX; vm_features.set_feature(CPU_MMX);
if (std_cpuid1_edx.bits.sse != 0) if (std_cpuid1_edx.bits.sse != 0)
result |= CPU_SSE; vm_features.set_feature(CPU_SSE);
if (std_cpuid1_edx.bits.sse2 != 0) if (std_cpuid1_edx.bits.sse2 != 0)
result |= CPU_SSE2; vm_features.set_feature(CPU_SSE2);
if (std_cpuid1_ecx.bits.sse3 != 0) if (std_cpuid1_ecx.bits.sse3 != 0)
result |= CPU_SSE3; vm_features.set_feature(CPU_SSE3);
if (std_cpuid1_ecx.bits.ssse3 != 0) if (std_cpuid1_ecx.bits.ssse3 != 0)
result |= CPU_SSSE3; vm_features.set_feature(CPU_SSSE3);
if (std_cpuid1_ecx.bits.sse4_1 != 0) if (std_cpuid1_ecx.bits.sse4_1 != 0)
result |= CPU_SSE4_1; vm_features.set_feature(CPU_SSE4_1);
if (std_cpuid1_ecx.bits.sse4_2 != 0) if (std_cpuid1_ecx.bits.sse4_2 != 0)
result |= CPU_SSE4_2; vm_features.set_feature(CPU_SSE4_2);
if (std_cpuid1_ecx.bits.popcnt != 0) if (std_cpuid1_ecx.bits.popcnt != 0)
result |= CPU_POPCNT; vm_features.set_feature(CPU_POPCNT);
if (sefsl1_cpuid7_edx.bits.apx_f != 0 && if (sefsl1_cpuid7_edx.bits.apx_f != 0 &&
xem_xcr0_eax.bits.apx_f != 0) { xem_xcr0_eax.bits.apx_f != 0) {
result |= CPU_APX_F; vm_features.set_feature(CPU_APX_F);
} }
if (std_cpuid1_ecx.bits.avx != 0 && if (std_cpuid1_ecx.bits.avx != 0 &&
std_cpuid1_ecx.bits.osxsave != 0 && std_cpuid1_ecx.bits.osxsave != 0 &&
xem_xcr0_eax.bits.sse != 0 && xem_xcr0_eax.bits.sse != 0 &&
xem_xcr0_eax.bits.ymm != 0) { xem_xcr0_eax.bits.ymm != 0) {
result |= CPU_AVX; vm_features.set_feature(CPU_AVX);
result |= CPU_VZEROUPPER; vm_features.set_feature(CPU_VZEROUPPER);
if (sefsl1_cpuid7_eax.bits.sha512 != 0) if (sefsl1_cpuid7_eax.bits.sha512 != 0)
result |= CPU_SHA512; vm_features.set_feature(CPU_SHA512);
if (std_cpuid1_ecx.bits.f16c != 0) if (std_cpuid1_ecx.bits.f16c != 0)
result |= CPU_F16C; vm_features.set_feature(CPU_F16C);
if (sef_cpuid7_ebx.bits.avx2 != 0) { if (sef_cpuid7_ebx.bits.avx2 != 0) {
result |= CPU_AVX2; vm_features.set_feature(CPU_AVX2);
if (sefsl1_cpuid7_eax.bits.avx_ifma != 0) if (sefsl1_cpuid7_eax.bits.avx_ifma != 0)
result |= CPU_AVX_IFMA; vm_features.set_feature(CPU_AVX_IFMA);
} }
if (sef_cpuid7_ecx.bits.gfni != 0) if (sef_cpuid7_ecx.bits.gfni != 0)
result |= CPU_GFNI; vm_features.set_feature(CPU_GFNI);
if (sef_cpuid7_ebx.bits.avx512f != 0 && if (sef_cpuid7_ebx.bits.avx512f != 0 &&
xem_xcr0_eax.bits.opmask != 0 && xem_xcr0_eax.bits.opmask != 0 &&
xem_xcr0_eax.bits.zmm512 != 0 && xem_xcr0_eax.bits.zmm512 != 0 &&
xem_xcr0_eax.bits.zmm32 != 0) { xem_xcr0_eax.bits.zmm32 != 0) {
result |= CPU_AVX512F; vm_features.set_feature(CPU_AVX512F);
if (sef_cpuid7_ebx.bits.avx512cd != 0) if (sef_cpuid7_ebx.bits.avx512cd != 0)
result |= CPU_AVX512CD; vm_features.set_feature(CPU_AVX512CD);
if (sef_cpuid7_ebx.bits.avx512dq != 0) if (sef_cpuid7_ebx.bits.avx512dq != 0)
result |= CPU_AVX512DQ; vm_features.set_feature(CPU_AVX512DQ);
if (sef_cpuid7_ebx.bits.avx512ifma != 0) if (sef_cpuid7_ebx.bits.avx512ifma != 0)
result |= CPU_AVX512_IFMA; vm_features.set_feature(CPU_AVX512_IFMA);
if (sef_cpuid7_ebx.bits.avx512pf != 0) if (sef_cpuid7_ebx.bits.avx512pf != 0)
result |= CPU_AVX512PF; vm_features.set_feature(CPU_AVX512PF);
if (sef_cpuid7_ebx.bits.avx512er != 0) if (sef_cpuid7_ebx.bits.avx512er != 0)
result |= CPU_AVX512ER; vm_features.set_feature(CPU_AVX512ER);
if (sef_cpuid7_ebx.bits.avx512bw != 0) if (sef_cpuid7_ebx.bits.avx512bw != 0)
result |= CPU_AVX512BW; vm_features.set_feature(CPU_AVX512BW);
if (sef_cpuid7_ebx.bits.avx512vl != 0) if (sef_cpuid7_ebx.bits.avx512vl != 0)
result |= CPU_AVX512VL; vm_features.set_feature(CPU_AVX512VL);
if (sef_cpuid7_ecx.bits.avx512_vpopcntdq != 0) if (sef_cpuid7_ecx.bits.avx512_vpopcntdq != 0)
result |= CPU_AVX512_VPOPCNTDQ; vm_features.set_feature(CPU_AVX512_VPOPCNTDQ);
if (sef_cpuid7_ecx.bits.avx512_vpclmulqdq != 0) if (sef_cpuid7_ecx.bits.avx512_vpclmulqdq != 0)
result |= CPU_AVX512_VPCLMULQDQ; vm_features.set_feature(CPU_AVX512_VPCLMULQDQ);
if (sef_cpuid7_ecx.bits.vaes != 0) if (sef_cpuid7_ecx.bits.vaes != 0)
result |= CPU_AVX512_VAES; vm_features.set_feature(CPU_AVX512_VAES);
if (sef_cpuid7_ecx.bits.avx512_vnni != 0) if (sef_cpuid7_ecx.bits.avx512_vnni != 0)
result |= CPU_AVX512_VNNI; vm_features.set_feature(CPU_AVX512_VNNI);
if (sef_cpuid7_ecx.bits.avx512_bitalg != 0) if (sef_cpuid7_ecx.bits.avx512_bitalg != 0)
result |= CPU_AVX512_BITALG; vm_features.set_feature(CPU_AVX512_BITALG);
if (sef_cpuid7_ecx.bits.avx512_vbmi != 0) if (sef_cpuid7_ecx.bits.avx512_vbmi != 0)
result |= CPU_AVX512_VBMI; vm_features.set_feature(CPU_AVX512_VBMI);
if (sef_cpuid7_ecx.bits.avx512_vbmi2 != 0) if (sef_cpuid7_ecx.bits.avx512_vbmi2 != 0)
result |= CPU_AVX512_VBMI2; vm_features.set_feature(CPU_AVX512_VBMI2);
}
if (is_intel()) {
if (sefsl1_cpuid7_edx.bits.avx10 != 0 &&
std_cpuid24_ebx.bits.avx10_vlen_512 !=0 &&
std_cpuid24_ebx.bits.avx10_converged_isa_version >= 1 &&
xem_xcr0_eax.bits.opmask != 0 &&
xem_xcr0_eax.bits.zmm512 != 0 &&
xem_xcr0_eax.bits.zmm32 != 0) {
vm_features.set_feature(CPU_AVX10_1);
vm_features.set_feature(CPU_AVX512F);
vm_features.set_feature(CPU_AVX512CD);
vm_features.set_feature(CPU_AVX512DQ);
vm_features.set_feature(CPU_AVX512PF);
vm_features.set_feature(CPU_AVX512ER);
vm_features.set_feature(CPU_AVX512BW);
vm_features.set_feature(CPU_AVX512VL);
vm_features.set_feature(CPU_AVX512_VPOPCNTDQ);
vm_features.set_feature(CPU_AVX512_VPCLMULQDQ);
vm_features.set_feature(CPU_AVX512_VAES);
vm_features.set_feature(CPU_AVX512_VNNI);
vm_features.set_feature(CPU_AVX512_BITALG);
vm_features.set_feature(CPU_AVX512_VBMI);
vm_features.set_feature(CPU_AVX512_VBMI2);
if (std_cpuid24_ebx.bits.avx10_converged_isa_version >= 2) {
vm_features.set_feature(CPU_AVX10_2);
}
}
} }
} }
if (std_cpuid1_ecx.bits.hv != 0) if (std_cpuid1_ecx.bits.hv != 0)
result |= CPU_HV; vm_features.set_feature(CPU_HV);
if (sef_cpuid7_ebx.bits.bmi1 != 0) if (sef_cpuid7_ebx.bits.bmi1 != 0)
result |= CPU_BMI1; vm_features.set_feature(CPU_BMI1);
if (std_cpuid1_edx.bits.tsc != 0) if (std_cpuid1_edx.bits.tsc != 0)
result |= CPU_TSC; vm_features.set_feature(CPU_TSC);
if (ext_cpuid7_edx.bits.tsc_invariance != 0) if (ext_cpuid7_edx.bits.tsc_invariance != 0)
result |= CPU_TSCINV_BIT; vm_features.set_feature(CPU_TSCINV_BIT);
if (std_cpuid1_ecx.bits.aes != 0) if (std_cpuid1_ecx.bits.aes != 0)
result |= CPU_AES; vm_features.set_feature(CPU_AES);
if (ext_cpuid1_ecx.bits.lzcnt != 0) if (ext_cpuid1_ecx.bits.lzcnt != 0)
result |= CPU_LZCNT; vm_features.set_feature(CPU_LZCNT);
if (ext_cpuid1_ecx.bits.prefetchw != 0) if (ext_cpuid1_ecx.bits.prefetchw != 0)
result |= CPU_3DNOW_PREFETCH; vm_features.set_feature(CPU_3DNOW_PREFETCH);
if (sef_cpuid7_ebx.bits.erms != 0) if (sef_cpuid7_ebx.bits.erms != 0)
result |= CPU_ERMS; vm_features.set_feature(CPU_ERMS);
if (sef_cpuid7_edx.bits.fast_short_rep_mov != 0) if (sef_cpuid7_edx.bits.fast_short_rep_mov != 0)
result |= CPU_FSRM; vm_features.set_feature(CPU_FSRM);
if (std_cpuid1_ecx.bits.clmul != 0) if (std_cpuid1_ecx.bits.clmul != 0)
result |= CPU_CLMUL; vm_features.set_feature(CPU_CLMUL);
if (sef_cpuid7_ebx.bits.rtm != 0) if (sef_cpuid7_ebx.bits.rtm != 0)
result |= CPU_RTM; vm_features.set_feature(CPU_RTM);
if (sef_cpuid7_ebx.bits.adx != 0) if (sef_cpuid7_ebx.bits.adx != 0)
result |= CPU_ADX; vm_features.set_feature(CPU_ADX);
if (sef_cpuid7_ebx.bits.bmi2 != 0) if (sef_cpuid7_ebx.bits.bmi2 != 0)
result |= CPU_BMI2; vm_features.set_feature(CPU_BMI2);
if (sef_cpuid7_ebx.bits.sha != 0) if (sef_cpuid7_ebx.bits.sha != 0)
result |= CPU_SHA; vm_features.set_feature(CPU_SHA);
if (std_cpuid1_ecx.bits.fma != 0) if (std_cpuid1_ecx.bits.fma != 0)
result |= CPU_FMA; vm_features.set_feature(CPU_FMA);
if (sef_cpuid7_ebx.bits.clflushopt != 0) if (sef_cpuid7_ebx.bits.clflushopt != 0)
result |= CPU_FLUSHOPT; vm_features.set_feature(CPU_FLUSHOPT);
if (sef_cpuid7_ebx.bits.clwb != 0) if (sef_cpuid7_ebx.bits.clwb != 0)
result |= CPU_CLWB; vm_features.set_feature(CPU_CLWB);
if (ext_cpuid1_edx.bits.rdtscp != 0) if (ext_cpuid1_edx.bits.rdtscp != 0)
result |= CPU_RDTSCP; vm_features.set_feature(CPU_RDTSCP);
if (sef_cpuid7_ecx.bits.rdpid != 0) if (sef_cpuid7_ecx.bits.rdpid != 0)
result |= CPU_RDPID; vm_features.set_feature(CPU_RDPID);
// AMD|Hygon additional features. // AMD|Hygon additional features.
if (is_amd_family()) { if (is_amd_family()) {
// PREFETCHW was checked above, check TDNOW here. // PREFETCHW was checked above, check TDNOW here.
if ((ext_cpuid1_edx.bits.tdnow != 0)) if ((ext_cpuid1_edx.bits.tdnow != 0))
result |= CPU_3DNOW_PREFETCH; vm_features.set_feature(CPU_3DNOW_PREFETCH);
if (ext_cpuid1_ecx.bits.sse4a != 0) if (ext_cpuid1_ecx.bits.sse4a != 0)
result |= CPU_SSE4A; vm_features.set_feature(CPU_SSE4A);
} }
// Intel additional features. // Intel additional features.
if (is_intel()) { if (is_intel()) {
if (sef_cpuid7_edx.bits.serialize != 0) if (sef_cpuid7_edx.bits.serialize != 0)
result |= CPU_SERIALIZE; vm_features.set_feature(CPU_SERIALIZE);
if (_cpuid_info.sef_cpuid7_edx.bits.avx512_fp16 != 0) if (_cpuid_info.sef_cpuid7_edx.bits.avx512_fp16 != 0)
result |= CPU_AVX512_FP16; vm_features.set_feature(CPU_AVX512_FP16);
} }
// ZX additional features. // ZX additional features.
if (is_zx()) { if (is_zx()) {
// We do not know if these are supported by ZX, so we cannot trust // We do not know if these are supported by ZX, so we cannot trust
// common CPUID bit for them. // common CPUID bit for them.
assert((result & CPU_CLWB) == 0, "Check if it is supported?"); assert(vm_features.supports_feature(CPU_CLWB), "Check if it is supported?");
result &= ~CPU_CLWB; vm_features.clear_feature(CPU_CLWB);
} }
// Protection key features. // Protection key features.
if (sef_cpuid7_ecx.bits.pku != 0) { if (sef_cpuid7_ecx.bits.pku != 0) {
result |= CPU_PKU; vm_features.set_feature(CPU_PKU);
} }
if (sef_cpuid7_ecx.bits.ospke != 0) { if (sef_cpuid7_ecx.bits.ospke != 0) {
result |= CPU_OSPKE; vm_features.set_feature(CPU_OSPKE);
} }
// Control flow enforcement (CET) features. // Control flow enforcement (CET) features.
if (sef_cpuid7_ecx.bits.cet_ss != 0) { if (sef_cpuid7_ecx.bits.cet_ss != 0) {
result |= CPU_CET_SS; vm_features.set_feature(CPU_CET_SS);
} }
if (sef_cpuid7_edx.bits.cet_ibt != 0) { if (sef_cpuid7_edx.bits.cet_ibt != 0) {
result |= CPU_CET_IBT; vm_features.set_feature(CPU_CET_IBT);
} }
// Composite features. // Composite features.
if (supports_tscinv_bit() && if (supports_tscinv_bit() &&
((is_amd_family() && !is_amd_Barcelona()) || ((is_amd_family() && !is_amd_Barcelona()) ||
is_intel_tsc_synched_at_init())) { is_intel_tsc_synched_at_init())) {
result |= CPU_TSCINV; vm_features.set_feature(CPU_TSCINV);
} }
return vm_features;
return result;
} }
bool VM_Version::os_supports_avx_vectors() { bool VM_Version::os_supports_avx_vectors() {
@ -3231,3 +3281,14 @@ bool VM_Version::is_intrinsic_supported(vmIntrinsicID id) {
} }
return true; return true;
} }
void VM_Version::insert_features_names(VM_Version::VM_Features features, char* buf, size_t buflen) {
for (int i = 0; i < MAX_CPU_FEATURES; i++) {
if (features.supports_feature((VM_Version::Feature_Flag)i)) {
int res = jio_snprintf(buf, buflen, ", %s", _features_names[i]);
assert(res > 0, "not enough temporary space allocated");
buf += res;
buflen -= res;
}
}
}

View File

@ -295,12 +295,32 @@ class VM_Version : public Abstract_VM_Version {
union SefCpuid7SubLeaf1Edx { union SefCpuid7SubLeaf1Edx {
uint32_t value; uint32_t value;
struct { struct {
uint32_t : 21, uint32_t : 19,
avx10 : 1,
: 1,
apx_f : 1, apx_f : 1,
: 10; : 10;
} bits; } bits;
}; };
union StdCpuid24MainLeafEax {
uint32_t value;
struct {
uint32_t sub_leaves_cnt : 31;
} bits;
};
union StdCpuid24MainLeafEbx {
uint32_t value;
struct {
uint32_t avx10_converged_isa_version : 8,
: 8,
: 2,
avx10_vlen_512 : 1,
: 13;
} bits;
};
union ExtCpuid1EEbx { union ExtCpuid1EEbx {
uint32_t value; uint32_t value;
struct { struct {
@ -342,9 +362,9 @@ protected:
/* /*
* Update following files when declaring new flags: * Update following files when declaring new flags:
* test/lib-test/jdk/test/whitebox/CPUInfoTest.java * test/lib-test/jdk/test/whitebox/CPUInfoTest.java
* src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java * src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java
*/ */
enum Feature_Flag : uint64_t { enum Feature_Flag {
#define CPU_FEATURE_FLAGS(decl) \ #define CPU_FEATURE_FLAGS(decl) \
decl(CX8, "cx8", 0) /* next bits are from cpuid 1 (EDX) */ \ decl(CX8, "cx8", 0) /* next bits are from cpuid 1 (EDX) */ \
decl(CMOV, "cmov", 1) \ decl(CMOV, "cmov", 1) \
@ -420,15 +440,85 @@ protected:
decl(AVX_IFMA, "avx_ifma", 59) /* 256-bit VEX-coded variant of AVX512-IFMA*/ \ decl(AVX_IFMA, "avx_ifma", 59) /* 256-bit VEX-coded variant of AVX512-IFMA*/ \
decl(APX_F, "apx_f", 60) /* Intel Advanced Performance Extensions*/ \ decl(APX_F, "apx_f", 60) /* Intel Advanced Performance Extensions*/ \
decl(SHA512, "sha512", 61) /* SHA512 instructions*/ \ decl(SHA512, "sha512", 61) /* SHA512 instructions*/ \
decl(AVX512_FP16, "avx512_fp16", 62) /* AVX512 FP16 ISA support*/ decl(AVX512_FP16, "avx512_fp16", 62) /* AVX512 FP16 ISA support*/ \
decl(AVX10_1, "avx10_1", 63) /* AVX10 512 bit vector ISA Version 1 support*/ \
decl(AVX10_2, "avx10_2", 64) /* AVX10 512 bit vector ISA Version 2 support*/
#define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = (1ULL << bit), #define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = (bit),
CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_FLAG) CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_FLAG)
#undef DECLARE_CPU_FEATURE_FLAG #undef DECLARE_CPU_FEATURE_FLAG
MAX_CPU_FEATURES
}; };
class VM_Features {
friend class VMStructs;
friend class JVMCIVMStructs;
private:
uint64_t _features_bitmap[(MAX_CPU_FEATURES / BitsPerLong) + 1];
STATIC_ASSERT(sizeof(_features_bitmap) * BitsPerByte >= MAX_CPU_FEATURES);
// Number of 8-byte elements in _bitmap.
constexpr static int features_bitmap_element_count() {
return sizeof(_features_bitmap) / sizeof(uint64_t);
}
constexpr static int features_bitmap_element_shift_count() {
return LogBitsPerLong;
}
constexpr static uint64_t features_bitmap_element_mask() {
return (1ULL << features_bitmap_element_shift_count()) - 1;
}
static int index(Feature_Flag feature) {
int idx = feature >> features_bitmap_element_shift_count();
assert(idx < features_bitmap_element_count(), "Features array index out of bounds");
return idx;
}
static uint64_t bit_mask(Feature_Flag feature) {
return (1ULL << (feature & features_bitmap_element_mask()));
}
static int _features_bitmap_size; // for JVMCI purposes
public:
VM_Features() {
for (int i = 0; i < features_bitmap_element_count(); i++) {
_features_bitmap[i] = 0;
}
}
void set_feature(Feature_Flag feature) {
int idx = index(feature);
_features_bitmap[idx] |= bit_mask(feature);
}
void clear_feature(VM_Version::Feature_Flag feature) {
int idx = index(feature);
_features_bitmap[idx] &= ~bit_mask(feature);
}
bool supports_feature(VM_Version::Feature_Flag feature) {
int idx = index(feature);
return (_features_bitmap[idx] & bit_mask(feature)) != 0;
}
};
// CPU feature flags vector, can be affected by VM settings.
static VM_Features _features;
// Original CPU feature flags vector, not affected by VM settings.
static VM_Features _cpu_features;
static const char* _features_names[]; static const char* _features_names[];
static void clear_cpu_features() {
_features = VM_Features();
_cpu_features = VM_Features();
}
enum Extended_Family { enum Extended_Family {
// AMD // AMD
CPU_FAMILY_AMD_11H = 0x11, CPU_FAMILY_AMD_11H = 0x11,
@ -492,6 +582,11 @@ protected:
SefCpuid7SubLeaf1Eax sefsl1_cpuid7_eax; SefCpuid7SubLeaf1Eax sefsl1_cpuid7_eax;
SefCpuid7SubLeaf1Edx sefsl1_cpuid7_edx; SefCpuid7SubLeaf1Edx sefsl1_cpuid7_edx;
// cpuid function 24 converged vector ISA main leaf
// eax = 24, ecx = 0
StdCpuid24MainLeafEax std_cpuid24_eax;
StdCpuid24MainLeafEbx std_cpuid24_ebx;
// cpuid function 0xB (processor topology) // cpuid function 0xB (processor topology)
// ecx = 0 // ecx = 0
uint32_t tpl_cpuidB0_eax; uint32_t tpl_cpuidB0_eax;
@ -565,7 +660,7 @@ protected:
// Space to save apx registers after signal handle // Space to save apx registers after signal handle
jlong apx_save[2]; // Save r16 and r31 jlong apx_save[2]; // Save r16 and r31
uint64_t feature_flags() const; VM_Features feature_flags() const;
// Asserts // Asserts
void assert_is_initialized() const { void assert_is_initialized() const {
@ -611,6 +706,7 @@ public:
// Offsets for cpuid asm stub // Offsets for cpuid asm stub
static ByteSize std_cpuid0_offset() { return byte_offset_of(CpuidInfo, std_max_function); } static ByteSize std_cpuid0_offset() { return byte_offset_of(CpuidInfo, std_max_function); }
static ByteSize std_cpuid1_offset() { return byte_offset_of(CpuidInfo, std_cpuid1_eax); } static ByteSize std_cpuid1_offset() { return byte_offset_of(CpuidInfo, std_cpuid1_eax); }
static ByteSize std_cpuid24_offset() { return byte_offset_of(CpuidInfo, std_cpuid24_eax); }
static ByteSize dcp_cpuid4_offset() { return byte_offset_of(CpuidInfo, dcp_cpuid4_eax); } static ByteSize dcp_cpuid4_offset() { return byte_offset_of(CpuidInfo, dcp_cpuid4_eax); }
static ByteSize sef_cpuid7_offset() { return byte_offset_of(CpuidInfo, sef_cpuid7_eax); } static ByteSize sef_cpuid7_offset() { return byte_offset_of(CpuidInfo, sef_cpuid7_eax); }
static ByteSize sefsl1_cpuid7_offset() { return byte_offset_of(CpuidInfo, sefsl1_cpuid7_eax); } static ByteSize sefsl1_cpuid7_offset() { return byte_offset_of(CpuidInfo, sefsl1_cpuid7_eax); }
@ -644,11 +740,29 @@ public:
static void clear_apx_test_state(); static void clear_apx_test_state();
static void clean_cpuFeatures() { _features = 0; } static void clean_cpuFeatures() {
static void set_avx_cpuFeatures() { _features |= (CPU_SSE | CPU_SSE2 | CPU_AVX | CPU_VZEROUPPER ); } VM_Version::clear_cpu_features();
static void set_evex_cpuFeatures() { _features |= (CPU_AVX512F | CPU_SSE | CPU_SSE2 | CPU_VZEROUPPER ); } }
static void set_apx_cpuFeatures() { _features |= CPU_APX_F; } static void set_avx_cpuFeatures() {
static void set_bmi_cpuFeatures() { _features |= (CPU_BMI1 | CPU_BMI2 | CPU_LZCNT | CPU_POPCNT); } _features.set_feature(CPU_SSE);
_features.set_feature(CPU_SSE2);
_features.set_feature(CPU_AVX);
_features.set_feature(CPU_VZEROUPPER);
}
static void set_evex_cpuFeatures() {
_features.set_feature(CPU_AVX10_1);
_features.set_feature(CPU_AVX512F);
_features.set_feature(CPU_SSE);
_features.set_feature(CPU_SSE2);
_features.set_feature(CPU_VZEROUPPER);
}
static void set_apx_cpuFeatures() { _features.set_feature(CPU_APX_F); }
static void set_bmi_cpuFeatures() {
_features.set_feature(CPU_BMI1);
_features.set_feature(CPU_BMI2);
_features.set_feature(CPU_LZCNT);
_features.set_feature(CPU_POPCNT);
}
// Initialization // Initialization
static void initialize(); static void initialize();
@ -703,40 +817,39 @@ public:
// //
// Feature identification which can be affected by VM settings // Feature identification which can be affected by VM settings
// //
static bool supports_cpuid() { return _features != 0; } static bool supports_cmov() { return _features.supports_feature(CPU_CMOV); }
static bool supports_cmov() { return (_features & CPU_CMOV) != 0; } static bool supports_fxsr() { return _features.supports_feature(CPU_FXSR); }
static bool supports_fxsr() { return (_features & CPU_FXSR) != 0; } static bool supports_ht() { return _features.supports_feature(CPU_HT); }
static bool supports_ht() { return (_features & CPU_HT) != 0; } static bool supports_mmx() { return _features.supports_feature(CPU_MMX); }
static bool supports_mmx() { return (_features & CPU_MMX) != 0; } static bool supports_sse() { return _features.supports_feature(CPU_SSE); }
static bool supports_sse() { return (_features & CPU_SSE) != 0; } static bool supports_sse2() { return _features.supports_feature(CPU_SSE2); }
static bool supports_sse2() { return (_features & CPU_SSE2) != 0; } static bool supports_sse3() { return _features.supports_feature(CPU_SSE3); }
static bool supports_sse3() { return (_features & CPU_SSE3) != 0; } static bool supports_ssse3() { return _features.supports_feature(CPU_SSSE3); }
static bool supports_ssse3() { return (_features & CPU_SSSE3)!= 0; } static bool supports_sse4_1() { return _features.supports_feature(CPU_SSE4_1); }
static bool supports_sse4_1() { return (_features & CPU_SSE4_1) != 0; } static bool supports_sse4_2() { return _features.supports_feature(CPU_SSE4_2); }
static bool supports_sse4_2() { return (_features & CPU_SSE4_2) != 0; } static bool supports_popcnt() { return _features.supports_feature(CPU_POPCNT); }
static bool supports_popcnt() { return (_features & CPU_POPCNT) != 0; } static bool supports_avx() { return _features.supports_feature(CPU_AVX); }
static bool supports_avx() { return (_features & CPU_AVX) != 0; } static bool supports_avx2() { return _features.supports_feature(CPU_AVX2); }
static bool supports_avx2() { return (_features & CPU_AVX2) != 0; } static bool supports_tsc() { return _features.supports_feature(CPU_TSC); }
static bool supports_tsc() { return (_features & CPU_TSC) != 0; } static bool supports_rdtscp() { return _features.supports_feature(CPU_RDTSCP); }
static bool supports_rdtscp() { return (_features & CPU_RDTSCP) != 0; } static bool supports_rdpid() { return _features.supports_feature(CPU_RDPID); }
static bool supports_rdpid() { return (_features & CPU_RDPID) != 0; } static bool supports_aes() { return _features.supports_feature(CPU_AES); }
static bool supports_aes() { return (_features & CPU_AES) != 0; } static bool supports_erms() { return _features.supports_feature(CPU_ERMS); }
static bool supports_erms() { return (_features & CPU_ERMS) != 0; } static bool supports_fsrm() { return _features.supports_feature(CPU_FSRM); }
static bool supports_fsrm() { return (_features & CPU_FSRM) != 0; } static bool supports_clmul() { return _features.supports_feature(CPU_CLMUL); }
static bool supports_clmul() { return (_features & CPU_CLMUL) != 0; } static bool supports_rtm() { return _features.supports_feature(CPU_RTM); }
static bool supports_rtm() { return (_features & CPU_RTM) != 0; } static bool supports_bmi1() { return _features.supports_feature(CPU_BMI1); }
static bool supports_bmi1() { return (_features & CPU_BMI1) != 0; } static bool supports_bmi2() { return _features.supports_feature(CPU_BMI2); }
static bool supports_bmi2() { return (_features & CPU_BMI2) != 0; } static bool supports_adx() { return _features.supports_feature(CPU_ADX); }
static bool supports_adx() { return (_features & CPU_ADX) != 0; } static bool supports_evex() { return _features.supports_feature(CPU_AVX512F); }
static bool supports_evex() { return (_features & CPU_AVX512F) != 0; } static bool supports_avx512dq() { return _features.supports_feature(CPU_AVX512DQ); }
static bool supports_avx512dq() { return (_features & CPU_AVX512DQ) != 0; } static bool supports_avx512ifma() { return _features.supports_feature(CPU_AVX512_IFMA); }
static bool supports_avx512ifma() { return (_features & CPU_AVX512_IFMA) != 0; } static bool supports_avxifma() { return _features.supports_feature(CPU_AVX_IFMA); }
static bool supports_avxifma() { return (_features & CPU_AVX_IFMA) != 0; } static bool supports_avx512pf() { return _features.supports_feature(CPU_AVX512PF); }
static bool supports_avx512pf() { return (_features & CPU_AVX512PF) != 0; } static bool supports_avx512er() { return _features.supports_feature(CPU_AVX512ER); }
static bool supports_avx512er() { return (_features & CPU_AVX512ER) != 0; } static bool supports_avx512cd() { return _features.supports_feature(CPU_AVX512CD); }
static bool supports_avx512cd() { return (_features & CPU_AVX512CD) != 0; } static bool supports_avx512bw() { return _features.supports_feature(CPU_AVX512BW); }
static bool supports_avx512bw() { return (_features & CPU_AVX512BW) != 0; } static bool supports_avx512vl() { return _features.supports_feature(CPU_AVX512VL); }
static bool supports_avx512vl() { return (_features & CPU_AVX512VL) != 0; }
static bool supports_avx512vlbw() { return (supports_evex() && supports_avx512bw() && supports_avx512vl()); } static bool supports_avx512vlbw() { return (supports_evex() && supports_avx512bw() && supports_avx512vl()); }
static bool supports_avx512bwdq() { return (supports_evex() && supports_avx512bw() && supports_avx512dq()); } static bool supports_avx512bwdq() { return (supports_evex() && supports_avx512bw() && supports_avx512dq()); }
static bool supports_avx512vldq() { return (supports_evex() && supports_avx512dq() && supports_avx512vl()); } static bool supports_avx512vldq() { return (supports_evex() && supports_avx512dq() && supports_avx512vl()); }
@ -745,33 +858,39 @@ public:
static bool supports_avx512novl() { return (supports_evex() && !supports_avx512vl()); } static bool supports_avx512novl() { return (supports_evex() && !supports_avx512vl()); }
static bool supports_avx512nobw() { return (supports_evex() && !supports_avx512bw()); } static bool supports_avx512nobw() { return (supports_evex() && !supports_avx512bw()); }
static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); } static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); }
static bool supports_apx_f() { return (_features & CPU_APX_F) != 0; } static bool supports_apx_f() { return _features.supports_feature(CPU_APX_F); }
static bool supports_avxonly() { return ((supports_avx2() || supports_avx()) && !supports_evex()); } static bool supports_avxonly() { return ((supports_avx2() || supports_avx()) && !supports_evex()); }
static bool supports_sha() { return (_features & CPU_SHA) != 0; } static bool supports_sha() { return _features.supports_feature(CPU_SHA); }
static bool supports_fma() { return (_features & CPU_FMA) != 0 && supports_avx(); } static bool supports_fma() { return _features.supports_feature(CPU_FMA) && supports_avx(); }
static bool supports_vzeroupper() { return (_features & CPU_VZEROUPPER) != 0; } static bool supports_vzeroupper() { return _features.supports_feature(CPU_VZEROUPPER); }
static bool supports_avx512_vpopcntdq() { return (_features & CPU_AVX512_VPOPCNTDQ) != 0; } static bool supports_avx512_vpopcntdq() { return _features.supports_feature(CPU_AVX512_VPOPCNTDQ); }
static bool supports_avx512_vpclmulqdq() { return (_features & CPU_AVX512_VPCLMULQDQ) != 0; } static bool supports_avx512_vpclmulqdq() { return _features.supports_feature(CPU_AVX512_VPCLMULQDQ); }
static bool supports_avx512_vaes() { return (_features & CPU_AVX512_VAES) != 0; } static bool supports_avx512_vaes() { return _features.supports_feature(CPU_AVX512_VAES); }
static bool supports_gfni() { return (_features & CPU_GFNI) != 0; } static bool supports_gfni() { return _features.supports_feature(CPU_GFNI); }
static bool supports_avx512_vnni() { return (_features & CPU_AVX512_VNNI) != 0; } static bool supports_avx512_vnni() { return _features.supports_feature(CPU_AVX512_VNNI); }
static bool supports_avx512_bitalg() { return (_features & CPU_AVX512_BITALG) != 0; } static bool supports_avx512_bitalg() { return _features.supports_feature(CPU_AVX512_BITALG); }
static bool supports_avx512_vbmi() { return (_features & CPU_AVX512_VBMI) != 0; } static bool supports_avx512_vbmi() { return _features.supports_feature(CPU_AVX512_VBMI); }
static bool supports_avx512_vbmi2() { return (_features & CPU_AVX512_VBMI2) != 0; } static bool supports_avx512_vbmi2() { return _features.supports_feature(CPU_AVX512_VBMI2); }
static bool supports_avx512_fp16() { return (_features & CPU_AVX512_FP16) != 0; } static bool supports_avx512_fp16() { return _features.supports_feature(CPU_AVX512_FP16); }
static bool supports_hv() { return (_features & CPU_HV) != 0; } static bool supports_hv() { return _features.supports_feature(CPU_HV); }
static bool supports_serialize() { return (_features & CPU_SERIALIZE) != 0; } static bool supports_serialize() { return _features.supports_feature(CPU_SERIALIZE); }
static bool supports_f16c() { return (_features & CPU_F16C) != 0; } static bool supports_f16c() { return _features.supports_feature(CPU_F16C); }
static bool supports_pku() { return (_features & CPU_PKU) != 0; } static bool supports_pku() { return _features.supports_feature(CPU_PKU); }
static bool supports_ospke() { return (_features & CPU_OSPKE) != 0; } static bool supports_ospke() { return _features.supports_feature(CPU_OSPKE); }
static bool supports_cet_ss() { return (_features & CPU_CET_SS) != 0; } static bool supports_cet_ss() { return _features.supports_feature(CPU_CET_SS); }
static bool supports_cet_ibt() { return (_features & CPU_CET_IBT) != 0; } static bool supports_cet_ibt() { return _features.supports_feature(CPU_CET_IBT); }
static bool supports_sha512() { return (_features & CPU_SHA512) != 0; } static bool supports_sha512() { return _features.supports_feature(CPU_SHA512); }
// Intel® AVX10 introduces a versioned approach for enumeration that is monotonically increasing, inclusive,
// and supporting all vector lengths. Feature set supported by an AVX10 vector ISA version is also supported
// by all the versions above it.
static bool supports_avx10_1() { return _features.supports_feature(CPU_AVX10_1);}
static bool supports_avx10_2() { return _features.supports_feature(CPU_AVX10_2);}
// //
// Feature identification not affected by VM flags // Feature identification not affected by VM flags
// //
static bool cpu_supports_evex() { return (_cpu_features & CPU_AVX512F) != 0; } static bool cpu_supports_evex() { return _cpu_features.supports_feature(CPU_AVX512F); }
static bool supports_avx512_simd_sort() { static bool supports_avx512_simd_sort() {
if (supports_avx512dq()) { if (supports_avx512dq()) {
@ -802,6 +921,8 @@ public:
static bool is_intel_tsc_synched_at_init(); static bool is_intel_tsc_synched_at_init();
static void insert_features_names(VM_Version::VM_Features features, char* buf, size_t buflen);
// This checks if the JVM is potentially affected by an erratum on Intel CPUs (SKX102) // This checks if the JVM is potentially affected by an erratum on Intel CPUs (SKX102)
// that causes unpredictable behaviour when jcc crosses 64 byte boundaries. Its microcode // that causes unpredictable behaviour when jcc crosses 64 byte boundaries. Its microcode
// mitigation causes regressions when jumps or fused conditional branches cross or end at // mitigation causes regressions when jumps or fused conditional branches cross or end at
@ -809,19 +930,19 @@ public:
static bool has_intel_jcc_erratum() { return _has_intel_jcc_erratum; } static bool has_intel_jcc_erratum() { return _has_intel_jcc_erratum; }
// AMD features // AMD features
static bool supports_3dnow_prefetch() { return (_features & CPU_3DNOW_PREFETCH) != 0; } static bool supports_3dnow_prefetch() { return _features.supports_feature(CPU_3DNOW_PREFETCH); }
static bool supports_lzcnt() { return (_features & CPU_LZCNT) != 0; } static bool supports_lzcnt() { return _features.supports_feature(CPU_LZCNT); }
static bool supports_sse4a() { return (_features & CPU_SSE4A) != 0; } static bool supports_sse4a() { return _features.supports_feature(CPU_SSE4A); }
static bool is_amd_Barcelona() { return is_amd() && static bool is_amd_Barcelona() { return is_amd() &&
extended_cpu_family() == CPU_FAMILY_AMD_11H; } extended_cpu_family() == CPU_FAMILY_AMD_11H; }
// Intel and AMD newer cores support fast timestamps well // Intel and AMD newer cores support fast timestamps well
static bool supports_tscinv_bit() { static bool supports_tscinv_bit() {
return (_features & CPU_TSCINV_BIT) != 0; return _features.supports_feature(CPU_TSCINV_BIT);
} }
static bool supports_tscinv() { static bool supports_tscinv() {
return (_features & CPU_TSCINV) != 0; return _features.supports_feature(CPU_TSCINV);
} }
// Intel Core and newer cpus have fast IDIV instruction (excluding Atom). // Intel Core and newer cpus have fast IDIV instruction (excluding Atom).
@ -882,8 +1003,8 @@ public:
static bool supports_clflush(); // Can't inline due to header file conflict static bool supports_clflush(); // Can't inline due to header file conflict
// Note: CPU_FLUSHOPT and CPU_CLWB bits should always be zero for 32-bit // Note: CPU_FLUSHOPT and CPU_CLWB bits should always be zero for 32-bit
static bool supports_clflushopt() { return ((_features & CPU_FLUSHOPT) != 0); } static bool supports_clflushopt() { return (_features.supports_feature(CPU_FLUSHOPT)); }
static bool supports_clwb() { return ((_features & CPU_CLWB) != 0); } static bool supports_clwb() { return (_features.supports_feature(CPU_CLWB)); }
// Old CPUs perform lea on AGU which causes additional latency transferring the // Old CPUs perform lea on AGU which causes additional latency transferring the
// value from/to ALU for other operations // value from/to ALU for other operations

View File

@ -470,6 +470,7 @@ jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS) {
strcmp(vmField.typeString, "intptr_t") == 0 || strcmp(vmField.typeString, "intptr_t") == 0 ||
strcmp(vmField.typeString, "uintptr_t") == 0 || strcmp(vmField.typeString, "uintptr_t") == 0 ||
strcmp(vmField.typeString, "OopHandle") == 0 || strcmp(vmField.typeString, "OopHandle") == 0 ||
strcmp(vmField.typeString, "VM_Version::VM_Features") == 0 ||
strcmp(vmField.typeString, "size_t") == 0 || strcmp(vmField.typeString, "size_t") == 0 ||
// All foo* types are addresses. // All foo* types are addresses.
vmField.typeString[strlen(vmField.typeString) - 1] == '*') { vmField.typeString[strlen(vmField.typeString) - 1] == '*') {

View File

@ -150,7 +150,7 @@
\ \
static_field(CompilerToVM::Data, data_section_item_alignment, int) \ static_field(CompilerToVM::Data, data_section_item_alignment, int) \
\ \
JVMTI_ONLY(static_field(CompilerToVM::Data, _should_notify_object_alloc, int*)) \ JVMTI_ONLY(static_field(CompilerToVM::Data, _should_notify_object_alloc, int*)) \
\ \
static_field(Abstract_VM_Version, _features, uint64_t) \ static_field(Abstract_VM_Version, _features, uint64_t) \
\ \
@ -997,7 +997,11 @@
#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ #define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \
volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \
static_field(VM_Version, _has_intel_jcc_erratum, bool) static_field(VM_Version, _features, VM_Version::VM_Features) \
\
nonstatic_field(VM_Version::VM_Features, _features_bitmap[0], uint64_t) \
static_field(VM_Version::VM_Features, _features_bitmap_size, int) \
static_field(VM_Version, _has_intel_jcc_erratum, bool)
#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) \ #define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) \
LP64_ONLY(declare_constant(frame::arg_reg_save_area_bytes)) \ LP64_ONLY(declare_constant(frame::arg_reg_save_area_bytes)) \
@ -1005,7 +1009,8 @@
declare_constant(frame::interpreter_frame_last_sp_offset) declare_constant(frame::interpreter_frame_last_sp_offset)
#define DECLARE_LONG_CPU_FEATURE_CONSTANT(id, name, bit) GENERATE_VM_LONG_CONSTANT_ENTRY(VM_Version::CPU_##id) #define DECLARE_LONG_CPU_FEATURE_CONSTANT(id, name, bit) GENERATE_VM_LONG_CONSTANT_ENTRY(VM_Version::CPU_##id)
#define VM_LONG_CPU_FEATURE_CONSTANTS CPU_FEATURE_FLAGS(DECLARE_LONG_CPU_FEATURE_CONSTANT) #define VM_LONG_CPU_FEATURE_CONSTANTS \
CPU_FEATURE_FLAGS(DECLARE_LONG_CPU_FEATURE_CONSTANT)
#endif #endif

View File

@ -325,22 +325,6 @@ unsigned int Abstract_VM_Version::jvm_version() {
(Abstract_VM_Version::vm_build_number() & 0xFF); (Abstract_VM_Version::vm_build_number() & 0xFF);
} }
void Abstract_VM_Version::insert_features_names(char* buf, size_t buflen, const char* features_names[]) {
uint64_t features = _features;
uint features_names_index = 0;
while (features != 0) {
if (features & 1) {
int res = jio_snprintf(buf, buflen, ", %s", features_names[features_names_index]);
assert(res > 0, "not enough temporary space allocated");
buf += res;
buflen -= res;
}
features >>= 1;
++features_names_index;
}
}
const char* Abstract_VM_Version::extract_features_string(const char* cpu_info_string, const char* Abstract_VM_Version::extract_features_string(const char* cpu_info_string,
size_t cpu_info_string_len, size_t cpu_info_string_len,
size_t features_offset) { size_t features_offset) {

View File

@ -56,6 +56,7 @@ class Abstract_VM_Version: AllStatic {
// CPU feature flags, can be affected by VM settings. // CPU feature flags, can be affected by VM settings.
static uint64_t _features; static uint64_t _features;
static const char* _features_string; static const char* _features_string;
static const char* _cpu_info_string; static const char* _cpu_info_string;
@ -128,10 +129,9 @@ class Abstract_VM_Version: AllStatic {
static const char* jdk_debug_level(); static const char* jdk_debug_level();
static const char* printable_jdk_debug_level(); static const char* printable_jdk_debug_level();
static uint64_t features() { return _features; }
static const char* features_string() { return _features_string; } static const char* features_string() { return _features_string; }
static const char* cpu_info_string() { return _cpu_info_string; } static const char* cpu_info_string() { return _cpu_info_string; }
static void insert_features_names(char* buf, size_t buflen, const char* features_names[]);
static const char* extract_features_string(const char* cpu_info_string, static const char* extract_features_string(const char* cpu_info_string,
size_t cpu_info_string_len, size_t cpu_info_string_len,
size_t features_offset); size_t features_offset);

View File

@ -1,3 +1,4 @@
/* /*
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@ -1164,6 +1165,7 @@
/********************/ \ /********************/ \
\ \
declare_toplevel_type(Abstract_VM_Version) \ declare_toplevel_type(Abstract_VM_Version) \
declare_toplevel_type(VM_Version) \
\ \
/*************/ \ /*************/ \
/* Arguments */ \ /* Arguments */ \
@ -1716,7 +1718,6 @@
/**********************/ \ /**********************/ \
NOT_ZERO(PPC64_ONLY(declare_constant(frame::entry_frame_locals_size))) \ NOT_ZERO(PPC64_ONLY(declare_constant(frame::entry_frame_locals_size))) \
\ \
NOT_ZERO(X86_ONLY(declare_constant(frame::entry_frame_call_wrapper_offset))) \
declare_constant(frame::pc_return_offset) \ declare_constant(frame::pc_return_offset) \
\ \
/*************/ \ /*************/ \
@ -2146,3 +2147,4 @@ void vmStructs_init() {
VMStructs::init(); VMStructs::init();
} }
#endif // ASSERT #endif // ASSERT

View File

@ -258,6 +258,8 @@ public class AMD64 extends Architecture {
APX_F, APX_F,
SHA512, SHA512,
AVX512_FP16, AVX512_FP16,
AVX10_1,
AVX10_2
} }
private final EnumSet<CPUFeature> features; private final EnumSet<CPUFeature> features;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,7 @@ import java.util.Map.Entry;
import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.common.JVMCIError;
import jdk.vm.ci.runtime.JVMCIBackend; import jdk.vm.ci.runtime.JVMCIBackend;
import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
public interface HotSpotJVMCIBackendFactory { public interface HotSpotJVMCIBackendFactory {
@ -80,4 +81,58 @@ public interface HotSpotJVMCIBackendFactory {
} }
return outFeatures; return outFeatures;
} }
/**
* Converts CPU features bit map into enum constants.
*
* @param <CPUFeatureType> CPU feature enum type
* @param enumType the class of {@code CPUFeatureType}
* @param constants VM constants. Each entry whose key starts with {@code "VM_Version::CPU_"}
* specifies a CPU feature and its value is a mask for a bit in {@code features}
* @param featuresBitMapAddress pointer to {@code VM_Features::_features_bitmap} field of {@code VM_Version::_features}
* @param featuresBitMapSize size of feature bit map in bytes
* @param renaming maps from VM feature names to enum constant names where the two differ
* @throws IllegalArgumentException if any VM CPU feature constant cannot be converted to an
* enum value
* @return the set of converted values
*/
static <CPUFeatureType extends Enum<CPUFeatureType>> EnumSet<CPUFeatureType> convertFeatures(
Class<CPUFeatureType> enumType,
Map<String, Long> constants,
long featuresBitMapAddress,
long featuresBitMapSize,
Map<String, String> renaming) {
EnumSet<CPUFeatureType> outFeatures = EnumSet.noneOf(enumType);
List<String> missing = new ArrayList<>();
for (Entry<String, Long> e : constants.entrySet()) {
String key = e.getKey();
long bitIndex = e.getValue();
if (key.startsWith("VM_Version::CPU_")) {
String name = key.substring("VM_Version::CPU_".length());
try {
final long featuresElementShiftCount = 6; // log (# of bits per long)
final long featuresElementMask = (1L << featuresElementShiftCount) - 1;
CPUFeatureType feature = Enum.valueOf(enumType, renaming.getOrDefault(name, name));
long featureIndex = bitIndex >>> featuresElementShiftCount;
long featureBitMask = 1L << (bitIndex & featuresElementMask);
assert featureIndex < featuresBitMapSize;
long featuresElement = UNSAFE.getLong(featuresBitMapAddress + featureIndex * Long.BYTES);
if ((featuresElement & featureBitMask) != 0) {
outFeatures.add(feature);
}
} catch (IllegalArgumentException iae) {
missing.add(name);
}
}
}
if (!missing.isEmpty()) {
throw new JVMCIError("Missing CPU feature constants: %s", missing);
}
return outFeatures;
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -50,7 +50,12 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto
Map<String, Long> constants = config.getStore().getConstants(); Map<String, Long> constants = config.getStore().getConstants();
Map<String, String> renaming = Map.of("3DNOW_PREFETCH", "AMD_3DNOW_PREFETCH"); Map<String, String> renaming = Map.of("3DNOW_PREFETCH", "AMD_3DNOW_PREFETCH");
assert config.useSSE >= 2 : "minimum config for x64"; assert config.useSSE >= 2 : "minimum config for x64";
EnumSet<CPUFeature> features = HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, config.vmVersionFeatures, renaming); long featuresBitMapAddress = config.vmVersionFeatures + config.vmFeaturesFeaturesOffset;
EnumSet<CPUFeature> features = HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class,
constants,
featuresBitMapAddress,
config.vmFeaturesFeaturesSize,
renaming);
features.add(AMD64.CPUFeature.SSE); features.add(AMD64.CPUFeature.SSE);
features.add(AMD64.CPUFeature.SSE2); features.add(AMD64.CPUFeature.SSE2);
return features; return features;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -42,12 +42,14 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess {
final boolean useCountTrailingZerosInstruction = getFlag("UseCountTrailingZerosInstruction", Boolean.class); final boolean useCountTrailingZerosInstruction = getFlag("UseCountTrailingZerosInstruction", Boolean.class);
final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class); final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
final long vmVersionFeatures = getFieldAddress("VM_Version::_features", "VM_Version::VM_Features");
final long vmFeaturesFeaturesOffset = getFieldOffset("VM_Version::VM_Features::_features_bitmap[0]", Long.class, "uint64_t");
final long vmFeaturesFeaturesSize = getFieldValue("VM_Version::VM_Features::_features_bitmap_size", Long.class, "int");
// CPU capabilities // CPU capabilities
final int useSSE = getFlag("UseSSE", Integer.class); final int useSSE = getFlag("UseSSE", Integer.class);
final int useAVX = getFlag("UseAVX", Integer.class); final int useAVX = getFlag("UseAVX", Integer.class);
final long vmVersionFeatures = getFieldValue("Abstract_VM_Version::_features", Long.class, "uint64_t");
// CPU feature flags // CPU feature flags
final long amd64CX8 = getConstant("VM_Version::CPU_CX8", Long.class); final long amd64CX8 = getConstant("VM_Version::CPU_CX8", Long.class);
final long amd64CMOV = getConstant("VM_Version::CPU_CMOV", Long.class); final long amd64CMOV = getConstant("VM_Version::CPU_CMOV", Long.class);
@ -88,4 +90,6 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess {
final long amd64OSPKE = getConstant("VM_Version::CPU_OSPKE", Long.class); final long amd64OSPKE = getConstant("VM_Version::CPU_OSPKE", Long.class);
final long amd64CET_IBT = getConstant("VM_Version::CPU_CET_IBT", Long.class); final long amd64CET_IBT = getConstant("VM_Version::CPU_CET_IBT", Long.class);
final long amd64CET_SS = getConstant("VM_Version::CPU_CET_SS", Long.class); final long amd64CET_SS = getConstant("VM_Version::CPU_CET_SS", Long.class);
final long amd64AVX10_1 = getConstant("VM_Version::CPU_AVX10_1", Long.class);
final long amd64AVX10_2 = getConstant("VM_Version::CPU_AVX10_2", Long.class);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -92,7 +92,7 @@ public class ClhsdbLongConstant {
// Expected output snippet is of the form (on x64-64): // Expected output snippet is of the form (on x64-64):
// ... // ...
// longConstant VM_Version::CPU_SHA 17179869184 // longConstant VM_Version::CPU_SHA 34
// longConstant markWord::age_shift 3 // longConstant markWord::age_shift 3
// longConstant markWord::hash_mask_in_place 4398046509056 // longConstant markWord::hash_mask_in_place 4398046509056
// ... // ...
@ -106,7 +106,7 @@ public class ClhsdbLongConstant {
// Expected value obtained from the CPU_SHA definition in vm_version_x86.hpp // Expected value obtained from the CPU_SHA definition in vm_version_x86.hpp
checkLongValue("VM_Version::CPU_SHA ", checkLongValue("VM_Version::CPU_SHA ",
longConstantOutput, longConstantOutput,
17179869184L); 34L);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -66,7 +66,7 @@ public class CPUInfoTest {
"hv", "fsrm", "avx512_bitalg", "gfni", "hv", "fsrm", "avx512_bitalg", "gfni",
"f16c", "pku", "ospke", "cet_ibt", "f16c", "pku", "ospke", "cet_ibt",
"cet_ss", "avx512_ifma", "serialize", "avx_ifma", "cet_ss", "avx512_ifma", "serialize", "avx_ifma",
"apx_f" "apx_f", "avx10_1", "avx10_2"
); );
// @formatter:on // @formatter:on
// Checkstyle: resume // Checkstyle: resume