|
#include <stdint.h> |
|
#include <stddef.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
|
|
#include <cpuinfo.h> |
|
#include <arm/linux/api.h> |
|
#if defined(__ANDROID__) |
|
#include <arm/android/api.h> |
|
#endif |
|
#include <arm/api.h> |
|
#include <arm/midr.h> |
|
#include <linux/api.h> |
|
#include <cpuinfo/internal-api.h> |
|
#include <cpuinfo/log.h> |
|
#include <cpuinfo/common.h> |
|
|
|
|
|
#define CLUSTERS_MAX 3 |
|
|
|
static inline bool bitmask_all(uint32_t bitfield, uint32_t mask) { |
|
return (bitfield & mask) == mask; |
|
} |
|
|
|
|
|
struct cluster_config { |
|
|
|
uint8_t cores; |
|
|
|
uint8_t series; |
|
|
|
uint16_t model; |
|
|
|
uint8_t clusters; |
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t cluster_cores[CLUSTERS_MAX]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t cluster_midr[CLUSTERS_MAX]; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const struct cluster_config cluster_configs[] = { |
|
#if CPUINFO_ARCH_ARM |
|
{ |
|
|
|
|
|
|
|
|
|
.cores = 4, |
|
.series = cpuinfo_arm_chipset_series_qualcomm_msm, |
|
.model = UINT16_C(8916), |
|
.clusters = 1, |
|
.cluster_cores = { |
|
[0] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD030), |
|
}, |
|
}, |
|
{ |
|
|
|
|
|
|
|
|
|
.cores = 8, |
|
.series = cpuinfo_arm_chipset_series_qualcomm_msm, |
|
.model = UINT16_C(8939), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD034), |
|
[1] = UINT32_C(0x410FD034), |
|
}, |
|
}, |
|
#endif |
|
{ |
|
|
|
.cores = 6, |
|
.series = cpuinfo_arm_chipset_series_qualcomm_msm, |
|
.model = UINT16_C(8956), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 2, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD034), |
|
[1] = UINT32_C(0x410FD080), |
|
}, |
|
}, |
|
{ |
|
|
|
.cores = 8, |
|
.series = cpuinfo_arm_chipset_series_qualcomm_msm, |
|
.model = UINT16_C(8976), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD034), |
|
[1] = UINT32_C(0x410FD080), |
|
}, |
|
}, |
|
{ |
|
|
|
.cores = 6, |
|
.series = cpuinfo_arm_chipset_series_qualcomm_msm, |
|
.model = UINT16_C(8992), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 2, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD033), |
|
[1] = UINT32_C(0x411FD072), |
|
}, |
|
}, |
|
{ |
|
|
|
.cores = 8, |
|
.series = cpuinfo_arm_chipset_series_qualcomm_msm, |
|
.model = UINT16_C(8994), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD032), |
|
[1] = UINT32_C(0x411FD071), |
|
}, |
|
}, |
|
#if CPUINFO_ARCH_ARM |
|
{ |
|
|
|
.cores = 8, |
|
.series = cpuinfo_arm_chipset_series_samsung_exynos, |
|
.model = UINT16_C(5422), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FC073), |
|
[1] = UINT32_C(0x412FC0F3), |
|
}, |
|
}, |
|
{ |
|
|
|
.cores = 8, |
|
.series = cpuinfo_arm_chipset_series_samsung_exynos, |
|
.model = UINT16_C(5430), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FC074), |
|
[1] = UINT32_C(0x413FC0F3), |
|
}, |
|
}, |
|
#endif |
|
{ |
|
|
|
.cores = 8, |
|
.series = cpuinfo_arm_chipset_series_samsung_exynos, |
|
.model = UINT16_C(5433), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD031), |
|
[1] = UINT32_C(0x411FD070), |
|
}, |
|
}, |
|
{ |
|
|
|
.cores = 8, |
|
.series = cpuinfo_arm_chipset_series_samsung_exynos, |
|
.model = UINT16_C(7420), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD032), |
|
[1] = UINT32_C(0x411FD070), |
|
}, |
|
}, |
|
{ |
|
|
|
.cores = 8, |
|
.series = cpuinfo_arm_chipset_series_samsung_exynos, |
|
.model = UINT16_C(8890), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD034), |
|
[1] = UINT32_C(0x531F0011), |
|
}, |
|
}, |
|
#if CPUINFO_ARCH_ARM |
|
{ |
|
|
|
.cores = 8, |
|
.series = cpuinfo_arm_chipset_series_hisilicon_kirin, |
|
.model = UINT16_C(920), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FC075), |
|
[1] = UINT32_C(0x413FC0F3), |
|
}, |
|
}, |
|
{ |
|
|
|
.cores = 8, |
|
.series = cpuinfo_arm_chipset_series_hisilicon_kirin, |
|
.model = UINT16_C(925), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FC075), |
|
[1] = UINT32_C(0x413FC0F3), |
|
}, |
|
}, |
|
{ |
|
|
|
.cores = 8, |
|
.series = cpuinfo_arm_chipset_series_hisilicon_kirin, |
|
.model = UINT16_C(928), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FC075), |
|
[1] = UINT32_C(0x413FC0F3), |
|
}, |
|
}, |
|
#endif |
|
{ |
|
|
|
.cores = 8, |
|
.series = cpuinfo_arm_chipset_series_hisilicon_kirin, |
|
.model = UINT16_C(950), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD034), |
|
[1] = UINT32_C(0x410FD080), |
|
}, |
|
}, |
|
{ |
|
|
|
.cores = 8, |
|
.series = cpuinfo_arm_chipset_series_hisilicon_kirin, |
|
.model = UINT16_C(955), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD034), |
|
[1] = UINT32_C(0x410FD080), |
|
}, |
|
}, |
|
#if CPUINFO_ARCH_ARM |
|
{ |
|
|
|
.cores = 4, |
|
.series = cpuinfo_arm_chipset_series_mediatek_mt, |
|
.model = UINT16_C(8135), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 2, |
|
[1] = 2, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FC073), |
|
[1] = UINT32_C(0x413FC0F2), |
|
}, |
|
}, |
|
#endif |
|
{ |
|
|
|
.cores = 4, |
|
.series = cpuinfo_arm_chipset_series_mediatek_mt, |
|
.model = UINT16_C(8173), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 2, |
|
[1] = 2, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD032), |
|
[1] = UINT32_C(0x410FD080), |
|
}, |
|
}, |
|
{ |
|
|
|
.cores = 6, |
|
.series = cpuinfo_arm_chipset_series_mediatek_mt, |
|
.model = UINT16_C(8176), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 2, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD032), |
|
[1] = UINT32_C(0x410FD080), |
|
}, |
|
}, |
|
#if CPUINFO_ARCH_ARM64 |
|
{ |
|
|
|
|
|
|
|
|
|
.cores = 4, |
|
.series = cpuinfo_arm_chipset_series_mediatek_mt, |
|
.model = UINT16_C(8735), |
|
.clusters = 1, |
|
.cluster_cores = { |
|
[0] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD034), |
|
}, |
|
}, |
|
#endif |
|
#if CPUINFO_ARCH_ARM |
|
{ |
|
|
|
|
|
|
|
|
|
.cores = 4, |
|
.series = cpuinfo_arm_chipset_series_mediatek_mt, |
|
.model = UINT16_C(6592), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FC074), |
|
[1] = UINT32_C(0x410FC074), |
|
}, |
|
}, |
|
{ |
|
|
|
.cores = 8, |
|
.series = cpuinfo_arm_chipset_series_mediatek_mt, |
|
.model = UINT16_C(6595), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FC075), |
|
[1] = UINT32_C(0x410FC0E0), |
|
}, |
|
}, |
|
#endif |
|
{ |
|
|
|
.cores = 10, |
|
.series = cpuinfo_arm_chipset_series_mediatek_mt, |
|
.model = UINT16_C(6797), |
|
.clusters = 3, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
[2] = 2, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD034), |
|
[1] = UINT32_C(0x410FD034), |
|
[2] = UINT32_C(0x410FD081), |
|
}, |
|
}, |
|
{ |
|
|
|
.cores = 10, |
|
.series = cpuinfo_arm_chipset_series_mediatek_mt, |
|
.model = UINT16_C(6799), |
|
.clusters = 3, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 4, |
|
[2] = 2, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD041), |
|
[1] = UINT32_C(0x410FD034), |
|
[2] = UINT32_C(0x410FD092), |
|
}, |
|
}, |
|
{ |
|
|
|
.cores = 6, |
|
.series = cpuinfo_arm_chipset_series_rockchip_rk, |
|
.model = UINT16_C(3399), |
|
.clusters = 2, |
|
.cluster_cores = { |
|
[0] = 4, |
|
[1] = 2, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FD034), |
|
[1] = UINT32_C(0x410FD082), |
|
}, |
|
}, |
|
#if CPUINFO_ARCH_ARM |
|
{ |
|
|
|
|
|
|
|
.cores = 4, |
|
.series = cpuinfo_arm_chipset_series_actions_atm, |
|
.model = UINT16_C(7029), |
|
.clusters = 1, |
|
.cluster_cores = { |
|
[0] = 4, |
|
}, |
|
.cluster_midr = { |
|
[0] = UINT32_C(0x410FC051), |
|
}, |
|
}, |
|
#endif |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool cpuinfo_arm_linux_detect_cluster_midr_by_chipset( |
|
const struct cpuinfo_arm_chipset chipset[restrict static 1], |
|
uint32_t clusters_count, |
|
const uint32_t cluster_leaders[restrict static CLUSTERS_MAX], |
|
uint32_t processors_count, |
|
struct cpuinfo_arm_linux_processor processors[restrict static processors_count], |
|
bool verify_midr) |
|
{ |
|
if (clusters_count <= CLUSTERS_MAX) { |
|
for (uint32_t c = 0; c < CPUINFO_COUNT_OF(cluster_configs); c++) { |
|
if (cluster_configs[c].model == chipset->model && cluster_configs[c].series == chipset->series) { |
|
|
|
if (cluster_configs[c].cores != processors_count || cluster_configs[c].clusters != clusters_count) { |
|
return false; |
|
} |
|
|
|
|
|
for (uint32_t cluster = 0; cluster < clusters_count; cluster++) { |
|
const uint32_t cluster_leader = cluster_leaders[cluster]; |
|
if (cluster_configs[c].cluster_cores[cluster] != processors[cluster_leader].package_processor_count) { |
|
return false; |
|
} |
|
} |
|
|
|
if (verify_midr) { |
|
|
|
for (uint32_t cluster = 0; cluster < clusters_count; cluster++) { |
|
const uint32_t cluster_leader = cluster_leaders[cluster]; |
|
|
|
|
|
uint32_t midr_mask = 0; |
|
if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_IMPLEMENTER) { |
|
midr_mask |= CPUINFO_ARM_MIDR_IMPLEMENTER_MASK; |
|
} |
|
if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_VARIANT) { |
|
midr_mask |= CPUINFO_ARM_MIDR_VARIANT_MASK; |
|
} |
|
if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_PART) { |
|
midr_mask |= CPUINFO_ARM_MIDR_PART_MASK; |
|
} |
|
if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_REVISION) { |
|
midr_mask |= CPUINFO_ARM_MIDR_REVISION_MASK; |
|
} |
|
|
|
|
|
if ((processors[cluster_leader].midr ^ cluster_configs[c].cluster_midr[cluster]) & midr_mask) { |
|
cpuinfo_log_debug("parsed MIDR of cluster %08"PRIu32" does not match tabulated value %08"PRIu32, |
|
processors[cluster_leader].midr, cluster_configs[c].cluster_midr[cluster]); |
|
return false; |
|
} |
|
} |
|
} |
|
|
|
|
|
for (uint32_t cluster = 0; cluster < clusters_count; cluster++) { |
|
const uint32_t cluster_leader = cluster_leaders[cluster]; |
|
processors[cluster_leader].midr = cluster_configs[c].cluster_midr[cluster]; |
|
processors[cluster_leader].flags |= CPUINFO_ARM_LINUX_VALID_MIDR; |
|
cpuinfo_log_debug("cluster %"PRIu32" MIDR = 0x%08"PRIx32, cluster, cluster_configs[c].cluster_midr[cluster]); |
|
} |
|
return true; |
|
} |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool cpuinfo_arm_linux_detect_cluster_midr_by_big_little_heuristic( |
|
uint32_t clusters_count, |
|
uint32_t cluster_with_midr_count, |
|
uint32_t last_processor_with_midr, |
|
const uint32_t cluster_leaders[restrict static CLUSTERS_MAX], |
|
struct cpuinfo_arm_linux_processor processors[restrict static last_processor_with_midr], |
|
bool verify_midr) |
|
{ |
|
if (clusters_count != 2 || cluster_with_midr_count != 1) { |
|
|
|
return false; |
|
} |
|
|
|
const uint32_t midr_flags = |
|
(processors[processors[last_processor_with_midr].package_leader_id].flags & CPUINFO_ARM_LINUX_VALID_MIDR); |
|
const uint32_t big_midr = processors[processors[last_processor_with_midr].package_leader_id].midr; |
|
const uint32_t little_midr = midr_little_core_for_big(big_midr); |
|
|
|
|
|
uint32_t little_cluster_leader = cluster_leaders[0]; |
|
const uint32_t other_cluster_leader = cluster_leaders[1]; |
|
|
|
if (processors[little_cluster_leader].flags & processors[other_cluster_leader].flags & CPUINFO_LINUX_FLAG_MAX_FREQUENCY) { |
|
if (processors[little_cluster_leader].max_frequency > processors[other_cluster_leader].max_frequency) { |
|
little_cluster_leader = other_cluster_leader; |
|
} |
|
} |
|
|
|
if (verify_midr) { |
|
|
|
for (uint32_t cluster = 0; cluster < clusters_count; cluster++) { |
|
const uint32_t cluster_leader = cluster_leaders[cluster]; |
|
|
|
|
|
uint32_t midr_mask = 0; |
|
if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_IMPLEMENTER) { |
|
midr_mask |= CPUINFO_ARM_MIDR_IMPLEMENTER_MASK; |
|
} |
|
if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_VARIANT) { |
|
midr_mask |= CPUINFO_ARM_MIDR_VARIANT_MASK; |
|
} |
|
if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_PART) { |
|
midr_mask |= CPUINFO_ARM_MIDR_PART_MASK; |
|
} |
|
if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_REVISION) { |
|
midr_mask |= CPUINFO_ARM_MIDR_REVISION_MASK; |
|
} |
|
|
|
|
|
const uint32_t midr = (cluster_leader == little_cluster_leader) ? little_midr : big_midr; |
|
if ((processors[cluster_leader].midr ^ midr) & midr_mask) { |
|
cpuinfo_log_debug( |
|
"parsed MIDR %08"PRIu32" of cluster leader %"PRIu32" is inconsistent with expected value %08"PRIu32, |
|
processors[cluster_leader].midr, cluster_leader, midr); |
|
return false; |
|
} |
|
} |
|
} |
|
|
|
for (uint32_t c = 0; c < clusters_count; c++) { |
|
|
|
const uint32_t cluster_leader = cluster_leaders[c]; |
|
if (bitmask_all(processors[cluster_leader].flags, CPUINFO_ARM_LINUX_VALID_MIDR)) { |
|
continue; |
|
} |
|
|
|
const uint32_t midr = (cluster_leader == little_cluster_leader) ? little_midr : big_midr; |
|
cpuinfo_log_info("assume processor %"PRIu32" to have MIDR %08"PRIx32, cluster_leader, midr); |
|
|
|
processors[cluster_leader].midr = midr; |
|
processors[cluster_leader].flags |= midr_flags; |
|
} |
|
return true; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void cpuinfo_arm_linux_detect_cluster_midr_by_sequential_scan( |
|
uint32_t default_midr, |
|
uint32_t processors_count, |
|
struct cpuinfo_arm_linux_processor processors[restrict static processors_count]) |
|
{ |
|
uint32_t midr = default_midr; |
|
for (uint32_t i = 0; i < processors_count; i++) { |
|
if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { |
|
if (processors[i].package_leader_id == i) { |
|
if (bitmask_all(processors[i].flags, CPUINFO_ARM_LINUX_VALID_MIDR)) { |
|
midr = processors[i].midr; |
|
} else { |
|
cpuinfo_log_info("assume processor %"PRIu32" to have MIDR %08"PRIx32, i, midr); |
|
|
|
processors[i].midr = midr; |
|
processors[i].flags |= CPUINFO_ARM_LINUX_VALID_MIDR; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t cpuinfo_arm_linux_detect_cluster_midr( |
|
const struct cpuinfo_arm_chipset chipset[restrict static 1], |
|
uint32_t max_processors, |
|
uint32_t usable_processors, |
|
struct cpuinfo_arm_linux_processor processors[restrict static max_processors]) |
|
{ |
|
uint32_t clusters_count = 0; |
|
uint32_t cluster_leaders[CLUSTERS_MAX]; |
|
uint32_t last_processor_in_cpuinfo = max_processors; |
|
uint32_t last_processor_with_midr = max_processors; |
|
uint32_t processors_with_midr_count = 0; |
|
for (uint32_t i = 0; i < max_processors; i++) { |
|
if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { |
|
if (processors[i].flags & CPUINFO_ARM_LINUX_VALID_PROCESSOR) { |
|
last_processor_in_cpuinfo = i; |
|
} |
|
if (bitmask_all(processors[i].flags, CPUINFO_ARM_LINUX_VALID_IMPLEMENTER | CPUINFO_ARM_LINUX_VALID_PART)) { |
|
last_processor_with_midr = i; |
|
processors_with_midr_count += 1; |
|
} |
|
const uint32_t group_leader = processors[i].package_leader_id; |
|
if (group_leader == i) { |
|
if (clusters_count < CLUSTERS_MAX) { |
|
cluster_leaders[clusters_count] = i; |
|
} |
|
clusters_count += 1; |
|
} else { |
|
|
|
|
|
if ((processors[i].flags & ~processors[group_leader].flags) & CPUINFO_LINUX_FLAG_MAX_FREQUENCY) { |
|
processors[group_leader].max_frequency = processors[i].max_frequency; |
|
processors[group_leader].flags |= CPUINFO_LINUX_FLAG_MAX_FREQUENCY; |
|
} |
|
if (!bitmask_all(processors[group_leader].flags, CPUINFO_ARM_LINUX_VALID_MIDR) && |
|
bitmask_all(processors[i].flags, CPUINFO_ARM_LINUX_VALID_MIDR)) |
|
{ |
|
processors[group_leader].midr = processors[i].midr; |
|
processors[group_leader].flags |= CPUINFO_ARM_LINUX_VALID_MIDR; |
|
} |
|
} |
|
} |
|
} |
|
cpuinfo_log_debug("detected %"PRIu32" core clusters", clusters_count); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (processors_with_midr_count == 1 && last_processor_in_cpuinfo == last_processor_with_midr && clusters_count > 1) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cpuinfo_log_debug("the only reported MIDR can not be attributed to a particular processor"); |
|
|
|
if (cpuinfo_arm_linux_detect_cluster_midr_by_chipset( |
|
chipset, clusters_count, cluster_leaders, usable_processors, processors, false)) |
|
{ |
|
return clusters_count; |
|
} |
|
|
|
|
|
if (cpuinfo_arm_linux_detect_cluster_midr_by_big_little_heuristic( |
|
clusters_count, 1, last_processor_with_midr, |
|
cluster_leaders, processors, false)) |
|
{ |
|
return clusters_count; |
|
} |
|
|
|
|
|
cpuinfo_arm_linux_detect_cluster_midr_by_sequential_scan( |
|
processors[processors[last_processor_with_midr].package_leader_id].midr, |
|
max_processors, processors); |
|
} else if (processors_with_midr_count < usable_processors) { |
|
|
|
|
|
|
|
|
|
uint32_t clusters_with_midr_count = 0; |
|
for (uint32_t i = 0; i < max_processors; i++) { |
|
if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID | CPUINFO_ARM_LINUX_VALID_MIDR)) { |
|
if (processors[i].package_leader_id == i) { |
|
clusters_with_midr_count += 1; |
|
} |
|
} |
|
} |
|
|
|
if (clusters_with_midr_count < clusters_count) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (cpuinfo_arm_linux_detect_cluster_midr_by_chipset( |
|
chipset, clusters_count, cluster_leaders, usable_processors, processors, true)) |
|
{ |
|
return clusters_count; |
|
} |
|
|
|
if (last_processor_with_midr != max_processors) { |
|
|
|
if (cpuinfo_arm_linux_detect_cluster_midr_by_big_little_heuristic( |
|
clusters_count, processors_with_midr_count, last_processor_with_midr, |
|
cluster_leaders, processors, true)) |
|
{ |
|
return clusters_count; |
|
} |
|
|
|
|
|
cpuinfo_arm_linux_detect_cluster_midr_by_sequential_scan( |
|
processors[processors[last_processor_with_midr].package_leader_id].midr, |
|
max_processors, processors); |
|
} |
|
} |
|
} |
|
return clusters_count; |
|
} |
|
|