1
0
Fork 0
mirror of https://github.com/anrieff/libcpuid synced 2025-10-03 11:01:30 +00:00

Add cpu_feature_level_t enumerated values for x86 CPUs

I had to fix run_tests.py to update all test files properly.
Fix #177
This commit is contained in:
The Tumultuous Unicorn Of Darkness 2024-06-29 17:01:50 +02:00
commit 959edc34e7
No known key found for this signature in database
GPG key ID: 1E55EE2EFF18BC1A
229 changed files with 388 additions and 12 deletions

View file

@ -1628,7 +1628,17 @@ const char* cpu_feature_level_str(cpu_feature_level_t level)
{
const struct { cpu_feature_level_t level; const char* name; }
matchtable[] = {
{ FEATURE_LEVEL_UNKNOWN, "unknown" },
{ FEATURE_LEVEL_UNKNOWN, "unknown" },
/* x86 */
{ CPU_FEATURE_LEVEL_I386, "i386" },
{ CPU_FEATURE_LEVEL_I486, "i486" },
{ CPU_FEATURE_LEVEL_I586, "i586" },
{ CPU_FEATURE_LEVEL_I686, "i686" },
{ CPU_FEATURE_LEVEL_X86_64_V1, "x86-64-v1" },
{ CPU_FEATURE_LEVEL_X86_64_V2, "x86-64-v2" },
{ CPU_FEATURE_LEVEL_X86_64_V3, "x86-64-v3" },
{ CPU_FEATURE_LEVEL_X86_64_V4, "x86-64-v4" },
/* ARM */
{ FEATURE_LEVEL_ARM_V1, "ARMv1" },
{ FEATURE_LEVEL_ARM_V2, "ARMv2" },
{ FEATURE_LEVEL_ARM_V3, "ARMv3" },
@ -1664,7 +1674,7 @@ const char* cpu_feature_level_str(cpu_feature_level_t level)
{ FEATURE_LEVEL_ARM_V9_4_A, "ARMv9.4-A" },
};
unsigned i, n = COUNT_OF(matchtable);
if (n != (NUM_CPU_FEATURE_LEVELS - FEATURE_LEVEL_ARM_V1) + 1) {
if (n != (NUM_CPU_FEATURE_LEVELS - FEATURE_LEVEL_ARM_V1) + (CPU_FEATURE_LEVEL_X86_64_V4 - CPU_FEATURE_LEVEL_I386) + 2) {
warnf("Warning: incomplete library, feature level matchtable size differs from the actual number of levels.\n");
}
for (i = 0; i < n; i++)

View file

@ -190,7 +190,17 @@ typedef enum {
* @brief CPU architecture
*/
typedef enum {
/* TODO: add x86 levels */
/* x86: https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels */
CPU_FEATURE_LEVEL_I386, /*!< i386 */
CPU_FEATURE_LEVEL_I486, /*!< i486 */
CPU_FEATURE_LEVEL_I586, /*!< i586 */
CPU_FEATURE_LEVEL_I686, /*!< i686 */
CPU_FEATURE_LEVEL_X86_64_V1, /*!< x86-64-v1 */
CPU_FEATURE_LEVEL_X86_64_V2, /*!< x86-64-v2 */
CPU_FEATURE_LEVEL_X86_64_V3, /*!< x86-64-v3 */
CPU_FEATURE_LEVEL_X86_64_V4, /*!< x86-64-v4 */
/* ARM: https://en.wikipedia.org/wiki/ARM_architecture_family#Cores */
FEATURE_LEVEL_ARM_V1 = 100, /*!< ARMv1 */
FEATURE_LEVEL_ARM_V2, /*!< ARMv2 */
FEATURE_LEVEL_ARM_V3, /*!< ARMv3 */

View file

@ -413,3 +413,104 @@ void decode_deterministic_cache_info_x86(uint32_t cache_regs[][NUM_REGS],
assign_cache_data(1, type, size, ways, linesize, data);
}
}
void decode_architecture_version_x86(struct cpu_id_t* data)
{
bool is_compliant, has_all_features;
int i, j;
cpu_feature_level_t feature_level = FEATURE_LEVEL_UNKNOWN;
const struct { const int family; const cpu_feature_level_t feature_level; }
architecture_matchtable_ia_32[] = {
{ 4, CPU_FEATURE_LEVEL_I486 },
{ 5, CPU_FEATURE_LEVEL_I586 },
{ 6, CPU_FEATURE_LEVEL_I686 },
{ 15, CPU_FEATURE_LEVEL_I686 }, // Intel Pentium 4, AMD K8
};
const cpu_feature_t architecture_x86_64_v1[] = {
CPU_FEATURE_CMOV,
CPU_FEATURE_CX8,
CPU_FEATURE_FPU,
CPU_FEATURE_FXSR,
CPU_FEATURE_MMX,
CPU_FEATURE_SSE,
CPU_FEATURE_SSE2,
-1
};
const cpu_feature_t architecture_x86_64_v2[] = {
CPU_FEATURE_CX16,
CPU_FEATURE_LAHF_LM,
CPU_FEATURE_POPCNT,
CPU_FEATURE_PNI,
CPU_FEATURE_SSE4_1,
CPU_FEATURE_SSE4_2,
CPU_FEATURE_SSSE3,
-1
};
const cpu_feature_t architecture_x86_64_v3[] = {
CPU_FEATURE_AVX,
CPU_FEATURE_AVX2,
CPU_FEATURE_BMI1,
CPU_FEATURE_BMI2,
CPU_FEATURE_F16C,
CPU_FEATURE_FMA3,
CPU_FEATURE_ABM,
CPU_FEATURE_MOVBE,
CPU_FEATURE_OSXSAVE,
-1
};
const cpu_feature_t architecture_x86_64_v4[] = {
CPU_FEATURE_AVX512F,
CPU_FEATURE_AVX512BW,
CPU_FEATURE_AVX512CD,
CPU_FEATURE_AVX512DQ,
CPU_FEATURE_AVX512VL,
-1
};
const struct { const cpu_feature_t* features_array; const cpu_feature_level_t feature_level; }
architecture_matchtable_x86_64[] = {
{ architecture_x86_64_v1, CPU_FEATURE_LEVEL_X86_64_V1 },
{ architecture_x86_64_v2, CPU_FEATURE_LEVEL_X86_64_V2 },
{ architecture_x86_64_v3, CPU_FEATURE_LEVEL_X86_64_V3 },
{ architecture_x86_64_v4, CPU_FEATURE_LEVEL_X86_64_V4 },
};
if (!data->flags[CPU_FEATURE_LM]) {
/* Check Intel Architecture, 32-bit */
for (i = 0; i < COUNT_OF(architecture_matchtable_ia_32); i++) {
is_compliant = (data->x86.family == architecture_matchtable_ia_32[i].family);
debugf(3, "Check if CPU is %s compliant: %s for family %i\n", cpu_feature_level_str(architecture_matchtable_ia_32[i].feature_level), is_compliant ? "yes" : "no", architecture_matchtable_ia_32[i].family);
if (is_compliant) {
feature_level = architecture_matchtable_ia_32[i].feature_level;
break;
}
}
}
else {
/* Check Intel Architecture, 64-bit */
for (i = 0; i < COUNT_OF(architecture_matchtable_x86_64); i++) {
debugf(3, "Check if CPU is %s compliant:\n", cpu_feature_level_str(architecture_matchtable_x86_64[i].feature_level));
has_all_features = true;
for (j = 0; architecture_matchtable_x86_64[i].features_array[j] != -1; j++) {
is_compliant = data->flags[ architecture_matchtable_x86_64[i].features_array[j] ];
has_all_features = has_all_features && is_compliant;
debugf(3, " - feature %s is %s\n", cpu_feature_str(architecture_matchtable_x86_64[i].features_array[j]), is_compliant ? "present" : "absent");
}
if (is_compliant)
feature_level = architecture_matchtable_x86_64[i].feature_level;
else
break;
}
}
data->feature_level = feature_level;
if (feature_level == FEATURE_LEVEL_UNKNOWN)
warnf("Warning: CPU with CPUID signature %02X_%02XH has an unkown architecture version (LM=%i).\n", data->x86.ext_family, data->x86.ext_model, data->flags[CPU_FEATURE_LM]);
else
debugf(2, "x86 architecture version is %s\n", cpu_feature_level_str(feature_level));
}

View file

@ -134,4 +134,7 @@ void decode_deterministic_cache_info_x86(uint32_t cache_regs[][NUM_REGS],
struct cpu_id_t* data,
struct internal_id_info_t* internal);
/* generic way to get microarchitecture levels for x86 CPUs */
void decode_architecture_version_x86(struct cpu_id_t* data);
#endif /* __LIBCPUID_UTIL_H__ */

View file

@ -676,6 +676,7 @@ int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct
decode_amd_cache_info(raw, data);
decode_amd_number_of_cores(raw, data);
decode_amd_codename(data, internal);
decode_architecture_version_x86(data);
return 0;
}

View file

@ -207,6 +207,7 @@ int cpuid_identify_centaur(struct cpu_raw_data_t* raw, struct cpu_id_t* data, st
if (raw->basic_cpuid[0][EAX] >= 4)
decode_deterministic_cache_info_x86(raw->intel_fn4, MAX_INTELFN4_LEVEL, data, internal);
decode_number_of_cores_x86(raw, data);
decode_architecture_version_x86(data);
brand = get_brand_code_and_bits(data);
model_code = get_model_code(data, brand);

View file

@ -1100,6 +1100,7 @@ int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, stru
if ((raw->basic_cpuid[0][EAX] < 11) || (decode_intel_extended_topology(raw, data) == 0))
decode_number_of_cores_x86(raw, data);
data->purpose = cpuid_identify_purpose_intel(raw);
decode_architecture_version_x86(data);
brand = get_brand_code_and_bits(data);
model_code = get_model_code(data);