--- old/make/autoconf/libraries.m4 2020-08-05 18:24:46.436248721 +0900 +++ new/make/autoconf/libraries.m4 2020-08-05 18:24:46.358246281 +0900 @@ -130,7 +130,7 @@ if test "x$OPENJDK_TARGET_OS" = xwindows; then BASIC_JVM_LIBS="$BASIC_JVM_LIBS kernel32.lib user32.lib gdi32.lib winspool.lib \ comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib \ - wsock32.lib winmm.lib version.lib psapi.lib" + wsock32.lib winmm.lib version.lib psapi.lib wbemuuid.lib" fi JDKLIB_LIBS="$BASIC_JDKLIB_LIBS" --- old/src/hotspot/cpu/x86/vm_version_x86.cpp 2020-08-05 18:24:46.729257885 +0900 +++ new/src/hotspot/cpu/x86/vm_version_x86.cpp 2020-08-05 18:24:46.654255539 +0900 @@ -1667,53 +1667,58 @@ st->print_cr("VMWare virtualization detected"); VirtualizationSupport::print_virtualization_info(st); } else if (vrt == HyperV) { - st->print_cr("HyperV virtualization detected"); + st->print_cr("Hyper-V virtualization detected"); + } else if (vrt == HyperVRole) { + st->print_cr("Hyper-V role detected"); } } -void VM_Version::check_virt_cpuid(uint32_t idx, uint32_t *regs) { -// TODO support 32 bit -#if defined(_LP64) -#if defined(_MSC_VER) +void VM_Version::check_virt_cpuid(uint32_t *regs) { // 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; + void (*test)(uint32_t *regs) = (void(*)(uint32_t *regs))a->pc(); - a->movq(r9, rbx); // save nonvolatile register + // save nonvolatile register + a->push(rbx); +#ifdef _WINDOWS + a->push(rsi); // RSI is nonvolatile register for Windows +#endif + + // Copy 1st argument to SI +#ifdef _LP64 + a->movptr(rsi, c_rarg0); +#else + int ofs = 8; // return address + EBX +#ifdef _WINDOWS + ofs += 4; // ESI +#endif + a->movptr(rsi, Address(rsp, ofs)); +#endif + + a->movl(rax, 0x40000000); - // 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->movl(Address(rsi, 0), rax); + a->movl(Address(rsi, 4), rbx); + a->movl(Address(rsi, 8), rcx); + a->movl(Address(rsi, 12), rdx); + + // restore nonvolatile register +#ifdef _WINDOWS + a->pop(rsi); +#endif + a->pop(rbx); + 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 + test(regs); } @@ -1817,39 +1822,27 @@ // 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; - } + uint32_t registers[4] = {0}; + char signature[13] = {0}; - if (strncmp("KVMKVMKVM", signature, 9) == 0) { - Abstract_VM_Version::_detected_virtualization = KVM; - } + check_virt_cpuid(registers); + memcpy(signature, ®isters[1], 12); - if (strncmp("XenVMMXenVMM", signature, 12) == 0) { - Abstract_VM_Version::_detected_virtualization = XenHVM; - } - } + 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) { +#ifdef _WINDOWS + Abstract_VM_Version::_detected_virtualization = is_in_VM() ? HyperV : HyperVRole; +#else + Abstract_VM_Version::_detected_virtualization = HyperV; #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() { @@ -1869,7 +1862,7 @@ LP64_ONLY(Assembler::precompute_instructions();) - if (cpu_family() > 4) { // it supports CPUID + if (VM_Version::supports_hv()) { // Supports hypervisor check_virtualizations(); } } --- old/src/hotspot/cpu/x86/vm_version_x86.hpp 2020-08-05 18:24:47.025267143 +0900 +++ new/src/hotspot/cpu/x86/vm_version_x86.hpp 2020-08-05 18:24:46.950264797 +0900 @@ -89,7 +89,8 @@ : 1, osxsave : 1, avx : 1, - : 3; + : 2, + hv : 1; } bits; }; @@ -348,6 +349,7 @@ #define CPU_CLWB ((uint64_t)UCONST64( 0x80000000000)) // clwb instruction #define CPU_AVX512_VBMI2 ((uint64_t)UCONST64(0x100000000000)) // VBMI2 shift left double instructions #define CPU_AVX512_VBMI ((uint64_t)UCONST64(0x200000000000)) // Vector BMI instructions +#define CPU_HV_PRESENT ((uint64_t)UCONST64(0x400000000000)) // for hypervisor detection // NB! When adding new CPU feature detection consider updating vmStructs_x86.hpp, vmStructs_jvmci.hpp, and VM_Version::get_processor_features(). @@ -580,6 +582,8 @@ result |= CPU_AVX512_VBMI2; } } + if (_cpuid_info.std_cpuid1_ecx.bits.hv != 0) + result |= CPU_HV_PRESENT; if (_cpuid_info.sef_cpuid7_ebx.bits.bmi1 != 0) result |= CPU_BMI1; if (_cpuid_info.std_cpuid1_edx.bits.tsc != 0) @@ -871,6 +875,7 @@ static bool supports_avx512_vnni() { return (_features & CPU_AVX512_VNNI) != 0; } static bool supports_avx512_vbmi() { return (_features & CPU_AVX512_VBMI) != 0; } static bool supports_avx512_vbmi2() { return (_features & CPU_AVX512_VBMI2) != 0; } + static bool supports_hv() { return (_features & CPU_HV_PRESENT) != 0; } // Intel features static bool is_intel_family_core() { return is_intel() && @@ -1023,8 +1028,13 @@ // support functions for virtualization detection private: - static void check_virt_cpuid(uint32_t idx, uint32_t *regs); + static void check_virt_cpuid(uint32_t *regs); static void check_virtualizations(); + +#ifdef _WINDOWS + static bool is_in_VM(); +#endif + }; #endif // CPU_X86_VM_VERSION_X86_HPP --- old/src/hotspot/os/windows/os_windows.cpp 2020-08-05 18:24:47.318276308 +0900 +++ new/src/hotspot/os/windows/os_windows.cpp 2020-08-05 18:24:47.242273931 +0900 @@ -1609,9 +1609,7 @@ os::win32::print_uptime_info(st); -#ifdef _LP64 VM_Version::print_platform_virtualization_info(st); -#endif } void os::win32::print_windows_version(outputStream* st) { --- old/src/hotspot/os_cpu/windows_x86/vm_version_windows_x86.cpp 2020-08-05 18:24:47.633286160 +0900 +++ new/src/hotspot/os_cpu/windows_x86/vm_version_windows_x86.cpp 2020-08-05 18:24:47.557283783 +0900 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,3 +26,94 @@ #include "runtime/os.hpp" #include "runtime/vm_version.hpp" +#include +#include + +#define VM_MODEL L"Virtual Machine" + + +bool VM_Version::is_in_VM() { + HRESULT hres; + + hres = CoInitializeEx(0, COINIT_MULTITHREADED); + if (hres != S_OK) { + return false; + } + + hres = CoInitializeSecurity(NULL, -1, NULL, NULL, + RPC_C_AUTHN_LEVEL_DEFAULT, + RPC_C_IMP_LEVEL_IMPERSONATE, + NULL, EOAC_NONE, NULL); + if (hres != S_OK) { + CoUninitialize(); + return false; + } + + IWbemLocator* pLoc = NULL; + hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, + IID_IWbemLocator, (LPVOID*)&pLoc); + if (hres != S_OK) { + CoUninitialize(); + return false; + } + + IWbemServices* pSvc = NULL; + BSTR resource = SysAllocString(L"ROOT\\CIMV2"); + hres = pLoc->ConnectServer(resource, + NULL, NULL, 0, NULL, 0, 0, &pSvc); + SysFreeString(resource); + if (hres != S_OK) { + pLoc->Release(); + CoUninitialize(); + return false; + } + + hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, + NULL, RPC_C_AUTHN_LEVEL_CALL, + RPC_C_IMP_LEVEL_IMPERSONATE, + NULL, EOAC_NONE); + if (hres != S_OK) { + pSvc->Release(); + pLoc->Release(); + CoUninitialize(); + return false; + } + + IEnumWbemClassObject* pEnumerator = NULL; + BSTR lang = SysAllocString(L"WQL"); + BSTR query = SysAllocString(L"SELECT Model FROM Win32_ComputerSystem"); + hres = pSvc->ExecQuery(lang, query, + WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, + NULL, &pEnumerator); + SysFreeString(lang); + SysFreeString(query); + if (hres != S_OK) { + pSvc->Release(); + pLoc->Release(); + CoUninitialize(); + return false; + } + + bool result = false; + IWbemClassObject* pclsObj = NULL; + ULONG uReturn = 0; + hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); + if (uReturn != 0) { + VARIANT vtProp; + hres = pclsObj->Get(L"Model", 0, &vtProp, 0, 0); + if (hres == S_OK) { + if (wcscmp(VM_MODEL, vtProp.bstrVal) == 0) { + result = true; + } + VariantClear(&vtProp); + } + pclsObj->Release(); + } + + pSvc->Release(); + pLoc->Release(); + pEnumerator->Release(); + CoUninitialize(); + + return result; +} --- old/src/hotspot/share/jfr/periodic/jfrOSInterface.cpp 2020-08-05 18:24:47.919295106 +0900 +++ new/src/hotspot/share/jfr/periodic/jfrOSInterface.cpp 2020-08-05 18:24:47.844292760 +0900 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -265,7 +265,9 @@ } else if (vrt == VMWare) { return "VMWare virtualization"; } else if (vrt == HyperV) { - return "HyperV virtualization"; + return "Hyper-V virtualization"; + } else if (vrt == HyperVRole) { + return "Hyper-V role"; } else if (vrt == PowerVM) { return "PowerVM virtualization"; } else if (vrt == PowerKVM) { --- old/src/hotspot/share/runtime/abstract_vm_version.hpp 2020-08-05 18:24:48.207304114 +0900 +++ new/src/hotspot/share/runtime/abstract_vm_version.hpp 2020-08-05 18:24:48.132301768 +0900 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ KVM, VMWare, HyperV, + HyperVRole, PowerVM, // on AIX or Linux ppc64(le) PowerFullPartitionMode, // on Linux ppc64(le) PowerKVM