src/cpu/x86/vm/vm_version_ext_x86.cpp

Sat, 07 Nov 2020 10:30:02 +0800

author
aoqi
date
Sat, 07 Nov 2020 10:30:02 +0800
changeset 10026
8c95980d0b66
parent 9858
b985cbb00e68
permissions
-rw-r--r--

Added tag mips-jdk8u275-b01 for changeset d3b4d62f391f

     1 /*
     2  * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "precompiled.hpp"
    26 #include "jvm.h"
    27 #include "utilities/macros.hpp"
    28 #include "asm/macroAssembler.hpp"
    29 #include "asm/macroAssembler.inline.hpp"
    30 #include "memory/allocation.inline.hpp"
    31 #include "memory/resourceArea.hpp"
    32 #include "runtime/java.hpp"
    33 #include "runtime/stubCodeGenerator.hpp"
    34 #include "vm_version_ext_x86.hpp"
    36 typedef enum {
    37    CPU_FAMILY_8086_8088  = 0,
    38    CPU_FAMILY_INTEL_286  = 2,
    39    CPU_FAMILY_INTEL_386  = 3,
    40    CPU_FAMILY_INTEL_486  = 4,
    41    CPU_FAMILY_PENTIUM    = 5,
    42    CPU_FAMILY_PENTIUMPRO = 6,    // Same family several models
    43    CPU_FAMILY_PENTIUM_4  = 0xF
    44 } FamilyFlag;
    46  typedef enum {
    47     RDTSCP_FLAG  = 0x08000000, // bit 27
    48     INTEL64_FLAG = 0x20000000  // bit 29
    49   } _featureExtendedEdxFlag;
    51 #define CPUID_STANDARD_FN   0x0
    52 #define CPUID_STANDARD_FN_1 0x1
    53 #define CPUID_STANDARD_FN_4 0x4
    54 #define CPUID_STANDARD_FN_B 0xb
    56 #define CPUID_EXTENDED_FN   0x80000000
    57 #define CPUID_EXTENDED_FN_1 0x80000001
    58 #define CPUID_EXTENDED_FN_2 0x80000002
    59 #define CPUID_EXTENDED_FN_3 0x80000003
    60 #define CPUID_EXTENDED_FN_4 0x80000004
    61 #define CPUID_EXTENDED_FN_7 0x80000007
    62 #define CPUID_EXTENDED_FN_8 0x80000008
    64 typedef enum {
    65    FPU_FLAG     = 0x00000001,
    66    VME_FLAG     = 0x00000002,
    67    DE_FLAG      = 0x00000004,
    68    PSE_FLAG     = 0x00000008,
    69    TSC_FLAG     = 0x00000010,
    70    MSR_FLAG     = 0x00000020,
    71    PAE_FLAG     = 0x00000040,
    72    MCE_FLAG     = 0x00000080,
    73    CX8_FLAG     = 0x00000100,
    74    APIC_FLAG    = 0x00000200,
    75    SEP_FLAG     = 0x00000800,
    76    MTRR_FLAG    = 0x00001000,
    77    PGE_FLAG     = 0x00002000,
    78    MCA_FLAG     = 0x00004000,
    79    CMOV_FLAG    = 0x00008000,
    80    PAT_FLAG     = 0x00010000,
    81    PSE36_FLAG   = 0x00020000,
    82    PSNUM_FLAG   = 0x00040000,
    83    CLFLUSH_FLAG = 0x00080000,
    84    DTS_FLAG     = 0x00200000,
    85    ACPI_FLAG    = 0x00400000,
    86    MMX_FLAG     = 0x00800000,
    87    FXSR_FLAG    = 0x01000000,
    88    SSE_FLAG     = 0x02000000,
    89    SSE2_FLAG    = 0x04000000,
    90    SS_FLAG      = 0x08000000,
    91    HTT_FLAG     = 0x10000000,
    92    TM_FLAG      = 0x20000000
    93 } FeatureEdxFlag;
    95 static BufferBlob* cpuid_brand_string_stub_blob;
    96 static const int   cpuid_brand_string_stub_size = 550;
    98 extern "C" {
    99   typedef void (*getCPUIDBrandString_stub_t)(void*);
   100 }
   102 static getCPUIDBrandString_stub_t getCPUIDBrandString_stub = NULL;
   104 class VM_Version_Ext_StubGenerator: public StubCodeGenerator {
   105  public:
   107   VM_Version_Ext_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
   109   address generate_getCPUIDBrandString(void) {
   110     // Flags to test CPU type.
   111     const uint32_t HS_EFL_AC           = 0x40000;
   112     const uint32_t HS_EFL_ID           = 0x200000;
   113     // Values for when we don't have a CPUID instruction.
   114     const int      CPU_FAMILY_SHIFT = 8;
   115     const uint32_t CPU_FAMILY_386   = (3 << CPU_FAMILY_SHIFT);
   116     const uint32_t CPU_FAMILY_486   = (4 << CPU_FAMILY_SHIFT);
   118     Label detect_486, cpu486, detect_586, done, ext_cpuid;
   120     StubCodeMark mark(this, "VM_Version_Ext", "getCPUIDNameInfo_stub");
   121 #   define __ _masm->
   123     address start = __ pc();
   125     //
   126     // void getCPUIDBrandString(VM_Version::CpuidInfo* cpuid_info);
   127     //
   128     // LP64: rcx and rdx are first and second argument registers on windows
   130     __ push(rbp);
   131 #ifdef _LP64
   132     __ mov(rbp, c_rarg0); // cpuid_info address
   133 #else
   134     __ movptr(rbp, Address(rsp, 8)); // cpuid_info address
   135 #endif
   136     __ push(rbx);
   137     __ push(rsi);
   138     __ pushf();          // preserve rbx, and flags
   139     __ pop(rax);
   140     __ push(rax);
   141     __ mov(rcx, rax);
   142     //
   143     // if we are unable to change the AC flag, we have a 386
   144     //
   145     __ xorl(rax, HS_EFL_AC);
   146     __ push(rax);
   147     __ popf();
   148     __ pushf();
   149     __ pop(rax);
   150     __ cmpptr(rax, rcx);
   151     __ jccb(Assembler::notEqual, detect_486);
   153     __ movl(rax, CPU_FAMILY_386);
   154     __ jmp(done);
   156     //
   157     // If we are unable to change the ID flag, we have a 486 which does
   158     // not support the "cpuid" instruction.
   159     //
   160     __ bind(detect_486);
   161     __ mov(rax, rcx);
   162     __ xorl(rax, HS_EFL_ID);
   163     __ push(rax);
   164     __ popf();
   165     __ pushf();
   166     __ pop(rax);
   167     __ cmpptr(rcx, rax);
   168     __ jccb(Assembler::notEqual, detect_586);
   170     __ bind(cpu486);
   171     __ movl(rax, CPU_FAMILY_486);
   172     __ jmp(done);
   174     //
   175     // At this point, we have a chip which supports the "cpuid" instruction
   176     //
   177     __ bind(detect_586);
   178     __ xorl(rax, rax);
   179     __ cpuid();
   180     __ orl(rax, rax);
   181     __ jcc(Assembler::equal, cpu486);   // if cpuid doesn't support an input
   182                                         // value of at least 1, we give up and
   183                                         // assume a 486
   185     //
   186     // Extended cpuid(0x80000000) for processor brand string detection
   187     //
   188     __ bind(ext_cpuid);
   189     __ movl(rax, CPUID_EXTENDED_FN);
   190     __ cpuid();
   191     __ cmpl(rax, CPUID_EXTENDED_FN_4);
   192     __ jcc(Assembler::below, done);
   194     //
   195     // Extended cpuid(0x80000002)  // first 16 bytes in brand string
   196     //
   197     __ movl(rax, CPUID_EXTENDED_FN_2);
   198     __ cpuid();
   199     __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_0_offset())));
   200     __ movl(Address(rsi, 0), rax);
   201     __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_1_offset())));
   202     __ movl(Address(rsi, 0), rbx);
   203     __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_2_offset())));
   204     __ movl(Address(rsi, 0), rcx);
   205     __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_3_offset())));
   206     __ movl(Address(rsi,0), rdx);
   208     //
   209     // Extended cpuid(0x80000003) // next 16 bytes in brand string
   210     //
   211     __ movl(rax, CPUID_EXTENDED_FN_3);
   212     __ cpuid();
   213     __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_4_offset())));
   214     __ movl(Address(rsi, 0), rax);
   215     __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_5_offset())));
   216     __ movl(Address(rsi, 0), rbx);
   217     __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_6_offset())));
   218     __ movl(Address(rsi, 0), rcx);
   219     __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_7_offset())));
   220     __ movl(Address(rsi,0), rdx);
   222     //
   223     // Extended cpuid(0x80000004) // last 16 bytes in brand string
   224     //
   225     __ movl(rax, CPUID_EXTENDED_FN_4);
   226     __ cpuid();
   227     __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_8_offset())));
   228     __ movl(Address(rsi, 0), rax);
   229     __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_9_offset())));
   230     __ movl(Address(rsi, 0), rbx);
   231     __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_10_offset())));
   232     __ movl(Address(rsi, 0), rcx);
   233     __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_11_offset())));
   234     __ movl(Address(rsi,0), rdx);
   236     //
   237     // return
   238     //
   239     __ bind(done);
   240     __ popf();
   241     __ pop(rsi);
   242     __ pop(rbx);
   243     __ pop(rbp);
   244     __ ret(0);
   246 #   undef __
   248     return start;
   249   };
   250 };
   253 // VM_Version_Ext statics
   254 const size_t VM_Version_Ext::VENDOR_LENGTH = 13;
   255 const size_t VM_Version_Ext::CPU_EBS_MAX_LENGTH = (3 * 4 * 4 + 1);
   256 const size_t VM_Version_Ext::CPU_TYPE_DESC_BUF_SIZE = 256;
   257 const size_t VM_Version_Ext::CPU_DETAILED_DESC_BUF_SIZE = 4096;
   258 char* VM_Version_Ext::_cpu_brand_string = NULL;
   259 jlong VM_Version_Ext::_max_qualified_cpu_frequency = 0;
   261 int VM_Version_Ext::_no_of_threads = 0;
   262 int VM_Version_Ext::_no_of_cores = 0;
   263 int VM_Version_Ext::_no_of_packages = 0;
   265 void VM_Version_Ext::initialize(void) {
   266   ResourceMark rm;
   268   cpuid_brand_string_stub_blob = BufferBlob::create("getCPUIDBrandString_stub", cpuid_brand_string_stub_size);
   269   if (cpuid_brand_string_stub_blob == NULL) {
   270     vm_exit_during_initialization("Unable to allocate getCPUIDBrandString_stub");
   271   }
   272   CodeBuffer c(cpuid_brand_string_stub_blob);
   273   VM_Version_Ext_StubGenerator g(&c);
   274   getCPUIDBrandString_stub = CAST_TO_FN_PTR(getCPUIDBrandString_stub_t,
   275                                    g.generate_getCPUIDBrandString());
   276 }
   278 const char* VM_Version_Ext::cpu_model_description(void) {
   279   uint32_t cpu_family = extended_cpu_family();
   280   uint32_t cpu_model = extended_cpu_model();
   281   const char* model = NULL;
   283   if (cpu_family == CPU_FAMILY_PENTIUMPRO) {
   284     for (uint32_t i = 0; i <= cpu_model; i++) {
   285       model = _model_id_pentium_pro[i];
   286       if (model == NULL) {
   287         break;
   288       }
   289     }
   290   }
   291   return model;
   292 }
   294 const char* VM_Version_Ext::cpu_brand_string(void) {
   295   if (_cpu_brand_string == NULL) {
   296     _cpu_brand_string = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_EBS_MAX_LENGTH, mtInternal);
   297     if (NULL == _cpu_brand_string) {
   298       return NULL;
   299     }
   300     int ret_val = cpu_extended_brand_string(_cpu_brand_string, CPU_EBS_MAX_LENGTH);
   301     if (ret_val != OS_OK) {
   302       FREE_C_HEAP_ARRAY(char, _cpu_brand_string, mtInternal);
   303       _cpu_brand_string = NULL;
   304     }
   305   }
   306   return _cpu_brand_string;
   307 }
   309 const char* VM_Version_Ext::cpu_brand(void) {
   310   const char*  brand  = NULL;
   312   if ((_cpuid_info.std_cpuid1_ebx.value & 0xFF) > 0) {
   313     int brand_num = _cpuid_info.std_cpuid1_ebx.value & 0xFF;
   314     brand = _brand_id[0];
   315     for (int i = 0; brand != NULL && i <= brand_num; i += 1) {
   316       brand = _brand_id[i];
   317     }
   318   }
   319   return brand;
   320 }
   322 bool VM_Version_Ext::cpu_is_em64t(void) {
   323   return ((_cpuid_info.ext_cpuid1_edx.value & INTEL64_FLAG) == INTEL64_FLAG);
   324 }
   326 bool VM_Version_Ext::is_netburst(void) {
   327   return (is_intel() && (extended_cpu_family() == CPU_FAMILY_PENTIUM_4));
   328 }
   330 bool VM_Version_Ext::supports_tscinv_ext(void) {
   331   if (!supports_tscinv_bit()) {
   332     return false;
   333   }
   335   if (is_intel()) {
   336     return true;
   337   }
   339   if (is_amd()) {
   340     return !is_amd_Barcelona();
   341   }
   343   return false;
   344 }
   346 void VM_Version_Ext::resolve_cpu_information_details(void) {
   348   // in future we want to base this information on proper cpu
   349   // and cache topology enumeration such as:
   350   // Intel 64 Architecture Processor Topology Enumeration
   351   // which supports system cpu and cache topology enumeration
   352   // either using 2xAPICIDs or initial APICIDs
   354   // currently only rough cpu information estimates
   355   // which will not necessarily reflect the exact configuration of the system
   357   // this is the number of logical hardware threads
   358   // visible to the operating system
   359   _no_of_threads = os::processor_count();
   361   // find out number of threads per cpu package
   362   int threads_per_package = threads_per_core() * cores_per_cpu();
   364   // use amount of threads visible to the process in order to guess number of sockets
   365   _no_of_packages = _no_of_threads / threads_per_package;
   367   // process might only see a subset of the total number of threads
   368   // from a single processor package. Virtualization/resource management for example.
   369   // If so then just write a hard 1 as num of pkgs.
   370   if (0 == _no_of_packages) {
   371     _no_of_packages = 1;
   372   }
   374   // estimate the number of cores
   375   _no_of_cores = cores_per_cpu() * _no_of_packages;
   376 }
   378 int VM_Version_Ext::number_of_threads(void) {
   379   if (_no_of_threads == 0) {
   380    resolve_cpu_information_details();
   381   }
   382   return _no_of_threads;
   383 }
   385 int VM_Version_Ext::number_of_cores(void) {
   386   if (_no_of_cores == 0) {
   387     resolve_cpu_information_details();
   388   }
   389   return _no_of_cores;
   390 }
   392 int VM_Version_Ext::number_of_sockets(void) {
   393   if (_no_of_packages == 0) {
   394     resolve_cpu_information_details();
   395   }
   396   return _no_of_packages;
   397 }
   399 const char* VM_Version_Ext::cpu_family_description(void) {
   400   int cpu_family_id = extended_cpu_family();
   401   if (is_amd()) {
   402     return _family_id_amd[cpu_family_id];
   403   }
   404   if (is_intel()) {
   405     if (cpu_family_id == CPU_FAMILY_PENTIUMPRO) {
   406       return cpu_model_description();
   407     }
   408     return _family_id_intel[cpu_family_id];
   409   }
   410   return "Unknown x86";
   411 }
   413 int VM_Version_Ext::cpu_type_description(char* const buf, size_t buf_len) {
   414   assert(buf != NULL, "buffer is NULL!");
   415   assert(buf_len >= CPU_TYPE_DESC_BUF_SIZE, "buffer len should at least be == CPU_TYPE_DESC_BUF_SIZE!");
   417   const char* cpu_type = NULL;
   418   const char* x64 = NULL;
   420   if (is_intel()) {
   421     cpu_type = "Intel";
   422     x64 = cpu_is_em64t() ? " Intel64" : "";
   423   } else if (is_amd()) {
   424     cpu_type = "AMD";
   425     x64 = cpu_is_em64t() ? " AMD64" : "";
   426   } else {
   427     cpu_type = "Unknown x86";
   428     x64 = cpu_is_em64t() ? " x86_64" : "";
   429   }
   431   jio_snprintf(buf, buf_len, "%s %s%s SSE SSE2%s%s%s%s%s%s%s%s",
   432     cpu_type,
   433     cpu_family_description(),
   434     supports_ht() ? " (HT)" : "",
   435     supports_sse3() ? " SSE3" : "",
   436     supports_ssse3() ? " SSSE3" : "",
   437     supports_sse4_1() ? " SSE4.1" : "",
   438     supports_sse4_2() ? " SSE4.2" : "",
   439     supports_sse4a() ? " SSE4A" : "",
   440     is_netburst() ? " Netburst" : "",
   441     is_intel_family_core() ? " Core" : "",
   442     x64);
   444   return OS_OK;
   445 }
   447 int VM_Version_Ext::cpu_extended_brand_string(char* const buf, size_t buf_len) {
   448   assert(buf != NULL, "buffer is NULL!");
   449   assert(buf_len >= CPU_EBS_MAX_LENGTH, "buffer len should at least be == CPU_EBS_MAX_LENGTH!");
   450   assert(getCPUIDBrandString_stub != NULL, "not initialized");
   452   // invoke newly generated asm code to fetch CPU Brand String
   453   getCPUIDBrandString_stub(&_cpuid_info);
   455   // fetch results into buffer
   456   *((uint32_t*) &buf[0])  = _cpuid_info.proc_name_0;
   457   *((uint32_t*) &buf[4])  = _cpuid_info.proc_name_1;
   458   *((uint32_t*) &buf[8])  = _cpuid_info.proc_name_2;
   459   *((uint32_t*) &buf[12]) = _cpuid_info.proc_name_3;
   460   *((uint32_t*) &buf[16]) = _cpuid_info.proc_name_4;
   461   *((uint32_t*) &buf[20]) = _cpuid_info.proc_name_5;
   462   *((uint32_t*) &buf[24]) = _cpuid_info.proc_name_6;
   463   *((uint32_t*) &buf[28]) = _cpuid_info.proc_name_7;
   464   *((uint32_t*) &buf[32]) = _cpuid_info.proc_name_8;
   465   *((uint32_t*) &buf[36]) = _cpuid_info.proc_name_9;
   466   *((uint32_t*) &buf[40]) = _cpuid_info.proc_name_10;
   467   *((uint32_t*) &buf[44]) = _cpuid_info.proc_name_11;
   469   return OS_OK;
   470 }
   472 size_t VM_Version_Ext::cpu_write_support_string(char* const buf, size_t buf_len) {
   473   guarantee(buf != NULL, "buffer is NULL!");
   474   guarantee(buf_len > 0, "buffer len not enough!");
   476   unsigned int flag = 0;
   477   unsigned int fi = 0;
   478   size_t       written = 0;
   479   const char*  prefix = "";
   481 #define WRITE_TO_BUF(string)                                                          \
   482   {                                                                                   \
   483     int res = jio_snprintf(&buf[written], buf_len - written, "%s%s", prefix, string); \
   484     if (res < 0) {                                                                    \
   485       return buf_len - 1;                                                             \
   486     }                                                                                 \
   487     written += res;                                                                   \
   488     if (prefix[0] == '\0') {                                                          \
   489       prefix = ", ";                                                                  \
   490     }                                                                                 \
   491   }
   493   for (flag = 1, fi = 0; flag <= 0x20000000 ; flag <<= 1, fi++) {
   494     if (flag == HTT_FLAG && (((_cpuid_info.std_cpuid1_ebx.value >> 16) & 0xff) <= 1)) {
   495       continue; /* no hyperthreading */
   496     } else if (flag == SEP_FLAG && (cpu_family() == CPU_FAMILY_PENTIUMPRO && ((_cpuid_info.std_cpuid1_eax.value & 0xff) < 0x33))) {
   497       continue; /* no fast system call */
   498     }
   499     if ((_cpuid_info.std_cpuid1_edx.value & flag) && strlen(_feature_edx_id[fi]) > 0) {
   500       WRITE_TO_BUF(_feature_edx_id[fi]);
   501     }
   502   }
   504   for (flag = 1, fi = 0; flag <= 0x20000000; flag <<= 1, fi++) {
   505     if ((_cpuid_info.std_cpuid1_ecx.value & flag) && strlen(_feature_ecx_id[fi]) > 0) {
   506       WRITE_TO_BUF(_feature_ecx_id[fi]);
   507     }
   508   }
   510   for (flag = 1, fi = 0; flag <= 0x20000000 ; flag <<= 1, fi++) {
   511     if ((_cpuid_info.ext_cpuid1_ecx.value & flag) && strlen(_feature_extended_ecx_id[fi]) > 0) {
   512       WRITE_TO_BUF(_feature_extended_ecx_id[fi]);
   513     }
   514   }
   516   for (flag = 1, fi = 0; flag <= 0x20000000; flag <<= 1, fi++) {
   517     if ((_cpuid_info.ext_cpuid1_edx.value & flag) && strlen(_feature_extended_edx_id[fi]) > 0) {
   518       WRITE_TO_BUF(_feature_extended_edx_id[fi]);
   519     }
   520   }
   522   if (supports_tscinv_bit()) {
   523       WRITE_TO_BUF("Invariant TSC");
   524   }
   526   return written;
   527 }
   529 /**
   530  * Write a detailed description of the cpu to a given buffer, including
   531  * feature set.
   532  */
   533 int VM_Version_Ext::cpu_detailed_description(char* const buf, size_t buf_len) {
   534   assert(buf != NULL, "buffer is NULL!");
   535   assert(buf_len >= CPU_DETAILED_DESC_BUF_SIZE, "buffer len should at least be == CPU_DETAILED_DESC_BUF_SIZE!");
   537   static const char* unknown = "<unknown>";
   538   char               vendor_id[VENDOR_LENGTH];
   539   const char*        family = NULL;
   540   const char*        model = NULL;
   541   const char*        brand = NULL;
   542   int                outputLen = 0;
   544   family = cpu_family_description();
   545   if (family == NULL) {
   546     family = unknown;
   547   }
   549   model = cpu_model_description();
   550   if (model == NULL) {
   551     model = unknown;
   552   }
   554   brand = cpu_brand_string();
   556   if (brand == NULL) {
   557     brand = cpu_brand();
   558     if (brand == NULL) {
   559       brand = unknown;
   560     }
   561   }
   563   *((uint32_t*) &vendor_id[0]) = _cpuid_info.std_vendor_name_0;
   564   *((uint32_t*) &vendor_id[4]) = _cpuid_info.std_vendor_name_2;
   565   *((uint32_t*) &vendor_id[8]) = _cpuid_info.std_vendor_name_1;
   566   vendor_id[VENDOR_LENGTH-1] = '\0';
   568   outputLen = jio_snprintf(buf, buf_len, "Brand: %s, Vendor: %s\n"
   569     "Family: %s (0x%x), Model: %s (0x%x), Stepping: 0x%x\n"
   570     "Ext. family: 0x%x, Ext. model: 0x%x, Type: 0x%x, Signature: 0x%8.8x\n"
   571     "Features: ebx: 0x%8.8x, ecx: 0x%8.8x, edx: 0x%8.8x\n"
   572     "Ext. features: eax: 0x%8.8x, ebx: 0x%8.8x, ecx: 0x%8.8x, edx: 0x%8.8x\n"
   573     "Supports: ",
   574     brand,
   575     vendor_id,
   576     family,
   577     extended_cpu_family(),
   578     model,
   579     extended_cpu_model(),
   580     cpu_stepping(),
   581     _cpuid_info.std_cpuid1_eax.bits.ext_family,
   582     _cpuid_info.std_cpuid1_eax.bits.ext_model,
   583     _cpuid_info.std_cpuid1_eax.bits.proc_type,
   584     _cpuid_info.std_cpuid1_eax.value,
   585     _cpuid_info.std_cpuid1_ebx.value,
   586     _cpuid_info.std_cpuid1_ecx.value,
   587     _cpuid_info.std_cpuid1_edx.value,
   588     _cpuid_info.ext_cpuid1_eax,
   589     _cpuid_info.ext_cpuid1_ebx,
   590     _cpuid_info.ext_cpuid1_ecx,
   591     _cpuid_info.ext_cpuid1_edx);
   593   if (outputLen < 0 || (size_t) outputLen >= buf_len - 1) {
   594     if (buf_len > 0) { buf[buf_len-1] = '\0'; }
   595     return OS_ERR;
   596   }
   598   cpu_write_support_string(&buf[outputLen], buf_len - outputLen);
   600   return OS_OK;
   601 }
   603 const char* VM_Version_Ext::cpu_name(void) {
   604   char cpu_type_desc[CPU_TYPE_DESC_BUF_SIZE];
   605   size_t cpu_desc_len = sizeof(cpu_type_desc);
   607   cpu_type_description(cpu_type_desc, cpu_desc_len);
   608   char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, cpu_desc_len, mtTracing);
   609   if (NULL == tmp) {
   610     return NULL;
   611   }
   612   strncpy(tmp, cpu_type_desc, cpu_desc_len);
   613   return tmp;
   614 }
   616 const char* VM_Version_Ext::cpu_description(void) {
   617   char cpu_detailed_desc_buffer[CPU_DETAILED_DESC_BUF_SIZE];
   618   size_t cpu_detailed_desc_len = sizeof(cpu_detailed_desc_buffer);
   620   cpu_detailed_description(cpu_detailed_desc_buffer, cpu_detailed_desc_len);
   622   char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, cpu_detailed_desc_len, mtTracing);
   624   if (NULL == tmp) {
   625     return NULL;
   626   }
   628   strncpy(tmp, cpu_detailed_desc_buffer, cpu_detailed_desc_len);
   629   return tmp;
   630 }
   632 /**
   633  *  See Intel Application note 485 (chapter 10) for details
   634  *  on frequency extraction from cpu brand string.
   635  *  http://www.intel.com/content/dam/www/public/us/en/documents/application-notes/processor-identification-cpuid-instruction-note.pdf
   636  *
   637  */
   638 jlong VM_Version_Ext::max_qualified_cpu_freq_from_brand_string(void) {
   639   // get brand string
   640   const char* const brand_string = cpu_brand_string();
   641   if (brand_string == NULL) {
   642     return 0;
   643   }
   645   const u8 MEGA = 1000000;
   646   u8 multiplier = 0;
   647   jlong frequency = 0;
   649   // the frequency information in the cpu brand string
   650   // is given in either of two formats "x.xxyHz" or "xxxxyHz",
   651   // where y=M,G,T and x is digits
   652   const char* Hz_location = strchr(brand_string, 'H');
   654   if (Hz_location != NULL) {
   655     if (*(Hz_location + 1) == 'z') {
   656       // switch on y in "yHz"
   657       switch(*(Hz_location - 1)) {
   658         case 'M' :
   659           // Set multiplier to frequency is in Hz
   660           multiplier = MEGA;
   661           break;
   662         case 'G' :
   663           multiplier = MEGA * 1000;
   664           break;
   665         case 'T' :
   666           multiplier = MEGA * 1000 * 1000;
   667           break;
   668       }
   669     }
   670   }
   672   if (multiplier > 0) {
   673     // compute frequency (in Hz) from brand string
   674     if (*(Hz_location - 4) == '.') { // if format is "x.xx"
   675       frequency =  (jlong)(*(Hz_location - 5) - '0') * (multiplier);
   676       frequency += (jlong)(*(Hz_location - 3) - '0') * (multiplier / 10);
   677       frequency += (jlong)(*(Hz_location - 2) - '0') * (multiplier / 100);
   678     } else { // format is "xxxx"
   679       frequency =  (jlong)(*(Hz_location - 5) - '0') * 1000;
   680       frequency += (jlong)(*(Hz_location - 4) - '0') * 100;
   681       frequency += (jlong)(*(Hz_location - 3) - '0') * 10;
   682       frequency += (jlong)(*(Hz_location - 2) - '0');
   683       frequency *= multiplier;
   684     }
   685   }
   686   return frequency;
   687 }
   690 jlong VM_Version_Ext::maximum_qualified_cpu_frequency(void) {
   691   if (_max_qualified_cpu_frequency == 0) {
   692     _max_qualified_cpu_frequency = max_qualified_cpu_freq_from_brand_string();
   693   }
   694   return _max_qualified_cpu_frequency;
   695 }
   697 const char* const VM_Version_Ext::_family_id_intel[] = {
   698   "8086/8088",
   699   "",
   700   "286",
   701   "386",
   702   "486",
   703   "Pentium",
   704   "Pentium Pro",   //or Pentium-M/Woodcrest depeding on model
   705   "",
   706   "",
   707   "",
   708   "",
   709   "",
   710   "",
   711   "",
   712   "",
   713   "Pentium 4"
   714 };
   716 const char* const VM_Version_Ext::_family_id_amd[] = {
   717   "",
   718   "",
   719   "",
   720   "",
   721   "5x86",
   722   "K5/K6",
   723   "Athlon/AthlonXP",
   724   "",
   725   "",
   726   "",
   727   "",
   728   "",
   729   "",
   730   "",
   731   "",
   732   "Opteron/Athlon64",
   733   "Opteron QC/Phenom"  // Barcelona et.al.
   734 };
   735 // Partially from Intel 64 and IA-32 Architecture Software Developer's Manual,
   736 // September 2013, Vol 3C Table 35-1
   737 const char* const VM_Version_Ext::_model_id_pentium_pro[] = {
   738   "",
   739   "Pentium Pro",
   740   "",
   741   "Pentium II model 3",
   742   "",
   743   "Pentium II model 5/Xeon/Celeron",
   744   "Celeron",
   745   "Pentium III/Pentium III Xeon",
   746   "Pentium III/Pentium III Xeon",
   747   "Pentium M model 9",    // Yonah
   748   "Pentium III, model A",
   749   "Pentium III, model B",
   750   "",
   751   "Pentium M model D",    // Dothan
   752   "",
   753   "Core 2",               // 0xf Woodcrest/Conroe/Merom/Kentsfield/Clovertown
   754   "",
   755   "",
   756   "",
   757   "",
   758   "",
   759   "",
   760   "Celeron",              // 0x16 Celeron 65nm
   761   "Core 2",               // 0x17 Penryn / Harpertown
   762   "",
   763   "",
   764   "Core i7",              // 0x1A CPU_MODEL_NEHALEM_EP
   765   "Atom",                 // 0x1B Z5xx series Silverthorn
   766   "",
   767   "Core 2",               // 0x1D Dunnington (6-core)
   768   "Nehalem",              // 0x1E CPU_MODEL_NEHALEM
   769   "",
   770   "",
   771   "",
   772   "",
   773   "",
   774   "",
   775   "Westmere",             // 0x25 CPU_MODEL_WESTMERE
   776   "",
   777   "",
   778   "",                     // 0x28
   779   "",
   780   "Sandy Bridge",         // 0x2a "2nd Generation Intel Core i7, i5, i3"
   781   "",
   782   "Westmere-EP",          // 0x2c CPU_MODEL_WESTMERE_EP
   783   "Sandy Bridge-EP",      // 0x2d CPU_MODEL_SANDYBRIDGE_EP
   784   "Nehalem-EX",           // 0x2e CPU_MODEL_NEHALEM_EX
   785   "Westmere-EX",          // 0x2f CPU_MODEL_WESTMERE_EX
   786   "",
   787   "",
   788   "",
   789   "",
   790   "",
   791   "",
   792   "",
   793   "",
   794   "",
   795   "",
   796   "Ivy Bridge",           // 0x3a
   797   "",
   798   "Haswell",              // 0x3c "4th Generation Intel Core Processor"
   799   "",                     // 0x3d "Next Generation Intel Core Processor"
   800   "Ivy Bridge-EP",        // 0x3e "Next Generation Intel Xeon Processor E7 Family"
   801   "",                     // 0x3f "Future Generation Intel Xeon Processor"
   802   "",
   803   "",
   804   "",
   805   "",
   806   "",
   807   "Haswell",              // 0x45 "4th Generation Intel Core Processor"
   808   "Haswell",              // 0x46 "4th Generation Intel Core Processor"
   809   NULL
   810 };
   812 /* Brand ID is for back compability
   813  * Newer CPUs uses the extended brand string */
   814 const char* const VM_Version_Ext::_brand_id[] = {
   815   "",
   816   "Celeron processor",
   817   "Pentium III processor",
   818   "Intel Pentium III Xeon processor",
   819   "",
   820   "",
   821   "",
   822   "",
   823   "Intel Pentium 4 processor",
   824   NULL
   825 };
   828 const char* const VM_Version_Ext::_feature_edx_id[] = {
   829   "On-Chip FPU",
   830   "Virtual Mode Extensions",
   831   "Debugging Extensions",
   832   "Page Size Extensions",
   833   "Time Stamp Counter",
   834   "Model Specific Registers",
   835   "Physical Address Extension",
   836   "Machine Check Exceptions",
   837   "CMPXCHG8B Instruction",
   838   "On-Chip APIC",
   839   "",
   840   "Fast System Call",
   841   "Memory Type Range Registers",
   842   "Page Global Enable",
   843   "Machine Check Architecture",
   844   "Conditional Mov Instruction",
   845   "Page Attribute Table",
   846   "36-bit Page Size Extension",
   847   "Processor Serial Number",
   848   "CLFLUSH Instruction",
   849   "",
   850   "Debug Trace Store feature",
   851   "ACPI registers in MSR space",
   852   "Intel Architecture MMX Technology",
   853   "Fast Float Point Save and Restore",
   854   "Streaming SIMD extensions",
   855   "Streaming SIMD extensions 2",
   856   "Self-Snoop",
   857   "Hyper Threading",
   858   "Thermal Monitor",
   859   "",
   860   "Pending Break Enable"
   861 };
   863 const char* const VM_Version_Ext::_feature_extended_edx_id[] = {
   864   "",
   865   "",
   866   "",
   867   "",
   868   "",
   869   "",
   870   "",
   871   "",
   872   "",
   873   "",
   874   "",
   875   "SYSCALL/SYSRET",
   876   "",
   877   "",
   878   "",
   879   "",
   880   "",
   881   "",
   882   "",
   883   "",
   884   "Execute Disable Bit",
   885   "",
   886   "",
   887   "",
   888   "",
   889   "",
   890   "",
   891   "RDTSCP",
   892   "",
   893   "Intel 64 Architecture",
   894   "",
   895   ""
   896 };
   898 const char* const VM_Version_Ext::_feature_ecx_id[] = {
   899   "Streaming SIMD Extensions 3",
   900   "PCLMULQDQ",
   901   "64-bit DS Area",
   902   "MONITOR/MWAIT instructions",
   903   "CPL Qualified Debug Store",
   904   "Virtual Machine Extensions",
   905   "Safer Mode Extensions",
   906   "Enhanced Intel SpeedStep technology",
   907   "Thermal Monitor 2",
   908   "Supplemental Streaming SIMD Extensions 3",
   909   "L1 Context ID",
   910   "",
   911   "Fused Multiply-Add",
   912   "CMPXCHG16B",
   913   "xTPR Update Control",
   914   "Perfmon and Debug Capability",
   915   "",
   916   "Process-context identifiers",
   917   "Direct Cache Access",
   918   "Streaming SIMD extensions 4.1",
   919   "Streaming SIMD extensions 4.2",
   920   "x2APIC",
   921   "MOVBE",
   922   "Popcount instruction",
   923   "TSC-Deadline",
   924   "AESNI",
   925   "XSAVE",
   926   "OSXSAVE",
   927   "AVX",
   928   "F16C",
   929   "RDRAND",
   930   ""
   931 };
   933 const char* const VM_Version_Ext::_feature_extended_ecx_id[] = {
   934   "LAHF/SAHF instruction support",
   935   "Core multi-processor leagacy mode",
   936   "",
   937   "",
   938   "",
   939   "Advanced Bit Manipulations: LZCNT",
   940   "SSE4A: MOVNTSS, MOVNTSD, EXTRQ, INSERTQ",
   941   "Misaligned SSE mode",
   942   "",
   943   "",
   944   "",
   945   "",
   946   "",
   947   "",
   948   "",
   949   "",
   950   "",
   951   "",
   952   "",
   953   "",
   954   "",
   955   "",
   956   "",
   957   "",
   958   "",
   959   "",
   960   "",
   961   "",
   962   "",
   963   "",
   964   "",
   965   ""
   966 };

mercurial