1
0
Fork 0
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 since 5667e1401c

* Fix affinity_mask computation

* Define _GNU_SOURCE in configure.ac

Forgotten in 4f80964db5

* 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:
Xorg 2022-09-15 18:37:08 +02:00 committed by GitHub
commit 2b8023f733
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
157 changed files with 8473 additions and 384 deletions

View file

@ -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;
}