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 }
|