diff options
| author | sumuel <samuel@yakubos.org> | 2026-08-17 20:44:55 +0000 |
|---|---|---|
| committer | sumuel <samuel@yakubos.org> | 2026-08-17 20:44:55 +0000 |
| commit | 76424950e373d3b04ac3dd13019151bfba3e8423 (patch) | |
| tree | 4c3cfdbda039e592b9186be3e28f8d7cfd439e8a /src/detection/cpu/cpu_sunos.c | |
Add the files
Diffstat (limited to 'src/detection/cpu/cpu_sunos.c')
| -rw-r--r-- | src/detection/cpu/cpu_sunos.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/src/detection/cpu/cpu_sunos.c b/src/detection/cpu/cpu_sunos.c new file mode 100644 index 0000000..9b1cab5 --- /dev/null +++ b/src/detection/cpu/cpu_sunos.c @@ -0,0 +1,154 @@ +#include "cpu.h" +#include "common/processing.h" +#include "common/strutil.h" +#include <kstat.h> + +static const char* detectCPUTempByKstat(const FFCPUOptions* options, kstat_ctl_t* kc, FFCPUResult* cpu) { + const char* possibleModules[] = { "temperature", "cpu_temp", "acpi_thermal", NULL }; + + if (options->tempSensor.length > 0) { + possibleModules[0] = options->tempSensor.chars; + possibleModules[1] = NULL; + } + + for (int i = 0; possibleModules[i] != NULL; i++) { + kstat_t* ks = kstat_lookup(kc, possibleModules[i], -1, NULL); + if (ks && kstat_read(kc, ks, NULL) >= 0) { + kstat_named_t* kn = kstat_data_lookup(ks, "temperature"); + if (kn) { + switch (kn->data_type) { + case KSTAT_DATA_INT32: + cpu->temperature = (float) kn->value.i32; + return NULL; + case KSTAT_DATA_UINT32: + cpu->temperature = (float) kn->value.ui32; + return NULL; + case KSTAT_DATA_FLOAT: + cpu->temperature = kn->value.f; + return NULL; + } + } + } + } + + return "Failed to find CPU temperature using kstat"; +} + +static const char* detectCPUTempByIpmiTool(FFCPUResult* cpu) { + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + const char* error = ffProcessAppendStdOut(&buffer, (char* const[]) { "ipmitool", "-c", "sdr", "list", NULL }); + + if (error) { + return error; + } + + char* line = NULL; + size_t len = 0; + while (ffStrbufGetline(&line, &len, &buffer)) { + if (sscanf(line, "CPU%*d Temp,%lf,degrees C,ok", &cpu->temperature) == 1) { + return NULL; + } + } + + return "ipmitool sdr list failed to find CPU temperature"; +} + +static inline void kstatFreeWrap(kstat_ctl_t** pkc) { + assert(pkc); + if (*pkc) { + kstat_close(*pkc); + } +} + +static inline uint16_t countTypeId(kstat_ctl_t* kc, const char* type) { + uint64_t low = 0, high = 0; + for (kstat_t* ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { + if (ffStrStartsWith(ksp->ks_module, "cpu_info")) { + if (kstat_read(kc, ksp, NULL) < 0) { + continue; + } + + kstat_named_t* stat = kstat_data_lookup(ksp, type); + if (!stat) { + continue; + } + + uint32_t id = 0; + switch (stat->data_type) { +#ifdef _INT64_TYPE + case KSTAT_DATA_INT64: + case KSTAT_DATA_UINT64: + id = (uint32_t) stat->value.ui64; + break; +#endif + case KSTAT_DATA_INT32: + case KSTAT_DATA_UINT32: + id = stat->value.ui32; + break; + default: + continue; + } + if (__builtin_expect(id > 64, false)) { + high |= 1ULL << (id - 64); + } else { + low |= 1ULL << id; + } + } + } + return (uint16_t) (__builtin_popcountll(low) + __builtin_popcountll(high)); +} + +const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) { + FF_A_CLEANUP(kstatFreeWrap) kstat_ctl_t* kc = kstat_open(); + if (!kc) { + return "kstat_open() failed"; + } + + kstat_t* ks = kstat_lookup(kc, "cpu_info", -1, NULL); + if (!ks) { + return "kstat_lookup() failed"; + } + + if (kstat_read(kc, ks, NULL) < 0) { + return "kstat_read() failed"; + } + + { + kstat_named_t* kn = kstat_data_lookup(ks, "brand"); + if (kn) { + ffStrbufSetNS(&cpu->name, KSTAT_NAMED_STR_BUFLEN(kn) - 1, KSTAT_NAMED_STR_PTR(kn)); + } + } + { + kstat_named_t* kn = kstat_data_lookup(ks, "vendor_id"); + if (kn) { + ffStrbufSetNS(&cpu->vendor, KSTAT_NAMED_STR_BUFLEN(kn) - 1, KSTAT_NAMED_STR_PTR(kn)); + } + } + ffCPUDetectByCpuid(cpu); + { + kstat_named_t* kn = kstat_data_lookup(ks, "clock_MHz"); + if (kn && kn->value.ui32 > cpu->frequencyBase) { + cpu->frequencyBase = kn->value.ui32; + } + } + + ks = kstat_lookup(kc, "unix", -1, "system_misc"); + if (ks && kstat_read(kc, ks, NULL) >= 0) { + kstat_named_t* kn = kstat_data_lookup(ks, "ncpus"); + if (kn) { + cpu->coresLogical = cpu->coresOnline = (uint16_t) kn->value.ui32; + } + } + + cpu->packages = countTypeId(kc, "chip_id"); + cpu->coresPhysical = countTypeId(kc, "core_id"); + + if (options->temp) { + if (detectCPUTempByKstat(options, kc, cpu) != NULL) { + detectCPUTempByIpmiTool(cpu); + } + } + + return NULL; +} |