< prev index next >

src/hotspot/cpu/x86/vm_version_x86.cpp

Print this page

        

*** 48,63 **** address VM_Version::_cpuinfo_segv_addr = 0; // Address of instruction after the one which causes SEGV address VM_Version::_cpuinfo_cont_addr = 0; static BufferBlob* stub_blob; ! static const int stub_size = 1100; extern "C" { typedef void (*get_cpu_info_stub_t)(void*); } static get_cpu_info_stub_t get_cpu_info_stub = NULL; class VM_Version_StubGenerator: public StubCodeGenerator { public: --- 48,65 ---- address VM_Version::_cpuinfo_segv_addr = 0; // Address of instruction after the one which causes SEGV address VM_Version::_cpuinfo_cont_addr = 0; static BufferBlob* stub_blob; ! static const int stub_size = 2000; extern "C" { typedef void (*get_cpu_info_stub_t)(void*); + typedef void (*detect_virt_stub_t)(uint32_t, uint32_t*); } static get_cpu_info_stub_t get_cpu_info_stub = NULL; + static detect_virt_stub_t detect_virt_stub = NULL; class VM_Version_StubGenerator: public StubCodeGenerator { public:
*** 566,575 **** --- 568,613 ---- // can't compute until after we've determined CPU capabilities. Use // uncached variant here directly to be able to bootstrap correctly __ vzeroupper_uncached(); # undef __ } + address generate_detect_virt() { + StubCodeMark mark(this, "VM_Version", "detect_virt_stub"); + # define __ _masm-> + + address start = __ pc(); + + // Evacuate callee-saved registers + __ push(rbp); + __ push(rbx); + __ push(rsi); // for Windows + #ifdef _LP64 + __ mov(rax, c_rarg0); // CPUID leaf + __ mov(rsi, c_rarg1); // register array address (eax, ebx, ecx, edx) + #else + __ movptr(rax, Address(rsp, 16)); // CPUID leaf + __ movptr(rsi, Address(rsp, 20)); // register array address + #endif + + __ cpuid(); + + // Store result to register array + __ movl(Address(rsi, 0), rax); + __ movl(Address(rsi, 4), rbx); + __ movl(Address(rsi, 8), rcx); + __ movl(Address(rsi, 12), rdx); + + // Epilogue + __ pop(rsi); + __ pop(rbx); + __ pop(rbp); + __ ret(0); + + # undef __ + + return start; + }; }; void VM_Version::get_processor_features() { _cpu = 4; // 486 by default
*** 1669,1728 **** st->print_cr("KVM virtualization detected"); } else if (vrt == VMWare) { st->print_cr("VMWare virtualization detected"); VirtualizationSupport::print_virtualization_info(st); } else if (vrt == HyperV) { ! st->print_cr("HyperV virtualization detected"); } } - void VM_Version::check_virt_cpuid(uint32_t idx, uint32_t *regs) { - // TODO support 32 bit - #if defined(_LP64) - #if defined(_MSC_VER) - // Allocate space for the code - const int code_size = 100; - ResourceMark rm; - CodeBuffer cb("detect_virt", code_size, 0); - MacroAssembler* a = new MacroAssembler(&cb); - address code = a->pc(); - void (*test)(uint32_t idx, uint32_t *regs) = (void(*)(uint32_t idx, uint32_t *regs))code; - - a->movq(r9, rbx); // save nonvolatile register - - // next line would not work on 32-bit - a->movq(rax, c_rarg0 /* rcx */); - a->movq(r8, c_rarg1 /* rdx */); - a->cpuid(); - a->movl(Address(r8, 0), rax); - a->movl(Address(r8, 4), rbx); - a->movl(Address(r8, 8), rcx); - a->movl(Address(r8, 12), rdx); - - a->movq(rbx, r9); // restore nonvolatile register - a->ret(0); - - uint32_t *code_end = (uint32_t *)a->pc(); - a->flush(); - - // execute code - (*test)(idx, regs); - #elif defined(__GNUC__) - __asm__ volatile ( - " cpuid;" - " mov %%eax,(%1);" - " mov %%ebx,4(%1);" - " mov %%ecx,8(%1);" - " mov %%edx,12(%1);" - : "+a" (idx) - : "S" (regs) - : "ebx", "ecx", "edx", "memory" ); - #endif - #endif - } - - bool VM_Version::use_biased_locking() { #if INCLUDE_RTM_OPT // RTM locking is most useful when there is high lock contention and // low data contention. With high lock contention the lock is usually // inflated and biased locking is not suitable for that case. --- 1707,1722 ---- st->print_cr("KVM virtualization detected"); } else if (vrt == VMWare) { st->print_cr("VMWare virtualization detected"); VirtualizationSupport::print_virtualization_info(st); } else if (vrt == HyperV) { ! st->print_cr("Hyper-V virtualization detected"); ! } else if (vrt == HyperVRole) { ! st->print_cr("Hyper-V role detected"); } } bool VM_Version::use_biased_locking() { #if INCLUDE_RTM_OPT // RTM locking is most useful when there is high lock contention and // low data contention. With high lock contention the lock is usually // inflated and biased locking is not suitable for that case.
*** 1819,1879 **** // // more information : // https://kb.vmware.com/s/article/1009458 // void VM_Version::check_virtualizations() { ! #if defined(_LP64) ! uint32_t registers[4]; ! char signature[13]; ! uint32_t base; ! signature[12] = '\0'; ! memset((void*)registers, 0, 4*sizeof(uint32_t)); ! ! for (base = 0x40000000; base < 0x40010000; base += 0x100) { ! check_virt_cpuid(base, registers); ! ! *(uint32_t *)(signature + 0) = registers[1]; ! *(uint32_t *)(signature + 4) = registers[2]; ! *(uint32_t *)(signature + 8) = registers[3]; if (strncmp("VMwareVMware", signature, 12) == 0) { Abstract_VM_Version::_detected_virtualization = VMWare; // check for extended metrics from guestlib VirtualizationSupport::initialize(); ! } ! ! if (strncmp("Microsoft Hv", signature, 12) == 0) { Abstract_VM_Version::_detected_virtualization = HyperV; } ! ! if (strncmp("KVMKVMKVM", signature, 9) == 0) { Abstract_VM_Version::_detected_virtualization = KVM; ! } ! ! if (strncmp("XenVMMXenVMM", signature, 12) == 0) { Abstract_VM_Version::_detected_virtualization = XenHVM; } } - #endif } void VM_Version::initialize() { ResourceMark rm; // Making this stub must be FIRST use of assembler ! ! stub_blob = BufferBlob::create("get_cpu_info_stub", stub_size); if (stub_blob == NULL) { ! vm_exit_during_initialization("Unable to allocate get_cpu_info_stub"); } CodeBuffer c(stub_blob); VM_Version_StubGenerator g(&c); get_cpu_info_stub = CAST_TO_FN_PTR(get_cpu_info_stub_t, g.generate_get_cpu_info()); get_processor_features(); LP64_ONLY(Assembler::precompute_instructions();) ! if (cpu_family() > 4) { // it supports CPUID check_virtualizations(); } } --- 1813,1875 ---- // // more information : // https://kb.vmware.com/s/article/1009458 // void VM_Version::check_virtualizations() { ! uint32_t registers[4] = {0}; ! char signature[13] = {0}; ! ! // In case of Xen, it might be appear until 0x40010000. ! // https://lists.linuxfoundation.org/pipermail/virtualization/2012-May/019974.html ! for (int leaf = 0x40000000; leaf < 0x40010000; leaf += 0x100) { ! detect_virt_stub(leaf, registers); ! memcpy(signature, &registers[1], 12); if (strncmp("VMwareVMware", signature, 12) == 0) { Abstract_VM_Version::_detected_virtualization = VMWare; // check for extended metrics from guestlib VirtualizationSupport::initialize(); ! } else if (strncmp("Microsoft Hv", signature, 12) == 0) { Abstract_VM_Version::_detected_virtualization = HyperV; + #ifdef _WINDOWS + // CPUID leaf 0x40000007 is available to the root partition only. + // See Hypervisor Top Level Functional Specification section 2.4.8 for more details. + // https://github.com/MicrosoftDocs/Virtualization-Documentation/raw/master/tlfs/Hypervisor%20Top%20Level%20Functional%20Specification%20v6.0b.pdf + detect_virt_stub(0x40000007, registers); + if ((registers[0] != 0x0) || + (registers[1] != 0x0) || + (registers[2] != 0x0) || + (registers[3] != 0x0)) { + Abstract_VM_Version::_detected_virtualization = HyperVRole; } ! #endif ! } else if (strncmp("KVMKVMKVM", signature, 9) == 0) { Abstract_VM_Version::_detected_virtualization = KVM; ! } else if (strncmp("XenVMMXenVMM", signature, 12) == 0) { Abstract_VM_Version::_detected_virtualization = XenHVM; } } } void VM_Version::initialize() { ResourceMark rm; // Making this stub must be FIRST use of assembler ! stub_blob = BufferBlob::create("VM_Version stub", stub_size); if (stub_blob == NULL) { ! vm_exit_during_initialization("Unable to allocate stub for VM_Version"); } CodeBuffer c(stub_blob); VM_Version_StubGenerator g(&c); + get_cpu_info_stub = CAST_TO_FN_PTR(get_cpu_info_stub_t, g.generate_get_cpu_info()); + detect_virt_stub = CAST_TO_FN_PTR(detect_virt_stub_t, + g.generate_detect_virt()); get_processor_features(); LP64_ONLY(Assembler::precompute_instructions();) ! if (VM_Version::supports_hv()) { // Supports hypervisor check_virtualizations(); } }
< prev index next >