diff options
author | Marat Dukhan <marat@fb.com> | 2018-12-19 05:14:31 +0300 |
---|---|---|
committer | Marat Dukhan <marat@fb.com> | 2018-12-19 05:14:31 +0300 |
commit | a61747aebe5748505c2430d7e4335c7f85d31275 (patch) | |
tree | 99d454703415744fa1b0a77278ebbd4e50d13bdb /src | |
parent | 204ef6ed78d51470f97f40c7180e66fe487b9168 (diff) |
Support Linux x86 systems without /sys/devices/system/cpu/{possible,present} files
- On x86 Linux, if processor doesn't have /sys/devices/system/cpu/{possible,present} files, cpuinfo will fall back to counting processors in /proc/cpuinfo
- On ARM Linux, we still require /sys/devices/system/cpu/{possible,present} to be available, as missing processors in /proc/cpuinfo are very common
Diffstat (limited to 'src')
-rw-r--r-- | src/arm/linux/clusters.c | 12 | ||||
-rw-r--r-- | src/arm/linux/cpuinfo.c | 6 | ||||
-rw-r--r-- | src/arm/linux/init.c | 107 | ||||
-rw-r--r-- | src/arm/linux/midr.c | 6 | ||||
-rw-r--r-- | src/linux/api.h | 3 | ||||
-rw-r--r-- | src/linux/processors.c | 6 | ||||
-rw-r--r-- | src/x86/linux/cpuinfo.c | 10 | ||||
-rw-r--r-- | src/x86/linux/init.c | 54 |
8 files changed, 125 insertions, 79 deletions
diff --git a/src/arm/linux/clusters.c b/src/arm/linux/clusters.c index d36c2df..8daeae5 100644 --- a/src/arm/linux/clusters.c +++ b/src/arm/linux/clusters.c @@ -45,7 +45,7 @@ static inline bool bitmask_all(uint32_t bitfield, uint32_t mask) { * * If the heuristic assignment of processors to clusters of cores fails, all processors' clusters are unchanged. * - * @param usable_processors - number of processors in the @p processors array with CPUINFO_LINUX_MASK_USABLE flags. + * @param usable_processors - number of processors in the @p processors array with CPUINFO_LINUX_FLAG_VALID flags. * @param max_processors - number of elements in the @p processors array. * @param[in,out] processors - processor descriptors with pre-parsed POSSIBLE and PRESENT flags, minimum/maximum * frequency, MIDR infromation, and core cluster (package siblings list) information. @@ -98,7 +98,7 @@ bool cpuinfo_arm_linux_detect_core_clusters_by_heuristic( uint32_t cluster_start, cluster_flags, cluster_midr, cluster_max_frequency, cluster_min_frequency; bool expected_cluster_exists; for (uint32_t i = 0; i < max_processors; i++) { - if (bitmask_all(processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) { + if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { if (expected_cluster_processors == 0) { /* Expect this processor to start a new cluster */ @@ -263,7 +263,7 @@ bool cpuinfo_arm_linux_detect_core_clusters_by_heuristic( cluster = 0; expected_cluster_processors = 0; for (uint32_t i = 0; i < max_processors; i++) { - if (bitmask_all(processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) { + if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { if (expected_cluster_processors == 0) { /* Expect this processor to start a new cluster */ @@ -322,7 +322,7 @@ void cpuinfo_arm_linux_detect_core_clusters_by_sequential_scan( uint32_t cluster_processors = 0; uint32_t cluster_start, cluster_midr, cluster_max_frequency, cluster_min_frequency; for (uint32_t i = 0; i < max_processors; i++) { - if ((processors[i].flags & (CPUINFO_LINUX_MASK_USABLE | CPUINFO_LINUX_FLAG_PACKAGE_CLUSTER)) == CPUINFO_LINUX_MASK_USABLE) { + if ((processors[i].flags & (CPUINFO_LINUX_FLAG_VALID | CPUINFO_LINUX_FLAG_PACKAGE_CLUSTER)) == CPUINFO_LINUX_FLAG_VALID) { if (cluster_processors == 0) { goto new_cluster; } @@ -478,14 +478,14 @@ void cpuinfo_arm_linux_count_cluster_processors( { /* First pass: accumulate the number of processors at the group leader's package_processor_count */ for (uint32_t i = 0; i < max_processors; i++) { - if (bitmask_all(processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) { + if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { const uint32_t package_leader_id = processors[i].package_leader_id; processors[package_leader_id].package_processor_count += 1; } } /* Second pass: copy the package_processor_count from the group leader processor */ for (uint32_t i = 0; i < max_processors; i++) { - if (bitmask_all(processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) { + if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { const uint32_t package_leader_id = processors[i].package_leader_id; processors[i].package_processor_count = processors[package_leader_id].package_processor_count; } diff --git a/src/arm/linux/cpuinfo.c b/src/arm/linux/cpuinfo.c index e9bdd4b..2df0c6e 100644 --- a/src/arm/linux/cpuinfo.c +++ b/src/arm/linux/cpuinfo.c @@ -680,7 +680,7 @@ static bool parse_line( } /* Skip line if no ':' separator was found. */ if (separator == line_end) { - cpuinfo_log_warning("Line %.*s in /proc/cpuinfo is ignored: key/value separator ':' not found", + cpuinfo_log_info("Line %.*s in /proc/cpuinfo is ignored: key/value separator ':' not found", (int) (line_end - line_start), line_start); return true; } @@ -694,7 +694,7 @@ static bool parse_line( } /* Skip line if key contains nothing but spaces. */ if (key_end == line_start) { - cpuinfo_log_warning("Line %.*s in /proc/cpuinfo is ignored: key contains only spaces", + cpuinfo_log_info("Line %.*s in /proc/cpuinfo is ignored: key contains only spaces", (int) (line_end - line_start), line_start); return true; } @@ -708,7 +708,7 @@ static bool parse_line( } /* Value part contains nothing but spaces. Skip line. */ if (value_start == line_end) { - cpuinfo_log_warning("Line %.*s in /proc/cpuinfo is ignored: value contains only spaces", + cpuinfo_log_info("Line %.*s in /proc/cpuinfo is ignored: value contains only spaces", (int) (line_end - line_start), line_start); return true; } diff --git a/src/arm/linux/init.c b/src/arm/linux/init.c index 262bb55..23dc762 100644 --- a/src/arm/linux/init.c +++ b/src/arm/linux/init.c @@ -39,7 +39,7 @@ static bool cluster_siblings_parser( uint32_t package_leader_id = processors[processor].package_leader_id; for (uint32_t sibling = siblings_start; sibling < siblings_end; sibling++) { - if (!bitmask_all(processors[sibling].flags, CPUINFO_LINUX_MASK_USABLE)) { + if (!bitmask_all(processors[sibling].flags, CPUINFO_LINUX_FLAG_VALID)) { cpuinfo_log_info("invalid processor %"PRIu32" reported as a sibling for processor %"PRIu32, sibling, processor); continue; @@ -64,8 +64,8 @@ static int cmp_arm_linux_processor(const void* ptr_a, const void* ptr_b) { const struct cpuinfo_arm_linux_processor* processor_b = (const struct cpuinfo_arm_linux_processor*) ptr_b; /* Move usable processors towards the start of the array */ - const bool usable_a = bitmask_all(processor_a->flags, CPUINFO_LINUX_MASK_USABLE); - const bool usable_b = bitmask_all(processor_b->flags, CPUINFO_LINUX_MASK_USABLE); + const bool usable_a = bitmask_all(processor_a->flags, CPUINFO_LINUX_FLAG_VALID); + const bool usable_b = bitmask_all(processor_b->flags, CPUINFO_LINUX_FLAG_VALID); if (usable_a != usable_b) { return (int) usable_b - (int) usable_a; } @@ -123,7 +123,21 @@ void cpuinfo_arm_linux_init(void) { cpuinfo_linux_get_max_present_processor(max_processors_count); cpuinfo_log_debug("maximum present processors count: %"PRIu32, max_present_processors_count); - const uint32_t arm_linux_processors_count = min(max_possible_processors_count, max_present_processors_count); + uint32_t valid_processor_mask = 0; + uint32_t arm_linux_processors_count = max_processors_count; + if (max_present_processors_count != 0) { + arm_linux_processors_count = min(arm_linux_processors_count, max_present_processors_count); + valid_processor_mask = CPUINFO_LINUX_FLAG_PRESENT; + } + if (max_possible_processors_count != 0) { + arm_linux_processors_count = min(arm_linux_processors_count, max_possible_processors_count); + valid_processor_mask |= CPUINFO_LINUX_FLAG_POSSIBLE; + } + if ((max_present_processors_count | max_possible_processors_count) == 0) { + cpuinfo_log_error("failed to parse both lists of possible and present processors"); + return; + } + arm_linux_processors = calloc(arm_linux_processors_count, sizeof(struct cpuinfo_arm_linux_processor)); if (arm_linux_processors == NULL) { cpuinfo_log_error( @@ -133,15 +147,19 @@ void cpuinfo_arm_linux_init(void) { return; } - cpuinfo_linux_detect_possible_processors( - arm_linux_processors_count, &arm_linux_processors->flags, - sizeof(struct cpuinfo_arm_linux_processor), - CPUINFO_LINUX_FLAG_POSSIBLE); + if (max_possible_processors_count) { + cpuinfo_linux_detect_possible_processors( + arm_linux_processors_count, &arm_linux_processors->flags, + sizeof(struct cpuinfo_arm_linux_processor), + CPUINFO_LINUX_FLAG_POSSIBLE); + } - cpuinfo_linux_detect_present_processors( - arm_linux_processors_count, &arm_linux_processors->flags, - sizeof(struct cpuinfo_arm_linux_processor), - CPUINFO_LINUX_FLAG_PRESENT); + if (max_present_processors_count) { + cpuinfo_linux_detect_present_processors( + arm_linux_processors_count, &arm_linux_processors->flags, + sizeof(struct cpuinfo_arm_linux_processor), + CPUINFO_LINUX_FLAG_PRESENT); + } #if defined(__ANDROID__) struct cpuinfo_android_properties android_properties; @@ -163,20 +181,21 @@ void cpuinfo_arm_linux_init(void) { } for (uint32_t i = 0; i < arm_linux_processors_count; i++) { - if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) { + if (bitmask_all(arm_linux_processors[i].flags, valid_processor_mask)) { + arm_linux_processors[i].flags |= CPUINFO_LINUX_FLAG_VALID; cpuinfo_log_debug("parsed processor %"PRIu32" MIDR 0x%08"PRIx32, i, arm_linux_processors[i].midr); } } - uint32_t usable_processors = 0, last_midr = 0; + uint32_t valid_processors = 0, last_midr = 0; #if CPUINFO_ARCH_ARM uint32_t last_architecture_version = 0, last_architecture_flags = 0; #endif for (uint32_t i = 0; i < arm_linux_processors_count; i++) { arm_linux_processors[i].system_processor_id = i; - if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) { - usable_processors += 1; + if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { + valid_processors += 1; if (!(arm_linux_processors[i].flags & CPUINFO_ARM_LINUX_VALID_PROCESSOR)) { /* @@ -205,7 +224,7 @@ void cpuinfo_arm_linux_init(void) { #if defined(__ANDROID__) const struct cpuinfo_arm_chipset chipset = - cpuinfo_arm_android_decode_chipset(&android_properties, usable_processors, 0); + cpuinfo_arm_android_decode_chipset(&android_properties, valid_processors, 0); #else const struct cpuinfo_arm_chipset chipset = { .vendor = cpuinfo_arm_chipset_vendor_unknown, @@ -234,7 +253,7 @@ void cpuinfo_arm_linux_init(void) { */ uint32_t processors_with_features = 0; for (uint32_t i = 0; i < arm_linux_processors_count; i++) { - if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_MASK_USABLE | CPUINFO_ARM_LINUX_VALID_FEATURES)) { + if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_FLAG_VALID | CPUINFO_ARM_LINUX_VALID_FEATURES)) { if (processors_with_features == 0) { isa_features = arm_linux_processors[i].features; isa_features2 = arm_linux_processors[i].features2; @@ -264,7 +283,7 @@ void cpuinfo_arm_linux_init(void) { /* Detect min/max frequency and package ID */ for (uint32_t i = 0; i < arm_linux_processors_count; i++) { - if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) { + if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { const uint32_t max_frequency = cpuinfo_linux_get_processor_max_frequency(i); if (max_frequency != 0) { arm_linux_processors[i].max_frequency = max_frequency; @@ -290,7 +309,7 @@ void cpuinfo_arm_linux_init(void) { /* Propagate topology group IDs among siblings */ for (uint32_t i = 0; i < arm_linux_processors_count; i++) { - if (!bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) { + if (!bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { continue; } @@ -305,7 +324,7 @@ void cpuinfo_arm_linux_init(void) { /* Propagate all cluster IDs */ uint32_t clustered_processors = 0; for (uint32_t i = 0; i < arm_linux_processors_count; i++) { - if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_MASK_USABLE | CPUINFO_LINUX_FLAG_PACKAGE_CLUSTER)) { + if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_FLAG_VALID | CPUINFO_LINUX_FLAG_PACKAGE_CLUSTER)) { clustered_processors += 1; const uint32_t package_leader_id = arm_linux_processors[i].package_leader_id; @@ -318,7 +337,7 @@ void cpuinfo_arm_linux_init(void) { } } - if (clustered_processors != usable_processors) { + if (clustered_processors != valid_processors) { /* * Topology information about some or all logical processors may be unavailable, for the following reasons: * - Linux kernel is too old, or configured without support for topology information in sysfs. @@ -328,7 +347,7 @@ void cpuinfo_arm_linux_init(void) { * - Try heuristic cluster configurations (e.g. 6-core SoC usually has 4+2 big.LITTLE configuration). * - If heuristic failed, assign processors to core clusters in a sequential scan. */ - if (!cpuinfo_arm_linux_detect_core_clusters_by_heuristic(usable_processors, arm_linux_processors_count, arm_linux_processors)) { + if (!cpuinfo_arm_linux_detect_core_clusters_by_heuristic(valid_processors, arm_linux_processors_count, arm_linux_processors)) { cpuinfo_arm_linux_detect_core_clusters_by_sequential_scan(arm_linux_processors_count, arm_linux_processors); } } @@ -337,11 +356,11 @@ void cpuinfo_arm_linux_init(void) { const uint32_t cluster_count = cpuinfo_arm_linux_detect_cluster_midr( &chipset, - arm_linux_processors_count, usable_processors, arm_linux_processors); + arm_linux_processors_count, valid_processors, arm_linux_processors); /* Initialize core vendor, uarch, MIDR, and frequency for every logical processor */ for (uint32_t i = 0; i < arm_linux_processors_count; i++) { - if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) { + if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { const uint32_t cluster_leader = arm_linux_processors[i].package_leader_id; if (cluster_leader == i) { /* Cluster leader: decode core vendor and uarch */ @@ -365,7 +384,7 @@ void cpuinfo_arm_linux_init(void) { } for (uint32_t i = 0; i < arm_linux_processors_count; i++) { - if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) { + if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { cpuinfo_log_debug("post-analysis processor %"PRIu32": MIDR %08"PRIx32" frequency %"PRIu32, i, arm_linux_processors[i].midr, arm_linux_processors[i].max_frequency); } @@ -375,7 +394,7 @@ void cpuinfo_arm_linux_init(void) { sizeof(struct cpuinfo_arm_linux_processor), cmp_arm_linux_processor); for (uint32_t i = 0; i < arm_linux_processors_count; i++) { - if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) { + if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { cpuinfo_log_debug("post-sort processor %"PRIu32": system id %"PRIu32" MIDR %08"PRIx32" frequency %"PRIu32, i, arm_linux_processors[i].system_processor_id, arm_linux_processors[i].midr, arm_linux_processors[i].max_frequency); } @@ -388,21 +407,21 @@ void cpuinfo_arm_linux_init(void) { * - Level 2 and level 3 cache is shared between cores in the same cluster. */ cpuinfo_arm_chipset_to_string(&chipset, package.name); - package.processor_count = usable_processors; - package.core_count = usable_processors; + package.processor_count = valid_processors; + package.core_count = valid_processors; package.cluster_count = cluster_count; - processors = calloc(usable_processors, sizeof(struct cpuinfo_processor)); + processors = calloc(valid_processors, sizeof(struct cpuinfo_processor)); if (processors == NULL) { cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" logical processors", - usable_processors * sizeof(struct cpuinfo_processor), usable_processors); + valid_processors * sizeof(struct cpuinfo_processor), valid_processors); goto cleanup; } - cores = calloc(usable_processors, sizeof(struct cpuinfo_core)); + cores = calloc(valid_processors, sizeof(struct cpuinfo_core)); if (cores == NULL) { cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" cores", - usable_processors * sizeof(struct cpuinfo_core), usable_processors); + valid_processors * sizeof(struct cpuinfo_core), valid_processors); goto cleanup; } @@ -427,17 +446,17 @@ void cpuinfo_arm_linux_init(void) { goto cleanup; } - l1i = calloc(usable_processors, sizeof(struct cpuinfo_cache)); + l1i = calloc(valid_processors, sizeof(struct cpuinfo_cache)); if (l1i == NULL) { cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L1I caches", - usable_processors * sizeof(struct cpuinfo_cache), usable_processors); + valid_processors * sizeof(struct cpuinfo_cache), valid_processors); goto cleanup; } - l1d = calloc(usable_processors, sizeof(struct cpuinfo_cache)); + l1d = calloc(valid_processors, sizeof(struct cpuinfo_cache)); if (l1d == NULL) { cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L1D caches", - usable_processors * sizeof(struct cpuinfo_cache), usable_processors); + valid_processors * sizeof(struct cpuinfo_cache), valid_processors); goto cleanup; } @@ -445,7 +464,7 @@ void cpuinfo_arm_linux_init(void) { /* Indication whether L3 (if it exists) is shared between all cores */ bool shared_l3 = true; /* Populate cache infromation structures in l1i, l1d */ - for (uint32_t i = 0; i < usable_processors; i++) { + for (uint32_t i = 0; i < valid_processors; i++) { if (arm_linux_processors[i].package_leader_id == arm_linux_processors[i].system_processor_id) { cluster_id += 1; clusters[cluster_id] = (struct cpuinfo_cluster) { @@ -564,7 +583,7 @@ void cpuinfo_arm_linux_init(void) { cluster_id = UINT32_MAX; uint32_t l2_index = UINT32_MAX, l3_index = UINT32_MAX; - for (uint32_t i = 0; i < usable_processors; i++) { + for (uint32_t i = 0; i < valid_processors; i++) { if (arm_linux_processors[i].package_leader_id == arm_linux_processors[i].system_processor_id) { cluster_id++; } @@ -610,7 +629,7 @@ void cpuinfo_arm_linux_init(void) { .flags = temp_l3.flags, .processor_start = i, .processor_count = - shared_l3 ? usable_processors : arm_linux_processors[i].package_processor_count, + shared_l3 ? valid_processors : arm_linux_processors[i].package_processor_count, }; } } @@ -650,12 +669,12 @@ void cpuinfo_arm_linux_init(void) { cpuinfo_cache[cpuinfo_cache_level_2] = l2; cpuinfo_cache[cpuinfo_cache_level_3] = l3; - cpuinfo_processors_count = usable_processors; - cpuinfo_cores_count = usable_processors; + cpuinfo_processors_count = valid_processors; + cpuinfo_cores_count = valid_processors; cpuinfo_clusters_count = cluster_count; cpuinfo_packages_count = 1; - cpuinfo_cache_count[cpuinfo_cache_level_1i] = usable_processors; - cpuinfo_cache_count[cpuinfo_cache_level_1d] = usable_processors; + cpuinfo_cache_count[cpuinfo_cache_level_1i] = valid_processors; + cpuinfo_cache_count[cpuinfo_cache_level_1d] = valid_processors; cpuinfo_cache_count[cpuinfo_cache_level_2] = l2_count; cpuinfo_cache_count[cpuinfo_cache_level_3] = l3_count; diff --git a/src/arm/linux/midr.c b/src/arm/linux/midr.c index df80d2b..668fc72 100644 --- a/src/arm/linux/midr.c +++ b/src/arm/linux/midr.c @@ -692,7 +692,7 @@ static void cpuinfo_arm_linux_detect_cluster_midr_by_sequential_scan( { uint32_t midr = default_midr; for (uint32_t i = 0; i < processors_count; i++) { - if (bitmask_all(processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) { + 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; @@ -732,7 +732,7 @@ uint32_t cpuinfo_arm_linux_detect_cluster_midr( 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_MASK_USABLE)) { + if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { if (processors[i].flags & CPUINFO_ARM_LINUX_VALID_PROCESSOR) { last_processor_in_cpuinfo = i; } @@ -817,7 +817,7 @@ uint32_t cpuinfo_arm_linux_detect_cluster_midr( */ uint32_t clusters_with_midr_count = 0; for (uint32_t i = 0; i < max_processors; i++) { - if (bitmask_all(processors[i].flags, CPUINFO_LINUX_MASK_USABLE | CPUINFO_ARM_LINUX_VALID_MIDR)) { + 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; } diff --git a/src/linux/api.h b/src/linux/api.h index aa1c7d7..f55b8ac 100644 --- a/src/linux/api.h +++ b/src/linux/api.h @@ -10,7 +10,6 @@ #define CPUINFO_LINUX_FLAG_PRESENT UINT32_C(0x00000001) #define CPUINFO_LINUX_FLAG_POSSIBLE UINT32_C(0x00000002) -#define CPUINFO_LINUX_MASK_USABLE UINT32_C(0x00000003) #define CPUINFO_LINUX_FLAG_MAX_FREQUENCY UINT32_C(0x00000004) #define CPUINFO_LINUX_FLAG_MIN_FREQUENCY UINT32_C(0x00000008) #define CPUINFO_LINUX_FLAG_SMT_ID UINT32_C(0x00000010) @@ -20,6 +19,8 @@ #define CPUINFO_LINUX_FLAG_SMT_CLUSTER UINT32_C(0x00000100) #define CPUINFO_LINUX_FLAG_CORE_CLUSTER UINT32_C(0x00000200) #define CPUINFO_LINUX_FLAG_PACKAGE_CLUSTER UINT32_C(0x00000400) +#define CPUINFO_LINUX_FLAG_PROC_CPUINFO UINT32_C(0x00000800) +#define CPUINFO_LINUX_FLAG_VALID UINT32_C(0x00001000) typedef bool (*cpuinfo_cpulist_callback)(uint32_t, uint32_t, void*); diff --git a/src/linux/processors.c b/src/linux/processors.c index cf87548..849c6a1 100644 --- a/src/linux/processors.c +++ b/src/linux/processors.c @@ -228,7 +228,7 @@ uint32_t cpuinfo_linux_get_max_possible_processor(uint32_t max_processors_count) uint32_t max_possible_processor = 0; if (!cpuinfo_linux_parse_cpulist(POSSIBLE_CPULIST_FILENAME, max_processor_number_parser, &max_possible_processor)) { cpuinfo_log_error("failed to parse the list of possible processors in %s", POSSIBLE_CPULIST_FILENAME); - return max_processors_count; + return UINT32_MAX; } if (max_possible_processor >= max_processors_count) { cpuinfo_log_warning( @@ -243,7 +243,7 @@ uint32_t cpuinfo_linux_get_max_present_processor(uint32_t max_processors_count) uint32_t max_present_processor = 0; if (!cpuinfo_linux_parse_cpulist(PRESENT_CPULIST_FILENAME, max_processor_number_parser, &max_present_processor)) { cpuinfo_log_error("failed to parse the list of present processors in %s", PRESENT_CPULIST_FILENAME); - return max_processors_count; + return UINT32_MAX; } if (max_present_processor >= max_processors_count) { cpuinfo_log_warning( @@ -271,7 +271,7 @@ static bool detect_processor_parser(uint32_t processor_list_start, uint32_t proc if (processor >= max_processors_count) { break; } - *((uint32_t*) ((void*) processor0_flags + processor_struct_size * processor)) |= detected_flag; + *((uint32_t*) ((uintptr_t) processor0_flags + processor_struct_size * processor)) |= detected_flag; } return true; } diff --git a/src/x86/linux/cpuinfo.c b/src/x86/linux/cpuinfo.c index 79255f2..90ff814 100644 --- a/src/x86/linux/cpuinfo.c +++ b/src/x86/linux/cpuinfo.c @@ -90,7 +90,7 @@ static bool parse_line( if (line_start == line_end) { return true; } - + /* Search for ':' on the line. */ const char* separator = line_start; for (; separator != line_end; separator++) { @@ -100,7 +100,7 @@ static bool parse_line( } /* Skip line if no ':' separator was found. */ if (separator == line_end) { - cpuinfo_log_warning("Line %.*s in /proc/cpuinfo is ignored: key/value separator ':' not found", + cpuinfo_log_info("Line %.*s in /proc/cpuinfo is ignored: key/value separator ':' not found", (int) (line_end - line_start), line_start); return true; } @@ -114,7 +114,7 @@ static bool parse_line( } /* Skip line if key contains nothing but spaces. */ if (key_end == line_start) { - cpuinfo_log_warning("Line %.*s in /proc/cpuinfo is ignored: key contains only spaces", + cpuinfo_log_info("Line %.*s in /proc/cpuinfo is ignored: key contains only spaces", (int) (line_end - line_start), line_start); return true; } @@ -128,7 +128,7 @@ static bool parse_line( } /* Value part contains nothing but spaces. Skip line. */ if (value_start == line_end) { - cpuinfo_log_warning("Line %.*s in /proc/cpuinfo is ignored: value contains only spaces", + cpuinfo_log_info("Line %.*s in /proc/cpuinfo is ignored: value contains only spaces", (int) (line_end - line_start), line_start); return true; } @@ -176,6 +176,8 @@ static bool parse_line( /* Log and ignore processor */ cpuinfo_log_warning("processor %"PRIu32" in /proc/cpuinfo is ignored: index exceeds system limit %"PRIu32, new_processor_index, max_processors_count - 1); + } else { + processors[new_processor_index].flags |= CPUINFO_LINUX_FLAG_PROC_CPUINFO; } state->processor_index = new_processor_index; return true; diff --git a/src/x86/linux/init.c b/src/x86/linux/init.c index 0c80d55..b5f74d0 100644 --- a/src/x86/linux/init.c +++ b/src/x86/linux/init.c @@ -32,8 +32,8 @@ static int cmp_x86_linux_processor(const void* ptr_a, const void* ptr_b) { const struct cpuinfo_x86_linux_processor* processor_b = (const struct cpuinfo_x86_linux_processor*) ptr_b; /* Move usable processors towards the start of the array */ - const bool usable_a = bitmask_all(processor_a->flags, CPUINFO_LINUX_MASK_USABLE); - const bool usable_b = bitmask_all(processor_b->flags, CPUINFO_LINUX_MASK_USABLE); + const bool usable_a = bitmask_all(processor_a->flags, CPUINFO_LINUX_FLAG_VALID); + const bool usable_b = bitmask_all(processor_b->flags, CPUINFO_LINUX_FLAG_VALID); if (usable_a != usable_b) { return (int) usable_b - (int) usable_a; } @@ -48,6 +48,7 @@ static void cpuinfo_x86_count_objects( 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 valid_processor_mask, uint32_t llc_apic_bits, uint32_t cores_count_ptr[restrict static 1], uint32_t clusters_count_ptr[restrict static 1], @@ -71,7 +72,7 @@ static void cpuinfo_x86_count_objects( 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++) { - if (bitmask_all(linux_processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) { + if (bitmask_all(linux_processors[i].flags, valid_processor_mask)) { const uint32_t apic_id = linux_processors[i].apic_id; cpuinfo_log_debug("APID ID %"PRIu32": system processor %"PRIu32, apic_id, linux_processors[i].linux_id); @@ -164,7 +165,19 @@ void cpuinfo_x86_linux_init(void) { cpuinfo_linux_get_max_present_processor(max_processors_count); cpuinfo_log_debug("maximum present processors count: %"PRIu32, max_present_processors_count); - const uint32_t x86_linux_processors_count = min(max_possible_processors_count, max_present_processors_count); + uint32_t valid_processor_mask = 0; + uint32_t x86_linux_processors_count = max_processors_count; + if (max_present_processors_count != 0) { + x86_linux_processors_count = min(x86_linux_processors_count, max_present_processors_count); + valid_processor_mask = CPUINFO_LINUX_FLAG_PRESENT; + } else { + valid_processor_mask = CPUINFO_LINUX_FLAG_PROC_CPUINFO; + } + if (max_possible_processors_count != 0) { + x86_linux_processors_count = min(x86_linux_processors_count, max_possible_processors_count); + valid_processor_mask |= CPUINFO_LINUX_FLAG_POSSIBLE; + } + x86_linux_processors = calloc(x86_linux_processors_count, sizeof(struct cpuinfo_x86_linux_processor)); if (x86_linux_processors == NULL) { cpuinfo_log_error( @@ -174,21 +187,31 @@ void cpuinfo_x86_linux_init(void) { return; } - cpuinfo_linux_detect_possible_processors( - x86_linux_processors_count, &x86_linux_processors->flags, - sizeof(struct cpuinfo_x86_linux_processor), - CPUINFO_LINUX_FLAG_POSSIBLE); + if (max_possible_processors_count != 0) { + cpuinfo_linux_detect_possible_processors( + x86_linux_processors_count, &x86_linux_processors->flags, + sizeof(struct cpuinfo_x86_linux_processor), + CPUINFO_LINUX_FLAG_POSSIBLE); + } - cpuinfo_linux_detect_present_processors( - x86_linux_processors_count, &x86_linux_processors->flags, - sizeof(struct cpuinfo_x86_linux_processor), - CPUINFO_LINUX_FLAG_PRESENT); + if (max_present_processors_count != 0) { + cpuinfo_linux_detect_present_processors( + x86_linux_processors_count, &x86_linux_processors->flags, + sizeof(struct cpuinfo_x86_linux_processor), + CPUINFO_LINUX_FLAG_PRESENT); + } if (!cpuinfo_x86_linux_parse_proc_cpuinfo(x86_linux_processors_count, x86_linux_processors)) { cpuinfo_log_error("failed to parse processor information from /proc/cpuinfo"); return; } + for (uint32_t i = 0; i < x86_linux_processors_count; i++) { + if (bitmask_all(x86_linux_processors[i].flags, valid_processor_mask)) { + x86_linux_processors[i].flags |= CPUINFO_LINUX_FLAG_VALID; + } + } + struct cpuinfo_x86_processor x86_processor; memset(&x86_processor, 0, sizeof(x86_processor)); cpuinfo_x86_init_processor(&x86_processor); @@ -197,7 +220,7 @@ void cpuinfo_x86_linux_init(void) { uint32_t processors_count = 0; for (uint32_t i = 0; i < x86_linux_processors_count; i++) { - if (bitmask_all(x86_linux_processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) { + if (bitmask_all(x86_linux_processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { x86_linux_processors[i].linux_id = i; processors_count++; } @@ -225,7 +248,8 @@ void cpuinfo_x86_linux_init(void) { } 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, llc_apic_bits, + cpuinfo_x86_count_objects( + x86_linux_processors_count, x86_linux_processors, &x86_processor, valid_processor_mask, 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); @@ -329,7 +353,7 @@ void cpuinfo_x86_linux_init(void) { 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++) { - if (bitmask_all(x86_linux_processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) { + if (bitmask_all(x86_linux_processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { const uint32_t apic_id = x86_linux_processors[i].apic_id; processor_index++; smt_id++; |