--- old/src/cpu/ppc/vm/vm_version_ppc.cpp 2019-09-02 18:06:29.207474900 +0300 +++ new/src/cpu/ppc/vm/vm_version_ppc.cpp 2019-09-02 18:06:28.604306300 +0300 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2018 SAP AG. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019 SAP SE. 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 @@ -250,6 +250,71 @@ if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) { UseMontgomerySquareIntrinsic = true; } + + check_virtualizations(); +} + +void VM_Version::check_virtualizations() { +#if defined(_AIX) + int rc = 0; + perfstat_partition_total_t pinfo; + rc = perfstat_partition_total(NULL, &pinfo, sizeof(perfstat_partition_total_t), 1); + if (rc == 1) { + Abstract_VM_Version::_detected_virtualization = PowerVM; + } +#else + const char* info_file = "/proc/ppc64/lparcfg"; + // system_type=...qemu indicates PowerKVM + // e.g. system_type=IBM pSeries (emulated by qemu) + char line[500]; + FILE* fp = fopen(info_file, "r"); + if (fp == NULL) { + return; + } + const char* system_type="system_type="; // in case this line contains qemu, it is KVM + const char* num_lpars="NumLpars="; // in case of non-KVM : if this line is found it is PowerVM + bool num_lpars_found = false; + + while (fgets(line, sizeof(line), fp) != NULL) { + if (strncmp(line, system_type, strlen(system_type)) == 0) { + if (strstr(line, "qemu") != 0) { + Abstract_VM_Version::_detected_virtualization = PowerKVM; + fclose(fp); + return; + } + } + if (strncmp(line, num_lpars, strlen(num_lpars)) == 0) { + num_lpars_found = true; + } + } + if (num_lpars_found) { + Abstract_VM_Version::_detected_virtualization = PowerVM; + } else { + Abstract_VM_Version::_detected_virtualization = PowerFullPartitionMode; + } + fclose(fp); +#endif +} + +void VM_Version::print_platform_virtualization_info(outputStream* st) { + const char* info_file = "/proc/ppc64/lparcfg"; + const char* kw[] = { "system_type=", // qemu indicates PowerKVM + "partition_entitled_capacity=", // entitled processor capacity percentage + "partition_max_entitled_capacity=", + "capacity_weight=", // partition CPU weight + "partition_active_processors=", + "partition_potential_processors=", + "entitled_proc_capacity_available=", + "capped=", // 0 - uncapped, 1 - vcpus capped at entitled processor capacity percentage + "shared_processor_mode=", // (non)dedicated partition + "system_potential_processors=", + "pool=", // CPU-pool number + "pool_capacity=", + "NumLpars=", // on non-KVM machines, NumLpars is not found for full partition mode machines + NULL }; + if (!print_matching_lines_from_file(info_file, st, kw)) { + st->print_cr(" <%s Not Available>", info_file); + } } void VM_Version::print_features() { --- old/src/cpu/ppc/vm/vm_version_ppc.hpp 2019-09-02 18:06:33.900089300 +0300 +++ new/src/cpu/ppc/vm/vm_version_ppc.hpp 2019-09-02 18:06:33.287158600 +0300 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2018 SAP AG. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019 SAP SE. 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 @@ -83,6 +83,10 @@ public: // Initialization static void initialize(); + static void check_virtualizations(); + + // Override Abstract_VM_Version implementation + static void print_platform_virtualization_info(outputStream*); static bool is_determine_features_test_running() { return _is_determine_features_test_running; } // CPU instruction support --- old/src/cpu/x86/vm/vm_version_x86.cpp 2019-09-02 18:06:38.729342600 +0300 +++ new/src/cpu/x86/vm/vm_version_x86.cpp 2019-09-02 18:06:38.105681100 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, 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 @@ -1092,6 +1092,65 @@ #endif // !PRODUCT } +void VM_Version::print_platform_virtualization_info(outputStream* st) { + VirtualizationType vrt = VM_Version::get_detected_virtualization(); + if (vrt == XenHVM) { + st->print_cr("Xen hardware-assisted virtualization detected"); + } else if (vrt == KVM) { + st->print_cr("KVM virtualization detected"); + } else if (vrt == VMWare) { + st->print_cr("VMWare virtualization detected"); + } 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 @@ -1113,6 +1172,54 @@ return UseBiasedLocking; } +// On Xen, the cpuid instruction returns +// eax / registers[0]: Version of Xen +// ebx / registers[1]: chars 'XenV' +// ecx / registers[2]: chars 'MMXe' +// edx / registers[3]: chars 'nVMM' +// +// On KVM / VMWare / MS Hyper-V, the cpuid instruction returns +// ebx / registers[1]: chars 'KVMK' / 'VMwa' / 'Micr' +// ecx / registers[2]: chars 'VMKV' / 'reVM' / 'osof' +// edx / registers[3]: chars 'M' / 'ware' / 't Hv' +// +// 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; + } + + 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 @@ -1127,4 +1234,7 @@ g.generate_get_cpu_info()); get_processor_features(); + if (cpu_family() > 4) { // it supports CPUID + check_virtualizations(); + } } --- old/src/cpu/x86/vm/vm_version_x86.hpp 2019-09-02 18:06:43.650339600 +0300 +++ new/src/cpu/x86/vm/vm_version_x86.hpp 2019-09-02 18:06:42.995443700 +0300 @@ -533,6 +533,9 @@ static void initialize(); // Override Abstract_VM_Version implementation + static void print_platform_virtualization_info(outputStream*); + + // Override Abstract_VM_Version implementation static bool use_biased_locking(); // Asserts @@ -751,6 +754,11 @@ intx count = PrefetchFieldsAhead; return count >= 0 ? count : 1; } + + // support functions for virtualization detection +private: + static void check_virt_cpuid(uint32_t idx, uint32_t *regs); + static void check_virtualizations(); }; #endif // CPU_X86_VM_VM_VERSION_X86_HPP --- old/src/os/linux/vm/os_linux.cpp 2019-09-02 18:06:49.649819300 +0300 +++ new/src/os/linux/vm/os_linux.cpp 2019-09-02 18:06:48.829002900 +0300 @@ -59,6 +59,7 @@ #include "runtime/thread.inline.hpp" #include "runtime/threadCritical.hpp" #include "runtime/timer.hpp" +#include "runtime/vm_version.hpp" #include "services/attachListener.hpp" #include "services/memTracker.hpp" #include "services/runtimeService.hpp" @@ -2212,6 +2213,8 @@ os::Linux::print_full_memory_info(st); os::Linux::print_container_info(st); + + VM_Version::print_platform_virtualization_info(st); } // Try to identify popular distros. --- old/src/os/windows/vm/os_windows.cpp 2019-09-02 18:06:56.261254300 +0300 +++ new/src/os/windows/vm/os_windows.cpp 2019-09-02 18:06:55.571217600 +0300 @@ -1721,6 +1721,10 @@ st->print("OS:"); os::win32::print_windows_version(st); + +#ifdef _LP64 + VM_Version::print_platform_virtualization_info(st); +#endif } void os::win32::print_windows_version(outputStream* st) { --- old/src/share/vm/classfile/dictionary.hpp 2019-09-02 18:07:03.860346200 +0300 +++ new/src/share/vm/classfile/dictionary.hpp 2019-09-02 18:07:02.971207500 +0300 @@ -129,6 +129,7 @@ void reorder_dictionary(); ProtectionDomainCacheEntry* cache_get(oop protection_domain); + ProtectionDomainCacheTable* pd_cache_table() { return _pd_cache_table; } void print(bool details = true); void verify(); --- old/src/share/vm/classfile/symbolTable.cpp 2019-09-02 18:07:09.861775900 +0300 +++ new/src/share/vm/classfile/symbolTable.cpp 2019-09-02 18:07:09.156126700 +0300 @@ -482,6 +482,9 @@ return true; } +TableStatistics SymbolTable::get_table_statistics() { + return the_table()->statistics_calculate(); +} void SymbolTable::verify() { for (int i = 0; i < the_table()->table_size(); ++i) { @@ -926,6 +929,10 @@ } } +TableStatistics StringTable::get_table_statistics() { + return the_table()->statistics_calculate(); +} + // This verification is part of Universe::verify() and needs to be quick. // See StringTable::verify_and_compare() below for exhaustive verification. void StringTable::verify() { --- old/src/share/vm/classfile/symbolTable.hpp 2019-09-02 18:07:14.990663800 +0300 +++ new/src/share/vm/classfile/symbolTable.hpp 2019-09-02 18:07:14.355286800 +0300 @@ -139,6 +139,8 @@ // The symbol table static SymbolTable* the_table() { return _the_table; } + TableStatistics get_table_statistics(); + // Size of one bucket in the string table. Used when checking for rollover. static uint bucket_size() { return sizeof(HashtableBucket); } @@ -294,6 +296,7 @@ public: // The string table static StringTable* the_table() { return _the_table; } + TableStatistics get_table_statistics(); // Size of one bucket in the string table. Used when checking for rollover. static uint bucket_size() { return sizeof(HashtableBucket); } --- old/src/share/vm/classfile/systemDictionary.cpp 2019-09-02 18:07:19.994619700 +0300 +++ new/src/share/vm/classfile/systemDictionary.cpp 2019-09-02 18:07:19.320206100 +0300 @@ -2724,6 +2724,21 @@ constraints()->verify(dictionary(), placeholders()); } +TableStatistics SystemDictionary::placeholders_statistics() { + MutexLocker ml(SystemDictionary_lock); + return placeholders()->statistics_calculate(); +} + +TableStatistics SystemDictionary::loader_constraints_statistics() { + MutexLocker ml(SystemDictionary_lock); + return constraints()->statistics_calculate(); +} + +TableStatistics SystemDictionary::protection_domain_cache_statistics() { + MutexLocker ml(SystemDictionary_lock); + return dictionary()->pd_cache_table()->statistics_calculate(); +} + #ifndef PRODUCT // statistics code --- old/src/share/vm/classfile/systemDictionary.hpp 2019-09-02 18:07:25.126433900 +0300 +++ new/src/share/vm/classfile/systemDictionary.hpp 2019-09-02 18:07:24.525219200 +0300 @@ -709,6 +709,11 @@ static bool _has_loadClassInternal; static bool _has_checkPackageAccess; + +public: + static TableStatistics placeholders_statistics(); + static TableStatistics loader_constraints_statistics(); + static TableStatistics protection_domain_cache_statistics(); }; #endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_HPP --- old/src/share/vm/jfr/metadata/metadata.xml 2019-09-02 18:07:29.529179800 +0300 +++ new/src/share/vm/jfr/metadata/metadata.xml 2019-09-02 18:07:28.962118800 +0300 @@ -1,7 +1,7 @@