8249675: x86: frequency extraction from cpu brand string is incomplete
Reviewed-by: egahlin, dholmes
This commit is contained in:
parent
e52156d730
commit
63ce304ea4
src/hotspot/cpu/x86
@ -256,7 +256,7 @@ const size_t VM_Version_Ext::CPU_EBS_MAX_LENGTH = (3 * 4 * 4 + 1);
|
||||
const size_t VM_Version_Ext::CPU_TYPE_DESC_BUF_SIZE = 256;
|
||||
const size_t VM_Version_Ext::CPU_DETAILED_DESC_BUF_SIZE = 4096;
|
||||
char* VM_Version_Ext::_cpu_brand_string = NULL;
|
||||
jlong VM_Version_Ext::_max_qualified_cpu_frequency = 0;
|
||||
int64_t VM_Version_Ext::_max_qualified_cpu_frequency = 0;
|
||||
|
||||
int VM_Version_Ext::_no_of_threads = 0;
|
||||
int VM_Version_Ext::_no_of_cores = 0;
|
||||
@ -644,56 +644,50 @@ const char* VM_Version_Ext::cpu_description(void) {
|
||||
}
|
||||
|
||||
/**
|
||||
* See Intel Application note 485 (chapter 10) for details
|
||||
* on frequency extraction from cpu brand string.
|
||||
* http://www.intel.com/content/dam/www/public/us/en/documents/application-notes/processor-identification-cpuid-instruction-note.pdf
|
||||
* For information about extracting the frequency from the cpu brand string, please see:
|
||||
*
|
||||
* Intel Processor Identification and the CPUID Instruction
|
||||
* Application Note 485
|
||||
* May 2012
|
||||
*
|
||||
* The return value is the frequency in Hz.
|
||||
*/
|
||||
jlong VM_Version_Ext::max_qualified_cpu_freq_from_brand_string(void) {
|
||||
// get brand string
|
||||
int64_t VM_Version_Ext::max_qualified_cpu_freq_from_brand_string(void) {
|
||||
const char* const brand_string = cpu_brand_string();
|
||||
if (brand_string == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const u8 MEGA = 1000000;
|
||||
u8 multiplier = 0;
|
||||
jlong frequency = 0;
|
||||
|
||||
// the frequency information in the cpu brand string
|
||||
// is given in either of two formats "x.xxyHz" or "xxxxyHz",
|
||||
// where y=M,G,T and x is digits
|
||||
const char* Hz_location = strchr(brand_string, 'H');
|
||||
|
||||
if (Hz_location != NULL) {
|
||||
if (*(Hz_location + 1) == 'z') {
|
||||
// switch on y in "yHz"
|
||||
switch(*(Hz_location - 1)) {
|
||||
case 'M' :
|
||||
// Set multiplier to frequency is in Hz
|
||||
multiplier = MEGA;
|
||||
break;
|
||||
case 'G' :
|
||||
multiplier = MEGA * 1000;
|
||||
break;
|
||||
case 'T' :
|
||||
multiplier = MEGA * 1000 * 1000;
|
||||
break;
|
||||
const int64_t MEGA = 1000000;
|
||||
int64_t multiplier = 0;
|
||||
int64_t frequency = 0;
|
||||
uint8_t idx = 0;
|
||||
// The brand string buffer is at most 48 bytes.
|
||||
// -2 is to prevent buffer overrun when looking for y in yHz, as z is +2 from y.
|
||||
for (; idx < 48-2; ++idx) {
|
||||
// Format is either "x.xxyHz" or "xxxxyHz", where y=M, G, T and x are digits.
|
||||
// Search brand string for "yHz" where y is M, G, or T.
|
||||
if (brand_string[idx+1] == 'H' && brand_string[idx+2] == 'z') {
|
||||
if (brand_string[idx] == 'M') {
|
||||
multiplier = MEGA;
|
||||
} else if (brand_string[idx] == 'G') {
|
||||
multiplier = MEGA * 1000;
|
||||
} else if (brand_string[idx] == 'T') {
|
||||
multiplier = MEGA * MEGA;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (multiplier > 0) {
|
||||
// compute frequency (in Hz) from brand string
|
||||
if (*(Hz_location - 4) == '.') { // if format is "x.xx"
|
||||
frequency = (jlong)(*(Hz_location - 5) - '0') * (multiplier);
|
||||
frequency += (jlong)(*(Hz_location - 3) - '0') * (multiplier / 10);
|
||||
frequency += (jlong)(*(Hz_location - 2) - '0') * (multiplier / 100);
|
||||
// Compute freqency (in Hz) from brand string.
|
||||
if (brand_string[idx-3] == '.') { // if format is "x.xx"
|
||||
frequency = (brand_string[idx-4] - '0') * multiplier;
|
||||
frequency += (brand_string[idx-2] - '0') * multiplier / 10;
|
||||
frequency += (brand_string[idx-1] - '0') * multiplier / 100;
|
||||
} else { // format is "xxxx"
|
||||
frequency = (jlong)(*(Hz_location - 5) - '0') * 1000;
|
||||
frequency += (jlong)(*(Hz_location - 4) - '0') * 100;
|
||||
frequency += (jlong)(*(Hz_location - 3) - '0') * 10;
|
||||
frequency += (jlong)(*(Hz_location - 2) - '0');
|
||||
frequency = (brand_string[idx-4] - '0') * 1000;
|
||||
frequency += (brand_string[idx-3] - '0') * 100;
|
||||
frequency += (brand_string[idx-2] - '0') * 10;
|
||||
frequency += (brand_string[idx-1] - '0');
|
||||
frequency *= multiplier;
|
||||
}
|
||||
}
|
||||
@ -701,7 +695,7 @@ jlong VM_Version_Ext::max_qualified_cpu_freq_from_brand_string(void) {
|
||||
}
|
||||
|
||||
|
||||
jlong VM_Version_Ext::maximum_qualified_cpu_frequency(void) {
|
||||
int64_t VM_Version_Ext::maximum_qualified_cpu_frequency(void) {
|
||||
if (_max_qualified_cpu_frequency == 0) {
|
||||
_max_qualified_cpu_frequency = max_qualified_cpu_freq_from_brand_string();
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ class VM_Version_Ext : public VM_Version {
|
||||
static int _no_of_cores;
|
||||
static int _no_of_packages;
|
||||
static char* _cpu_brand_string;
|
||||
static jlong _max_qualified_cpu_frequency;
|
||||
static int64_t _max_qualified_cpu_frequency;
|
||||
|
||||
static const char* cpu_family_description(void);
|
||||
static const char* cpu_model_description(void);
|
||||
@ -72,7 +72,7 @@ class VM_Version_Ext : public VM_Version {
|
||||
// Returns bytes written excluding termninating null byte.
|
||||
static size_t cpu_write_support_string(char* const buf, size_t buf_len);
|
||||
static void resolve_cpu_information_details(void);
|
||||
static jlong max_qualified_cpu_freq_from_brand_string(void);
|
||||
static int64_t max_qualified_cpu_freq_from_brand_string(void);
|
||||
|
||||
public:
|
||||
// Offsets for cpuid asm stub brand string
|
||||
@ -93,7 +93,7 @@ class VM_Version_Ext : public VM_Version {
|
||||
static int number_of_cores(void);
|
||||
static int number_of_sockets(void);
|
||||
|
||||
static jlong maximum_qualified_cpu_frequency(void);
|
||||
static int64_t maximum_qualified_cpu_frequency(void);
|
||||
|
||||
static bool supports_tscinv_ext(void);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user