1
0
Fork 0
mirror of https://github.com/anrieff/libcpuid synced 2024-12-16 16:35:45 +00:00

Use APIC ID to count physical core when supported

Fix #175
This commit is contained in:
Xorg 2022-10-22 20:32:05 +02:00
parent 23b6f5cf54
commit 737cc3d98e
No known key found for this signature in database
GPG key ID: 1E55EE2EFF18BC1A
2 changed files with 50 additions and 6 deletions

View file

@ -103,6 +103,12 @@ static void apic_info_t_constructor(struct internal_apic_info_t* apic_info, logi
apic_info->logical_cpu = logical_cpu;
}
static void core_instances_t_constructor(struct internal_core_instances_t* data)
{
data->instances = 0;
memset(data->htable, 0, sizeof(data->htable));
}
static void cache_instances_t_constructor(struct internal_cache_instances_t* data)
{
memset(data->instances, 0, sizeof(data->instances));
@ -1009,6 +1015,24 @@ int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
return r;
}
static void update_core_instances(struct internal_core_instances_t* cores,
struct internal_apic_info_t* apic_info)
{
uint32_t core_id_index = 0;
core_id_index = apic_info->core_id % CORES_HTABLE_SIZE;
if ((cores->htable[core_id_index].core_id == 0) || (cores->htable[core_id_index].core_id == apic_info->core_id)) {
if (cores->htable[core_id_index].num_logical_cpu == 0)
cores->instances++;
cores->htable[core_id_index].core_id = apic_info->core_id;
cores->htable[core_id_index].num_logical_cpu++;
}
else {
warnf("update_core_instances: collision at index %u (core ID is %i, not %i)\n",
core_id_index, cores->htable[core_id_index].core_id, apic_info->core_id);
}
}
static void update_cache_instances(struct internal_cache_instances_t* caches,
struct internal_apic_info_t* apic_info,
struct internal_id_info_t* id_info)
@ -1059,6 +1083,7 @@ int cpu_identify_all(struct cpu_raw_data_array_t* raw_array, struct system_id_t*
struct cpu_raw_data_array_t my_raw_array;
struct internal_id_info_t id_info;
struct internal_apic_info_t apic_info;
struct internal_core_instances_t cores_type;
struct internal_cache_instances_t caches_type, caches_all;
if (system == NULL)
@ -1069,6 +1094,7 @@ int cpu_identify_all(struct cpu_raw_data_array_t* raw_array, struct system_id_t*
raw_array = &my_raw_array;
}
system_id_t_constructor(system);
core_instances_t_constructor(&cores_type);
cache_instances_t_constructor(&caches_type);
cache_instances_t_constructor(&caches_all);
if (raw_array->with_affinity)
@ -1104,6 +1130,7 @@ int cpu_identify_all(struct cpu_raw_data_array_t* raw_array, struct system_id_t*
set_affinity_mask_bit(logical_cpu, &affinity_mask);
num_logical_cpus++;
if (is_apic_supported) {
update_core_instances(&cores_type, &apic_info);
update_cache_instances(&caches_type, &apic_info, &id_info);
update_cache_instances(&caches_all, &apic_info, &id_info);
}
@ -1112,29 +1139,35 @@ int cpu_identify_all(struct cpu_raw_data_array_t* raw_array, struct system_id_t*
/* Update logical and physical CPU counters in system->cpu_types on the last iteration or when purpose is different than previous core */
if (raw_array->with_affinity && (is_last_item || (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;
is_smt_supported = (system->cpu_types[cpu_type_index].num_logical_cpus % system->cpu_types[cpu_type_index].num_cores) == 0;
smt_divisor = is_smt_supported ? system->cpu_types[cpu_type_index].num_logical_cpus / system->cpu_types[cpu_type_index].num_cores : 1.0;
/* Save current values in system->cpu_types[cpu_type_index] and reset values for the next purpose */
system->cpu_types[cpu_type_index].num_cores = num_logical_cpus / smt_divisor;
system->cpu_types[cpu_type_index].num_logical_cpus = num_logical_cpus;
num_logical_cpus = 1;
copy_affinity_mask(&system->cpu_types[cpu_type_index].affinity_mask, &affinity_mask);
if (!is_last_item) {
init_affinity_mask(&affinity_mask);
set_affinity_mask_bit(logical_cpu, &affinity_mask);
}
if (is_apic_supported) {
system->cpu_types[cpu_type_index].num_cores = cores_type.instances;
system->cpu_types[cpu_type_index].l1_instruction_instances = caches_type.instances[L1I];
system->cpu_types[cpu_type_index].l1_data_instances = caches_type.instances[L1D];
system->cpu_types[cpu_type_index].l2_instances = caches_type.instances[L2];
system->cpu_types[cpu_type_index].l3_instances = caches_type.instances[L3];
system->cpu_types[cpu_type_index].l4_instances = caches_type.instances[L4];
if (!is_last_item) {
core_instances_t_constructor(&cores_type);
cache_instances_t_constructor(&caches_type);
update_core_instances(&cores_type, &apic_info);
update_cache_instances(&caches_type, &apic_info, &id_info);
update_cache_instances(&caches_all, &apic_info, &id_info);
}
}
else {
/* Note: if SMT is disabled by BIOS, smt_divisor will no reflect the current state properly */
is_smt_supported = (system->cpu_types[cpu_type_index].num_logical_cpus % system->cpu_types[cpu_type_index].num_cores) == 0;
smt_divisor = is_smt_supported ? system->cpu_types[cpu_type_index].num_logical_cpus / system->cpu_types[cpu_type_index].num_cores : 1.0;
system->cpu_types[cpu_type_index].num_cores = num_logical_cpus / smt_divisor;
}
/* Save current values in system->cpu_types[cpu_type_index] and reset values for the next purpose */
system->cpu_types[cpu_type_index].num_logical_cpus = num_logical_cpus;
num_logical_cpus = 1;
}
prev_package_id = cur_package_id;
}

View file

@ -81,11 +81,22 @@ struct internal_apic_info_t {
logical_cpu_t logical_cpu;
};
struct internal_core_id_t {
logical_cpu_t num_logical_cpu;
int32_t core_id;
};
struct internal_cache_id_t {
logical_cpu_t num_logical_cpu;
int32_t cache_id;
};
#define CORES_HTABLE_SIZE 256
struct internal_core_instances_t {
uint8_t instances;
struct internal_core_id_t htable[CORES_HTABLE_SIZE];
};
#define CACHES_HTABLE_SIZE 256
struct internal_cache_instances_t {
uint8_t instances[NUM_CACHE_TYPES];