Mercurial > hg > graal-jvmci-8
comparison src/cpu/x86/vm/vm_version_x86.cpp @ 17739:98af1e198e73
8037226: compiler/7196199/Test7196199.java fails on 32-bit linux with MaxVectorSize > 16
Summary: verify YMM registers after signal processing and set limit on vector's size.
Reviewed-by: iveresov, twisti
author | kvn |
---|---|
date | Fri, 14 Mar 2014 17:28:58 -0700 |
parents | 8a8ff6b577ed |
children | 606acabe7b5c |
comparison
equal
deleted
inserted
replaced
17737:0d2ce7411240 | 17739:98af1e198e73 |
---|---|
48 int VM_Version::_stepping; | 48 int VM_Version::_stepping; |
49 int VM_Version::_cpuFeatures; | 49 int VM_Version::_cpuFeatures; |
50 const char* VM_Version::_features_str = ""; | 50 const char* VM_Version::_features_str = ""; |
51 VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, }; | 51 VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, }; |
52 | 52 |
53 // Address of instruction which causes SEGV | |
54 address VM_Version::_cpuinfo_segv_addr = 0; | |
55 // Address of instruction after the one which causes SEGV | |
56 address VM_Version::_cpuinfo_cont_addr = 0; | |
57 | |
53 static BufferBlob* stub_blob; | 58 static BufferBlob* stub_blob; |
54 static const int stub_size = 550; | 59 static const int stub_size = 600; |
55 | 60 |
56 extern "C" { | 61 extern "C" { |
57 typedef void (*getPsrInfo_stub_t)(void*); | 62 typedef void (*getPsrInfo_stub_t)(void*); |
58 } | 63 } |
59 static getPsrInfo_stub_t getPsrInfo_stub = NULL; | 64 static getPsrInfo_stub_t getPsrInfo_stub = NULL; |
232 | 237 |
233 // | 238 // |
234 // Check if OS has enabled XGETBV instruction to access XCR0 | 239 // Check if OS has enabled XGETBV instruction to access XCR0 |
235 // (OSXSAVE feature flag) and CPU supports AVX | 240 // (OSXSAVE feature flag) and CPU supports AVX |
236 // | 241 // |
237 __ andl(rcx, 0x18000000); | 242 __ andl(rcx, 0x18000000); // cpuid1 bits osxsave | avx |
238 __ cmpl(rcx, 0x18000000); | 243 __ cmpl(rcx, 0x18000000); |
239 __ jccb(Assembler::notEqual, sef_cpuid); | 244 __ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported |
240 | 245 |
241 // | 246 // |
242 // XCR0, XFEATURE_ENABLED_MASK register | 247 // XCR0, XFEATURE_ENABLED_MASK register |
243 // | 248 // |
244 __ xorl(rcx, rcx); // zero for XCR0 register | 249 __ xorl(rcx, rcx); // zero for XCR0 register |
245 __ xgetbv(); | 250 __ xgetbv(); |
246 __ lea(rsi, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); | 251 __ lea(rsi, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); |
247 __ movl(Address(rsi, 0), rax); | 252 __ movl(Address(rsi, 0), rax); |
248 __ movl(Address(rsi, 4), rdx); | 253 __ movl(Address(rsi, 4), rdx); |
254 | |
255 __ andl(rax, 0x6); // xcr0 bits sse | ymm | |
256 __ cmpl(rax, 0x6); | |
257 __ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported | |
258 | |
259 // | |
260 // Some OSs have a bug when upper 128bits of YMM | |
261 // registers are not restored after a signal processing. | |
262 // Generate SEGV here (reference through NULL) | |
263 // and check upper YMM bits after it. | |
264 // | |
265 VM_Version::set_avx_cpuFeatures(); // Enable temporary to pass asserts | |
266 | |
267 // load value into all 32 bytes of ymm7 register | |
268 __ movl(rcx, VM_Version::ymm_test_value()); | |
269 | |
270 __ movdl(xmm0, rcx); | |
271 __ pshufd(xmm0, xmm0, 0x00); | |
272 __ vinsertf128h(xmm0, xmm0, xmm0); | |
273 __ vmovdqu(xmm7, xmm0); | |
274 #ifdef _LP64 | |
275 __ vmovdqu(xmm8, xmm0); | |
276 __ vmovdqu(xmm15, xmm0); | |
277 #endif | |
278 | |
279 __ xorl(rsi, rsi); | |
280 VM_Version::set_cpuinfo_segv_addr( __ pc() ); | |
281 // Generate SEGV | |
282 __ movl(rax, Address(rsi, 0)); | |
283 | |
284 VM_Version::set_cpuinfo_cont_addr( __ pc() ); | |
285 // Returns here after signal. Save xmm0 to check it later. | |
286 __ lea(rsi, Address(rbp, in_bytes(VM_Version::ymm_save_offset()))); | |
287 __ vmovdqu(Address(rsi, 0), xmm0); | |
288 __ vmovdqu(Address(rsi, 32), xmm7); | |
289 #ifdef _LP64 | |
290 __ vmovdqu(Address(rsi, 64), xmm8); | |
291 __ vmovdqu(Address(rsi, 96), xmm15); | |
292 #endif | |
293 | |
294 VM_Version::clean_cpuFeatures(); | |
249 | 295 |
250 // | 296 // |
251 // cpuid(0x7) Structured Extended Features | 297 // cpuid(0x7) Structured Extended Features |
252 // | 298 // |
253 __ bind(sef_cpuid); | 299 __ bind(sef_cpuid); |
538 FLAG_SET_DEFAULT(MaxVectorSize, 32); | 584 FLAG_SET_DEFAULT(MaxVectorSize, 32); |
539 } | 585 } |
540 if (MaxVectorSize > 32) { | 586 if (MaxVectorSize > 32) { |
541 FLAG_SET_DEFAULT(MaxVectorSize, 32); | 587 FLAG_SET_DEFAULT(MaxVectorSize, 32); |
542 } | 588 } |
543 if (MaxVectorSize > 16 && UseAVX == 0) { | 589 if (MaxVectorSize > 16 && (UseAVX == 0 || !os_supports_avx_vectors())) { |
544 // Only supported with AVX+ | 590 // 32 bytes vectors (in YMM) are only supported with AVX+ |
545 FLAG_SET_DEFAULT(MaxVectorSize, 16); | 591 FLAG_SET_DEFAULT(MaxVectorSize, 16); |
546 } | 592 } |
547 if (UseSSE < 2) { | 593 if (UseSSE < 2) { |
548 // Only supported with SSE2+ | 594 // Vectors (in XMM) are only supported with SSE2+ |
549 FLAG_SET_DEFAULT(MaxVectorSize, 0); | 595 FLAG_SET_DEFAULT(MaxVectorSize, 0); |
550 } | 596 } |
597 #ifdef ASSERT | |
598 if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) { | |
599 tty->print_cr("State of YMM registers after signal handle:"); | |
600 int nreg = 2 LP64_ONLY(+2); | |
601 const char* ymm_name[4] = {"0", "7", "8", "15"}; | |
602 for (int i = 0; i < nreg; i++) { | |
603 tty->print("YMM%s:", ymm_name[i]); | |
604 for (int j = 7; j >=0; j--) { | |
605 tty->print(" %x", _cpuid_info.ymm_save[i*8 + j]); | |
606 } | |
607 tty->cr(); | |
608 } | |
609 } | |
610 #endif | |
551 } | 611 } |
552 #endif | 612 #endif |
553 | 613 |
554 // On new cpus instructions which update whole XMM register should be used | 614 // On new cpus instructions which update whole XMM register should be used |
555 // to prevent partial register stall due to dependencies on high half. | 615 // to prevent partial register stall due to dependencies on high half. |
676 UseSSE42Intrinsics = true; | 736 UseSSE42Intrinsics = true; |
677 } | 737 } |
678 } | 738 } |
679 } | 739 } |
680 } | 740 } |
681 #if defined(COMPILER2) && defined(_ALLBSD_SOURCE) | |
682 if (MaxVectorSize > 16) { | |
683 // Limit vectors size to 16 bytes on BSD until it fixes | |
684 // restoring upper 128bit of YMM registers on return | |
685 // from signal handler. | |
686 FLAG_SET_DEFAULT(MaxVectorSize, 16); | |
687 } | |
688 #endif // COMPILER2 | |
689 | 741 |
690 // Use count leading zeros count instruction if available. | 742 // Use count leading zeros count instruction if available. |
691 if (supports_lzcnt()) { | 743 if (supports_lzcnt()) { |
692 if (FLAG_IS_DEFAULT(UseCountLeadingZerosInstruction)) { | 744 if (FLAG_IS_DEFAULT(UseCountLeadingZerosInstruction)) { |
693 UseCountLeadingZerosInstruction = true; | 745 UseCountLeadingZerosInstruction = true; |
812 tty->print(" UseAVX=%d",UseAVX); | 864 tty->print(" UseAVX=%d",UseAVX); |
813 } | 865 } |
814 if (UseAES) { | 866 if (UseAES) { |
815 tty->print(" UseAES=1"); | 867 tty->print(" UseAES=1"); |
816 } | 868 } |
869 #ifdef COMPILER2 | |
870 if (MaxVectorSize > 0) { | |
871 tty->print(" MaxVectorSize=%d", MaxVectorSize); | |
872 } | |
873 #endif | |
817 tty->cr(); | 874 tty->cr(); |
818 tty->print("Allocation"); | 875 tty->print("Allocation"); |
819 if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) { | 876 if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) { |
820 tty->print_cr(": no prefetching"); | 877 tty->print_cr(": no prefetching"); |
821 } else { | 878 } else { |