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  */
  24 
  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"
  35 
  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;
  45 
  46  typedef enum {
  47     RDTSCP_FLAG  = 0x08000000, // bit 27
  48     INTEL64_FLAG = 0x20000000  // bit 29
  49   } _featureExtendedEdxFlag;
  50 
  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
  55 
  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
  63 
  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;
  94 
  95 static BufferBlob* cpuid_brand_string_stub_blob;
  96 static const int   cpuid_brand_string_stub_size = 550;
  97 
  98 extern "C" {
  99   typedef void (*getCPUIDBrandString_stub_t)(void*);
 100 }
 101 
 102 static getCPUIDBrandString_stub_t getCPUIDBrandString_stub = NULL;
 103 
 104 class VM_Version_Ext_StubGenerator: public StubCodeGenerator {
 105  public:
 106 
 107   VM_Version_Ext_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
 108 
 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);
 117 
 118     Label detect_486, cpu486, detect_586, done, ext_cpuid;
 119 
 120     StubCodeMark mark(this, "VM_Version_Ext", "getCPUIDNameInfo_stub");
 121 #   define __ _masm->
 122 
 123     address start = __ pc();
 124 
 125     //
 126     // void getCPUIDBrandString(VM_Version::CpuidInfo* cpuid_info);
 127     //
 128     // LP64: rcx and rdx are first and second argument registers on windows
 129 
 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);
 152 
 153     __ movl(rax, CPU_FAMILY_386);
 154     __ jmp(done);
 155 
 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);
 169 
 170     __ bind(cpu486);
 171     __ movl(rax, CPU_FAMILY_486);
 172     __ jmp(done);
 173 
 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
 184 
 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);
 193 
 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);
 207 
 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);
 221 
 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);
 235 
 236     //
 237     // return
 238     //
 239     __ bind(done);
 240     __ popf();
 241     __ pop(rsi);
 242     __ pop(rbx);
 243     __ pop(rbp);
 244     __ ret(0);
 245 
 246 #   undef __
 247 
 248     return start;
 249   };
 250 };
 251 
 252 
 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;
 260 
 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;
 264 
 265 void VM_Version_Ext::initialize(void) {
 266   ResourceMark rm;
 267 
 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 }
 277 
 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;
 282 
 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 }
 293 
 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);
 303       _cpu_brand_string = NULL;
 304     }
 305   }
 306   return _cpu_brand_string;
 307 }
 308 
 309 const char* VM_Version_Ext::cpu_brand(void) {
 310   const char*  brand  = NULL;
 311 
 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 }
 321 
 322 bool VM_Version_Ext::cpu_is_em64t(void) {
 323   return ((_cpuid_info.ext_cpuid1_edx.value & INTEL64_FLAG) == INTEL64_FLAG);
 324 }
 325 
 326 bool VM_Version_Ext::is_netburst(void) {
 327   return (is_intel() && (extended_cpu_family() == CPU_FAMILY_PENTIUM_4));
 328 }
 329 
 330 bool VM_Version_Ext::supports_tscinv_ext(void) {
 331   if (!supports_tscinv_bit()) {
 332     return false;
 333   }
 334 
 335   if (is_intel()) {
 336     return true;
 337   }
 338 
 339   if (is_amd()) {
 340     return !is_amd_Barcelona();
 341   }
 342 
 343   if (is_hygon()) {
 344     return true;
 345   }
 346 
 347   return false;
 348 }
 349 
 350 void VM_Version_Ext::resolve_cpu_information_details(void) {
 351 
 352   // in future we want to base this information on proper cpu
 353   // and cache topology enumeration such as:
 354   // Intel 64 Architecture Processor Topology Enumeration
 355   // which supports system cpu and cache topology enumeration
 356   // either using 2xAPICIDs or initial APICIDs
 357 
 358   // currently only rough cpu information estimates
 359   // which will not necessarily reflect the exact configuration of the system
 360 
 361   // this is the number of logical hardware threads
 362   // visible to the operating system
 363   _no_of_threads = os::processor_count();
 364 
 365   // find out number of threads per cpu package
 366   int threads_per_package = threads_per_core() * cores_per_cpu();
 367 
 368   // use amount of threads visible to the process in order to guess number of sockets
 369   _no_of_packages = _no_of_threads / threads_per_package;
 370 
 371   // process might only see a subset of the total number of threads
 372   // from a single processor package. Virtualization/resource management for example.
 373   // If so then just write a hard 1 as num of pkgs.
 374   if (0 == _no_of_packages) {
 375     _no_of_packages = 1;
 376   }
 377 
 378   // estimate the number of cores
 379   _no_of_cores = cores_per_cpu() * _no_of_packages;
 380 }
 381 
 382 int VM_Version_Ext::number_of_threads(void) {
 383   if (_no_of_threads == 0) {
 384    resolve_cpu_information_details();
 385   }
 386   return _no_of_threads;
 387 }
 388 
 389 int VM_Version_Ext::number_of_cores(void) {
 390   if (_no_of_cores == 0) {
 391     resolve_cpu_information_details();
 392   }
 393   return _no_of_cores;
 394 }
 395 
 396 int VM_Version_Ext::number_of_sockets(void) {
 397   if (_no_of_packages == 0) {
 398     resolve_cpu_information_details();
 399   }
 400   return _no_of_packages;
 401 }
 402 
 403 const char* VM_Version_Ext::cpu_family_description(void) {
 404   int cpu_family_id = extended_cpu_family();
 405   if (is_amd()) {
 406     return _family_id_amd[cpu_family_id];
 407   }
 408   if (is_intel()) {
 409     if (cpu_family_id == CPU_FAMILY_PENTIUMPRO) {
 410       return cpu_model_description();
 411     }
 412     return _family_id_intel[cpu_family_id];
 413   }
 414   if (is_hygon()) {
 415     return _family_id_hygon[cpu_family_id];
 416   }
 417 
 418   return "Unknown x86";
 419 }
 420 
 421 int VM_Version_Ext::cpu_type_description(char* const buf, size_t buf_len) {
 422   assert(buf != NULL, "buffer is NULL!");
 423   assert(buf_len >= CPU_TYPE_DESC_BUF_SIZE, "buffer len should at least be == CPU_TYPE_DESC_BUF_SIZE!");
 424 
 425   const char* cpu_type = NULL;
 426   const char* x64 = NULL;
 427 
 428   if (is_intel()) {
 429     cpu_type = "Intel";
 430     x64 = cpu_is_em64t() ? " Intel64" : "";
 431   } else if (is_amd()) {
 432     cpu_type = "AMD";
 433     x64 = cpu_is_em64t() ? " AMD64" : "";
 434   } else if (is_hygon()) {
 435         cpu_type = "HYGON";
 436         x64 = cpu_is_em64t() ? " AMD64" : "";
 437   } else {
 438     cpu_type = "Unknown x86";
 439     x64 = cpu_is_em64t() ? " x86_64" : "";
 440   }
 441 
 442   jio_snprintf(buf, buf_len, "%s %s%s SSE SSE2%s%s%s%s%s%s%s%s",
 443     cpu_type,
 444     cpu_family_description(),
 445     supports_ht() ? " (HT)" : "",
 446     supports_sse3() ? " SSE3" : "",
 447     supports_ssse3() ? " SSSE3" : "",
 448     supports_sse4_1() ? " SSE4.1" : "",
 449     supports_sse4_2() ? " SSE4.2" : "",
 450     supports_sse4a() ? " SSE4A" : "",
 451     is_netburst() ? " Netburst" : "",
 452     is_intel_family_core() ? " Core" : "",
 453     x64);
 454 
 455   return OS_OK;
 456 }
 457 
 458 int VM_Version_Ext::cpu_extended_brand_string(char* const buf, size_t buf_len) {
 459   assert(buf != NULL, "buffer is NULL!");
 460   assert(buf_len >= CPU_EBS_MAX_LENGTH, "buffer len should at least be == CPU_EBS_MAX_LENGTH!");
 461   assert(getCPUIDBrandString_stub != NULL, "not initialized");
 462 
 463   // invoke newly generated asm code to fetch CPU Brand String
 464   getCPUIDBrandString_stub(&_cpuid_info);
 465 
 466   // fetch results into buffer
 467   *((uint32_t*) &buf[0])  = _cpuid_info.proc_name_0;
 468   *((uint32_t*) &buf[4])  = _cpuid_info.proc_name_1;
 469   *((uint32_t*) &buf[8])  = _cpuid_info.proc_name_2;
 470   *((uint32_t*) &buf[12]) = _cpuid_info.proc_name_3;
 471   *((uint32_t*) &buf[16]) = _cpuid_info.proc_name_4;
 472   *((uint32_t*) &buf[20]) = _cpuid_info.proc_name_5;
 473   *((uint32_t*) &buf[24]) = _cpuid_info.proc_name_6;
 474   *((uint32_t*) &buf[28]) = _cpuid_info.proc_name_7;
 475   *((uint32_t*) &buf[32]) = _cpuid_info.proc_name_8;
 476   *((uint32_t*) &buf[36]) = _cpuid_info.proc_name_9;
 477   *((uint32_t*) &buf[40]) = _cpuid_info.proc_name_10;
 478   *((uint32_t*) &buf[44]) = _cpuid_info.proc_name_11;
 479 
 480   return OS_OK;
 481 }
 482 
 483 size_t VM_Version_Ext::cpu_write_support_string(char* const buf, size_t buf_len) {
 484   guarantee(buf != NULL, "buffer is NULL!");
 485   guarantee(buf_len > 0, "buffer len not enough!");
 486 
 487   unsigned int flag = 0;
 488   unsigned int fi = 0;
 489   size_t       written = 0;
 490   const char*  prefix = "";
 491 
 492 #define WRITE_TO_BUF(string)                                                          \
 493   {                                                                                   \
 494     int res = jio_snprintf(&buf[written], buf_len - written, "%s%s", prefix, string); \
 495     if (res < 0) {                                                                    \
 496       return buf_len - 1;                                                             \
 497     }                                                                                 \
 498     written += res;                                                                   \
 499     if (prefix[0] == '\0') {                                                          \
 500       prefix = ", ";                                                                  \
 501     }                                                                                 \
 502   }
 503 
 504   for (flag = 1, fi = 0; flag <= 0x20000000 ; flag <<= 1, fi++) {
 505     if (flag == HTT_FLAG && (((_cpuid_info.std_cpuid1_ebx.value >> 16) & 0xff) <= 1)) {
 506       continue; /* no hyperthreading */
 507     } else if (flag == SEP_FLAG && (cpu_family() == CPU_FAMILY_PENTIUMPRO && ((_cpuid_info.std_cpuid1_eax.value & 0xff) < 0x33))) {
 508       continue; /* no fast system call */
 509     }
 510     if ((_cpuid_info.std_cpuid1_edx.value & flag) && strlen(_feature_edx_id[fi]) > 0) {
 511       WRITE_TO_BUF(_feature_edx_id[fi]);
 512     }
 513   }
 514 
 515   for (flag = 1, fi = 0; flag <= 0x20000000; flag <<= 1, fi++) {
 516     if ((_cpuid_info.std_cpuid1_ecx.value & flag) && strlen(_feature_ecx_id[fi]) > 0) {
 517       WRITE_TO_BUF(_feature_ecx_id[fi]);
 518     }
 519   }
 520 
 521   for (flag = 1, fi = 0; flag <= 0x20000000 ; flag <<= 1, fi++) {
 522     if ((_cpuid_info.ext_cpuid1_ecx.value & flag) && strlen(_feature_extended_ecx_id[fi]) > 0) {
 523       WRITE_TO_BUF(_feature_extended_ecx_id[fi]);
 524     }
 525   }
 526 
 527   for (flag = 1, fi = 0; flag <= 0x20000000; flag <<= 1, fi++) {
 528     if ((_cpuid_info.ext_cpuid1_edx.value & flag) && strlen(_feature_extended_edx_id[fi]) > 0) {
 529       WRITE_TO_BUF(_feature_extended_edx_id[fi]);
 530     }
 531   }
 532 
 533   if (supports_tscinv_bit()) {
 534       WRITE_TO_BUF("Invariant TSC");
 535   }
 536 
 537   return written;
 538 }
 539 
 540 /**
 541  * Write a detailed description of the cpu to a given buffer, including
 542  * feature set.
 543  */
 544 int VM_Version_Ext::cpu_detailed_description(char* const buf, size_t buf_len) {
 545   assert(buf != NULL, "buffer is NULL!");
 546   assert(buf_len >= CPU_DETAILED_DESC_BUF_SIZE, "buffer len should at least be == CPU_DETAILED_DESC_BUF_SIZE!");
 547 
 548   static const char* unknown = "<unknown>";
 549   char               vendor_id[VENDOR_LENGTH];
 550   const char*        family = NULL;
 551   const char*        model = NULL;
 552   const char*        brand = NULL;
 553   int                outputLen = 0;
 554 
 555   family = cpu_family_description();
 556   if (family == NULL) {
 557     family = unknown;
 558   }
 559 
 560   model = cpu_model_description();
 561   if (model == NULL) {
 562     model = unknown;
 563   }
 564 
 565   brand = cpu_brand_string();
 566 
 567   if (brand == NULL) {
 568     brand = cpu_brand();
 569     if (brand == NULL) {
 570       brand = unknown;
 571     }
 572   }
 573 
 574   *((uint32_t*) &vendor_id[0]) = _cpuid_info.std_vendor_name_0;
 575   *((uint32_t*) &vendor_id[4]) = _cpuid_info.std_vendor_name_2;
 576   *((uint32_t*) &vendor_id[8]) = _cpuid_info.std_vendor_name_1;
 577   vendor_id[VENDOR_LENGTH-1] = '\0';
 578 
 579   outputLen = jio_snprintf(buf, buf_len, "Brand: %s, Vendor: %s\n"
 580     "Family: %s (0x%x), Model: %s (0x%x), Stepping: 0x%x\n"
 581     "Ext. family: 0x%x, Ext. model: 0x%x, Type: 0x%x, Signature: 0x%8.8x\n"
 582     "Features: ebx: 0x%8.8x, ecx: 0x%8.8x, edx: 0x%8.8x\n"
 583     "Ext. features: eax: 0x%8.8x, ebx: 0x%8.8x, ecx: 0x%8.8x, edx: 0x%8.8x\n"
 584     "Supports: ",
 585     brand,
 586     vendor_id,
 587     family,
 588     extended_cpu_family(),
 589     model,
 590     extended_cpu_model(),
 591     cpu_stepping(),
 592     _cpuid_info.std_cpuid1_eax.bits.ext_family,
 593     _cpuid_info.std_cpuid1_eax.bits.ext_model,
 594     _cpuid_info.std_cpuid1_eax.bits.proc_type,
 595     _cpuid_info.std_cpuid1_eax.value,
 596     _cpuid_info.std_cpuid1_ebx.value,
 597     _cpuid_info.std_cpuid1_ecx.value,
 598     _cpuid_info.std_cpuid1_edx.value,
 599     _cpuid_info.ext_cpuid1_eax,
 600     _cpuid_info.ext_cpuid1_ebx,
 601     _cpuid_info.ext_cpuid1_ecx,
 602     _cpuid_info.ext_cpuid1_edx);
 603 
 604   if (outputLen < 0 || (size_t) outputLen >= buf_len - 1) {
 605     if (buf_len > 0) { buf[buf_len-1] = '\0'; }
 606     return OS_ERR;
 607   }
 608 
 609   cpu_write_support_string(&buf[outputLen], buf_len - outputLen);
 610 
 611   return OS_OK;
 612 }
 613 
 614 const char* VM_Version_Ext::cpu_name(void) {
 615   char cpu_type_desc[CPU_TYPE_DESC_BUF_SIZE];
 616   size_t cpu_desc_len = sizeof(cpu_type_desc);
 617 
 618   cpu_type_description(cpu_type_desc, cpu_desc_len);
 619   char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, cpu_desc_len, mtTracing);
 620   if (NULL == tmp) {
 621     return NULL;
 622   }
 623   strncpy(tmp, cpu_type_desc, cpu_desc_len);
 624   return tmp;
 625 }
 626 
 627 const char* VM_Version_Ext::cpu_description(void) {
 628   char cpu_detailed_desc_buffer[CPU_DETAILED_DESC_BUF_SIZE];
 629   size_t cpu_detailed_desc_len = sizeof(cpu_detailed_desc_buffer);
 630 
 631   cpu_detailed_description(cpu_detailed_desc_buffer, cpu_detailed_desc_len);
 632 
 633   char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, cpu_detailed_desc_len, mtTracing);
 634 
 635   if (NULL == tmp) {
 636     return NULL;
 637   }
 638 
 639   strncpy(tmp, cpu_detailed_desc_buffer, cpu_detailed_desc_len);
 640   return tmp;
 641 }
 642 
 643 /**
 644  *  See Intel Application note 485 (chapter 10) for details
 645  *  on frequency extraction from cpu brand string.
 646  *  http://www.intel.com/content/dam/www/public/us/en/documents/application-notes/processor-identification-cpuid-instruction-note.pdf
 647  *
 648  */
 649 jlong VM_Version_Ext::max_qualified_cpu_freq_from_brand_string(void) {
 650   // get brand string
 651   const char* const brand_string = cpu_brand_string();
 652   if (brand_string == NULL) {
 653     return 0;
 654   }
 655 
 656   const u8 MEGA = 1000000;
 657   u8 multiplier = 0;
 658   jlong frequency = 0;
 659 
 660   // the frequency information in the cpu brand string
 661   // is given in either of two formats "x.xxyHz" or "xxxxyHz",
 662   // where y=M,G,T and x is digits
 663   const char* Hz_location = strchr(brand_string, 'H');
 664 
 665   if (Hz_location != NULL) {
 666     if (*(Hz_location + 1) == 'z') {
 667       // switch on y in "yHz"
 668       switch(*(Hz_location - 1)) {
 669         case 'M' :
 670           // Set multiplier to frequency is in Hz
 671           multiplier = MEGA;
 672           break;
 673         case 'G' :
 674           multiplier = MEGA * 1000;
 675           break;
 676         case 'T' :
 677           multiplier = MEGA * 1000 * 1000;
 678           break;
 679       }
 680     }
 681   }
 682 
 683   if (multiplier > 0) {
 684     // compute frequency (in Hz) from brand string
 685     if (*(Hz_location - 4) == '.') { // if format is "x.xx"
 686       frequency =  (jlong)(*(Hz_location - 5) - '0') * (multiplier);
 687       frequency += (jlong)(*(Hz_location - 3) - '0') * (multiplier / 10);
 688       frequency += (jlong)(*(Hz_location - 2) - '0') * (multiplier / 100);
 689     } else { // format is "xxxx"
 690       frequency =  (jlong)(*(Hz_location - 5) - '0') * 1000;
 691       frequency += (jlong)(*(Hz_location - 4) - '0') * 100;
 692       frequency += (jlong)(*(Hz_location - 3) - '0') * 10;
 693       frequency += (jlong)(*(Hz_location - 2) - '0');
 694       frequency *= multiplier;
 695     }
 696   }
 697   return frequency;
 698 }
 699 
 700 
 701 jlong VM_Version_Ext::maximum_qualified_cpu_frequency(void) {
 702   if (_max_qualified_cpu_frequency == 0) {
 703     _max_qualified_cpu_frequency = max_qualified_cpu_freq_from_brand_string();
 704   }
 705   return _max_qualified_cpu_frequency;
 706 }
 707 
 708 const char* const VM_Version_Ext::_family_id_intel[] = {
 709   "8086/8088",
 710   "",
 711   "286",
 712   "386",
 713   "486",
 714   "Pentium",
 715   "Pentium Pro",   //or Pentium-M/Woodcrest depeding on model
 716   "",
 717   "",
 718   "",
 719   "",
 720   "",
 721   "",
 722   "",
 723   "",
 724   "Pentium 4"
 725 };
 726 
 727 const char* const VM_Version_Ext::_family_id_amd[] = {
 728   "",
 729   "",
 730   "",
 731   "",
 732   "5x86",
 733   "K5/K6",
 734   "Athlon/AthlonXP",
 735   "",
 736   "",
 737   "",
 738   "",
 739   "",
 740   "",
 741   "",
 742   "",
 743   "Opteron/Athlon64",
 744   "Opteron QC/Phenom"  // Barcelona et.al.
 745 };
 746 const char* const VM_Version_Ext::_family_id_hygon[] = {
 747   "",   //family 0
 748   "",
 749   "",
 750   "",
 751   "",
 752   "",
 753   "",
 754   "",
 755   "",
 756   "",
 757   "",
 758   "",
 759   "",
 760   "",
 761   "",
 762   "",
 763   "",
 764   "",
 765   "",
 766   "",
 767   "",
 768   "",
 769   "",
 770   "",
 771   "HygonGenuine",       //family 24
 772 };
 773 
 774 // Partially from Intel 64 and IA-32 Architecture Software Developer's Manual,
 775 // September 2013, Vol 3C Table 35-1
 776 const char* const VM_Version_Ext::_model_id_pentium_pro[] = {
 777   "",
 778   "Pentium Pro",
 779   "",
 780   "Pentium II model 3",
 781   "",
 782   "Pentium II model 5/Xeon/Celeron",
 783   "Celeron",
 784   "Pentium III/Pentium III Xeon",
 785   "Pentium III/Pentium III Xeon",
 786   "Pentium M model 9",    // Yonah
 787   "Pentium III, model A",
 788   "Pentium III, model B",
 789   "",
 790   "Pentium M model D",    // Dothan
 791   "",
 792   "Core 2",               // 0xf Woodcrest/Conroe/Merom/Kentsfield/Clovertown
 793   "",
 794   "",
 795   "",
 796   "",
 797   "",
 798   "",
 799   "Celeron",              // 0x16 Celeron 65nm
 800   "Core 2",               // 0x17 Penryn / Harpertown
 801   "",
 802   "",
 803   "Core i7",              // 0x1A CPU_MODEL_NEHALEM_EP
 804   "Atom",                 // 0x1B Z5xx series Silverthorn
 805   "",
 806   "Core 2",               // 0x1D Dunnington (6-core)
 807   "Nehalem",              // 0x1E CPU_MODEL_NEHALEM
 808   "",
 809   "",
 810   "",
 811   "",
 812   "",
 813   "",
 814   "Westmere",             // 0x25 CPU_MODEL_WESTMERE
 815   "",
 816   "",
 817   "",                     // 0x28
 818   "",
 819   "Sandy Bridge",         // 0x2a "2nd Generation Intel Core i7, i5, i3"
 820   "",
 821   "Westmere-EP",          // 0x2c CPU_MODEL_WESTMERE_EP
 822   "Sandy Bridge-EP",      // 0x2d CPU_MODEL_SANDYBRIDGE_EP
 823   "Nehalem-EX",           // 0x2e CPU_MODEL_NEHALEM_EX
 824   "Westmere-EX",          // 0x2f CPU_MODEL_WESTMERE_EX
 825   "",
 826   "",
 827   "",
 828   "",
 829   "",
 830   "",
 831   "",
 832   "",
 833   "",
 834   "",
 835   "Ivy Bridge",           // 0x3a
 836   "",
 837   "Haswell",              // 0x3c "4th Generation Intel Core Processor"
 838   "",                     // 0x3d "Next Generation Intel Core Processor"
 839   "Ivy Bridge-EP",        // 0x3e "Next Generation Intel Xeon Processor E7 Family"
 840   "",                     // 0x3f "Future Generation Intel Xeon Processor"
 841   "",
 842   "",
 843   "",
 844   "",
 845   "",
 846   "Haswell",              // 0x45 "4th Generation Intel Core Processor"
 847   "Haswell",              // 0x46 "4th Generation Intel Core Processor"
 848   NULL
 849 };
 850 
 851 /* Brand ID is for back compability
 852  * Newer CPUs uses the extended brand string */
 853 const char* const VM_Version_Ext::_brand_id[] = {
 854   "",
 855   "Celeron processor",
 856   "Pentium III processor",
 857   "Intel Pentium III Xeon processor",
 858   "",
 859   "",
 860   "",
 861   "",
 862   "Intel Pentium 4 processor",
 863   NULL
 864 };
 865 
 866 
 867 const char* const VM_Version_Ext::_feature_edx_id[] = {
 868   "On-Chip FPU",
 869   "Virtual Mode Extensions",
 870   "Debugging Extensions",
 871   "Page Size Extensions",
 872   "Time Stamp Counter",
 873   "Model Specific Registers",
 874   "Physical Address Extension",
 875   "Machine Check Exceptions",
 876   "CMPXCHG8B Instruction",
 877   "On-Chip APIC",
 878   "",
 879   "Fast System Call",
 880   "Memory Type Range Registers",
 881   "Page Global Enable",
 882   "Machine Check Architecture",
 883   "Conditional Mov Instruction",
 884   "Page Attribute Table",
 885   "36-bit Page Size Extension",
 886   "Processor Serial Number",
 887   "CLFLUSH Instruction",
 888   "",
 889   "Debug Trace Store feature",
 890   "ACPI registers in MSR space",
 891   "Intel Architecture MMX Technology",
 892   "Fast Float Point Save and Restore",
 893   "Streaming SIMD extensions",
 894   "Streaming SIMD extensions 2",
 895   "Self-Snoop",
 896   "Hyper Threading",
 897   "Thermal Monitor",
 898   "",
 899   "Pending Break Enable"
 900 };
 901 
 902 const char* const VM_Version_Ext::_feature_extended_edx_id[] = {
 903   "",
 904   "",
 905   "",
 906   "",
 907   "",
 908   "",
 909   "",
 910   "",
 911   "",
 912   "",
 913   "",
 914   "SYSCALL/SYSRET",
 915   "",
 916   "",
 917   "",
 918   "",
 919   "",
 920   "",
 921   "",
 922   "",
 923   "Execute Disable Bit",
 924   "",
 925   "",
 926   "",
 927   "",
 928   "",
 929   "",
 930   "RDTSCP",
 931   "",
 932   "Intel 64 Architecture",
 933   "",
 934   ""
 935 };
 936 
 937 const char* const VM_Version_Ext::_feature_ecx_id[] = {
 938   "Streaming SIMD Extensions 3",
 939   "PCLMULQDQ",
 940   "64-bit DS Area",
 941   "MONITOR/MWAIT instructions",
 942   "CPL Qualified Debug Store",
 943   "Virtual Machine Extensions",
 944   "Safer Mode Extensions",
 945   "Enhanced Intel SpeedStep technology",
 946   "Thermal Monitor 2",
 947   "Supplemental Streaming SIMD Extensions 3",
 948   "L1 Context ID",
 949   "",
 950   "Fused Multiply-Add",
 951   "CMPXCHG16B",
 952   "xTPR Update Control",
 953   "Perfmon and Debug Capability",
 954   "",
 955   "Process-context identifiers",
 956   "Direct Cache Access",
 957   "Streaming SIMD extensions 4.1",
 958   "Streaming SIMD extensions 4.2",
 959   "x2APIC",
 960   "MOVBE",
 961   "Popcount instruction",
 962   "TSC-Deadline",
 963   "AESNI",
 964   "XSAVE",
 965   "OSXSAVE",
 966   "AVX",
 967   "F16C",
 968   "RDRAND",
 969   ""
 970 };
 971 
 972 const char* const VM_Version_Ext::_feature_extended_ecx_id[] = {
 973   "LAHF/SAHF instruction support",
 974   "Core multi-processor leagacy mode",
 975   "",
 976   "",
 977   "",
 978   "Advanced Bit Manipulations: LZCNT",
 979   "SSE4A: MOVNTSS, MOVNTSD, EXTRQ, INSERTQ",
 980   "Misaligned SSE mode",
 981   "",
 982   "",
 983   "",
 984   "",
 985   "",
 986   "",
 987   "",
 988   "",
 989   "",
 990   "",
 991   "",
 992   "",
 993   "",
 994   "",
 995   "",
 996   "",
 997   "",
 998   "",
 999   "",
1000   "",
1001   "",
1002   "",
1003   "",
1004   ""
1005 };