mirror of
https://github.com/Dr-Noob/cpufetch.git
synced 2026-03-24 23:40:39 +01:00
[v1.00][X86] Retrieve topology from udev when APIC fails (like #119)
This commit is contained in:
@@ -3,7 +3,6 @@
|
|||||||
#include "midr.h"
|
#include "midr.h"
|
||||||
|
|
||||||
#define _PATH_DEVICETREE_MODEL "/sys/firmware/devicetree/base/model"
|
#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 "/proc/cpuinfo"
|
||||||
//#define _PATH_CPUINFO "cpuinfo_debug"
|
//#define _PATH_CPUINFO "cpuinfo_debug"
|
||||||
|
|
||||||
@@ -17,48 +16,6 @@
|
|||||||
|
|
||||||
#define CPUINFO_CPU_STRING "processor"
|
#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) {
|
long parse_cpuinfo_field(char* buf, char* field_str, int field_base) {
|
||||||
char* tmp = strstr(buf, field_str);
|
char* tmp = strstr(buf, field_str);
|
||||||
if(tmp == NULL) return -1;
|
if(tmp == NULL) return -1;
|
||||||
|
|||||||
@@ -2,6 +2,48 @@
|
|||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "cpu.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) {
|
char* read_file(char* path, int* len) {
|
||||||
int fd = open(path, O_RDONLY);
|
int fd = open(path, O_RDONLY);
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#define _PATH_CACHE_L3 "/cache/index3"
|
#define _PATH_CACHE_L3 "/cache/index3"
|
||||||
#define _PATH_CACHE_SIZE "/size"
|
#define _PATH_CACHE_SIZE "/size"
|
||||||
#define _PATH_CACHE_SHARED_MAP "/shared_cpu_map"
|
#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_FREQUENCY_MAX_LEN 100
|
||||||
#define _PATH_CACHE_MAX_LEN 200
|
#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_l2_cache_size(uint32_t core);
|
||||||
long get_l3_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_num_caches_by_level(struct cpuInfo* cpu, uint32_t level);
|
||||||
|
int get_ncores_from_cpuinfo();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -385,13 +385,8 @@ bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo) {
|
|||||||
|
|
||||||
get_cache_topology_from_apic(topo);
|
get_cache_topology_from_apic(topo);
|
||||||
|
|
||||||
if(!fill_apic_ids(apic_ids, topo->total_cores, x2apic_id)) {
|
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;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
for(int i=0; i < topo->total_cores; i++) {
|
for(int i=0; i < topo->total_cores; i++) {
|
||||||
apic_id = apic_ids[i];
|
apic_id = apic_ids[i];
|
||||||
|
|||||||
@@ -470,6 +470,16 @@ bool get_cache_topology_amd(struct cpuInfo* cpu, struct topology* topo) {
|
|||||||
return true;
|
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
|
// 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)
|
// Very interesting resource: https://wiki.osdev.org/Detecting_CPU_Topology_(80x86)
|
||||||
struct topology* get_topology_info(struct cpuInfo* cpu, struct cache* cach) {
|
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) {
|
switch(cpu->cpu_vendor) {
|
||||||
case CPU_VENDOR_INTEL:
|
case CPU_VENDOR_INTEL:
|
||||||
if (cpu->maxLevels >= 0x00000004) {
|
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 {
|
else {
|
||||||
printWarn("Can't read topology information from cpuid (needed level is 0x%.8X, max is 0x%.8X)", 0x00000001, cpu->maxLevels);
|
printWarn("Can't read topology information from cpuid (needed level is 0x%.8X, max is 0x%.8X)", 0x00000001, cpu->maxLevels);
|
||||||
|
|||||||
Reference in New Issue
Block a user