@@ -56,16 +56,22 @@ const char* VM_Version::_features_names[] = { CPU_FEATURE_FLAGS(DECLARE_CPU_FEAT
56
56
address VM_Version::_cpuinfo_segv_addr = 0 ;
57
57
// Address of instruction after the one which causes SEGV
58
58
address VM_Version::_cpuinfo_cont_addr = 0 ;
59
+ // Address of instruction which causes APX specific SEGV
60
+ address VM_Version::_cpuinfo_segv_addr_apx = 0 ;
61
+ // Address of instruction after the one which causes APX specific SEGV
62
+ address VM_Version::_cpuinfo_cont_addr_apx = 0 ;
59
63
60
64
static BufferBlob* stub_blob;
61
65
static const int stub_size = 2000 ;
62
66
63
67
extern " C" {
64
68
typedef void (*get_cpu_info_stub_t )(void *);
65
69
typedef void (*detect_virt_stub_t )(uint32_t , uint32_t *);
70
+ typedef void (*clear_apx_test_state_t )(void );
66
71
}
67
72
static get_cpu_info_stub_t get_cpu_info_stub = nullptr ;
68
73
static detect_virt_stub_t detect_virt_stub = nullptr ;
74
+ static clear_apx_test_state_t clear_apx_test_state_stub = nullptr ;
69
75
70
76
#ifdef _LP64
71
77
@@ -102,6 +108,27 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
102
108
103
109
VM_Version_StubGenerator (CodeBuffer *c) : StubCodeGenerator(c) {}
104
110
111
+ address clear_apx_test_state () {
112
+ # define __ _masm->
113
+ address start = __ pc ();
114
+ // EGPRs are call clobbered registers, Explicit clearing of r16 and r31 during signal
115
+ // handling guarantees that preserved register values post signal handling were
116
+ // re-instantiated by operating system and not because they were not modified externally.
117
+
118
+ /* FIXME Uncomment following code after OS enablement of
119
+ bool save_apx = UseAPX;
120
+ VM_Version::set_apx_cpuFeatures();
121
+ UseAPX = true;
122
+ // EGPR state save/restoration.
123
+ __ mov64(r16, 0L);
124
+ __ mov64(r31, 0L);
125
+ UseAPX = save_apx;
126
+ VM_Version::clean_cpuFeatures();
127
+ */
128
+ __ ret (0 );
129
+ return start;
130
+ }
131
+
105
132
address generate_get_cpu_info () {
106
133
// Flags to test CPU type.
107
134
const uint32_t HS_EFL_AC = 0x40000 ;
@@ -113,7 +140,8 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
113
140
bool use_evex = FLAG_IS_DEFAULT (UseAVX) || (UseAVX > 2 );
114
141
115
142
Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4;
116
- Label sef_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7, ext_cpuid8, done, wrapup;
143
+ Label sef_cpuid, sefsl1_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7;
144
+ Label ext_cpuid8, done, wrapup, vector_save_restore, apx_save_restore_warning;
117
145
Label legacy_setup, save_restore_except, legacy_save_restore, start_simd_check;
118
146
119
147
StubCodeMark mark (this , " VM_Version" , " get_cpu_info_stub" );
@@ -288,7 +316,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
288
316
__ movl (Address (rsi, 4 ), rdx);
289
317
290
318
//
291
- // cpuid(0x7) Structured Extended Features
319
+ // cpuid(0x7) Structured Extended Features Enumeration Leaf.
292
320
//
293
321
__ bind (sef_cpuid);
294
322
__ movl (rax, 7 );
@@ -303,12 +331,16 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
303
331
__ movl (Address (rsi, 8 ), rcx);
304
332
__ movl (Address (rsi, 12 ), rdx);
305
333
306
- // ECX = 1
334
+ //
335
+ // cpuid(0x7) Structured Extended Features Enumeration Sub-Leaf 1.
336
+ //
337
+ __ bind (sefsl1_cpuid);
307
338
__ movl (rax, 7 );
308
339
__ movl (rcx, 1 );
309
340
__ cpuid ();
310
- __ lea (rsi, Address (rbp, in_bytes (VM_Version::sef_cpuid7_ecx1_offset ())));
341
+ __ lea (rsi, Address (rbp, in_bytes (VM_Version::sefsl1_cpuid7_offset ())));
311
342
__ movl (Address (rsi, 0 ), rax);
343
+ __ movl (Address (rsi, 4 ), rdx);
312
344
313
345
//
314
346
// Extended cpuid(0x80000000)
@@ -387,6 +419,46 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
387
419
__ movl (Address (rsi, 8 ), rcx);
388
420
__ movl (Address (rsi,12 ), rdx);
389
421
422
+ #ifndef PRODUCT
423
+ //
424
+ // Check if OS has enabled XGETBV instruction to access XCR0
425
+ // (OSXSAVE feature flag) and CPU supports APX
426
+ //
427
+ // To enable APX, check CPUID.EAX=7.ECX=1.EDX[21] bit for HW support
428
+ // and XCRO[19] bit for OS support to save/restore extended GPR state.
429
+ __ lea (rsi, Address (rbp, in_bytes (VM_Version::sefsl1_cpuid7_offset ())));
430
+ __ movl (rax, 0x200000 );
431
+ __ andl (rax, Address (rsi, 4 ));
432
+ __ cmpl (rax, 0x200000 );
433
+ __ jcc (Assembler::notEqual, vector_save_restore);
434
+ // check _cpuid_info.xem_xcr0_eax.bits.apx_f
435
+ __ movl (rax, 0x80000 );
436
+ __ andl (rax, Address (rbp, in_bytes (VM_Version::xem_xcr0_offset ()))); // xcr0 bits apx_f
437
+ __ cmpl (rax, 0x80000 );
438
+ __ jcc (Assembler::notEqual, vector_save_restore);
439
+
440
+ /* FIXME: Uncomment while integrating JDK-8329032
441
+ bool save_apx = UseAPX;
442
+ VM_Version::set_apx_cpuFeatures();
443
+ UseAPX = true;
444
+ __ mov64(r16, VM_Version::egpr_test_value());
445
+ __ mov64(r31, VM_Version::egpr_test_value());
446
+ */
447
+ __ xorl (rsi, rsi);
448
+ VM_Version::set_cpuinfo_segv_addr_apx (__ pc ());
449
+ // Generate SEGV
450
+ __ movl (rax, Address (rsi, 0 ));
451
+
452
+ VM_Version::set_cpuinfo_cont_addr_apx (__ pc ());
453
+ /* FIXME: Uncomment after integration of JDK-8329032
454
+ __ lea(rsi, Address(rbp, in_bytes(VM_Version::apx_save_offset())));
455
+ __ movq(Address(rsi, 0), r16);
456
+ __ movq(Address(rsi, 8), r31);
457
+
458
+ UseAPX = save_apx;
459
+ */
460
+ #endif
461
+ __ bind (vector_save_restore);
390
462
//
391
463
// Check if OS has enabled XGETBV instruction to access XCR0
392
464
// (OSXSAVE feature flag) and CPU supports AVX
@@ -580,6 +652,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
580
652
__ vmovdqu (xmm7, Address (rsp, 0 ));
581
653
__ addptr (rsp, 32 );
582
654
#endif // _WINDOWS
655
+
583
656
generate_vzeroupper (wrapup);
584
657
VM_Version::clean_cpuFeatures ();
585
658
UseAVX = saved_useavx;
@@ -940,6 +1013,7 @@ void VM_Version::get_processor_features() {
940
1013
FLAG_SET_DEFAULT (UseAVX, use_avx_limit);
941
1014
}
942
1015
}
1016
+
943
1017
if (UseAVX > use_avx_limit) {
944
1018
if (UseSSE < 4 ) {
945
1019
warning (" UseAVX=%d requires UseSSE=4, setting it to UseAVX=0" , UseAVX);
@@ -963,6 +1037,16 @@ void VM_Version::get_processor_features() {
963
1037
_features &= ~CPU_AVX512_VBMI2;
964
1038
_features &= ~CPU_AVX512_BITALG;
965
1039
_features &= ~CPU_AVX512_IFMA;
1040
+ _features &= ~CPU_APX_F;
1041
+ }
1042
+
1043
+ // Currently APX support is only enabled for targets supporting AVX512VL feature.
1044
+ bool apx_supported = os_supports_apx_egprs () && supports_apx_f () && supports_avx512vl ();
1045
+ if (UseAPX && !apx_supported) {
1046
+ warning (" UseAPX is not supported on this CPU, setting it to false" );
1047
+ FLAG_SET_DEFAULT (UseAPX, false );
1048
+ } else if (FLAG_IS_DEFAULT (UseAPX)) {
1049
+ FLAG_SET_DEFAULT (UseAPX, apx_supported ? true : false );
966
1050
}
967
1051
968
1052
if (UseAVX < 2 ) {
@@ -1002,14 +1086,6 @@ void VM_Version::get_processor_features() {
1002
1086
}
1003
1087
}
1004
1088
1005
- // APX support not enabled yet
1006
- if (UseAPX) {
1007
- if (!FLAG_IS_DEFAULT (UseAPX)) {
1008
- warning (" APX is not supported on this CPU." );
1009
- }
1010
- FLAG_SET_DEFAULT (UseAPX, false );
1011
- }
1012
-
1013
1089
if (FLAG_IS_DEFAULT (IntelJccErratumMitigation)) {
1014
1090
_has_intel_jcc_erratum = compute_has_intel_jcc_erratum ();
1015
1091
} else {
@@ -2143,6 +2219,10 @@ int VM_Version::avx3_threshold() {
2143
2219
FLAG_IS_DEFAULT (AVX3Threshold)) ? 0 : AVX3Threshold;
2144
2220
}
2145
2221
2222
+ void VM_Version::clear_apx_test_state () {
2223
+ clear_apx_test_state_stub ();
2224
+ }
2225
+
2146
2226
static bool _vm_version_initialized = false ;
2147
2227
2148
2228
void VM_Version::initialize () {
@@ -2160,6 +2240,8 @@ void VM_Version::initialize() {
2160
2240
detect_virt_stub = CAST_TO_FN_PTR (detect_virt_stub_t ,
2161
2241
g.generate_detect_virt ());
2162
2242
2243
+ clear_apx_test_state_stub = CAST_TO_FN_PTR (clear_apx_test_state_t ,
2244
+ g.clear_apx_test_state ());
2163
2245
get_processor_features ();
2164
2246
2165
2247
LP64_ONLY (Assembler::precompute_instructions ();)
@@ -2958,6 +3040,10 @@ uint64_t VM_Version::CpuidInfo::feature_flags() const {
2958
3040
result |= CPU_SSE4_2;
2959
3041
if (std_cpuid1_ecx.bits .popcnt != 0 )
2960
3042
result |= CPU_POPCNT;
3043
+ if (sefsl1_cpuid7_edx.bits .apx_f != 0 &&
3044
+ xem_xcr0_eax.bits .apx_f != 0 ) {
3045
+ result |= CPU_APX_F;
3046
+ }
2961
3047
if (std_cpuid1_ecx.bits .avx != 0 &&
2962
3048
std_cpuid1_ecx.bits .osxsave != 0 &&
2963
3049
xem_xcr0_eax.bits .sse != 0 &&
@@ -2968,7 +3054,7 @@ uint64_t VM_Version::CpuidInfo::feature_flags() const {
2968
3054
result |= CPU_F16C;
2969
3055
if (sef_cpuid7_ebx.bits .avx2 != 0 ) {
2970
3056
result |= CPU_AVX2;
2971
- if (sef_cpuid7_ecx1_eax .bits .avx_ifma != 0 )
3057
+ if (sefsl1_cpuid7_eax .bits .avx_ifma != 0 )
2972
3058
result |= CPU_AVX_IFMA;
2973
3059
}
2974
3060
if (sef_cpuid7_ecx.bits .gfni != 0 )
@@ -3142,6 +3228,17 @@ bool VM_Version::os_supports_avx_vectors() {
3142
3228
return retVal;
3143
3229
}
3144
3230
3231
+ bool VM_Version::os_supports_apx_egprs () {
3232
+ if (!supports_apx_f ()) {
3233
+ return false ;
3234
+ }
3235
+ if (_cpuid_info.apx_save [0 ] != egpr_test_value () ||
3236
+ _cpuid_info.apx_save [1 ] != egpr_test_value ()) {
3237
+ return false ;
3238
+ }
3239
+ return true ;
3240
+ }
3241
+
3145
3242
uint VM_Version::cores_per_cpu () {
3146
3243
uint result = 1 ;
3147
3244
if (is_intel ()) {
0 commit comments