src/cpu/x86/vm/vm_version_x86.cpp

changeset 6388
98af1e198e73
parent 6378
8a8ff6b577ed
child 6429
606acabe7b5c
     1.1 --- a/src/cpu/x86/vm/vm_version_x86.cpp	Mon Mar 17 13:42:16 2014 +0100
     1.2 +++ b/src/cpu/x86/vm/vm_version_x86.cpp	Fri Mar 14 17:28:58 2014 -0700
     1.3 @@ -50,8 +50,13 @@
     1.4  const char*           VM_Version::_features_str = "";
     1.5  VM_Version::CpuidInfo VM_Version::_cpuid_info   = { 0, };
     1.6  
     1.7 +// Address of instruction which causes SEGV
     1.8 +address VM_Version::_cpuinfo_segv_addr = 0;
     1.9 +// Address of instruction after the one which causes SEGV
    1.10 +address VM_Version::_cpuinfo_cont_addr = 0;
    1.11 +
    1.12  static BufferBlob* stub_blob;
    1.13 -static const int stub_size = 550;
    1.14 +static const int stub_size = 600;
    1.15  
    1.16  extern "C" {
    1.17    typedef void (*getPsrInfo_stub_t)(void*);
    1.18 @@ -234,9 +239,9 @@
    1.19      // Check if OS has enabled XGETBV instruction to access XCR0
    1.20      // (OSXSAVE feature flag) and CPU supports AVX
    1.21      //
    1.22 -    __ andl(rcx, 0x18000000);
    1.23 +    __ andl(rcx, 0x18000000); // cpuid1 bits osxsave | avx
    1.24      __ cmpl(rcx, 0x18000000);
    1.25 -    __ jccb(Assembler::notEqual, sef_cpuid);
    1.26 +    __ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported
    1.27  
    1.28      //
    1.29      // XCR0, XFEATURE_ENABLED_MASK register
    1.30 @@ -247,6 +252,47 @@
    1.31      __ movl(Address(rsi, 0), rax);
    1.32      __ movl(Address(rsi, 4), rdx);
    1.33  
    1.34 +    __ andl(rax, 0x6); // xcr0 bits sse | ymm
    1.35 +    __ cmpl(rax, 0x6);
    1.36 +    __ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported
    1.37 +
    1.38 +    //
    1.39 +    // Some OSs have a bug when upper 128bits of YMM
    1.40 +    // registers are not restored after a signal processing.
    1.41 +    // Generate SEGV here (reference through NULL)
    1.42 +    // and check upper YMM bits after it.
    1.43 +    //
    1.44 +    VM_Version::set_avx_cpuFeatures(); // Enable temporary to pass asserts
    1.45 +
    1.46 +    // load value into all 32 bytes of ymm7 register
    1.47 +    __ movl(rcx, VM_Version::ymm_test_value());
    1.48 +
    1.49 +    __ movdl(xmm0, rcx);
    1.50 +    __ pshufd(xmm0, xmm0, 0x00);
    1.51 +    __ vinsertf128h(xmm0, xmm0, xmm0);
    1.52 +    __ vmovdqu(xmm7, xmm0);
    1.53 +#ifdef _LP64
    1.54 +    __ vmovdqu(xmm8,  xmm0);
    1.55 +    __ vmovdqu(xmm15, xmm0);
    1.56 +#endif
    1.57 +
    1.58 +    __ xorl(rsi, rsi);
    1.59 +    VM_Version::set_cpuinfo_segv_addr( __ pc() );
    1.60 +    // Generate SEGV
    1.61 +    __ movl(rax, Address(rsi, 0));
    1.62 +
    1.63 +    VM_Version::set_cpuinfo_cont_addr( __ pc() );
    1.64 +    // Returns here after signal. Save xmm0 to check it later.
    1.65 +    __ lea(rsi, Address(rbp, in_bytes(VM_Version::ymm_save_offset())));
    1.66 +    __ vmovdqu(Address(rsi,  0), xmm0);
    1.67 +    __ vmovdqu(Address(rsi, 32), xmm7);
    1.68 +#ifdef _LP64
    1.69 +    __ vmovdqu(Address(rsi, 64), xmm8);
    1.70 +    __ vmovdqu(Address(rsi, 96), xmm15);
    1.71 +#endif
    1.72 +
    1.73 +    VM_Version::clean_cpuFeatures();
    1.74 +
    1.75      //
    1.76      // cpuid(0x7) Structured Extended Features
    1.77      //
    1.78 @@ -540,14 +586,28 @@
    1.79      if (MaxVectorSize > 32) {
    1.80        FLAG_SET_DEFAULT(MaxVectorSize, 32);
    1.81      }
    1.82 -    if (MaxVectorSize > 16 && UseAVX == 0) {
    1.83 -      // Only supported with AVX+
    1.84 +    if (MaxVectorSize > 16 && (UseAVX == 0 || !os_supports_avx_vectors())) {
    1.85 +      // 32 bytes vectors (in YMM) are only supported with AVX+
    1.86        FLAG_SET_DEFAULT(MaxVectorSize, 16);
    1.87      }
    1.88      if (UseSSE < 2) {
    1.89 -      // Only supported with SSE2+
    1.90 +      // Vectors (in XMM) are only supported with SSE2+
    1.91        FLAG_SET_DEFAULT(MaxVectorSize, 0);
    1.92      }
    1.93 +#ifdef ASSERT
    1.94 +    if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) {
    1.95 +      tty->print_cr("State of YMM registers after signal handle:");
    1.96 +      int nreg = 2 LP64_ONLY(+2);
    1.97 +      const char* ymm_name[4] = {"0", "7", "8", "15"};
    1.98 +      for (int i = 0; i < nreg; i++) {
    1.99 +        tty->print("YMM%s:", ymm_name[i]);
   1.100 +        for (int j = 7; j >=0; j--) {
   1.101 +          tty->print(" %x", _cpuid_info.ymm_save[i*8 + j]);
   1.102 +        }
   1.103 +        tty->cr();
   1.104 +      }
   1.105 +    }
   1.106 +#endif
   1.107    }
   1.108  #endif
   1.109  
   1.110 @@ -678,14 +738,6 @@
   1.111        }
   1.112      }
   1.113    }
   1.114 -#if defined(COMPILER2) && defined(_ALLBSD_SOURCE)
   1.115 -    if (MaxVectorSize > 16) {
   1.116 -      // Limit vectors size to 16 bytes on BSD until it fixes
   1.117 -      // restoring upper 128bit of YMM registers on return
   1.118 -      // from signal handler.
   1.119 -      FLAG_SET_DEFAULT(MaxVectorSize, 16);
   1.120 -    }
   1.121 -#endif // COMPILER2
   1.122  
   1.123    // Use count leading zeros count instruction if available.
   1.124    if (supports_lzcnt()) {
   1.125 @@ -814,6 +866,11 @@
   1.126      if (UseAES) {
   1.127        tty->print("  UseAES=1");
   1.128      }
   1.129 +#ifdef COMPILER2
   1.130 +    if (MaxVectorSize > 0) {
   1.131 +      tty->print("  MaxVectorSize=%d", MaxVectorSize);
   1.132 +    }
   1.133 +#endif
   1.134      tty->cr();
   1.135      tty->print("Allocation");
   1.136      if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) {

mercurial