diff --git a/linux/LibSensors.c b/linux/LibSensors.c index c4ef05840..844bbd69d 100644 --- a/linux/LibSensors.c +++ b/linux/LibSensors.c @@ -159,6 +159,38 @@ static int tempDriverPriority(const sensors_chip_name* chip) { return -1; } +int LibSensors_countCCDs(void) { + +#ifndef BUILD_STATIC + if (!dlopenHandle) + return 0; +#endif /* !BUILD_STATIC */ + + int ccds = 0; + + int n = 0; + for (const sensors_chip_name* chip = sym_sensors_get_detected_chips(NULL, &n); chip; chip = sym_sensors_get_detected_chips(NULL, &n)) { + int m = 0; + for (const sensors_feature* feature = sym_sensors_get_features(chip, &m); feature; feature = sym_sensors_get_features(chip, &m)) { + if (feature->type != SENSORS_FEATURE_TEMP) + continue; + + if (!feature->name || !String_startsWith(feature->name, "temp")) + continue; + + char *label = sym_sensors_get_label(chip, feature); + if (label) { + if (String_startsWith(label, "Tccd")) { + ccds++; + } + free(label); + } + } + } + + return ccds; +} + void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int existingCPUs, unsigned int activeCPUs) { assert(existingCPUs > 0 && existingCPUs < 16384); diff --git a/linux/LibSensors.h b/linux/LibSensors.h index 6f0544897..bee2cc41b 100644 --- a/linux/LibSensors.h +++ b/linux/LibSensors.h @@ -14,6 +14,7 @@ int LibSensors_init(void); void LibSensors_cleanup(void); int LibSensors_reload(void); +int LibSensors_countCCDs(void); void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int existingCPUs, unsigned int activeCPUs); #endif /* HEADER_LibSensors */ diff --git a/linux/LinuxMachine.c b/linux/LinuxMachine.c index 95925cef6..4eb126888 100644 --- a/linux/LinuxMachine.c +++ b/linux/LinuxMachine.c @@ -669,6 +669,47 @@ static void LinuxMachine_fetchCPUTopologyFromCPUinfo(LinuxMachine* this) { fclose(file); } + +static void LinuxMachine_assignCCDs(LinuxMachine* this, int ccds) { + /* For AMD k10temp/zenpower, temperatures are provided for CCDs only, + which is an aggregate of multiple cores. + There's no obvious mapping between hwmon sensors and sockets and CCDs. + Assume both are iterated in order. + Hypothesis: Each CCD has same size N = #Cores/#CCD + and is assigned N coreID in sequence. + Also assume all CPUs have same number of CCDs. */ + + const Machine* super = &this->super; + CPUData *cpus = this->cpuData; + + if (ccds == 0) { + for (size_t i = 0; i < super->existingCPUs + 1; i++) { + cpus[i].ccdID = -1; + } + return; + } + + int coresPerCCD = super->existingCPUs / ccds; + + int ccd = 0; + int nc = coresPerCCD; + for (int p = 0; p <= (int)this->maxPhysicalID; p++) { + for (int c = 0; c <= (int)this->maxCoreID; c++) { + for (size_t i = 1; i <= super->existingCPUs; i++) { + if (cpus[i].physicalID != p || cpus[i].coreID != c) + continue; + + cpus[i].ccdID = ccd; + + if (--nc <= 0) { + nc = coresPerCCD; + ccd++; + } + } + } + } +} + #endif static void LinuxMachine_scanCPUFrequency(LinuxMachine* this) { @@ -749,6 +790,8 @@ Machine* Machine_new(UsersTable* usersTable, uid_t userId) { #ifdef HAVE_SENSORS_SENSORS_H // Fetch CPU topology LinuxMachine_fetchCPUTopologyFromCPUinfo(this); + int ccds = LibSensors_countCCDs(); + LinuxMachine_assignCCDs(this, ccds); #endif return super; diff --git a/linux/LinuxMachine.h b/linux/LinuxMachine.h index a3d6ec6fb..4bc334dda 100644 --- a/linux/LinuxMachine.h +++ b/linux/LinuxMachine.h @@ -51,6 +51,7 @@ typedef struct CPUData_ { int physicalID; /* different for each CPU socket */ int coreID; /* same for hyperthreading */ + int ccdID; /* same for each AMD chiplet */ #endif bool online;