From b714dcb00df17e91bbf47c88d4652579b2253070 Mon Sep 17 00:00:00 2001 From: Xorg Date: Sun, 4 Sep 2022 19:46:30 +0200 Subject: [PATCH] Add cpu_identify_all function --- libcpuid/cpuid_main.c | 71 ++++++++++++++++++++++++++++++++++++++++++- libcpuid/exports.def | 1 + libcpuid/libcpuid.h | 14 +++++++++ libcpuid/libcpuid.sym | 1 + 4 files changed, 86 insertions(+), 1 deletion(-) diff --git a/libcpuid/cpuid_main.c b/libcpuid/cpuid_main.c index 440cc63..54f804e 100644 --- a/libcpuid/cpuid_main.c +++ b/libcpuid/cpuid_main.c @@ -682,8 +682,77 @@ int cpu_ident_internal(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data) { + int r; struct internal_id_info_t throwaway; - return cpu_ident_internal(raw, data, &throwaway); + r = cpu_ident_internal(raw, data, &throwaway); + data->affinity_mask = (1 << data->num_logical_cpus) - 1; + return r; +} + +int cpu_identify_all(struct cpu_raw_data_array_t *raw_array, struct system_id_t* system) +{ + int cur_error = set_error(ERR_OK); + int ret_error = set_error(ERR_OK); bool is_new_cpu_type; + uint8_t logical_cpu; + uint8_t cpu_type_index = 0; + int32_t core_previous_id = -1; + int32_t num_cores = 1; + int32_t num_logical_cpus = 1; + uint32_t affinity_mask = 0x00000001; + struct cpu_raw_data_array_t my_raw_array; + struct internal_id_info_t throwaway; + + if (!raw_array) { + if ((ret_error = cpuid_get_all_raw_data(&my_raw_array)) < 0) + return set_error(ret_error); + raw_array = &my_raw_array; + } + if (system == NULL) + return set_error(ERR_HANDLE); + system->num_cpu_types = 0; + + /* Iterate over all RAW */ + for (logical_cpu = 0; logical_cpu < raw_array->num_raw; logical_cpu++) { + debugf(2, "Identifying logical core %u...\n", logical_cpu); + is_new_cpu_type = false; + cur_error = cpu_ident_internal(&raw_array->raw[logical_cpu], &system->cpu_types[system->num_cpu_types], &throwaway); + if (ret_error == ERR_OK) + ret_error = cur_error; + + /* Copy data to system->cpu_types on the first iteration or when purpose is different than previous core */ + if ((system->num_cpu_types == 0) || (system->cpu_types[system->num_cpu_types].purpose != system->cpu_types[system->num_cpu_types - 1].purpose)) { + is_new_cpu_type = true; + system->num_cpu_types++; + } + /* Increment logical and physical CPU counters for current purpose */ + else { + affinity_mask |= 1 << logical_cpu; + num_logical_cpus++; + if (core_previous_id != throwaway.core_id) + num_cores++; + } + /* Update logical and physical CPU counters in system->cpu_types on the last iteration or when purpose is different than previous core */ + if ((logical_cpu + 1 == raw_array->num_raw) || (is_new_cpu_type && (system->num_cpu_types > 1))) { + cpu_type_index = is_new_cpu_type ? system->num_cpu_types - 2 : system->num_cpu_types - 1; + /* Save current values in system->cpu_types[cpu_type_index] */ + system->cpu_types[cpu_type_index].affinity_mask = affinity_mask; + if (core_previous_id > 0) { + system->cpu_types[cpu_type_index].num_cores = num_cores; + system->cpu_types[cpu_type_index].num_logical_cpus = num_logical_cpus; + } + /* Reset values for the next purpose */ + affinity_mask = 1 << logical_cpu; + num_cores = 1; + num_logical_cpus = 1; + } + core_previous_id = throwaway.core_id; + } + + /* Update the total_logical_cpus value for each purpose */ + for (cpu_type_index = 0; cpu_type_index < system->num_cpu_types; cpu_type_index++) + system->cpu_types[cpu_type_index].total_logical_cpus = logical_cpu; + + return ret_error; } const char* cpu_architecture_str(cpu_architecture_t architecture) diff --git a/libcpuid/exports.def b/libcpuid/exports.def index 698e3f6..fa17205 100644 --- a/libcpuid/exports.def +++ b/libcpuid/exports.def @@ -33,5 +33,6 @@ cpuid_get_vendor @29 cpu_rdmsr_range @30 cpuid_get_epc @31 msr_serialize_raw_data @32 +cpu_identify_all @36 cpu_architecture_str @38 cpu_purpose_str @39 diff --git a/libcpuid/libcpuid.h b/libcpuid/libcpuid.h index ec8d5ec..b64bfd9 100644 --- a/libcpuid/libcpuid.h +++ b/libcpuid/libcpuid.h @@ -770,6 +770,20 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename */ int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data); +/** + * @brief Identifies all the CPUs + * @param raw_array - Input - a pointer to the array of raw CPUID data, which is obtained + * either by cpuid_get_all_raw_data or cpuid_deserialize_all_raw_data. + * Can also be NULL, in which case the functions calls + * cpuid_get_all_raw_data itself. + * @param system - Output - the decoded CPU features/info is written here for each CPU type. + * @note The function is similar to cpu_identify. Refer to cpu_identify notes. + * @returns zero if successful, and some negative number on error. + * The error message can be obtained by calling \ref cpuid_error. + * @see cpu_error_t + */ +int cpu_identify_all(struct cpu_raw_data_array_t *raw_array, struct system_id_t* system); + /** * @brief Returns the short textual representation of a CPU architecture * @param architecture - the architecture, whose textual representation is wanted. diff --git a/libcpuid/libcpuid.sym b/libcpuid/libcpuid.sym index e5ff9fa..00d09bf 100644 --- a/libcpuid/libcpuid.sym +++ b/libcpuid/libcpuid.sym @@ -30,5 +30,6 @@ cpuid_get_vendor cpu_rdmsr_range cpuid_get_epc msr_serialize_raw_data +cpu_identify_all cpu_architecture_str cpu_purpose_str