Skip to content

Commit 63ce304

Browse files
author
Markus Grönlund
committed
8249675: x86: frequency extraction from cpu brand string is incomplete
Reviewed-by: egahlin, dholmes
1 parent e52156d commit 63ce304

File tree

2 files changed

+38
-44
lines changed

2 files changed

+38
-44
lines changed

src/hotspot/cpu/x86/vm_version_ext_x86.cpp

Lines changed: 35 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ const size_t VM_Version_Ext::CPU_EBS_MAX_LENGTH = (3 * 4 * 4 + 1);
256256
const size_t VM_Version_Ext::CPU_TYPE_DESC_BUF_SIZE = 256;
257257
const size_t VM_Version_Ext::CPU_DETAILED_DESC_BUF_SIZE = 4096;
258258
char* VM_Version_Ext::_cpu_brand_string = NULL;
259-
jlong VM_Version_Ext::_max_qualified_cpu_frequency = 0;
259+
int64_t VM_Version_Ext::_max_qualified_cpu_frequency = 0;
260260

261261
int VM_Version_Ext::_no_of_threads = 0;
262262
int VM_Version_Ext::_no_of_cores = 0;
@@ -644,64 +644,58 @@ const char* VM_Version_Ext::cpu_description(void) {
644644
}
645645

646646
/**
647-
* See Intel Application note 485 (chapter 10) for details
648-
* on frequency extraction from cpu brand string.
649-
* http://www.intel.com/content/dam/www/public/us/en/documents/application-notes/processor-identification-cpuid-instruction-note.pdf
647+
* For information about extracting the frequency from the cpu brand string, please see:
650648
*
649+
* Intel Processor Identification and the CPUID Instruction
650+
* Application Note 485
651+
* May 2012
652+
*
653+
* The return value is the frequency in Hz.
651654
*/
652-
jlong VM_Version_Ext::max_qualified_cpu_freq_from_brand_string(void) {
653-
// get brand string
655+
int64_t VM_Version_Ext::max_qualified_cpu_freq_from_brand_string(void) {
654656
const char* const brand_string = cpu_brand_string();
655657
if (brand_string == NULL) {
656658
return 0;
657659
}
658-
659-
const u8 MEGA = 1000000;
660-
u8 multiplier = 0;
661-
jlong frequency = 0;
662-
663-
// the frequency information in the cpu brand string
664-
// is given in either of two formats "x.xxyHz" or "xxxxyHz",
665-
// where y=M,G,T and x is digits
666-
const char* Hz_location = strchr(brand_string, 'H');
667-
668-
if (Hz_location != NULL) {
669-
if (*(Hz_location + 1) == 'z') {
670-
// switch on y in "yHz"
671-
switch(*(Hz_location - 1)) {
672-
case 'M' :
673-
// Set multiplier to frequency is in Hz
674-
multiplier = MEGA;
675-
break;
676-
case 'G' :
677-
multiplier = MEGA * 1000;
678-
break;
679-
case 'T' :
680-
multiplier = MEGA * 1000 * 1000;
681-
break;
660+
const int64_t MEGA = 1000000;
661+
int64_t multiplier = 0;
662+
int64_t frequency = 0;
663+
uint8_t idx = 0;
664+
// The brand string buffer is at most 48 bytes.
665+
// -2 is to prevent buffer overrun when looking for y in yHz, as z is +2 from y.
666+
for (; idx < 48-2; ++idx) {
667+
// Format is either "x.xxyHz" or "xxxxyHz", where y=M, G, T and x are digits.
668+
// Search brand string for "yHz" where y is M, G, or T.
669+
if (brand_string[idx+1] == 'H' && brand_string[idx+2] == 'z') {
670+
if (brand_string[idx] == 'M') {
671+
multiplier = MEGA;
672+
} else if (brand_string[idx] == 'G') {
673+
multiplier = MEGA * 1000;
674+
} else if (brand_string[idx] == 'T') {
675+
multiplier = MEGA * MEGA;
682676
}
677+
break;
683678
}
684679
}
685-
686680
if (multiplier > 0) {
687-
// compute frequency (in Hz) from brand string
688-
if (*(Hz_location - 4) == '.') { // if format is "x.xx"
689-
frequency = (jlong)(*(Hz_location - 5) - '0') * (multiplier);
690-
frequency += (jlong)(*(Hz_location - 3) - '0') * (multiplier / 10);
691-
frequency += (jlong)(*(Hz_location - 2) - '0') * (multiplier / 100);
681+
// Compute freqency (in Hz) from brand string.
682+
if (brand_string[idx-3] == '.') { // if format is "x.xx"
683+
frequency = (brand_string[idx-4] - '0') * multiplier;
684+
frequency += (brand_string[idx-2] - '0') * multiplier / 10;
685+
frequency += (brand_string[idx-1] - '0') * multiplier / 100;
692686
} else { // format is "xxxx"
693-
frequency = (jlong)(*(Hz_location - 5) - '0') * 1000;
694-
frequency += (jlong)(*(Hz_location - 4) - '0') * 100;
695-
frequency += (jlong)(*(Hz_location - 3) - '0') * 10;
696-
frequency += (jlong)(*(Hz_location - 2) - '0');
687+
frequency = (brand_string[idx-4] - '0') * 1000;
688+
frequency += (brand_string[idx-3] - '0') * 100;
689+
frequency += (brand_string[idx-2] - '0') * 10;
690+
frequency += (brand_string[idx-1] - '0');
697691
frequency *= multiplier;
698692
}
699693
}
700694
return frequency;
701695
}
702696

703697

704-
jlong VM_Version_Ext::maximum_qualified_cpu_frequency(void) {
698+
int64_t VM_Version_Ext::maximum_qualified_cpu_frequency(void) {
705699
if (_max_qualified_cpu_frequency == 0) {
706700
_max_qualified_cpu_frequency = max_qualified_cpu_freq_from_brand_string();
707701
}

src/hotspot/cpu/x86/vm_version_ext_x86.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class VM_Version_Ext : public VM_Version {
5555
static int _no_of_cores;
5656
static int _no_of_packages;
5757
static char* _cpu_brand_string;
58-
static jlong _max_qualified_cpu_frequency;
58+
static int64_t _max_qualified_cpu_frequency;
5959

6060
static const char* cpu_family_description(void);
6161
static const char* cpu_model_description(void);
@@ -72,7 +72,7 @@ class VM_Version_Ext : public VM_Version {
7272
// Returns bytes written excluding termninating null byte.
7373
static size_t cpu_write_support_string(char* const buf, size_t buf_len);
7474
static void resolve_cpu_information_details(void);
75-
static jlong max_qualified_cpu_freq_from_brand_string(void);
75+
static int64_t max_qualified_cpu_freq_from_brand_string(void);
7676

7777
public:
7878
// Offsets for cpuid asm stub brand string
@@ -93,7 +93,7 @@ class VM_Version_Ext : public VM_Version {
9393
static int number_of_cores(void);
9494
static int number_of_sockets(void);
9595

96-
static jlong maximum_qualified_cpu_frequency(void);
96+
static int64_t maximum_qualified_cpu_frequency(void);
9797

9898
static bool supports_tscinv_ext(void);
9999

0 commit comments

Comments
 (0)