src/cpu/x86/vm/vm_version_x86.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File 8038633 Sdiff src/cpu/x86/vm

src/cpu/x86/vm/vm_version_x86.cpp

Print this page
rev 6204 : 8038633: crash in VM_Version::get_processor_features() on startup
Summary: Windows need an exception wrapper around getPsrInfo_stub() call in order to properly handle SEGV for YMM registers test.
Reviewed-by: iveresov, iignatyev


  42 # include "os_bsd.inline.hpp"
  43 #endif
  44 
  45 
  46 int VM_Version::_cpu;
  47 int VM_Version::_model;
  48 int VM_Version::_stepping;
  49 int VM_Version::_cpuFeatures;
  50 const char*           VM_Version::_features_str = "";
  51 VM_Version::CpuidInfo VM_Version::_cpuid_info   = { 0, };
  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 
  58 static BufferBlob* stub_blob;
  59 static const int stub_size = 600;
  60 
  61 extern "C" {
  62   typedef void (*getPsrInfo_stub_t)(void*);
  63 }
  64 static getPsrInfo_stub_t getPsrInfo_stub = NULL;
  65 
  66 
  67 class VM_Version_StubGenerator: public StubCodeGenerator {
  68  public:
  69 
  70   VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
  71 
  72   address generate_getPsrInfo() {
  73     // Flags to test CPU type.
  74     const uint32_t HS_EFL_AC           = 0x40000;
  75     const uint32_t HS_EFL_ID           = 0x200000;
  76     // Values for when we don't have a CPUID instruction.
  77     const int      CPU_FAMILY_SHIFT = 8;
  78     const uint32_t CPU_FAMILY_386   = (3 << CPU_FAMILY_SHIFT);
  79     const uint32_t CPU_FAMILY_486   = (4 << CPU_FAMILY_SHIFT);
  80 
  81     Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4;
  82     Label sef_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7, done;
  83 
  84     StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub");
  85 #   define __ _masm->
  86 
  87     address start = __ pc();
  88 
  89     //
  90     // void getPsrInfo(VM_Version::CpuidInfo* cpuid_info);
  91     //
  92     // LP64: rcx and rdx are first and second argument registers on windows
  93 
  94     __ push(rbp);
  95 #ifdef _LP64
  96     __ mov(rbp, c_rarg0); // cpuid_info address
  97 #else
  98     __ movptr(rbp, Address(rsp, 8)); // cpuid_info address
  99 #endif
 100     __ push(rbx);
 101     __ push(rsi);
 102     __ pushf();          // preserve rbx, and flags
 103     __ pop(rax);
 104     __ push(rax);
 105     __ mov(rcx, rax);
 106     //
 107     // if we are unable to change the AC flag, we have a 386
 108     //
 109     __ xorl(rax, HS_EFL_AC);
 110     __ push(rax);


 368     __ movl(Address(rsi, 8), rcx);
 369     __ movl(Address(rsi,12), rdx);
 370 
 371     //
 372     // return
 373     //
 374     __ bind(done);
 375     __ popf();
 376     __ pop(rsi);
 377     __ pop(rbx);
 378     __ pop(rbp);
 379     __ ret(0);
 380 
 381 #   undef __
 382 
 383     return start;
 384   };
 385 };
 386 
 387 








 388 void VM_Version::get_processor_features() {
 389 
 390   _cpu = 4; // 486 by default
 391   _model = 0;
 392   _stepping = 0;
 393   _cpuFeatures = 0;
 394   _logical_processors_per_package = 1;
 395 
 396   if (!Use486InstrsOnly) {
 397     // Get raw processor info
 398     getPsrInfo_stub(&_cpuid_info);




 399     assert_is_initialized();
 400     _cpu = extended_cpu_family();
 401     _model = extended_cpu_model();
 402     _stepping = cpu_stepping();
 403 
 404     if (cpu_family() > 4) { // it supports CPUID
 405       _cpuFeatures = feature_flags();
 406       // Logical processors are only available on P4s and above,
 407       // and only if hyperthreading is available.
 408       _logical_processors_per_package = logical_processor_count();
 409     }
 410   }
 411 
 412   _supports_cx8 = supports_cmpxchg8();
 413   // xchg and xadd instructions
 414   _supports_atomic_getset4 = true;
 415   _supports_atomic_getadd4 = true;
 416   LP64_ONLY(_supports_atomic_getset8 = true);
 417   LP64_ONLY(_supports_atomic_getadd8 = true);
 418 


 969   // RTM locking code requires that biased locking is off.
 970   // Note: we can't switch off UseBiasedLocking in get_processor_features()
 971   // because it is used by Thread::allocate() which is called before
 972   // VM_Version::initialize().
 973   if (UseRTMLocking && UseBiasedLocking) {
 974     if (FLAG_IS_DEFAULT(UseBiasedLocking)) {
 975       FLAG_SET_DEFAULT(UseBiasedLocking, false);
 976     } else {
 977       warning("Biased locking is not supported with RTM locking; ignoring UseBiasedLocking flag." );
 978       UseBiasedLocking = false;
 979     }
 980   }
 981 #endif
 982   return UseBiasedLocking;
 983 }
 984 
 985 void VM_Version::initialize() {
 986   ResourceMark rm;
 987   // Making this stub must be FIRST use of assembler
 988 
 989   stub_blob = BufferBlob::create("getPsrInfo_stub", stub_size);
 990   if (stub_blob == NULL) {
 991     vm_exit_during_initialization("Unable to allocate getPsrInfo_stub");
 992   }
 993   CodeBuffer c(stub_blob);
 994   VM_Version_StubGenerator g(&c);
 995   getPsrInfo_stub = CAST_TO_FN_PTR(getPsrInfo_stub_t,
 996                                    g.generate_getPsrInfo());
 997 
 998   get_processor_features();
 999 }


  42 # include "os_bsd.inline.hpp"
  43 #endif
  44 
  45 
  46 int VM_Version::_cpu;
  47 int VM_Version::_model;
  48 int VM_Version::_stepping;
  49 int VM_Version::_cpuFeatures;
  50 const char*           VM_Version::_features_str = "";
  51 VM_Version::CpuidInfo VM_Version::_cpuid_info   = { 0, };
  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 
  58 static BufferBlob* stub_blob;
  59 static const int stub_size = 600;
  60 
  61 extern "C" {
  62   typedef void (*get_cpu_info_stub_t)(void*);
  63 }
  64 static get_cpu_info_stub_t get_cpu_info_stub = NULL;
  65 
  66 
  67 class VM_Version_StubGenerator: public StubCodeGenerator {
  68  public:
  69 
  70   VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
  71 
  72   address generate_get_cpu_info() {
  73     // Flags to test CPU type.
  74     const uint32_t HS_EFL_AC           = 0x40000;
  75     const uint32_t HS_EFL_ID           = 0x200000;
  76     // Values for when we don't have a CPUID instruction.
  77     const int      CPU_FAMILY_SHIFT = 8;
  78     const uint32_t CPU_FAMILY_386   = (3 << CPU_FAMILY_SHIFT);
  79     const uint32_t CPU_FAMILY_486   = (4 << CPU_FAMILY_SHIFT);
  80 
  81     Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4;
  82     Label sef_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7, done;
  83 
  84     StubCodeMark mark(this, "VM_Version", "get_cpu_info_stub");
  85 #   define __ _masm->
  86 
  87     address start = __ pc();
  88 
  89     //
  90     // void get_cpu_info(VM_Version::CpuidInfo* cpuid_info);
  91     //
  92     // LP64: rcx and rdx are first and second argument registers on windows
  93 
  94     __ push(rbp);
  95 #ifdef _LP64
  96     __ mov(rbp, c_rarg0); // cpuid_info address
  97 #else
  98     __ movptr(rbp, Address(rsp, 8)); // cpuid_info address
  99 #endif
 100     __ push(rbx);
 101     __ push(rsi);
 102     __ pushf();          // preserve rbx, and flags
 103     __ pop(rax);
 104     __ push(rax);
 105     __ mov(rcx, rax);
 106     //
 107     // if we are unable to change the AC flag, we have a 386
 108     //
 109     __ xorl(rax, HS_EFL_AC);
 110     __ push(rax);


 368     __ movl(Address(rsi, 8), rcx);
 369     __ movl(Address(rsi,12), rdx);
 370 
 371     //
 372     // return
 373     //
 374     __ bind(done);
 375     __ popf();
 376     __ pop(rsi);
 377     __ pop(rbx);
 378     __ pop(rbp);
 379     __ ret(0);
 380 
 381 #   undef __
 382 
 383     return start;
 384   };
 385 };
 386 
 387 
 388 void VM_Version::get_cpu_info_wrapper() {
 389   get_cpu_info_stub(&_cpuid_info);
 390 }
 391 
 392 #ifndef CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED
 393   #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) f()
 394 #endif
 395 
 396 void VM_Version::get_processor_features() {
 397 
 398   _cpu = 4; // 486 by default
 399   _model = 0;
 400   _stepping = 0;
 401   _cpuFeatures = 0;
 402   _logical_processors_per_package = 1;
 403 
 404   if (!Use486InstrsOnly) {
 405     // Get raw processor info
 406 
 407     // Some platforms (like Win*) need a wrapper around here
 408     // in order to properly handle SEGV for YMM registers test.
 409     CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(get_cpu_info_wrapper);
 410 
 411     assert_is_initialized();
 412     _cpu = extended_cpu_family();
 413     _model = extended_cpu_model();
 414     _stepping = cpu_stepping();
 415 
 416     if (cpu_family() > 4) { // it supports CPUID
 417       _cpuFeatures = feature_flags();
 418       // Logical processors are only available on P4s and above,
 419       // and only if hyperthreading is available.
 420       _logical_processors_per_package = logical_processor_count();
 421     }
 422   }
 423 
 424   _supports_cx8 = supports_cmpxchg8();
 425   // xchg and xadd instructions
 426   _supports_atomic_getset4 = true;
 427   _supports_atomic_getadd4 = true;
 428   LP64_ONLY(_supports_atomic_getset8 = true);
 429   LP64_ONLY(_supports_atomic_getadd8 = true);
 430 


 981   // RTM locking code requires that biased locking is off.
 982   // Note: we can't switch off UseBiasedLocking in get_processor_features()
 983   // because it is used by Thread::allocate() which is called before
 984   // VM_Version::initialize().
 985   if (UseRTMLocking && UseBiasedLocking) {
 986     if (FLAG_IS_DEFAULT(UseBiasedLocking)) {
 987       FLAG_SET_DEFAULT(UseBiasedLocking, false);
 988     } else {
 989       warning("Biased locking is not supported with RTM locking; ignoring UseBiasedLocking flag." );
 990       UseBiasedLocking = false;
 991     }
 992   }
 993 #endif
 994   return UseBiasedLocking;
 995 }
 996 
 997 void VM_Version::initialize() {
 998   ResourceMark rm;
 999   // Making this stub must be FIRST use of assembler
1000 
1001   stub_blob = BufferBlob::create("get_cpu_info_stub", stub_size);
1002   if (stub_blob == NULL) {
1003     vm_exit_during_initialization("Unable to allocate get_cpu_info_stub");
1004   }
1005   CodeBuffer c(stub_blob);
1006   VM_Version_StubGenerator g(&c);
1007   get_cpu_info_stub = CAST_TO_FN_PTR(get_cpu_info_stub_t,
1008                                      g.generate_get_cpu_info());
1009 
1010   get_processor_features();
1011 }
src/cpu/x86/vm/vm_version_x86.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File