mirror of
https://github.com/anrieff/libcpuid
synced 2025-10-03 11:01:30 +00:00
Support for hybrid CPU (#166)
* Set CMAKE_C_FLAGS_DEBUG to display warnings during build CI workflows are reporting warnings. Adding more C flags here help to avoid that. * Add new types * Add set_cpu_affinity function * Add cpu_identify_all function * Add cpu_request_core_type function * Add cpuid_get_all_raw_data, cpuid_serialize_all_raw_data and cpuid_deserialize_all_raw_data functions * Detect hybrid architecture for Intel CPUs * Update cpuid_tool to detect all CPU logical cores * Rename tests subdirectories for Intel Core * Update all tests Since e4309a6c4bc3ad875711a1599cba01a205b3103e, new fields are reported by cpuid_tool * Add Intel Alder Lake Fix #157 * Remove convert_instlatx64.c This tool is not useful anymore because the cpuid_deserialize_raw_data_internal() function can natively parse them since5667e1401c
* Fix affinity_mask computation * Define _GNU_SOURCE in configure.ac Forgotten in4f80964db5
* Use dynamic raw array in cpu_raw_data_array_t * Add cpu_affinity_mask_t type * Improve set_cpu_affinity function - Print a warning if logical CPU number is not supported on operating system - Return a boolean value in case of success instead of an integer * Improve cpu_identify_all and cpu_request_core_type functions * Use dynamic array for cpu_types in system_id_t This commit also adds cleanups, fixes and consistency * Tests: update Ryzen 5 Matisse with all CPU cores * Add affinity_mask_str_r function and address other comments - Fixed cpuid_grow_raw_data_array and cpu_raw_data_array_t.logical_cpu_t with the correct type - Added a note about hard limit of cpu_raw_data_array_t - Fixed a typo in cpuid_deserialize_raw_data_internal * Fix build on Windows
This commit is contained in:
parent
9710e7c0ba
commit
2b8023f733
157 changed files with 8473 additions and 384 deletions
|
@ -58,6 +58,8 @@ char raw_data_file[256] = "";
|
|||
char out_file[256] = "";
|
||||
typedef enum {
|
||||
NEED_CPUID_PRESENT,
|
||||
NEED_ARCHITECTURE,
|
||||
NEED_PURPOSE,
|
||||
NEED_VENDOR_STR,
|
||||
NEED_VENDOR_ID,
|
||||
NEED_BRAND_STRING,
|
||||
|
@ -69,6 +71,7 @@ typedef enum {
|
|||
NEED_NUM_CORES,
|
||||
NEED_NUM_LOGICAL,
|
||||
NEED_TOTAL_CPUS,
|
||||
NEED_AFFI_MASK,
|
||||
NEED_L1D_SIZE,
|
||||
NEED_L1I_SIZE,
|
||||
NEED_L2_SIZE,
|
||||
|
@ -117,6 +120,8 @@ FILE *fout;
|
|||
const struct { output_data_switch sw; const char* synopsis; int ident_required; }
|
||||
matchtable[] = {
|
||||
{ NEED_CPUID_PRESENT, "--cpuid" , 0},
|
||||
{ NEED_ARCHITECTURE , "--architecture" , 1},
|
||||
{ NEED_PURPOSE , "--purpose" , 1},
|
||||
{ NEED_VENDOR_STR , "--vendorstr" , 1},
|
||||
{ NEED_VENDOR_ID , "--vendorid" , 1},
|
||||
{ NEED_BRAND_STRING , "--brandstr" , 1},
|
||||
|
@ -128,6 +133,7 @@ matchtable[] = {
|
|||
{ NEED_NUM_CORES , "--cores" , 1},
|
||||
{ NEED_NUM_LOGICAL , "--logical" , 1},
|
||||
{ NEED_TOTAL_CPUS , "--total-cpus" , 1},
|
||||
{ NEED_AFFI_MASK , "--affi-mask" , 1},
|
||||
{ NEED_L1D_SIZE , "--l1d-cache" , 1},
|
||||
{ NEED_L1I_SIZE , "--l1i-cache" , 1},
|
||||
{ NEED_L2_SIZE , "--cache" , 1},
|
||||
|
@ -337,8 +343,7 @@ static int check_need_raw_data(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void print_info(output_data_switch query, struct cpu_raw_data_t* raw,
|
||||
struct cpu_id_t* data)
|
||||
static void print_info(output_data_switch query, struct cpu_id_t* data)
|
||||
{
|
||||
int i, value;
|
||||
struct msr_driver_t* handle;
|
||||
|
@ -346,6 +351,12 @@ static void print_info(output_data_switch query, struct cpu_raw_data_t* raw,
|
|||
case NEED_CPUID_PRESENT:
|
||||
fprintf(fout, "%d\n", cpuid_present());
|
||||
break;
|
||||
case NEED_ARCHITECTURE:
|
||||
fprintf(fout, "%s\n", cpu_architecture_str(data->architecture));
|
||||
break;
|
||||
case NEED_PURPOSE:
|
||||
fprintf(fout, "%s\n", cpu_purpose_str(data->purpose));
|
||||
break;
|
||||
case NEED_VENDOR_STR:
|
||||
fprintf(fout, "%s\n", data->vendor_str);
|
||||
break;
|
||||
|
@ -379,6 +390,9 @@ static void print_info(output_data_switch query, struct cpu_raw_data_t* raw,
|
|||
case NEED_TOTAL_CPUS:
|
||||
fprintf(fout, "%d\n", cpuid_get_total_cpus());
|
||||
break;
|
||||
case NEED_AFFI_MASK:
|
||||
fprintf(fout, "0x%s\n", affinity_mask_str(&data->affinity_mask));
|
||||
break;
|
||||
case NEED_L1D_SIZE:
|
||||
fprintf(fout, "%d\n", data->l1_data_cache);
|
||||
break;
|
||||
|
@ -547,8 +561,15 @@ int main(int argc, char** argv)
|
|||
int parseres = parse_cmdline(argc, argv);
|
||||
int i, readres, writeres;
|
||||
int only_clock_queries;
|
||||
struct cpu_raw_data_t raw;
|
||||
struct cpu_id_t data;
|
||||
uint8_t cpu_type_index;
|
||||
struct cpu_raw_data_array_t raw_array = {
|
||||
.with_affinity = false,
|
||||
.num_raw = 0,
|
||||
.raw = NULL
|
||||
};
|
||||
struct system_id_t data = {
|
||||
.num_cpu_types = 0
|
||||
};
|
||||
|
||||
if (parseres != 1)
|
||||
return parseres;
|
||||
|
@ -580,10 +601,10 @@ int main(int argc, char** argv)
|
|||
/* We have a request to input raw CPUID data from file: */
|
||||
if (!strcmp(raw_data_file, "-"))
|
||||
/* Input from stdin */
|
||||
readres = cpuid_deserialize_raw_data(&raw, "");
|
||||
readres = cpuid_deserialize_all_raw_data(&raw_array, "");
|
||||
else
|
||||
/* Input from file */
|
||||
readres = cpuid_deserialize_raw_data(&raw, raw_data_file);
|
||||
readres = cpuid_deserialize_all_raw_data(&raw_array, raw_data_file);
|
||||
if (readres < 0) {
|
||||
if (!need_quiet) {
|
||||
fprintf(stderr, "Cannot deserialize raw data from ");
|
||||
|
@ -599,7 +620,7 @@ int main(int argc, char** argv)
|
|||
} else {
|
||||
if (check_need_raw_data()) {
|
||||
/* Try to obtain raw CPUID data from the CPU: */
|
||||
readres = cpuid_get_raw_data(&raw);
|
||||
readres = cpuid_get_all_raw_data(&raw_array);
|
||||
if (readres < 0) {
|
||||
if (!need_quiet) {
|
||||
fprintf(stderr, "Cannot obtain raw CPU data!\n");
|
||||
|
@ -616,10 +637,10 @@ int main(int argc, char** argv)
|
|||
printf("Writing raw CPUID dump to `%s'\n", raw_data_file);
|
||||
if (!strcmp(raw_data_file, "-"))
|
||||
/* Serialize to stdout */
|
||||
writeres = cpuid_serialize_raw_data(&raw, "");
|
||||
writeres = cpuid_serialize_all_raw_data(&raw_array, "");
|
||||
else
|
||||
/* Serialize to file */
|
||||
writeres = cpuid_serialize_raw_data(&raw, raw_data_file);
|
||||
writeres = cpuid_serialize_all_raw_data(&raw_array, raw_data_file);
|
||||
if (writeres < 0) {
|
||||
if (!need_quiet) {
|
||||
fprintf(stderr, "Cannot serialize raw data to ");
|
||||
|
@ -643,48 +664,53 @@ int main(int argc, char** argv)
|
|||
* Try CPU identification
|
||||
* (this fill the `data' structure with decoded CPU features)
|
||||
*/
|
||||
if (cpu_identify(&raw, &data) < 0)
|
||||
if (cpu_identify_all(&raw_array, &data) < 0)
|
||||
fprintf(fout, "Error identifying the CPU: %s\n", cpuid_error());
|
||||
|
||||
/* OK, now write what we have in `data'...: */
|
||||
fprintf(fout, "CPU Info:\n------------------\n");
|
||||
fprintf(fout, " vendor_str : `%s'\n", data.vendor_str);
|
||||
fprintf(fout, " vendor id : %d\n", (int) data.vendor);
|
||||
fprintf(fout, " brand_str : `%s'\n", data.brand_str);
|
||||
fprintf(fout, " family : %d (%02Xh)\n", data.family, data.family);
|
||||
fprintf(fout, " model : %d (%02Xh)\n", data.model, data.model);
|
||||
fprintf(fout, " stepping : %d (%02Xh)\n", data.stepping, data.stepping);
|
||||
fprintf(fout, " ext_family : %d (%02Xh)\n", data.ext_family, data.ext_family);
|
||||
fprintf(fout, " ext_model : %d (%02Xh)\n", data.ext_model, data.ext_model);
|
||||
fprintf(fout, " num_cores : %d\n", data.num_cores);
|
||||
fprintf(fout, " num_logical: %d\n", data.num_logical_cpus);
|
||||
fprintf(fout, " tot_logical: %d\n", data.total_logical_cpus);
|
||||
fprintf(fout, " L1 D cache : %d KB\n", data.l1_data_cache);
|
||||
fprintf(fout, " L1 I cache : %d KB\n", data.l1_instruction_cache);
|
||||
fprintf(fout, " L2 cache : %d KB\n", data.l2_cache);
|
||||
fprintf(fout, " L3 cache : %d KB\n", data.l3_cache);
|
||||
fprintf(fout, " L4 cache : %d KB\n", data.l4_cache);
|
||||
fprintf(fout, " L1D assoc. : %d-way\n", data.l1_data_assoc);
|
||||
fprintf(fout, " L1I assoc. : %d-way\n", data.l1_instruction_assoc);
|
||||
fprintf(fout, " L2 assoc. : %d-way\n", data.l2_assoc);
|
||||
fprintf(fout, " L3 assoc. : %d-way\n", data.l3_assoc);
|
||||
fprintf(fout, " L4 assoc. : %d-way\n", data.l4_assoc);
|
||||
fprintf(fout, " L1D line sz: %d bytes\n", data.l1_data_cacheline);
|
||||
fprintf(fout, " L1I line sz: %d bytes\n", data.l1_instruction_cacheline);
|
||||
fprintf(fout, " L2 line sz : %d bytes\n", data.l2_cacheline);
|
||||
fprintf(fout, " L3 line sz : %d bytes\n", data.l3_cacheline);
|
||||
fprintf(fout, " L4 line sz : %d bytes\n", data.l4_cacheline);
|
||||
fprintf(fout, " SSE units : %d bits (%s)\n", data.sse_size, data.detection_hints[CPU_HINT_SSE_SIZE_AUTH] ? "authoritative" : "non-authoritative");
|
||||
fprintf(fout, " code name : `%s'\n", data.cpu_codename);
|
||||
fprintf(fout, " features :");
|
||||
/*
|
||||
* Here we enumerate all CPU feature bits, and when a feature
|
||||
* is present output its name:
|
||||
*/
|
||||
for (i = 0; i < NUM_CPU_FEATURES; i++)
|
||||
if (data.flags[i])
|
||||
fprintf(fout, " %s", cpu_feature_str(i));
|
||||
fprintf(fout, "\n");
|
||||
for (cpu_type_index = 0; cpu_type_index < data.num_cpu_types; cpu_type_index++) {
|
||||
fprintf(fout, "CPU Info for type #%d:\n------------------\n", cpu_type_index);
|
||||
fprintf(fout, " arch : %s\n", cpu_architecture_str(data.cpu_types[cpu_type_index].architecture));
|
||||
fprintf(fout, " purpose : %s\n", cpu_purpose_str(data.cpu_types[cpu_type_index].purpose));
|
||||
fprintf(fout, " vendor_str : `%s'\n", data.cpu_types[cpu_type_index].vendor_str);
|
||||
fprintf(fout, " vendor id : %d\n", (int) data.cpu_types[cpu_type_index].vendor);
|
||||
fprintf(fout, " brand_str : `%s'\n", data.cpu_types[cpu_type_index].brand_str);
|
||||
fprintf(fout, " family : %d (%02Xh)\n", data.cpu_types[cpu_type_index].family, data.cpu_types[cpu_type_index].family);
|
||||
fprintf(fout, " model : %d (%02Xh)\n", data.cpu_types[cpu_type_index].model, data.cpu_types[cpu_type_index].model);
|
||||
fprintf(fout, " stepping : %d (%02Xh)\n", data.cpu_types[cpu_type_index].stepping, data.cpu_types[cpu_type_index].stepping);
|
||||
fprintf(fout, " ext_family : %d (%02Xh)\n", data.cpu_types[cpu_type_index].ext_family, data.cpu_types[cpu_type_index].ext_family);
|
||||
fprintf(fout, " ext_model : %d (%02Xh)\n", data.cpu_types[cpu_type_index].ext_model, data.cpu_types[cpu_type_index].ext_model);
|
||||
fprintf(fout, " num_cores : %d\n", data.cpu_types[cpu_type_index].num_cores);
|
||||
fprintf(fout, " num_logical: %d\n", data.cpu_types[cpu_type_index].num_logical_cpus);
|
||||
fprintf(fout, " tot_logical: %d\n", data.cpu_types[cpu_type_index].total_logical_cpus);
|
||||
fprintf(fout, " affi_mask : 0x%s\n", affinity_mask_str(&data.cpu_types[cpu_type_index].affinity_mask));
|
||||
fprintf(fout, " L1 D cache : %d KB\n", data.cpu_types[cpu_type_index].l1_data_cache);
|
||||
fprintf(fout, " L1 I cache : %d KB\n", data.cpu_types[cpu_type_index].l1_instruction_cache);
|
||||
fprintf(fout, " L2 cache : %d KB\n", data.cpu_types[cpu_type_index].l2_cache);
|
||||
fprintf(fout, " L3 cache : %d KB\n", data.cpu_types[cpu_type_index].l3_cache);
|
||||
fprintf(fout, " L4 cache : %d KB\n", data.cpu_types[cpu_type_index].l4_cache);
|
||||
fprintf(fout, " L1D assoc. : %d-way\n", data.cpu_types[cpu_type_index].l1_data_assoc);
|
||||
fprintf(fout, " L1I assoc. : %d-way\n", data.cpu_types[cpu_type_index].l1_instruction_assoc);
|
||||
fprintf(fout, " L2 assoc. : %d-way\n", data.cpu_types[cpu_type_index].l2_assoc);
|
||||
fprintf(fout, " L3 assoc. : %d-way\n", data.cpu_types[cpu_type_index].l3_assoc);
|
||||
fprintf(fout, " L4 assoc. : %d-way\n", data.cpu_types[cpu_type_index].l4_assoc);
|
||||
fprintf(fout, " L1D line sz: %d bytes\n", data.cpu_types[cpu_type_index].l1_data_cacheline);
|
||||
fprintf(fout, " L1I line sz: %d bytes\n", data.cpu_types[cpu_type_index].l1_instruction_cacheline);
|
||||
fprintf(fout, " L2 line sz : %d bytes\n", data.cpu_types[cpu_type_index].l2_cacheline);
|
||||
fprintf(fout, " L3 line sz : %d bytes\n", data.cpu_types[cpu_type_index].l3_cacheline);
|
||||
fprintf(fout, " L4 line sz : %d bytes\n", data.cpu_types[cpu_type_index].l4_cacheline);
|
||||
fprintf(fout, " SSE units : %d bits (%s)\n", data.cpu_types[cpu_type_index].sse_size, data.cpu_types[cpu_type_index].detection_hints[CPU_HINT_SSE_SIZE_AUTH] ? "authoritative" : "non-authoritative");
|
||||
fprintf(fout, " code name : `%s'\n", data.cpu_types[cpu_type_index].cpu_codename);
|
||||
fprintf(fout, " features :");
|
||||
/*
|
||||
* Here we enumerate all CPU feature bits, and when a feature
|
||||
* is present output its name:
|
||||
*/
|
||||
for (i = 0; i < NUM_CPU_FEATURES; i++)
|
||||
if (data.cpu_types[cpu_type_index].flags[i])
|
||||
fprintf(fout, " %s", cpu_feature_str(i));
|
||||
fprintf(fout, "\n");
|
||||
}
|
||||
|
||||
/* Is CPU clock info requested? */
|
||||
if (need_clockreport) {
|
||||
|
@ -714,23 +740,30 @@ int main(int argc, char** argv)
|
|||
}
|
||||
/* OK, process all queries. */
|
||||
if (((!need_report || !only_clock_queries) && num_requests > 0) || need_identify) {
|
||||
/* Identify the CPU. Make it do cpuid_get_raw_data() itself */
|
||||
if (check_need_raw_data() && cpu_identify(&raw, &data) < 0) {
|
||||
/* Identify the CPU. Make it do cpuid_get_all_raw_data() itself */
|
||||
if (check_need_raw_data() && cpu_identify_all(&raw_array, &data) < 0) {
|
||||
if (!need_quiet)
|
||||
fprintf(stderr,
|
||||
"Error identifying the CPU: %s\n",
|
||||
cpuid_error());
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < num_requests; i++)
|
||||
print_info(requests[i], &raw, &data);
|
||||
|
||||
for (cpu_type_index = 0; cpu_type_index < data.num_cpu_types; cpu_type_index++) {
|
||||
if (raw_array.with_affinity)
|
||||
fprintf(fout, "--------------------------------------------------------------------------------\n");
|
||||
for (i = 0; i < num_requests; i++)
|
||||
print_info(requests[i], &data.cpu_types[cpu_type_index]);
|
||||
}
|
||||
}
|
||||
if (need_cpulist) {
|
||||
print_cpulist();
|
||||
}
|
||||
if (need_sgx) {
|
||||
print_sgx_data(&raw, &data);
|
||||
print_sgx_data(&raw_array.raw[0], &data.cpu_types[0]);
|
||||
}
|
||||
|
||||
cpuid_free_raw_data_array(&raw_array);
|
||||
cpuid_free_system_id(&data);
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue