From a5b321a9668f4763225e54ac71ab7ee2f86fc468 Mon Sep 17 00:00:00 2001 From: Dr-Noob Date: Mon, 1 Nov 2021 13:55:49 +0100 Subject: [PATCH] [v1.00][X86] Retrieve topology from udev when APIC fails (like #119) --- src/arm/udev.c | 43 ------------------------------------------- src/common/udev.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/common/udev.h | 2 ++ src/x86/apic.c | 7 +------ src/x86/cpuid.c | 24 +++++++++++++++++++++++- 5 files changed, 68 insertions(+), 50 deletions(-) diff --git a/src/arm/udev.c b/src/arm/udev.c index b52bb8a..98c06b9 100644 --- a/src/arm/udev.c +++ b/src/arm/udev.c @@ -3,7 +3,6 @@ #include "midr.h" #define _PATH_DEVICETREE_MODEL "/sys/firmware/devicetree/base/model" -#define _PATH_CPUS_PRESENT _PATH_SYS_SYSTEM _PATH_SYS_CPU "/present" #define _PATH_CPUINFO "/proc/cpuinfo" //#define _PATH_CPUINFO "cpuinfo_debug" @@ -17,48 +16,6 @@ #define CPUINFO_CPU_STRING "processor" -// https://www.kernel.org/doc/html/latest/core-api/cpu_hotplug.html -int get_ncores_from_cpuinfo() { - // Examples: - // 0-271 - // 0-7 - // 0 - - int filelen; - char* buf; - if((buf = read_file(_PATH_CPUS_PRESENT, &filelen)) == NULL) { - printWarn("read_file: %s: %s\n", _PATH_CPUS_PRESENT, strerror(errno)); - return UNKNOWN; - } - - int ncores; - char* tmp1; - if((tmp1 = strstr(buf, "-")) == NULL) { - // file contains no - character, we assume that it contains 0, - // which means that the CPU contains only one core - return 1; - } - else { - tmp1++; - } - char* tmp2 = strstr(buf, "\n"); - char ncores_str[filelen]; - memset(ncores_str, 0, sizeof(char) * filelen); - memcpy(ncores_str, tmp1, tmp2-tmp1); - - char* end; - errno = 0; - ncores = strtol(ncores_str, &end, 10) + 1; - if(errno != 0) { - printWarn("strtol: %s:\n", strerror(errno)); - return UNKNOWN; - } - - free(buf); - - return ncores; -} - long parse_cpuinfo_field(char* buf, char* field_str, int field_base) { char* tmp = strstr(buf, field_str); if(tmp == NULL) return -1; diff --git a/src/common/udev.c b/src/common/udev.c index 0505ad0..75c60b2 100644 --- a/src/common/udev.c +++ b/src/common/udev.c @@ -2,6 +2,48 @@ #include "global.h" #include "cpu.h" +// https://www.kernel.org/doc/html/latest/core-api/cpu_hotplug.html +int get_ncores_from_cpuinfo() { + // Examples: + // 0-271 + // 0-7 + // 0 + + int filelen; + char* buf; + if((buf = read_file(_PATH_CPUS_PRESENT, &filelen)) == NULL) { + printWarn("read_file: %s: %s\n", _PATH_CPUS_PRESENT, strerror(errno)); + return -1; + } + + int ncores; + char* tmp1; + if((tmp1 = strstr(buf, "-")) == NULL) { + // file contains no - character, we assume that it contains 0, + // which means that the CPU contains only one core + return 1; + } + else { + tmp1++; + } + char* tmp2 = strstr(buf, "\n"); + char ncores_str[filelen]; + memset(ncores_str, 0, sizeof(char) * filelen); + memcpy(ncores_str, tmp1, tmp2-tmp1); + + char* end; + errno = 0; + ncores = strtol(ncores_str, &end, 10) + 1; + if(errno != 0) { + printWarn("strtol: %s:\n", strerror(errno)); + return -1; + } + + free(buf); + + return ncores; +} + char* read_file(char* path, int* len) { int fd = open(path, O_RDONLY); diff --git a/src/common/udev.h b/src/common/udev.h index bcac44f..b181b5f 100644 --- a/src/common/udev.h +++ b/src/common/udev.h @@ -23,6 +23,7 @@ #define _PATH_CACHE_L3 "/cache/index3" #define _PATH_CACHE_SIZE "/size" #define _PATH_CACHE_SHARED_MAP "/shared_cpu_map" +#define _PATH_CPUS_PRESENT _PATH_SYS_SYSTEM _PATH_SYS_CPU "/present" #define _PATH_FREQUENCY_MAX_LEN 100 #define _PATH_CACHE_MAX_LEN 200 @@ -36,5 +37,6 @@ long get_l1d_cache_size(uint32_t core); long get_l2_cache_size(uint32_t core); long get_l3_cache_size(uint32_t core); int get_num_caches_by_level(struct cpuInfo* cpu, uint32_t level); +int get_ncores_from_cpuinfo(); #endif diff --git a/src/x86/apic.c b/src/x86/apic.c index 2ce13b3..3e7a6d8 100644 --- a/src/x86/apic.c +++ b/src/x86/apic.c @@ -385,13 +385,8 @@ bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo) { get_cache_topology_from_apic(topo); - if(!fill_apic_ids(apic_ids, topo->total_cores, x2apic_id)) { - topo->logical_cores = UNKNOWN_DATA; - topo->physical_cores = UNKNOWN_DATA; - topo->smt_available = 1; - topo->smt_supported = 1; + if(!fill_apic_ids(apic_ids, topo->total_cores, x2apic_id)) return false; - } for(int i=0; i < topo->total_cores; i++) { apic_id = apic_ids[i]; diff --git a/src/x86/cpuid.c b/src/x86/cpuid.c index 9978521..322bf59 100644 --- a/src/x86/cpuid.c +++ b/src/x86/cpuid.c @@ -470,6 +470,16 @@ bool get_cache_topology_amd(struct cpuInfo* cpu, struct topology* topo) { return true; } +void get_topology_from_udev(struct cpuInfo* cpu, struct topology* topo) { + // TODO: To be improved in the future + topo->total_cores = get_ncores_from_cpuinfo(); + topo->logical_cores = topo->total_cores; + topo->physical_cores = topo->total_cores; + topo->smt_available = 1; + topo->smt_supported = 1; + topo->sockets = 1; +} + // Main reference: https://software.intel.com/content/www/us/en/develop/articles/intel-64-architecture-processor-topology-enumeration.html // Very interesting resource: https://wiki.osdev.org/Detecting_CPU_Topology_(80x86) struct topology* get_topology_info(struct cpuInfo* cpu, struct cache* cach) { @@ -499,7 +509,19 @@ struct topology* get_topology_info(struct cpuInfo* cpu, struct cache* cach) { switch(cpu->cpu_vendor) { case CPU_VENDOR_INTEL: if (cpu->maxLevels >= 0x00000004) { - get_topology_from_apic(cpu, topo); + bool toporet = get_topology_from_apic(cpu, topo); + if(!toporet) { + #ifdef __linux__ + printWarn("Failed to retrieve topology from APIC, using udev...\n"); + get_topology_from_udev(cpu, topo); + #else + printErr("Failed to retrieve topology from APIC, assumming default values...\n"); + topo->logical_cores = UNKNOWN_DATA; + topo->physical_cores = UNKNOWN_DATA; + topo->smt_available = 1; + topo->smt_supported = 1; + #endif + } } else { printWarn("Can't read topology information from cpuid (needed level is 0x%.8X, max is 0x%.8X)", 0x00000001, cpu->maxLevels);