Redefine cluster on x86 as min(LLC, package)
diff --git a/src/x86/linux/init.c b/src/x86/linux/init.c
index fadd99c..574ac43 100644
--- a/src/x86/linux/init.c
+++ b/src/x86/linux/init.c
@@ -49,7 +49,9 @@
uint32_t linux_processors_count,
const struct cpuinfo_x86_linux_processor linux_processors[restrict static linux_processors_count],
const struct cpuinfo_x86_processor processor[restrict static 1],
+ uint32_t llc_apic_bits,
uint32_t cores_count_ptr[restrict static 1],
+ uint32_t clusters_count_ptr[restrict static 1],
uint32_t packages_count_ptr[restrict static 1],
uint32_t l1i_count_ptr[restrict static 1],
uint32_t l1d_count_ptr[restrict static 1],
@@ -57,9 +59,16 @@
uint32_t l3_count_ptr[restrict static 1],
uint32_t l4_count_ptr[restrict static 1])
{
- uint32_t cores_count = 0, packages_count = 0;
+ const uint32_t core_apic_mask =
+ ~(bit_mask(processor->topology.thread_bits_length) << processor->topology.thread_bits_offset);
+ const uint32_t package_apic_mask =
+ core_apic_mask & ~(bit_mask(processor->topology.core_bits_length) << processor->topology.core_bits_offset);
+ const uint32_t llc_apic_mask = ~bit_mask(llc_apic_bits);
+ const uint32_t cluster_apic_mask = package_apic_mask | llc_apic_mask;
+
+ uint32_t cores_count = 0, clusters_count = 0, packages_count = 0;
uint32_t l1i_count = 0, l1d_count = 0, l2_count = 0, l3_count = 0, l4_count = 0;
- uint32_t last_core_id = UINT32_MAX, last_package_id = UINT32_MAX;
+ uint32_t last_core_id = UINT32_MAX, last_cluster_id = UINT32_MAX, last_package_id = UINT32_MAX;
uint32_t last_l1i_id = UINT32_MAX, last_l1d_id = UINT32_MAX;
uint32_t last_l2_id = UINT32_MAX, last_l3_id = UINT32_MAX, last_l4_id = UINT32_MAX;
for (uint32_t i = 0; i < linux_processors_count; i++) {
@@ -68,19 +77,23 @@
cpuinfo_log_debug("APID ID %"PRIu32": system processor %"PRIu32, apic_id, linux_processors[i].linux_id);
/* All bits of APIC ID except thread ID mask */
- const uint32_t core_id = apic_id &
- ~(bit_mask(processor->topology.thread_bits_length) << processor->topology.thread_bits_offset);
+ const uint32_t core_id = apic_id & core_apic_mask;
if (core_id != last_core_id) {
last_core_id = core_id;
cores_count++;
}
/* All bits of APIC ID except thread ID and core ID masks */
- const uint32_t package_id = core_id &
- ~(bit_mask(processor->topology.core_bits_length) << processor->topology.core_bits_offset);
+ const uint32_t package_id = apic_id & package_apic_mask;
if (package_id != last_package_id) {
last_package_id = package_id;
packages_count++;
}
+ /* Bits of APIC ID which are part of either LLC or package ID mask */
+ const uint32_t cluster_id = apic_id & cluster_apic_mask;
+ if (cluster_id != last_cluster_id) {
+ last_cluster_id = cluster_id;
+ clusters_count++;
+ }
if (processor->cache.l1i.size != 0) {
const uint32_t l1i_id = apic_id & ~bit_mask(processor->cache.l1i.apic_bits);
if (l1i_id != last_l1i_id) {
@@ -119,6 +132,7 @@
}
}
*cores_count_ptr = cores_count;
+ *clusters_count_ptr = clusters_count;
*packages_count_ptr = packages_count;
*l1i_count_ptr = l1i_count;
*l1d_count_ptr = l1d_count;
@@ -200,12 +214,23 @@
goto cleanup;
}
- uint32_t packages_count = 0, cores_count = 0;
+ uint32_t llc_apic_bits = 0;
+ if (x86_processor.cache.l4.size != 0) {
+ llc_apic_bits = x86_processor.cache.l4.apic_bits;
+ } else if (x86_processor.cache.l3.size != 0) {
+ llc_apic_bits = x86_processor.cache.l3.apic_bits;
+ } else if (x86_processor.cache.l2.size != 0) {
+ llc_apic_bits = x86_processor.cache.l2.apic_bits;
+ } else if (x86_processor.cache.l1d.size != 0) {
+ llc_apic_bits = x86_processor.cache.l1d.apic_bits;
+ }
+ uint32_t packages_count = 0, clusters_count = 0, cores_count = 0;
uint32_t l1i_count = 0, l1d_count = 0, l2_count = 0, l3_count = 0, l4_count = 0;
- cpuinfo_x86_count_objects(x86_linux_processors_count, x86_linux_processors, &x86_processor,
- &cores_count, &packages_count, &l1i_count, &l1d_count, &l2_count, &l3_count, &l4_count);
+ cpuinfo_x86_count_objects(x86_linux_processors_count, x86_linux_processors, &x86_processor, llc_apic_bits,
+ &cores_count, &clusters_count, &packages_count, &l1i_count, &l1d_count, &l2_count, &l3_count, &l4_count);
cpuinfo_log_debug("detected %"PRIu32" cores", cores_count);
+ cpuinfo_log_debug("detected %"PRIu32" clusters", clusters_count);
cpuinfo_log_debug("detected %"PRIu32" packages", packages_count);
cpuinfo_log_debug("detected %"PRIu32" L1I caches", l1i_count);
cpuinfo_log_debug("detected %"PRIu32" L1D caches", l1d_count);
@@ -236,11 +261,10 @@
goto cleanup;
}
- /* On x86 cluster of cores is a physical package */
- clusters = calloc(packages_count, sizeof(struct cpuinfo_cluster));
+ clusters = calloc(clusters_count, sizeof(struct cpuinfo_cluster));
if (clusters == NULL) {
cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" core clusters",
- packages_count * sizeof(struct cpuinfo_cluster), packages_count);
+ clusters_count * sizeof(struct cpuinfo_cluster), clusters_count);
goto cleanup;
}
@@ -292,10 +316,17 @@
}
}
- uint32_t processor_index = UINT32_MAX, core_index = UINT32_MAX, package_index = UINT32_MAX;
+ const uint32_t core_apic_mask =
+ ~(bit_mask(x86_processor.topology.thread_bits_length) << x86_processor.topology.thread_bits_offset);
+ const uint32_t package_apic_mask =
+ core_apic_mask & ~(bit_mask(x86_processor.topology.core_bits_length) << x86_processor.topology.core_bits_offset);
+ const uint32_t llc_apic_mask = ~bit_mask(llc_apic_bits);
+ const uint32_t cluster_apic_mask = package_apic_mask | llc_apic_mask;
+
+ uint32_t processor_index = UINT32_MAX, core_index = UINT32_MAX, cluster_index = UINT32_MAX, package_index = UINT32_MAX;
uint32_t l1i_index = UINT32_MAX, l1d_index = UINT32_MAX, l2_index = UINT32_MAX, l3_index = UINT32_MAX, l4_index = UINT32_MAX;
- uint32_t core_id = 0, smt_id = 0;
- uint32_t last_apic_core_id = UINT32_MAX, last_apic_package_id = UINT32_MAX;
+ uint32_t cluster_id = 0, core_id = 0, smt_id = 0;
+ uint32_t last_apic_core_id = UINT32_MAX, last_apic_cluster_id = UINT32_MAX, last_apic_package_id = UINT32_MAX;
uint32_t last_l1i_id = UINT32_MAX, last_l1d_id = UINT32_MAX;
uint32_t last_l2_id = UINT32_MAX, last_l3_id = UINT32_MAX, last_l4_id = UINT32_MAX;
for (uint32_t i = 0; i < x86_linux_processors_count; i++) {
@@ -305,25 +336,30 @@
smt_id++;
/* All bits of APIC ID except thread ID mask */
- const uint32_t apid_core_id = apic_id &
- ~(bit_mask(x86_processor.topology.thread_bits_length) << x86_processor.topology.thread_bits_offset);
+ const uint32_t apid_core_id = apic_id & core_apic_mask;
if (apid_core_id != last_apic_core_id) {
core_index++;
core_id++;
smt_id = 0;
}
+ /* Bits of APIC ID which are part of either LLC or package ID mask */
+ const uint32_t apic_cluster_id = apic_id & cluster_apic_mask;
+ if (apic_cluster_id != last_apic_cluster_id) {
+ cluster_index++;
+ cluster_id++;
+ }
/* All bits of APIC ID except thread ID and core ID masks */
- const uint32_t apic_package_id = apid_core_id &
- ~(bit_mask(x86_processor.topology.core_bits_length) << x86_processor.topology.core_bits_offset);
+ const uint32_t apic_package_id = apic_id & package_apic_mask;
if (apic_package_id != last_apic_package_id) {
package_index++;
core_id = 0;
+ cluster_id = 0;
}
/* Initialize logical processor object */
processors[processor_index].smt_id = smt_id;
processors[processor_index].core = cores + core_index;
- processors[processor_index].cluster = clusters + package_index;
+ processors[processor_index].cluster = clusters + cluster_index;
processors[processor_index].package = packages + package_index;
processors[processor_index].linux_id = x86_linux_processors[i].linux_id;
processors[processor_index].apic_id = x86_linux_processors[i].apic_id;
@@ -334,13 +370,13 @@
.processor_start = processor_index,
.processor_count = 1,
.core_id = core_id,
- .cluster = clusters + package_index,
+ .cluster = clusters + cluster_index,
.package = packages + package_index,
.vendor = x86_processor.vendor,
.uarch = x86_processor.uarch,
.cpuid = x86_processor.cpuid,
};
- clusters[package_index].core_count += 1;
+ clusters[cluster_index].core_count += 1;
packages[package_index].core_count += 1;
last_apic_core_id = apid_core_id;
} else {
@@ -348,26 +384,33 @@
cores[core_index].processor_count++;
}
- if (apic_package_id != last_apic_package_id) {
- /* new cluster/package */
+ if (apic_cluster_id != last_apic_cluster_id) {
+ /* new cluster */
+ clusters[cluster_index].processor_start = processor_index;
+ clusters[cluster_index].processor_count = 1;
+ clusters[cluster_index].core_start = core_index;
+ clusters[cluster_index].cluster_id = cluster_id;
+ clusters[cluster_index].package = packages + package_index;
+ clusters[cluster_index].vendor = x86_processor.vendor;
+ clusters[cluster_index].uarch = x86_processor.uarch;
+ clusters[cluster_index].cpuid = x86_processor.cpuid;
+ packages[package_index].cluster_count += 1;
+ last_apic_cluster_id = apic_cluster_id;
+ } else {
+ /* another logical processor on the same cluster */
+ clusters[cluster_index].processor_count++;
+ }
- clusters[package_index].processor_start = processor_index;
- clusters[package_index].processor_count = 1;
- clusters[package_index].core_start = core_index;
- clusters[package_index].package = packages + package_index;
- clusters[package_index].vendor = x86_processor.vendor;
- clusters[package_index].uarch = x86_processor.uarch;
- clusters[package_index].cpuid = x86_processor.cpuid;
+ if (apic_package_id != last_apic_package_id) {
+ /* new package */
packages[package_index].processor_start = processor_index;
packages[package_index].processor_count = 1;
packages[package_index].core_start = core_index;
- packages[package_index].cluster_start = package_index;
- packages[package_index].cluster_count = 1;
+ packages[package_index].cluster_start = cluster_index;
cpuinfo_x86_format_package_name(x86_processor.vendor, brand_string, packages[package_index].name);
last_apic_package_id = apic_package_id;
} else {
- /* another logical processor on the same cluster/package */
- clusters[package_index].processor_count++;
+ /* another logical processor on the same package */
packages[package_index].processor_count++;
}
@@ -526,7 +569,7 @@
cpuinfo_processors_count = processors_count;
cpuinfo_cores_count = cores_count;
- cpuinfo_clusters_count = packages_count;
+ cpuinfo_clusters_count = clusters_count;
cpuinfo_packages_count = packages_count;
cpuinfo_cache_count[cpuinfo_cache_level_1i] = l1i_count;
cpuinfo_cache_count[cpuinfo_cache_level_1d] = l1d_count;