mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-11-05 04:34:19 +01:00
Chore: run clang-format
```bash find . -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.hpp" \) ! -path "src/3rdparty/*" -print0 | xargs -0 clang-format -i ```
This commit is contained in:
+201
-188
@@ -2,111 +2,126 @@
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu);
|
||||
|
||||
const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu) {
|
||||
const char* error = ffDetectCPUImpl(options, cpu);
|
||||
if (error) return error;
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
const char* removeStrings[] = {
|
||||
" CPU", " FPU", " APU", " Processor",
|
||||
" Dual-Core", " Quad-Core", " Six-Core", " Eight-Core", " Ten-Core",
|
||||
" 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core"
|
||||
};
|
||||
" CPU", " FPU", " APU", " Processor", " Dual-Core", " Quad-Core", " Six-Core", " Eight-Core", " Ten-Core", " 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core"};
|
||||
ffStrbufRemoveStrings(&cpu->name, ARRAY_SIZE(removeStrings), removeStrings);
|
||||
uint32_t radeonGraphics = ffStrbufFirstIndexS(&cpu->name, " w/ Radeon "); // w/ Radeon 780M Graphics
|
||||
if (radeonGraphics >= cpu->name.length)
|
||||
if (radeonGraphics >= cpu->name.length) {
|
||||
radeonGraphics = ffStrbufFirstIndexS(&cpu->name, " with Radeon ");
|
||||
if (radeonGraphics < cpu->name.length)
|
||||
}
|
||||
if (radeonGraphics < cpu->name.length) {
|
||||
ffStrbufSubstrBefore(&cpu->name, radeonGraphics);
|
||||
ffStrbufSubstrBeforeFirstC(&cpu->name, '@'); //Cut the speed output in the name as we append our own
|
||||
ffStrbufTrimRight(&cpu->name, ' '); //If we removed the @ in previous step there was most likely a space before it
|
||||
}
|
||||
ffStrbufSubstrBeforeFirstC(&cpu->name, '@'); // Cut the speed output in the name as we append our own
|
||||
ffStrbufTrimRight(&cpu->name, ' '); // If we removed the @ in previous step there was most likely a space before it
|
||||
ffStrbufRemoveDupWhitespaces(&cpu->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffCPUAppleCodeToName(uint32_t code)
|
||||
{
|
||||
const char* ffCPUAppleCodeToName(uint32_t code) {
|
||||
// https://github.com/AsahiLinux/docs/wiki/Codenames
|
||||
switch (code)
|
||||
{
|
||||
case 8103: return "Apple M1";
|
||||
case 6000: return "Apple M1 Pro";
|
||||
case 6001: return "Apple M1 Max";
|
||||
case 6002: return "Apple M1 Ultra";
|
||||
case 8112: return "Apple M2";
|
||||
case 6020: return "Apple M2 Pro";
|
||||
case 6021: return "Apple M2 Max";
|
||||
case 6022: return "Apple M2 Ultra";
|
||||
case 8122: return "Apple M3";
|
||||
case 6030: return "Apple M3 Pro";
|
||||
switch (code) {
|
||||
case 8103:
|
||||
return "Apple M1";
|
||||
case 6000:
|
||||
return "Apple M1 Pro";
|
||||
case 6001:
|
||||
return "Apple M1 Max";
|
||||
case 6002:
|
||||
return "Apple M1 Ultra";
|
||||
case 8112:
|
||||
return "Apple M2";
|
||||
case 6020:
|
||||
return "Apple M2 Pro";
|
||||
case 6021:
|
||||
return "Apple M2 Max";
|
||||
case 6022:
|
||||
return "Apple M2 Ultra";
|
||||
case 8122:
|
||||
return "Apple M3";
|
||||
case 6030:
|
||||
return "Apple M3 Pro";
|
||||
case 6031:
|
||||
case 6034: return "Apple M3 Max";
|
||||
case 8132: return "Apple M4";
|
||||
case 6040: return "Apple M4 Pro";
|
||||
case 6041: return "Apple M4 Max";
|
||||
default: return NULL;
|
||||
case 6034:
|
||||
return "Apple M3 Max";
|
||||
case 8132:
|
||||
return "Apple M4";
|
||||
case 6040:
|
||||
return "Apple M4 Pro";
|
||||
case 6041:
|
||||
return "Apple M4 Max";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffCPUQualcommCodeToName(uint32_t code)
|
||||
{
|
||||
const char* ffCPUQualcommCodeToName(uint32_t code) {
|
||||
// https://github.com/AsahiLinux/docs/wiki/Codenames
|
||||
switch (code)
|
||||
{
|
||||
case 7180: return "Qualcomm Snapdragon 7c";
|
||||
case 7280: return "Qualcomm Snapdragon 7c+ Gen 3";
|
||||
case 8180: return "Qualcomm Snapdragon 8cx Gen 2 5G";
|
||||
case 8280: return "Qualcomm Snapdragon 8cx Gen 3";
|
||||
default: return NULL;
|
||||
switch (code) {
|
||||
case 7180:
|
||||
return "Qualcomm Snapdragon 7c";
|
||||
case 7280:
|
||||
return "Qualcomm Snapdragon 7c+ Gen 3";
|
||||
case 8180:
|
||||
return "Qualcomm Snapdragon 8cx Gen 2 5G";
|
||||
case 8280:
|
||||
return "Qualcomm Snapdragon 8cx Gen 3";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
|
||||
#include <cpuid.h>
|
||||
# include <cpuid.h>
|
||||
|
||||
void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
{
|
||||
void ffCPUDetectByCpuid(FFCPUResult* cpu) {
|
||||
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
|
||||
if (__get_cpuid(0x16, &eax, &ebx, &ecx, &edx))
|
||||
{
|
||||
if (__get_cpuid(0x16, &eax, &ebx, &ecx, &edx)) {
|
||||
// WARNING: CPUID may report frequencies of efficient cores
|
||||
// cpuid returns 0 MHz when hypervisor is enabled
|
||||
if (eax) cpu->frequencyBase = eax;
|
||||
if (ebx) cpu->frequencyMax = ebx;
|
||||
if (eax) {
|
||||
cpu->frequencyBase = eax;
|
||||
}
|
||||
if (ebx) {
|
||||
cpu->frequencyMax = ebx;
|
||||
}
|
||||
}
|
||||
|
||||
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx))
|
||||
{
|
||||
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
|
||||
// Feature tests (leaf1.ecx, leaf7.ebx)
|
||||
bool sse2 = (ecx & bit_SSE2) != 0;
|
||||
bool sse4_2 = (ecx & bit_SSE4_2) != 0;
|
||||
bool pclmul = (ecx & bit_PCLMUL) != 0;
|
||||
bool popcnt = (ecx & bit_POPCNT) != 0;
|
||||
bool fma = (ecx & bit_FMA) != 0;
|
||||
bool osxsave = (ecx & bit_OSXSAVE) != 0;
|
||||
bool sse2 = (ecx & bit_SSE2) != 0;
|
||||
bool sse4_2 = (ecx & bit_SSE4_2) != 0;
|
||||
bool pclmul = (ecx & bit_PCLMUL) != 0;
|
||||
bool popcnt = (ecx & bit_POPCNT) != 0;
|
||||
bool fma = (ecx & bit_FMA) != 0;
|
||||
bool osxsave = (ecx & bit_OSXSAVE) != 0;
|
||||
|
||||
unsigned int eax7 = 0, ebx7 = 0, ecx7 = 0, edx7 = 0;
|
||||
__get_cpuid_count(7, 0, &eax7, &ebx7, &ecx7, &edx7);
|
||||
|
||||
bool avx2 = (ebx7 & bit_AVX2) != 0;
|
||||
bool bmi2 = (ebx7 & bit_BMI2) != 0;
|
||||
bool avx512f = (ebx7 & bit_AVX512F) != 0;
|
||||
bool avx2 = (ebx7 & bit_AVX2) != 0;
|
||||
bool bmi2 = (ebx7 & bit_BMI2) != 0;
|
||||
bool avx512f = (ebx7 & bit_AVX512F) != 0;
|
||||
bool avx512bw = (ebx7 & bit_AVX512BW) != 0;
|
||||
bool avx512dq = (ebx7 & bit_AVX512DQ) != 0;
|
||||
|
||||
// OS support for AVX/AVX512: check XGETBV (requires OSXSAVE)
|
||||
bool avx_os = false;
|
||||
bool avx_os = false;
|
||||
bool avx512_os = false;
|
||||
if (osxsave)
|
||||
{
|
||||
if (osxsave) {
|
||||
__asm__ __volatile__(
|
||||
"xgetbv"
|
||||
: "=a"(eax), "=d"(edx)
|
||||
: "c"(0)
|
||||
:
|
||||
);
|
||||
uint64_t xcr0 = ((uint64_t)edx << 32) | eax;
|
||||
:);
|
||||
uint64_t xcr0 = ((uint64_t) edx << 32) | eax;
|
||||
|
||||
// AVX requires XCR0[1:2] == 11b (XMM and YMM state)
|
||||
avx_os = (xcr0 & 0x6ULL) == 0x6ULL;
|
||||
@@ -115,10 +130,15 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
}
|
||||
|
||||
cpu->march = "unknown";
|
||||
if (avx512f && avx512bw && avx512dq && avx512_os) cpu->march = "x86_64-v4";
|
||||
else if (avx2 && fma && bmi2 && avx_os) cpu->march = "x86_64-v3";
|
||||
else if (sse4_2 && popcnt && pclmul) cpu->march = "x86_64-v2";
|
||||
else if (sse2) cpu->march = "x86_64-v1";
|
||||
if (avx512f && avx512bw && avx512dq && avx512_os) {
|
||||
cpu->march = "x86_64-v4";
|
||||
} else if (avx2 && fma && bmi2 && avx_os) {
|
||||
cpu->march = "x86_64-v3";
|
||||
} else if (sse4_2 && popcnt && pclmul) {
|
||||
cpu->march = "x86_64-v2";
|
||||
} else if (sse2) {
|
||||
cpu->march = "x86_64-v1";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,33 +149,32 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
// https://en.wikipedia.org/wiki/AArch64#ARM-A_(application_architecture)
|
||||
// Worth noting: Apple M1 is marked as ARMv8.5-A on Wikipedia, but it lacks BTI (mandatory in v8.5)
|
||||
|
||||
#ifdef __linux__
|
||||
#include "common/io.h"
|
||||
#include <elf.h>
|
||||
# ifdef __linux__
|
||||
# include "common/io.h"
|
||||
# include <elf.h>
|
||||
// #include <asm/hwcap.h>
|
||||
|
||||
void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
{
|
||||
void ffCPUDetectByCpuid(FFCPUResult* cpu) {
|
||||
char buf[PROC_FILE_BUFFSIZ];
|
||||
ssize_t nRead = ffReadFileData("/proc/self/auxv", ARRAY_SIZE(buf), buf);
|
||||
|
||||
if (nRead < (ssize_t) sizeof(Elf64_auxv_t)) return;
|
||||
if (nRead < (ssize_t) sizeof(Elf64_auxv_t)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t hwcap = 0, hwcap2 = 0;
|
||||
|
||||
for (Elf64_auxv_t* auxv = (Elf64_auxv_t*)buf; (char*)auxv < buf + nRead; ++auxv)
|
||||
{
|
||||
if (auxv->a_type == AT_HWCAP)
|
||||
{
|
||||
for (Elf64_auxv_t* auxv = (Elf64_auxv_t*) buf; (char*) auxv < buf + nRead; ++auxv) {
|
||||
if (auxv->a_type == AT_HWCAP) {
|
||||
hwcap = auxv->a_un.a_val;
|
||||
}
|
||||
else if (auxv->a_type == AT_HWCAP2)
|
||||
{
|
||||
} else if (auxv->a_type == AT_HWCAP2) {
|
||||
hwcap2 = auxv->a_un.a_val;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hwcap) return;
|
||||
if (!hwcap) {
|
||||
return;
|
||||
}
|
||||
|
||||
cpu->march = "unknown";
|
||||
|
||||
@@ -164,31 +183,31 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
bool has_asimd = (hwcap & (1 << 1) /* HWCAP_ASIMD */) != 0;
|
||||
|
||||
// ARMv8.1-A
|
||||
bool has_atomics = (hwcap & (1 << 8) /* HWCAP_ATOMICS */) != 0; // optional from v8.0
|
||||
bool has_crc32 = (hwcap & (1 << 7) /* HWCAP_CRC32 */) != 0; // optional from v8.0
|
||||
bool has_atomics = (hwcap & (1 << 8) /* HWCAP_ATOMICS */) != 0; // optional from v8.0
|
||||
bool has_crc32 = (hwcap & (1 << 7) /* HWCAP_CRC32 */) != 0; // optional from v8.0
|
||||
bool has_asimdrdm = (hwcap & (1 << 12) /* HWCAP_ASIMDRDM */) != 0; // optional from v8.0
|
||||
|
||||
// ARMv8.2-A
|
||||
bool has_fphp = (hwcap & (1 << 9) /* HWCAP_FPHP */) != 0; // optional
|
||||
bool has_fphp = (hwcap & (1 << 9) /* HWCAP_FPHP */) != 0; // optional
|
||||
bool has_dcpop = (hwcap & (1 << 16) /* HWCAP_DCPOP */) != 0; // DC CVAP, optional from v8.1
|
||||
|
||||
// ARMv8.3-A
|
||||
bool has_paca = (hwcap & (1 << 30) /* HWCAP_PACA */) != 0; // optional from v8.2
|
||||
bool has_paca = (hwcap & (1 << 30) /* HWCAP_PACA */) != 0; // optional from v8.2
|
||||
bool has_lrcpc = (hwcap & (1 << 15) /* HWCAP_LRCPC */) != 0; // optional from v8.2
|
||||
bool has_fcma = (hwcap & (1 << 14) /* HWCAP_FCMA */) != 0; // optional from v8.2
|
||||
bool has_fcma = (hwcap & (1 << 14) /* HWCAP_FCMA */) != 0; // optional from v8.2
|
||||
bool has_jscvt = (hwcap & (1 << 13) /* HWCAP_JSCVT */) != 0; // optional from v8.2
|
||||
|
||||
// ARMv8.4-A
|
||||
bool has_dit = (hwcap & (1 << 24) /* HWCAP_DIT */) != 0; // optional from v8.3
|
||||
bool has_flagm = (hwcap & (1 << 27) /* HWCAP_FLAGM */) != 0; // optional from v8.1
|
||||
bool has_dit = (hwcap & (1 << 24) /* HWCAP_DIT */) != 0; // optional from v8.3
|
||||
bool has_flagm = (hwcap & (1 << 27) /* HWCAP_FLAGM */) != 0; // optional from v8.1
|
||||
bool has_ilrcpc = (hwcap & (1 << 26) /* HWCAP_ILRCPC */) != 0; // optional from v8.2
|
||||
|
||||
// ARMv8.5-A
|
||||
bool has_bti = (hwcap2 & (1 << 17) /* HWCAP2_BTI */) != 0; // optional from v8.4
|
||||
bool has_sb = (hwcap & (1 << 29) /* HWCAP_SB */) != 0; // optional from v8.0
|
||||
bool has_bti = (hwcap2 & (1 << 17) /* HWCAP2_BTI */) != 0; // optional from v8.4
|
||||
bool has_sb = (hwcap & (1 << 29) /* HWCAP_SB */) != 0; // optional from v8.0
|
||||
bool has_dcpodp = (hwcap2 & (1 << 0) /* HWCAP2_DCPODP */) != 0; // optional from v8.1
|
||||
bool has_flagm2 = (hwcap2 & (1 << 7) /* HWCAP2_FLAGM2 */) != 0; // optional from v8.4
|
||||
bool has_frint = (hwcap2 & (1 << 8) /* HWCAP2_FRINT */) != 0; // optional from v8.4
|
||||
bool has_frint = (hwcap2 & (1 << 8) /* HWCAP2_FRINT */) != 0; // optional from v8.4
|
||||
|
||||
// ARMv9.0-A
|
||||
bool has_sve2 = (hwcap2 & (1 << 1) /* HWCAP2_SVE2 */) != 0;
|
||||
@@ -221,7 +240,7 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
bool has_f8e5m2 = (hwcap2 & (1UL << 56) /* HWCAP2_F8E5M2 */) != 0; // optional from v9.2
|
||||
|
||||
// ARMv9.6-A
|
||||
bool has_cmpbr = (hwcap & (1UL << 33) /* HWCAP_CMPBR */) != 0; // optional from v9.5
|
||||
bool has_cmpbr = (hwcap & (1UL << 33) /* HWCAP_CMPBR */) != 0; // optional from v9.5
|
||||
bool has_fprcvt = (hwcap & (1UL << 34) /* HWCAP_FPRCVT */) != 0; // optional from v9.5
|
||||
|
||||
if (has_sve2 || has_sme) {
|
||||
@@ -266,77 +285,78 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif __APPLE__
|
||||
#include <sys/sysctl.h>
|
||||
# elif __APPLE__
|
||||
# include <sys/sysctl.h>
|
||||
// #include <arm/cpu_capabilities_public.h> // Not available in macOS 14-
|
||||
|
||||
void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
{
|
||||
void ffCPUDetectByCpuid(FFCPUResult* cpu) {
|
||||
uint64_t caps[2] = {0}; // 80-bit capability mask, split into two 64-bit values
|
||||
size_t size = sizeof(caps);
|
||||
|
||||
if (sysctlbyname("hw.optional.arm.caps", caps, &size, NULL, 0) != 0) return;
|
||||
if (sysctlbyname("hw.optional.arm.caps", caps, &size, NULL, 0) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Helper macro to test bit in 80-bit capability mask
|
||||
#define FF_HAS_CAP(bit) \
|
||||
(((bit) < 64) ? ((caps[0] >> (bit)) & 1ULL) : ((caps[1] >> ((bit) - 64U)) & 1ULL))
|
||||
// Helper macro to test bit in 80-bit capability mask
|
||||
# define FF_HAS_CAP(bit) \
|
||||
(((bit) < 64) ? ((caps[0] >> (bit)) & 1ULL) : ((caps[1] >> ((bit) - 64U)) & 1ULL))
|
||||
|
||||
cpu->march = "unknown";
|
||||
|
||||
// ARMv8-A
|
||||
bool has_fp = FF_HAS_CAP(50); /* CAP_BIT_AdvSIMD_HPFPCvt */ // Full FP16 support (implies FP/ASIMD)
|
||||
bool has_asimd = FF_HAS_CAP(49); /* CAP_BIT_AdvSIMD */ // Advanced SIMD (NEON)
|
||||
bool has_fp = FF_HAS_CAP(50); /* CAP_BIT_AdvSIMD_HPFPCvt */ // Full FP16 support (implies FP/ASIMD)
|
||||
bool has_asimd = FF_HAS_CAP(49); /* CAP_BIT_AdvSIMD */ // Advanced SIMD (NEON)
|
||||
|
||||
// ARMv8.1-A
|
||||
bool has_lse = FF_HAS_CAP(6); /* CAP_BIT_FEAT_LSE */ // Large System Extensions, optional in v8.0
|
||||
bool has_crc32 = FF_HAS_CAP(51); /* CAP_BIT_FEAT_CRC32 */ // CRC32 instructions, optional in v8.0
|
||||
bool has_rdm = FF_HAS_CAP(5); /* CAP_BIT_FEAT_RDM */ // AdvSIMD rounding double multiply accumulate, optional in v8.0
|
||||
bool has_lse = FF_HAS_CAP(6); /* CAP_BIT_FEAT_LSE */ // Large System Extensions, optional in v8.0
|
||||
bool has_crc32 = FF_HAS_CAP(51); /* CAP_BIT_FEAT_CRC32 */ // CRC32 instructions, optional in v8.0
|
||||
bool has_rdm = FF_HAS_CAP(5); /* CAP_BIT_FEAT_RDM */ // AdvSIMD rounding double multiply accumulate, optional in v8.0
|
||||
|
||||
// ARMv8.2-A
|
||||
bool has_fp16 = FF_HAS_CAP(34); /* CAP_BIT_FEAT_FP16 */ // Half-precision FP support, optional
|
||||
bool has_dpb = FF_HAS_CAP(22); /* CAP_BIT_FEAT_DPB */ // DC CVAP, optional from v8.1
|
||||
bool has_fp16 = FF_HAS_CAP(34); /* CAP_BIT_FEAT_FP16 */ // Half-precision FP support, optional
|
||||
bool has_dpb = FF_HAS_CAP(22); /* CAP_BIT_FEAT_DPB */ // DC CVAP, optional from v8.1
|
||||
|
||||
// ARMv8.3-A
|
||||
bool has_pauth = FF_HAS_CAP(19); /* CAP_BIT_FEAT_PAuth */ // Pointer Authentication (PAC), optional from v8.2
|
||||
bool has_lrcpc = FF_HAS_CAP(15); /* CAP_BIT_FEAT_LRCPC */ // LDAPR/LR with RCPC semantics, optional from v8.2
|
||||
bool has_fcma = FF_HAS_CAP(17); /* CAP_BIT_FEAT_FCMA */ // Complex number multiply-add, optional from v8.2
|
||||
bool has_jscvt = FF_HAS_CAP(18); /* CAP_BIT_FEAT_JSCVT */ // JavaScript-style conversion (FJCVTZS), optional from v8.2
|
||||
bool has_pauth = FF_HAS_CAP(19); /* CAP_BIT_FEAT_PAuth */ // Pointer Authentication (PAC), optional from v8.2
|
||||
bool has_lrcpc = FF_HAS_CAP(15); /* CAP_BIT_FEAT_LRCPC */ // LDAPR/LR with RCPC semantics, optional from v8.2
|
||||
bool has_fcma = FF_HAS_CAP(17); /* CAP_BIT_FEAT_FCMA */ // Complex number multiply-add, optional from v8.2
|
||||
bool has_jscvt = FF_HAS_CAP(18); /* CAP_BIT_FEAT_JSCVT */ // JavaScript-style conversion (FJCVTZS), optional from v8.2
|
||||
|
||||
// ARMv8.4-A
|
||||
bool has_lse2 = FF_HAS_CAP(30); /* CAP_BIT_FEAT_LSE2 */ // Large System Extensions version 2, optional from v8.2
|
||||
bool has_dit = FF_HAS_CAP(33); /* CAP_BIT_FEAT_DIT */ // Data Independent Timing, optional from v8.3
|
||||
bool has_flagm = FF_HAS_CAP(0); /* CAP_BIT_FEAT_FlagM */ // Flag manipulation (FMOV/FCVT), optional from v8.1
|
||||
bool has_lrcpc2 = FF_HAS_CAP(16); /* CAP_BIT_FEAT_LRCPC2 */ // Enhanced RCPC (LDAPUR/LDAPST), optional from v8.2
|
||||
bool has_lse2 = FF_HAS_CAP(30); /* CAP_BIT_FEAT_LSE2 */ // Large System Extensions version 2, optional from v8.2
|
||||
bool has_dit = FF_HAS_CAP(33); /* CAP_BIT_FEAT_DIT */ // Data Independent Timing, optional from v8.3
|
||||
bool has_flagm = FF_HAS_CAP(0); /* CAP_BIT_FEAT_FlagM */ // Flag manipulation (FMOV/FCVT), optional from v8.1
|
||||
bool has_lrcpc2 = FF_HAS_CAP(16); /* CAP_BIT_FEAT_LRCPC2 */ // Enhanced RCPC (LDAPUR/LDAPST), optional from v8.2
|
||||
|
||||
// ARMv8.5-A
|
||||
bool has_bti = FF_HAS_CAP(36); /* CAP_BIT_FEAT_BTI */ // Branch Target Identification, optional from v8.4
|
||||
bool has_sb = FF_HAS_CAP(13); /* CAP_BIT_FEAT_SB */ // Speculative Barrier, optional from v8.0
|
||||
bool has_dpb2 = FF_HAS_CAP(23); /* CAP_BIT_FEAT_DPB2 */ // DC CVADP (DPB2), optional from v8.1
|
||||
bool has_flagm2 = FF_HAS_CAP(1); /* CAP_BIT_FEAT_FlagM2 */ // Enhanced FlagM, optional from v8.4
|
||||
bool has_frintts = FF_HAS_CAP(14); /* CAP_BIT_FEAT_FRINTTS */ // Floating-point to integer instructions, optional from v8.4
|
||||
bool has_bti = FF_HAS_CAP(36); /* CAP_BIT_FEAT_BTI */ // Branch Target Identification, optional from v8.4
|
||||
bool has_sb = FF_HAS_CAP(13); /* CAP_BIT_FEAT_SB */ // Speculative Barrier, optional from v8.0
|
||||
bool has_dpb2 = FF_HAS_CAP(23); /* CAP_BIT_FEAT_DPB2 */ // DC CVADP (DPB2), optional from v8.1
|
||||
bool has_flagm2 = FF_HAS_CAP(1); /* CAP_BIT_FEAT_FlagM2 */ // Enhanced FlagM, optional from v8.4
|
||||
bool has_frintts = FF_HAS_CAP(14); /* CAP_BIT_FEAT_FRINTTS */ // Floating-point to integer instructions, optional from v8.4
|
||||
|
||||
// ARMv9.0-A
|
||||
bool has_sve2 = false; // Not exposed and not supported by Apple M4
|
||||
bool has_sve2 = false; // Not exposed and not supported by Apple M4
|
||||
|
||||
// ARMv9.1-A
|
||||
// ARMv8.6-A
|
||||
bool has_bf16 = FF_HAS_CAP(24); /* CAP_BIT_FEAT_BF16 */ // Brain float16, optional from v8.2
|
||||
bool has_i8mm = FF_HAS_CAP(25); /* CAP_BIT_FEAT_I8MM */ // Int8 Matrix Multiply, optional from v8.1
|
||||
bool has_bf16 = FF_HAS_CAP(24); /* CAP_BIT_FEAT_BF16 */ // Brain float16, optional from v8.2
|
||||
bool has_i8mm = FF_HAS_CAP(25); /* CAP_BIT_FEAT_I8MM */ // Int8 Matrix Multiply, optional from v8.1
|
||||
|
||||
// ARMv8.7-A
|
||||
bool has_afp = FF_HAS_CAP(29); /* CAP_BIT_FEAT_AFP */ // Alternate FP16 (FEXPA), optional from v8.6
|
||||
bool has_afp = FF_HAS_CAP(29); /* CAP_BIT_FEAT_AFP */ // Alternate FP16 (FEXPA), optional from v8.6
|
||||
|
||||
// ARMv9.2-A
|
||||
bool has_sme = FF_HAS_CAP(40); /* CAP_BIT_FEAT_SME */ // Scalable Matrix Extension, optional from v9.2
|
||||
bool has_sme = FF_HAS_CAP(40); /* CAP_BIT_FEAT_SME */ // Scalable Matrix Extension, optional from v9.2
|
||||
|
||||
// ARMv9.3-A
|
||||
bool has_sme2 = FF_HAS_CAP(41); /* CAP_BIT_FEAT_SME2 */ // SME2, optional from v9.2
|
||||
bool has_sme2 = FF_HAS_CAP(41); /* CAP_BIT_FEAT_SME2 */ // SME2, optional from v9.2
|
||||
|
||||
// ARMv8.8-A
|
||||
bool has_hbc = FF_HAS_CAP(64); /* CAP_BIT_FEAT_HBC */ // Hinted conditional branches, optional from v8.7
|
||||
bool has_hbc = FF_HAS_CAP(64); /* CAP_BIT_FEAT_HBC */ // Hinted conditional branches, optional from v8.7
|
||||
|
||||
// ARMv8.9-A
|
||||
bool has_cssc = FF_HAS_CAP(67); /* CAP_BIT_FEAT_CSSC */ // Common Short String Compare, optional from v8.7
|
||||
bool has_cssc = FF_HAS_CAP(67); /* CAP_BIT_FEAT_CSSC */ // Common Short String Compare, optional from v8.7
|
||||
|
||||
// ARMv9.4-A+ are not exposed yet
|
||||
|
||||
@@ -376,85 +396,82 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
}
|
||||
}
|
||||
|
||||
#undef HAS_CAP
|
||||
# undef HAS_CAP
|
||||
}
|
||||
#elif _WIN32
|
||||
#include <processthreadsapi.h>
|
||||
# elif _WIN32
|
||||
# include <processthreadsapi.h>
|
||||
|
||||
// Missing from winnt.h of MinGW-w64
|
||||
#define PF_ARM_LSE2_AVAILABLE 62
|
||||
#define PF_RESERVED_FEATURE 63
|
||||
#define PF_ARM_SHA3_INSTRUCTIONS_AVAILABLE 64
|
||||
#define PF_ARM_SHA512_INSTRUCTIONS_AVAILABLE 65
|
||||
#define PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE 66
|
||||
#define PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE 67
|
||||
#define PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE 68
|
||||
#define PF_ARM_V86_EBF16_INSTRUCTIONS_AVAILABLE 69
|
||||
#define PF_ARM_SME_INSTRUCTIONS_AVAILABLE 70
|
||||
#define PF_ARM_SME2_INSTRUCTIONS_AVAILABLE 71
|
||||
#define PF_ARM_SME2_1_INSTRUCTIONS_AVAILABLE 72
|
||||
#define PF_ARM_SME2_2_INSTRUCTIONS_AVAILABLE 73
|
||||
#define PF_ARM_SME_AES_INSTRUCTIONS_AVAILABLE 74
|
||||
#define PF_ARM_SME_SBITPERM_INSTRUCTIONS_AVAILABLE 75
|
||||
#define PF_ARM_SME_SF8MM4_INSTRUCTIONS_AVAILABLE 76
|
||||
#define PF_ARM_SME_SF8MM8_INSTRUCTIONS_AVAILABLE 77
|
||||
#define PF_ARM_SME_SF8DP2_INSTRUCTIONS_AVAILABLE 78
|
||||
#define PF_ARM_SME_SF8DP4_INSTRUCTIONS_AVAILABLE 79
|
||||
#define PF_ARM_SME_SF8FMA_INSTRUCTIONS_AVAILABLE 80
|
||||
#define PF_ARM_SME_F8F32_INSTRUCTIONS_AVAILABLE 81
|
||||
#define PF_ARM_SME_F8F16_INSTRUCTIONS_AVAILABLE 82
|
||||
#define PF_ARM_SME_F16F16_INSTRUCTIONS_AVAILABLE 83
|
||||
#define PF_ARM_SME_B16B16_INSTRUCTIONS_AVAILABLE 84
|
||||
#define PF_ARM_SME_F64F64_INSTRUCTIONS_AVAILABLE 85
|
||||
#define PF_ARM_SME_I16I64_INSTRUCTIONS_AVAILABLE 86
|
||||
#define PF_ARM_SME_LUTv2_INSTRUCTIONS_AVAILABLE 87
|
||||
#define PF_ARM_SME_FA64_INSTRUCTIONS_AVAILABLE 88
|
||||
# define PF_ARM_LSE2_AVAILABLE 62
|
||||
# define PF_RESERVED_FEATURE 63
|
||||
# define PF_ARM_SHA3_INSTRUCTIONS_AVAILABLE 64
|
||||
# define PF_ARM_SHA512_INSTRUCTIONS_AVAILABLE 65
|
||||
# define PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE 66
|
||||
# define PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE 67
|
||||
# define PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE 68
|
||||
# define PF_ARM_V86_EBF16_INSTRUCTIONS_AVAILABLE 69
|
||||
# define PF_ARM_SME_INSTRUCTIONS_AVAILABLE 70
|
||||
# define PF_ARM_SME2_INSTRUCTIONS_AVAILABLE 71
|
||||
# define PF_ARM_SME2_1_INSTRUCTIONS_AVAILABLE 72
|
||||
# define PF_ARM_SME2_2_INSTRUCTIONS_AVAILABLE 73
|
||||
# define PF_ARM_SME_AES_INSTRUCTIONS_AVAILABLE 74
|
||||
# define PF_ARM_SME_SBITPERM_INSTRUCTIONS_AVAILABLE 75
|
||||
# define PF_ARM_SME_SF8MM4_INSTRUCTIONS_AVAILABLE 76
|
||||
# define PF_ARM_SME_SF8MM8_INSTRUCTIONS_AVAILABLE 77
|
||||
# define PF_ARM_SME_SF8DP2_INSTRUCTIONS_AVAILABLE 78
|
||||
# define PF_ARM_SME_SF8DP4_INSTRUCTIONS_AVAILABLE 79
|
||||
# define PF_ARM_SME_SF8FMA_INSTRUCTIONS_AVAILABLE 80
|
||||
# define PF_ARM_SME_F8F32_INSTRUCTIONS_AVAILABLE 81
|
||||
# define PF_ARM_SME_F8F16_INSTRUCTIONS_AVAILABLE 82
|
||||
# define PF_ARM_SME_F16F16_INSTRUCTIONS_AVAILABLE 83
|
||||
# define PF_ARM_SME_B16B16_INSTRUCTIONS_AVAILABLE 84
|
||||
# define PF_ARM_SME_F64F64_INSTRUCTIONS_AVAILABLE 85
|
||||
# define PF_ARM_SME_I16I64_INSTRUCTIONS_AVAILABLE 86
|
||||
# define PF_ARM_SME_LUTv2_INSTRUCTIONS_AVAILABLE 87
|
||||
# define PF_ARM_SME_FA64_INSTRUCTIONS_AVAILABLE 88
|
||||
|
||||
void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
{
|
||||
void ffCPUDetectByCpuid(FFCPUResult* cpu) {
|
||||
// ARMv8-A
|
||||
bool has_vfp = IsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE); // Implies basic FP support
|
||||
bool has_neon = IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE); // NEON (ASIMD)
|
||||
bool has_vfp = IsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE); // Implies basic FP support
|
||||
bool has_neon = IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE); // NEON (ASIMD)
|
||||
|
||||
// ARMv8.1-A
|
||||
bool has_atomics = IsProcessorFeaturePresent(PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE); // LSE atomics
|
||||
bool has_crc32 = IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE); // CRC32
|
||||
bool has_atomics = IsProcessorFeaturePresent(PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE); // LSE atomics
|
||||
bool has_crc32 = IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE); // CRC32
|
||||
|
||||
// ARMv8.2-A
|
||||
bool has_fp16 = IsProcessorFeaturePresent(PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE); // Half-precision FP
|
||||
bool has_fp16 = IsProcessorFeaturePresent(PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE); // Half-precision FP
|
||||
|
||||
// ARMv8.3-A
|
||||
bool has_lrcpc = IsProcessorFeaturePresent(PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE); // LDAPR/LR with RCPC semantics
|
||||
bool has_jscvt = IsProcessorFeaturePresent(PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE); // FJCVTZS
|
||||
bool has_lrcpc = IsProcessorFeaturePresent(PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE); // LDAPR/LR with RCPC semantics
|
||||
bool has_jscvt = IsProcessorFeaturePresent(PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE); // FJCVTZS
|
||||
|
||||
// ARMv8.4-A
|
||||
// My CPU (Apple M1 Pro in VM) does support LSE2, but Windows doesn't detect it for some reason
|
||||
bool has_lse2 = IsProcessorFeaturePresent(PF_ARM_LSE2_AVAILABLE); // Large System Extensions version 2, optional from v8.2
|
||||
bool has_dp = IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE); // DotProd, optional from v8.1 (*)
|
||||
bool has_lse2 = IsProcessorFeaturePresent(PF_ARM_LSE2_AVAILABLE); // Large System Extensions version 2, optional from v8.2
|
||||
bool has_dp = IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE); // DotProd, optional from v8.1 (*)
|
||||
|
||||
// ARMv9.0-A
|
||||
bool has_sve2 = IsProcessorFeaturePresent(PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE); // SVE2
|
||||
bool has_sve2 = IsProcessorFeaturePresent(PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE); // SVE2
|
||||
|
||||
// ARMv9.1-A
|
||||
// ARMv8.6-A
|
||||
bool has_bf16 = IsProcessorFeaturePresent(PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE); // BF16, optional from v8.2
|
||||
bool has_i8mm = IsProcessorFeaturePresent(PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE); // Int8 matrix multiply, optional from v8.2
|
||||
bool has_bf16 = IsProcessorFeaturePresent(PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE); // BF16, optional from v8.2
|
||||
bool has_i8mm = IsProcessorFeaturePresent(PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE); // Int8 matrix multiply, optional from v8.2
|
||||
|
||||
// ARMv8.7-A
|
||||
bool has_ebf16 = IsProcessorFeaturePresent(PF_ARM_V86_EBF16_INSTRUCTIONS_AVAILABLE); // Extended BFloat16 behaviors, optional from v8.2
|
||||
bool has_ebf16 = IsProcessorFeaturePresent(PF_ARM_V86_EBF16_INSTRUCTIONS_AVAILABLE); // Extended BFloat16 behaviors, optional from v8.2
|
||||
|
||||
// ARMv9.2-A
|
||||
bool has_sme = IsProcessorFeaturePresent(PF_ARM_SME_INSTRUCTIONS_AVAILABLE); // SME
|
||||
bool has_sme = IsProcessorFeaturePresent(PF_ARM_SME_INSTRUCTIONS_AVAILABLE); // SME
|
||||
|
||||
// ARMv9.3-A
|
||||
bool has_sme2 = IsProcessorFeaturePresent(PF_ARM_SME2_INSTRUCTIONS_AVAILABLE); // SME2
|
||||
bool has_sme2 = IsProcessorFeaturePresent(PF_ARM_SME2_INSTRUCTIONS_AVAILABLE); // SME2
|
||||
|
||||
// ARMv9.4-A
|
||||
bool has_sme2p1 = IsProcessorFeaturePresent(PF_ARM_SME2_1_INSTRUCTIONS_AVAILABLE); // SME2.1
|
||||
bool has_sme2p1 = IsProcessorFeaturePresent(PF_ARM_SME2_1_INSTRUCTIONS_AVAILABLE); // SME2.1
|
||||
|
||||
|
||||
if (has_sve2 || has_sme)
|
||||
{
|
||||
if (has_sve2 || has_sme) {
|
||||
// ARMv9 family
|
||||
if (has_sme2p1) {
|
||||
cpu->march = "ARMv9.4-A";
|
||||
@@ -467,9 +484,7 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
} else {
|
||||
cpu->march = "ARMv9.0-A";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// ARMv8 family
|
||||
if (has_ebf16) {
|
||||
cpu->march = "ARMv8.7-A";
|
||||
@@ -488,17 +503,15 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
void ffCPUDetectByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu)
|
||||
{
|
||||
# else
|
||||
void ffCPUDetectByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu) {
|
||||
// Unsupported system
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
void ffCPUDetectByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu)
|
||||
{
|
||||
void ffCPUDetectByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu) {
|
||||
// Unsupported architecture
|
||||
}
|
||||
|
||||
|
||||
@@ -5,14 +5,12 @@
|
||||
|
||||
#define FF_CPU_TEMP_UNSET (-DBL_MAX)
|
||||
|
||||
typedef struct FFCPUCore
|
||||
{
|
||||
typedef struct FFCPUCore {
|
||||
uint32_t freq;
|
||||
uint32_t count;
|
||||
} FFCPUCore;
|
||||
|
||||
typedef struct FFCPUResult
|
||||
{
|
||||
typedef struct FFCPUResult {
|
||||
FFstrbuf name;
|
||||
FFstrbuf vendor;
|
||||
const char* march; // Microarchitecture
|
||||
@@ -24,7 +22,7 @@ typedef struct FFCPUResult
|
||||
uint16_t numaNodes;
|
||||
|
||||
uint32_t frequencyBase; // GHz
|
||||
uint32_t frequencyMax; // GHz
|
||||
uint32_t frequencyMax; // GHz
|
||||
|
||||
FFCPUCore coreTypes[16]; // number of P cores, E cores, etc.
|
||||
|
||||
|
||||
@@ -3,106 +3,114 @@
|
||||
#include "common/apple/smc_temps.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
static double detectCpuTemp(const FFCPUOptions* options, const FFstrbuf* cpuName)
|
||||
{
|
||||
static double detectCpuTemp(const FFCPUOptions* options, const FFstrbuf* cpuName) {
|
||||
double result = 0;
|
||||
|
||||
const char* error = NULL;
|
||||
|
||||
if (options->tempSensor.length)
|
||||
{
|
||||
if (options->tempSensor.length) {
|
||||
error = ffDetectSmcSpecificTemp(options->tempSensor.chars, &result);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ffStrbufStartsWithS(cpuName, "Apple M"))
|
||||
{
|
||||
switch (strtol(cpuName->chars + strlen("Apple M"), NULL, 10))
|
||||
{
|
||||
case 1: error = ffDetectSmcTemps(FF_TEMP_CPU_M1X, &result); break;
|
||||
case 2: error = ffDetectSmcTemps(FF_TEMP_CPU_M2X, &result); break;
|
||||
case 3: error = ffDetectSmcTemps(FF_TEMP_CPU_M3X, &result); break;
|
||||
case 4: error = ffDetectSmcTemps(FF_TEMP_CPU_M4X, &result); break;
|
||||
default: error = "Unsupported Apple Silicon CPU";
|
||||
} else {
|
||||
if (ffStrbufStartsWithS(cpuName, "Apple M")) {
|
||||
switch (strtol(cpuName->chars + strlen("Apple M"), NULL, 10)) {
|
||||
case 1:
|
||||
error = ffDetectSmcTemps(FF_TEMP_CPU_M1X, &result);
|
||||
break;
|
||||
case 2:
|
||||
error = ffDetectSmcTemps(FF_TEMP_CPU_M2X, &result);
|
||||
break;
|
||||
case 3:
|
||||
error = ffDetectSmcTemps(FF_TEMP_CPU_M3X, &result);
|
||||
break;
|
||||
case 4:
|
||||
error = ffDetectSmcTemps(FF_TEMP_CPU_M4X, &result);
|
||||
break;
|
||||
default:
|
||||
error = "Unsupported Apple Silicon CPU";
|
||||
}
|
||||
}
|
||||
else // PPC?
|
||||
} else { // PPC?
|
||||
error = ffDetectSmcTemps(FF_TEMP_CPU_X64, &result);
|
||||
}
|
||||
}
|
||||
|
||||
if (error)
|
||||
if (error) {
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef __aarch64__
|
||||
#include "common/apple/cf_helpers.h"
|
||||
# include "common/apple/cf_helpers.h"
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
# include <IOKit/IOKitLib.h>
|
||||
|
||||
static const char* detectFrequency(FFCPUResult* cpu)
|
||||
{
|
||||
static const char* detectFrequency(FFCPUResult* cpu) {
|
||||
// https://github.com/giampaolo/psutil/pull/2222/files
|
||||
|
||||
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDevice = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("pmgr"));
|
||||
if (!entryDevice)
|
||||
if (!entryDevice) {
|
||||
return "IOServiceGetMatchingService() failed";
|
||||
}
|
||||
|
||||
if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice"))
|
||||
if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice")) {
|
||||
return "\"pmgr\" should conform to \"AppleARMIODevice\"";
|
||||
}
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFDataRef freqProperty = (CFDataRef) IORegistryEntryCreateCFProperty(entryDevice, CFSTR("voltage-states5-sram"), kCFAllocatorDefault, kNilOptions);
|
||||
if (!freqProperty || CFGetTypeID(freqProperty) != CFDataGetTypeID())
|
||||
if (!freqProperty || CFGetTypeID(freqProperty) != CFDataGetTypeID()) {
|
||||
return "\"voltage-states5-sram\" in \"pmgr\" is not found";
|
||||
}
|
||||
|
||||
// voltage-states5-sram stores supported <frequency / voltage> pairs of pcores from the lowest to the highest
|
||||
// voltage-states1-sram stores ecores'
|
||||
CFIndex propLength = CFDataGetLength(freqProperty);
|
||||
if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0)
|
||||
if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0) {
|
||||
return "Invalid \"voltage-states5-sram\" length";
|
||||
}
|
||||
|
||||
uint32_t* pStart = (uint32_t*) CFDataGetBytePtr(freqProperty);
|
||||
uint32_t pMax = *pStart;
|
||||
for (CFIndex i = 2; i < propLength / (CFIndex) sizeof(uint32_t) && pStart[i] > 0; i += 2 /* skip voltage */)
|
||||
for (CFIndex i = 2; i < propLength / (CFIndex) sizeof(uint32_t) && pStart[i] > 0; i += 2 /* skip voltage */) {
|
||||
pMax = pMax > pStart[i] ? pMax : pStart[i];
|
||||
}
|
||||
|
||||
if (pMax > 0)
|
||||
{
|
||||
if (pMax > 100000000) // Assume that pMax is in Hz, M1~M3
|
||||
if (pMax > 0) {
|
||||
if (pMax > 100000000) { // Assume that pMax is in Hz, M1~M3
|
||||
cpu->frequencyMax = pMax / 1000 / 1000;
|
||||
else // Assume that pMax is in kHz, M4 and later (#1394)
|
||||
} else { // Assume that pMax is in kHz, M4 and later (#1394)
|
||||
cpu->frequencyMax = pMax / 1000;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
static const char* detectFrequency(FFCPUResult* cpu)
|
||||
{
|
||||
static const char* detectFrequency(FFCPUResult* cpu) {
|
||||
cpu->frequencyBase = (uint32_t) (ffSysctlGetInt64("hw.cpufrequency", 0) / 1000 / 1000);
|
||||
cpu->frequencyMax = (uint32_t) (ffSysctlGetInt64("hw.cpufrequency_max", 0) / 1000 / 1000);
|
||||
if(cpu->frequencyBase == 0)
|
||||
{
|
||||
if (cpu->frequencyBase == 0) {
|
||||
unsigned current = 0;
|
||||
size_t size = sizeof(current);
|
||||
if (sysctl((int[]){ CTL_HW, HW_CPU_FREQ }, 2, ¤t, &size, NULL, 0) == 0)
|
||||
if (sysctl((int[]) {CTL_HW, HW_CPU_FREQ}, 2, ¤t, &size, NULL, 0) == 0) {
|
||||
cpu->frequencyBase = (uint32_t) (current / 1000 / 1000);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* detectCoreCount(FFCPUResult* cpu)
|
||||
{
|
||||
static const char* detectCoreCount(FFCPUResult* cpu) {
|
||||
uint32_t nPerfLevels = (uint32_t) ffSysctlGetInt("hw.nperflevels", 0);
|
||||
if (nPerfLevels <= 0) return "sysctl(hw.nperflevels) failed";
|
||||
if (nPerfLevels <= 0) {
|
||||
return "sysctl(hw.nperflevels) failed";
|
||||
}
|
||||
|
||||
char sysctlKey[] = "hw.perflevelN.logicalcpu";
|
||||
if (nPerfLevels > ARRAY_SIZE(cpu->coreTypes))
|
||||
if (nPerfLevels > ARRAY_SIZE(cpu->coreTypes)) {
|
||||
nPerfLevels = ARRAY_SIZE(cpu->coreTypes);
|
||||
for (uint32_t i = 0; i < nPerfLevels; ++i)
|
||||
{
|
||||
}
|
||||
for (uint32_t i = 0; i < nPerfLevels; ++i) {
|
||||
sysctlKey[strlen("hw.perflevel")] = (char) ('0' + i);
|
||||
cpu->coreTypes[i] = (FFCPUCore) {
|
||||
.freq = nPerfLevels - i,
|
||||
@@ -112,31 +120,37 @@ static const char* detectCoreCount(FFCPUResult* cpu)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
if (ffSysctlGetString("machdep.cpu.brand_string", &cpu->name) != NULL)
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
|
||||
if (ffSysctlGetString("machdep.cpu.brand_string", &cpu->name) != NULL) {
|
||||
return "sysctlbyname(machdep.cpu.brand_string) failed";
|
||||
}
|
||||
|
||||
ffSysctlGetString("machdep.cpu.vendor", &cpu->vendor);
|
||||
cpu->packages = (uint16_t) ffSysctlGetInt("hw.packages", 1);
|
||||
if (cpu->vendor.length == 0 && ffStrbufStartsWithS(&cpu->name, "Apple "))
|
||||
if (cpu->vendor.length == 0 && ffStrbufStartsWithS(&cpu->name, "Apple ")) {
|
||||
ffStrbufAppendS(&cpu->vendor, "Apple");
|
||||
}
|
||||
|
||||
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu_max", 1);
|
||||
if(cpu->coresPhysical == 1)
|
||||
if (cpu->coresPhysical == 1) {
|
||||
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu", 1);
|
||||
}
|
||||
|
||||
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.logicalcpu_max", 1);
|
||||
if(cpu->coresLogical == 1)
|
||||
if (cpu->coresLogical == 1) {
|
||||
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
|
||||
}
|
||||
|
||||
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.logicalcpu", 1);
|
||||
if(cpu->coresOnline == 1)
|
||||
if (cpu->coresOnline == 1) {
|
||||
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1);
|
||||
}
|
||||
|
||||
ffCPUDetectByCpuid(cpu);
|
||||
detectFrequency(cpu);
|
||||
if (options->showPeCoreCount) detectCoreCount(cpu);
|
||||
if (options->showPeCoreCount) {
|
||||
detectCoreCount(cpu);
|
||||
}
|
||||
|
||||
cpu->temperature = options->temp ? detectCpuTemp(options, &cpu->name) : FF_CPU_TEMP_UNSET;
|
||||
|
||||
|
||||
+528
-318
@@ -5,374 +5,584 @@
|
||||
// https://github.com/util-linux/util-linux/blob/master/sys-utils/lscpu-arm.c
|
||||
// We use the util-linux's data but not its code. Call me if it violates util-linux's GPL license.
|
||||
|
||||
static const char* hwImplId2Vendor(uint32_t implId)
|
||||
{
|
||||
switch (implId)
|
||||
{
|
||||
case 0x41: return "ARM";
|
||||
case 0x42: return "Broadcom";
|
||||
case 0x43: return "Cavium";
|
||||
case 0x44: return "DEC";
|
||||
case 0x46: return "FUJITSU";
|
||||
case 0x48: return "HiSilicon";
|
||||
case 0x49: return "Infineon";
|
||||
case 0x4d: return "Motorola";
|
||||
case 0x4e: return "NVIDIA";
|
||||
case 0x50: return "APM";
|
||||
case 0x51: return "Qualcomm";
|
||||
case 0x53: return "Samsung";
|
||||
case 0x56: return "Marvell";
|
||||
case 0x61: return "Apple";
|
||||
case 0x66: return "Faraday";
|
||||
case 0x69: return "Intel";
|
||||
case 0x6D: return "Microsoft";
|
||||
case 0x70: return "Phytium";
|
||||
case 0xc0: return "Ampere";
|
||||
default: return "Unknown";
|
||||
static const char* hwImplId2Vendor(uint32_t implId) {
|
||||
switch (implId) {
|
||||
case 0x41:
|
||||
return "ARM";
|
||||
case 0x42:
|
||||
return "Broadcom";
|
||||
case 0x43:
|
||||
return "Cavium";
|
||||
case 0x44:
|
||||
return "DEC";
|
||||
case 0x46:
|
||||
return "FUJITSU";
|
||||
case 0x48:
|
||||
return "HiSilicon";
|
||||
case 0x49:
|
||||
return "Infineon";
|
||||
case 0x4d:
|
||||
return "Motorola";
|
||||
case 0x4e:
|
||||
return "NVIDIA";
|
||||
case 0x50:
|
||||
return "APM";
|
||||
case 0x51:
|
||||
return "Qualcomm";
|
||||
case 0x53:
|
||||
return "Samsung";
|
||||
case 0x56:
|
||||
return "Marvell";
|
||||
case 0x61:
|
||||
return "Apple";
|
||||
case 0x66:
|
||||
return "Faraday";
|
||||
case 0x69:
|
||||
return "Intel";
|
||||
case 0x6D:
|
||||
return "Microsoft";
|
||||
case 0x70:
|
||||
return "Phytium";
|
||||
case 0xc0:
|
||||
return "Ampere";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static const char* armPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x810: return "ARM810";
|
||||
case 0x920: return "ARM920";
|
||||
case 0x922: return "ARM922";
|
||||
case 0x926: return "ARM926";
|
||||
case 0x940: return "ARM940";
|
||||
case 0x946: return "ARM946";
|
||||
case 0x966: return "ARM966";
|
||||
case 0xa20: return "ARM1020";
|
||||
case 0xa22: return "ARM1022";
|
||||
case 0xa26: return "ARM1026";
|
||||
case 0xb02: return "ARM11-MPCore";
|
||||
case 0xb36: return "ARM1136";
|
||||
case 0xb56: return "ARM1156";
|
||||
case 0xb76: return "ARM1176";
|
||||
case 0xc05: return "Cortex-A5";
|
||||
case 0xc07: return "Cortex-A7";
|
||||
case 0xc08: return "Cortex-A8";
|
||||
case 0xc09: return "Cortex-A9";
|
||||
case 0xc0d: return "Cortex-A17"; /* Originally A12 */
|
||||
case 0xc0f: return "Cortex-A15";
|
||||
case 0xc0e: return "Cortex-A17";
|
||||
case 0xc14: return "Cortex-R4";
|
||||
case 0xc15: return "Cortex-R5";
|
||||
case 0xc17: return "Cortex-R7";
|
||||
case 0xc18: return "Cortex-R8";
|
||||
case 0xc20: return "Cortex-M0";
|
||||
case 0xc21: return "Cortex-M1";
|
||||
case 0xc23: return "Cortex-M3";
|
||||
case 0xc24: return "Cortex-M4";
|
||||
case 0xc27: return "Cortex-M7";
|
||||
case 0xc60: return "Cortex-M0+";
|
||||
case 0xd01: return "Cortex-A32";
|
||||
case 0xd02: return "Cortex-A34";
|
||||
case 0xd03: return "Cortex-A53";
|
||||
case 0xd04: return "Cortex-A35";
|
||||
case 0xd05: return "Cortex-A55";
|
||||
case 0xd06: return "Cortex-A65";
|
||||
case 0xd07: return "Cortex-A57";
|
||||
case 0xd08: return "Cortex-A72";
|
||||
case 0xd09: return "Cortex-A73";
|
||||
case 0xd0a: return "Cortex-A75";
|
||||
case 0xd0b: return "Cortex-A76";
|
||||
case 0xd0c: return "Neoverse-N1";
|
||||
case 0xd0d: return "Cortex-A77";
|
||||
case 0xd0e: return "Cortex-A76AE";
|
||||
case 0xd13: return "Cortex-R52";
|
||||
case 0xd14: return "Cortex-R82AE";
|
||||
case 0xd15: return "Cortex-R82";
|
||||
case 0xd16: return "Cortex-R52+";
|
||||
case 0xd20: return "Cortex-M23";
|
||||
case 0xd21: return "Cortex-M33";
|
||||
case 0xd24: return "Cortex-M52";
|
||||
case 0xd22: return "Cortex-M55";
|
||||
case 0xd23: return "Cortex-M85";
|
||||
case 0xd40: return "Neoverse-V1";
|
||||
case 0xd41: return "Cortex-A78";
|
||||
case 0xd42: return "Cortex-A78AE";
|
||||
case 0xd43: return "Cortex-A65AE";
|
||||
case 0xd44: return "Cortex-X1";
|
||||
case 0xd46: return "Cortex-A510";
|
||||
case 0xd47: return "Cortex-A710";
|
||||
case 0xd48: return "Cortex-X2";
|
||||
case 0xd49: return "Neoverse-N2";
|
||||
case 0xd4a: return "Neoverse-E1";
|
||||
case 0xd4b: return "Cortex-A78C";
|
||||
case 0xd4c: return "Cortex-X1C";
|
||||
case 0xd4d: return "Cortex-A715";
|
||||
case 0xd4e: return "Cortex-X3";
|
||||
case 0xd4f: return "Neoverse-V2";
|
||||
case 0xd80: return "Cortex-A520";
|
||||
case 0xd81: return "Cortex-A720";
|
||||
case 0xd82: return "Cortex-X4";
|
||||
case 0xd83: return "Neoverse-V3AE";
|
||||
case 0xd84: return "Neoverse-V3";
|
||||
case 0xd85: return "Cortex-X925";
|
||||
case 0xd87: return "Cortex-A725";
|
||||
case 0xd88: return "Cortex-A520AE";
|
||||
case 0xd89: return "Cortex-A720AE";
|
||||
case 0xd8a: return "C1-Nano";
|
||||
case 0xd8b: return "C1-Pro";
|
||||
case 0xd8c: return "C1-Ultra";
|
||||
case 0xd8e: return "Neoverse-N3";
|
||||
case 0xd8f: return "Cortex-A320";
|
||||
case 0xd90: return "C1-Premium";
|
||||
default: return NULL;
|
||||
static const char* armPartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0x810:
|
||||
return "ARM810";
|
||||
case 0x920:
|
||||
return "ARM920";
|
||||
case 0x922:
|
||||
return "ARM922";
|
||||
case 0x926:
|
||||
return "ARM926";
|
||||
case 0x940:
|
||||
return "ARM940";
|
||||
case 0x946:
|
||||
return "ARM946";
|
||||
case 0x966:
|
||||
return "ARM966";
|
||||
case 0xa20:
|
||||
return "ARM1020";
|
||||
case 0xa22:
|
||||
return "ARM1022";
|
||||
case 0xa26:
|
||||
return "ARM1026";
|
||||
case 0xb02:
|
||||
return "ARM11-MPCore";
|
||||
case 0xb36:
|
||||
return "ARM1136";
|
||||
case 0xb56:
|
||||
return "ARM1156";
|
||||
case 0xb76:
|
||||
return "ARM1176";
|
||||
case 0xc05:
|
||||
return "Cortex-A5";
|
||||
case 0xc07:
|
||||
return "Cortex-A7";
|
||||
case 0xc08:
|
||||
return "Cortex-A8";
|
||||
case 0xc09:
|
||||
return "Cortex-A9";
|
||||
case 0xc0d:
|
||||
return "Cortex-A17"; /* Originally A12 */
|
||||
case 0xc0f:
|
||||
return "Cortex-A15";
|
||||
case 0xc0e:
|
||||
return "Cortex-A17";
|
||||
case 0xc14:
|
||||
return "Cortex-R4";
|
||||
case 0xc15:
|
||||
return "Cortex-R5";
|
||||
case 0xc17:
|
||||
return "Cortex-R7";
|
||||
case 0xc18:
|
||||
return "Cortex-R8";
|
||||
case 0xc20:
|
||||
return "Cortex-M0";
|
||||
case 0xc21:
|
||||
return "Cortex-M1";
|
||||
case 0xc23:
|
||||
return "Cortex-M3";
|
||||
case 0xc24:
|
||||
return "Cortex-M4";
|
||||
case 0xc27:
|
||||
return "Cortex-M7";
|
||||
case 0xc60:
|
||||
return "Cortex-M0+";
|
||||
case 0xd01:
|
||||
return "Cortex-A32";
|
||||
case 0xd02:
|
||||
return "Cortex-A34";
|
||||
case 0xd03:
|
||||
return "Cortex-A53";
|
||||
case 0xd04:
|
||||
return "Cortex-A35";
|
||||
case 0xd05:
|
||||
return "Cortex-A55";
|
||||
case 0xd06:
|
||||
return "Cortex-A65";
|
||||
case 0xd07:
|
||||
return "Cortex-A57";
|
||||
case 0xd08:
|
||||
return "Cortex-A72";
|
||||
case 0xd09:
|
||||
return "Cortex-A73";
|
||||
case 0xd0a:
|
||||
return "Cortex-A75";
|
||||
case 0xd0b:
|
||||
return "Cortex-A76";
|
||||
case 0xd0c:
|
||||
return "Neoverse-N1";
|
||||
case 0xd0d:
|
||||
return "Cortex-A77";
|
||||
case 0xd0e:
|
||||
return "Cortex-A76AE";
|
||||
case 0xd13:
|
||||
return "Cortex-R52";
|
||||
case 0xd14:
|
||||
return "Cortex-R82AE";
|
||||
case 0xd15:
|
||||
return "Cortex-R82";
|
||||
case 0xd16:
|
||||
return "Cortex-R52+";
|
||||
case 0xd20:
|
||||
return "Cortex-M23";
|
||||
case 0xd21:
|
||||
return "Cortex-M33";
|
||||
case 0xd24:
|
||||
return "Cortex-M52";
|
||||
case 0xd22:
|
||||
return "Cortex-M55";
|
||||
case 0xd23:
|
||||
return "Cortex-M85";
|
||||
case 0xd40:
|
||||
return "Neoverse-V1";
|
||||
case 0xd41:
|
||||
return "Cortex-A78";
|
||||
case 0xd42:
|
||||
return "Cortex-A78AE";
|
||||
case 0xd43:
|
||||
return "Cortex-A65AE";
|
||||
case 0xd44:
|
||||
return "Cortex-X1";
|
||||
case 0xd46:
|
||||
return "Cortex-A510";
|
||||
case 0xd47:
|
||||
return "Cortex-A710";
|
||||
case 0xd48:
|
||||
return "Cortex-X2";
|
||||
case 0xd49:
|
||||
return "Neoverse-N2";
|
||||
case 0xd4a:
|
||||
return "Neoverse-E1";
|
||||
case 0xd4b:
|
||||
return "Cortex-A78C";
|
||||
case 0xd4c:
|
||||
return "Cortex-X1C";
|
||||
case 0xd4d:
|
||||
return "Cortex-A715";
|
||||
case 0xd4e:
|
||||
return "Cortex-X3";
|
||||
case 0xd4f:
|
||||
return "Neoverse-V2";
|
||||
case 0xd80:
|
||||
return "Cortex-A520";
|
||||
case 0xd81:
|
||||
return "Cortex-A720";
|
||||
case 0xd82:
|
||||
return "Cortex-X4";
|
||||
case 0xd83:
|
||||
return "Neoverse-V3AE";
|
||||
case 0xd84:
|
||||
return "Neoverse-V3";
|
||||
case 0xd85:
|
||||
return "Cortex-X925";
|
||||
case 0xd87:
|
||||
return "Cortex-A725";
|
||||
case 0xd88:
|
||||
return "Cortex-A520AE";
|
||||
case 0xd89:
|
||||
return "Cortex-A720AE";
|
||||
case 0xd8a:
|
||||
return "C1-Nano";
|
||||
case 0xd8b:
|
||||
return "C1-Pro";
|
||||
case 0xd8c:
|
||||
return "C1-Ultra";
|
||||
case 0xd8e:
|
||||
return "Neoverse-N3";
|
||||
case 0xd8f:
|
||||
return "Cortex-A320";
|
||||
case 0xd90:
|
||||
return "C1-Premium";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* brcmPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x0f: return "Brahma-B15";
|
||||
case 0x100: return "Brahma-B53";
|
||||
case 0x516: return "ThunderX2";
|
||||
default: return NULL;
|
||||
static const char* brcmPartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0x0f:
|
||||
return "Brahma-B15";
|
||||
case 0x100:
|
||||
return "Brahma-B53";
|
||||
case 0x516:
|
||||
return "ThunderX2";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* decPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0xa10: return "SA110";
|
||||
case 0xa11: return "SA1100";
|
||||
default: return NULL;
|
||||
static const char* decPartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0xa10:
|
||||
return "SA110";
|
||||
case 0xa11:
|
||||
return "SA1100";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* caviumPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x0a0: return "ThunderX";
|
||||
case 0x0a1: return "ThunderX-88XX";
|
||||
case 0x0a2: return "ThunderX-81XX";
|
||||
case 0x0a3: return "ThunderX-83XX";
|
||||
case 0x0af: return "ThunderX2-99xx";
|
||||
case 0x0b0: return "OcteonTX2";
|
||||
case 0x0b1: return "OcteonTX2-98XX";
|
||||
case 0x0b2: return "OcteonTX2-96XX";
|
||||
case 0x0b3: return "OcteonTX2-95XX";
|
||||
case 0x0b4: return "OcteonTX2-95XXN";
|
||||
case 0x0b5: return "OcteonTX2-95XXMM";
|
||||
case 0x0b6: return "OcteonTX2-95XXO";
|
||||
case 0x0b8: return "ThunderX3-T110";
|
||||
default: return NULL;
|
||||
static const char* caviumPartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0x0a0:
|
||||
return "ThunderX";
|
||||
case 0x0a1:
|
||||
return "ThunderX-88XX";
|
||||
case 0x0a2:
|
||||
return "ThunderX-81XX";
|
||||
case 0x0a3:
|
||||
return "ThunderX-83XX";
|
||||
case 0x0af:
|
||||
return "ThunderX2-99xx";
|
||||
case 0x0b0:
|
||||
return "OcteonTX2";
|
||||
case 0x0b1:
|
||||
return "OcteonTX2-98XX";
|
||||
case 0x0b2:
|
||||
return "OcteonTX2-96XX";
|
||||
case 0x0b3:
|
||||
return "OcteonTX2-95XX";
|
||||
case 0x0b4:
|
||||
return "OcteonTX2-95XXN";
|
||||
case 0x0b5:
|
||||
return "OcteonTX2-95XXMM";
|
||||
case 0x0b6:
|
||||
return "OcteonTX2-95XXO";
|
||||
case 0x0b8:
|
||||
return "ThunderX3-T110";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* apmPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x000: return "X-Gene";
|
||||
default: return NULL;
|
||||
static const char* apmPartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0x000:
|
||||
return "X-Gene";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* qcomPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x001: return "Oryon 1";
|
||||
case 0x002: return "Oryon 2";
|
||||
case 0x00f: return "Scorpion";
|
||||
case 0x02d: return "Scorpion";
|
||||
case 0x04d: return "Krait";
|
||||
case 0x06f: return "Krait";
|
||||
case 0x201: return "Kryo";
|
||||
case 0x205: return "Kryo";
|
||||
case 0x211: return "Kryo";
|
||||
case 0x800: return "Falkor-V1/Kryo";
|
||||
case 0x801: return "Kryo-V2";
|
||||
case 0x802: return "Kryo-3XX-Gold";
|
||||
case 0x803: return "Kryo-3XX-Silver";
|
||||
case 0x804: return "Kryo-4XX-Gold";
|
||||
case 0x805: return "Kryo-4XX-Silver";
|
||||
case 0xc00: return "Falkor";
|
||||
case 0xc01: return "Saphira";
|
||||
default: return NULL;
|
||||
static const char* qcomPartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0x001:
|
||||
return "Oryon 1";
|
||||
case 0x002:
|
||||
return "Oryon 2";
|
||||
case 0x00f:
|
||||
return "Scorpion";
|
||||
case 0x02d:
|
||||
return "Scorpion";
|
||||
case 0x04d:
|
||||
return "Krait";
|
||||
case 0x06f:
|
||||
return "Krait";
|
||||
case 0x201:
|
||||
return "Kryo";
|
||||
case 0x205:
|
||||
return "Kryo";
|
||||
case 0x211:
|
||||
return "Kryo";
|
||||
case 0x800:
|
||||
return "Falkor-V1/Kryo";
|
||||
case 0x801:
|
||||
return "Kryo-V2";
|
||||
case 0x802:
|
||||
return "Kryo-3XX-Gold";
|
||||
case 0x803:
|
||||
return "Kryo-3XX-Silver";
|
||||
case 0x804:
|
||||
return "Kryo-4XX-Gold";
|
||||
case 0x805:
|
||||
return "Kryo-4XX-Silver";
|
||||
case 0xc00:
|
||||
return "Falkor";
|
||||
case 0xc01:
|
||||
return "Saphira";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* samsungPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x001: return "Exynos-M1";
|
||||
case 0x002: return "Exynos-M3";
|
||||
case 0x003: return "Exynos-M4";
|
||||
case 0x004: return "Exynos-M5";
|
||||
default: return NULL;
|
||||
static const char* samsungPartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0x001:
|
||||
return "Exynos-M1";
|
||||
case 0x002:
|
||||
return "Exynos-M3";
|
||||
case 0x003:
|
||||
return "Exynos-M4";
|
||||
case 0x004:
|
||||
return "Exynos-M5";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* nvidiaPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x000: return "Denver";
|
||||
case 0x003: return "Denver-2";
|
||||
case 0x004: return "Carmel";
|
||||
case 0x010: return "Olympus";
|
||||
default: return NULL;
|
||||
static const char* nvidiaPartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0x000:
|
||||
return "Denver";
|
||||
case 0x003:
|
||||
return "Denver-2";
|
||||
case 0x004:
|
||||
return "Carmel";
|
||||
case 0x010:
|
||||
return "Olympus";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* marvellPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x131: return "Feroceon-88FR131";
|
||||
case 0x581: return "PJ4/PJ4b";
|
||||
case 0x584: return "PJ4B-MP";
|
||||
default: return NULL;
|
||||
static const char* marvellPartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0x131:
|
||||
return "Feroceon-88FR131";
|
||||
case 0x581:
|
||||
return "PJ4/PJ4b";
|
||||
case 0x584:
|
||||
return "PJ4B-MP";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* applePartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x000: return "Swift";
|
||||
case 0x001: return "Cyclone";
|
||||
case 0x002: return "Typhoon";
|
||||
case 0x003: return "Typhoon/Capri";
|
||||
case 0x004: return "Twister";
|
||||
case 0x005: return "Twister/Elba/Malta";
|
||||
case 0x006: return "Hurricane";
|
||||
case 0x007: return "Hurricane/Myst";
|
||||
case 0x008: return "Monsoon";
|
||||
case 0x009: return "Mistral";
|
||||
case 0x00b: return "Vortex";
|
||||
case 0x00c: return "Tempest";
|
||||
case 0x00f: return "Tempest-M9";
|
||||
case 0x010: return "Vortex/Aruba";
|
||||
case 0x011: return "Tempest/Aruba";
|
||||
case 0x012: return "Lightning";
|
||||
case 0x013: return "Thunder";
|
||||
case 0x020: return "Icestorm-A14";
|
||||
case 0x021: return "Firestorm-A14";
|
||||
case 0x022: return "Icestorm-M1";
|
||||
case 0x023: return "Firestorm-M1";
|
||||
case 0x024: return "Icestorm-M1-Pro";
|
||||
case 0x025: return "Firestorm-M1-Pro";
|
||||
case 0x026: return "Thunder-M10";
|
||||
case 0x028: return "Icestorm-M1-Max";
|
||||
case 0x029: return "Firestorm-M1-Max";
|
||||
case 0x030: return "Blizzard-A15";
|
||||
case 0x031: return "Avalanche-A15";
|
||||
case 0x032: return "Blizzard-M2";
|
||||
case 0x033: return "Avalanche-M2";
|
||||
case 0x034: return "Blizzard-M2-Pro";
|
||||
case 0x035: return "Avalanche-M2-Pro";
|
||||
case 0x036: return "Sawtooth-A16";
|
||||
case 0x037: return "Everest-A16";
|
||||
case 0x038: return "Blizzard-M2-Max";
|
||||
case 0x039: return "Avalanche-M2-Max";
|
||||
case 0x046: return "Sawtooth-M11";
|
||||
case 0x048: return "Sawtooth-M3-Max";
|
||||
case 0x049: return "Everest-M3-Max";
|
||||
default: return NULL;
|
||||
static const char* applePartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0x000:
|
||||
return "Swift";
|
||||
case 0x001:
|
||||
return "Cyclone";
|
||||
case 0x002:
|
||||
return "Typhoon";
|
||||
case 0x003:
|
||||
return "Typhoon/Capri";
|
||||
case 0x004:
|
||||
return "Twister";
|
||||
case 0x005:
|
||||
return "Twister/Elba/Malta";
|
||||
case 0x006:
|
||||
return "Hurricane";
|
||||
case 0x007:
|
||||
return "Hurricane/Myst";
|
||||
case 0x008:
|
||||
return "Monsoon";
|
||||
case 0x009:
|
||||
return "Mistral";
|
||||
case 0x00b:
|
||||
return "Vortex";
|
||||
case 0x00c:
|
||||
return "Tempest";
|
||||
case 0x00f:
|
||||
return "Tempest-M9";
|
||||
case 0x010:
|
||||
return "Vortex/Aruba";
|
||||
case 0x011:
|
||||
return "Tempest/Aruba";
|
||||
case 0x012:
|
||||
return "Lightning";
|
||||
case 0x013:
|
||||
return "Thunder";
|
||||
case 0x020:
|
||||
return "Icestorm-A14";
|
||||
case 0x021:
|
||||
return "Firestorm-A14";
|
||||
case 0x022:
|
||||
return "Icestorm-M1";
|
||||
case 0x023:
|
||||
return "Firestorm-M1";
|
||||
case 0x024:
|
||||
return "Icestorm-M1-Pro";
|
||||
case 0x025:
|
||||
return "Firestorm-M1-Pro";
|
||||
case 0x026:
|
||||
return "Thunder-M10";
|
||||
case 0x028:
|
||||
return "Icestorm-M1-Max";
|
||||
case 0x029:
|
||||
return "Firestorm-M1-Max";
|
||||
case 0x030:
|
||||
return "Blizzard-A15";
|
||||
case 0x031:
|
||||
return "Avalanche-A15";
|
||||
case 0x032:
|
||||
return "Blizzard-M2";
|
||||
case 0x033:
|
||||
return "Avalanche-M2";
|
||||
case 0x034:
|
||||
return "Blizzard-M2-Pro";
|
||||
case 0x035:
|
||||
return "Avalanche-M2-Pro";
|
||||
case 0x036:
|
||||
return "Sawtooth-A16";
|
||||
case 0x037:
|
||||
return "Everest-A16";
|
||||
case 0x038:
|
||||
return "Blizzard-M2-Max";
|
||||
case 0x039:
|
||||
return "Avalanche-M2-Max";
|
||||
case 0x046:
|
||||
return "Sawtooth-M11";
|
||||
case 0x048:
|
||||
return "Sawtooth-M3-Max";
|
||||
case 0x049:
|
||||
return "Everest-M3-Max";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* faradayPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x526: return "FA526";
|
||||
case 0x626: return "FA626";
|
||||
default: return NULL;
|
||||
static const char* faradayPartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0x526:
|
||||
return "FA526";
|
||||
case 0x626:
|
||||
return "FA626";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* intelPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x200: return "i80200";
|
||||
case 0x210: return "PXA250A";
|
||||
case 0x212: return "PXA210A";
|
||||
case 0x242: return "i80321-400";
|
||||
case 0x243: return "i80321-600";
|
||||
case 0x290: return "PXA250B/PXA26x";
|
||||
case 0x292: return "PXA210B";
|
||||
case 0x2c2: return "i80321-400-B0";
|
||||
case 0x2c3: return "i80321-600-B0";
|
||||
case 0x2d0: return "PXA250C/PXA255/PXA26x";
|
||||
case 0x2d2: return "PXA210C";
|
||||
case 0x411: return "PXA27x";
|
||||
case 0x41c: return "IPX425-533";
|
||||
case 0x41d: return "IPX425-400";
|
||||
case 0x41f: return "IPX425-266";
|
||||
case 0x682: return "PXA32x";
|
||||
case 0x683: return "PXA930/PXA935";
|
||||
case 0x688: return "PXA30x";
|
||||
case 0x689: return "PXA31x";
|
||||
case 0xb11: return "SA1110";
|
||||
case 0xc12: return "IPX1200";
|
||||
default: return NULL;
|
||||
static const char* intelPartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0x200:
|
||||
return "i80200";
|
||||
case 0x210:
|
||||
return "PXA250A";
|
||||
case 0x212:
|
||||
return "PXA210A";
|
||||
case 0x242:
|
||||
return "i80321-400";
|
||||
case 0x243:
|
||||
return "i80321-600";
|
||||
case 0x290:
|
||||
return "PXA250B/PXA26x";
|
||||
case 0x292:
|
||||
return "PXA210B";
|
||||
case 0x2c2:
|
||||
return "i80321-400-B0";
|
||||
case 0x2c3:
|
||||
return "i80321-600-B0";
|
||||
case 0x2d0:
|
||||
return "PXA250C/PXA255/PXA26x";
|
||||
case 0x2d2:
|
||||
return "PXA210C";
|
||||
case 0x411:
|
||||
return "PXA27x";
|
||||
case 0x41c:
|
||||
return "IPX425-533";
|
||||
case 0x41d:
|
||||
return "IPX425-400";
|
||||
case 0x41f:
|
||||
return "IPX425-266";
|
||||
case 0x682:
|
||||
return "PXA32x";
|
||||
case 0x683:
|
||||
return "PXA930/PXA935";
|
||||
case 0x688:
|
||||
return "PXA30x";
|
||||
case 0x689:
|
||||
return "PXA31x";
|
||||
case 0xb11:
|
||||
return "SA1110";
|
||||
case 0xc12:
|
||||
return "IPX1200";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* fujitsuPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x001: return "A64FX";
|
||||
case 0x003: return "MONAKA";
|
||||
default: return NULL;
|
||||
static const char* fujitsuPartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0x001:
|
||||
return "A64FX";
|
||||
case 0x003:
|
||||
return "MONAKA";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* hisiPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0xd01: return "TaiShan-v110"; /* used in Kunpeng-920 SoC */
|
||||
case 0xd02: return "TaiShan-v120"; /* used in Kirin 990A and 9000S SoCs */
|
||||
case 0xd40: return "Cortex-A76"; /* HiSilicon uses this ID though advertises A76 */
|
||||
case 0xd41: return "Cortex-A77"; /* HiSilicon uses this ID though advertises A77 */
|
||||
default: return NULL;
|
||||
static const char* hisiPartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0xd01:
|
||||
return "TaiShan-v110"; /* used in Kunpeng-920 SoC */
|
||||
case 0xd02:
|
||||
return "TaiShan-v120"; /* used in Kirin 990A and 9000S SoCs */
|
||||
case 0xd40:
|
||||
return "Cortex-A76"; /* HiSilicon uses this ID though advertises A76 */
|
||||
case 0xd41:
|
||||
return "Cortex-A77"; /* HiSilicon uses this ID though advertises A77 */
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* amperePartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0xac3: return "Ampere-1";
|
||||
case 0xac4: return "Ampere-1a";
|
||||
default: return NULL;
|
||||
static const char* amperePartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0xac3:
|
||||
return "Ampere-1";
|
||||
case 0xac4:
|
||||
return "Ampere-1a";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* ftPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x303: return "FTC310";
|
||||
case 0x660: return "FTC660";
|
||||
case 0x661: return "FTC661";
|
||||
case 0x662: return "FTC662";
|
||||
case 0x663: return "FTC663";
|
||||
case 0x664: return "FTC664";
|
||||
case 0x862: return "FTC862";
|
||||
default: return NULL;
|
||||
static const char* ftPartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0x303:
|
||||
return "FTC310";
|
||||
case 0x660:
|
||||
return "FTC660";
|
||||
case 0x661:
|
||||
return "FTC661";
|
||||
case 0x662:
|
||||
return "FTC662";
|
||||
case 0x663:
|
||||
return "FTC663";
|
||||
case 0x664:
|
||||
return "FTC664";
|
||||
case 0x862:
|
||||
return "FTC862";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* msPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0xd49: return "Azure-Cobalt-100";
|
||||
default: return NULL;
|
||||
static const char* msPartId2name(uint32_t partId) {
|
||||
switch (partId) {
|
||||
case 0xd49:
|
||||
return "Azure-Cobalt-100";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
+32
-29
@@ -4,28 +4,25 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#if __has_include(<sys/cpuset.h>)
|
||||
#include <sys/cpuset.h>
|
||||
#define FF_HAVE_CPUSET 1
|
||||
# include <sys/cpuset.h>
|
||||
# define FF_HAVE_CPUSET 1
|
||||
#endif
|
||||
|
||||
static const char* detectCpuTemp(const FFCPUOptions* options, double* current)
|
||||
{
|
||||
static const char* detectCpuTemp(const FFCPUOptions* options, double* current) {
|
||||
int temp;
|
||||
if (options->tempSensor.length > 0)
|
||||
{
|
||||
if (options->tempSensor.length > 0) {
|
||||
temp = ffSysctlGetInt(options->tempSensor.chars, -999999);
|
||||
if (temp == -999999)
|
||||
if (temp == -999999) {
|
||||
return "ffSysctlGetInt(options->tempSensor) failed";
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
} else {
|
||||
temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999);
|
||||
if (temp == -999999)
|
||||
{
|
||||
if (temp == -999999) {
|
||||
// Thermal zone temperature
|
||||
temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999);
|
||||
if (temp == -999999)
|
||||
if (temp == -999999) {
|
||||
return "ffSysctlGetInt(\"dev.cpu.0.temperature\" or \"hw.acpi.thermal.tz0.temperature\") failed";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,18 +31,17 @@ static const char* detectCpuTemp(const FFCPUOptions* options, double* current)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
if (ffSysctlGetString("hw.model", &cpu->name) != NULL)
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
|
||||
if (ffSysctlGetString("hw.model", &cpu->name) != NULL) {
|
||||
return "sysctlbyname(hw.model) failed";
|
||||
}
|
||||
|
||||
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
|
||||
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("kern.smp.cores", 0);
|
||||
cpu->coresOnline = (uint16_t) ffSysctlGetInt("kern.smp.cpus", cpu->coresLogical);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
if (ffSysctlGetString("kern.sched.topology_spec", &buffer) == NULL && buffer.length > 0)
|
||||
{
|
||||
if (ffSysctlGetString("kern.sched.topology_spec", &buffer) == NULL && buffer.length > 0) {
|
||||
// <groups>
|
||||
// <group level="1" cache-level="3">
|
||||
// <cpu count="4" mask="f,0,0,0">0, 1, 2, 3</cpu>
|
||||
@@ -61,8 +57,9 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
// </children>
|
||||
// </group>
|
||||
// </groups>
|
||||
for (char* p = buffer.chars; (p = strstr(p, "\n </group>\n")); ++p)
|
||||
for (char* p = buffer.chars; (p = strstr(p, "\n </group>\n")); ++p) {
|
||||
cpu->packages++;
|
||||
}
|
||||
}
|
||||
|
||||
#if FF_HAVE_CPUSET && (__x86_64__ || __i386__)
|
||||
@@ -77,28 +74,34 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
ffCPUDetectByCpuid(cpu);
|
||||
|
||||
uint32_t clockrate = (uint32_t) ffSysctlGetInt("hw.clockrate", 0);
|
||||
if (clockrate > cpu->frequencyBase) cpu->frequencyBase = clockrate;
|
||||
if (clockrate > cpu->frequencyBase) {
|
||||
cpu->frequencyBase = clockrate;
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < cpu->coresLogical; ++i)
|
||||
{
|
||||
for (uint16_t i = 0; i < cpu->coresLogical; ++i) {
|
||||
ffStrbufClear(&buffer);
|
||||
char key[32];
|
||||
snprintf(key, sizeof(key), "dev.cpu.%u.freq_levels", i);
|
||||
if (ffSysctlGetString(key, &buffer) == NULL)
|
||||
{
|
||||
if (buffer.length == 0) continue;
|
||||
if (ffSysctlGetString(key, &buffer) == NULL) {
|
||||
if (buffer.length == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// MHz/Watts pairs like: 2501/32000 2187/27125 2000/24000
|
||||
uint32_t fmax = (uint32_t) strtoul(buffer.chars, NULL, 10);
|
||||
if (cpu->frequencyMax < fmax) cpu->frequencyMax = fmax;
|
||||
}
|
||||
else
|
||||
if (cpu->frequencyMax < fmax) {
|
||||
cpu->frequencyMax = fmax;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
if (options->temp) detectCpuTemp(options, &cpu->temperature);
|
||||
if (options->temp) {
|
||||
detectCpuTemp(options, &cpu->temperature);
|
||||
}
|
||||
|
||||
cpu->numaNodes = (uint16_t) ffSysctlGetInt("vm.ndomains", 0);
|
||||
|
||||
|
||||
@@ -4,28 +4,29 @@
|
||||
#include <OS.h>
|
||||
#include <private/shared/cpu_type.h>
|
||||
|
||||
const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPUResult* cpu) {
|
||||
system_info sysInfo;
|
||||
if (get_system_info(&sysInfo) != B_OK)
|
||||
if (get_system_info(&sysInfo) != B_OK) {
|
||||
return "get_system_info() failed";
|
||||
}
|
||||
|
||||
uint32 topoNodeCount = 0;
|
||||
get_cpu_topology_info(NULL, &topoNodeCount);
|
||||
if (topoNodeCount == 0)
|
||||
if (topoNodeCount == 0) {
|
||||
return "get_cpu_topology_info(NULL) failed";
|
||||
}
|
||||
|
||||
FF_AUTO_FREE cpu_topology_node_info* topology = malloc(sizeof(*topology) * topoNodeCount);
|
||||
if (get_cpu_topology_info(topology, &topoNodeCount) != B_OK)
|
||||
if (get_cpu_topology_info(topology, &topoNodeCount) != B_OK) {
|
||||
return "get_cpu_topology_info(topology) failed";
|
||||
}
|
||||
|
||||
enum cpu_platform platform = B_CPU_UNKNOWN;
|
||||
enum cpu_vendor cpuVendor = B_CPU_VENDOR_UNKNOWN;
|
||||
uint32 cpuModel = 0, frequency = 0;
|
||||
uint16_t packages = 0, cores = 0;
|
||||
|
||||
for (uint32 i = 0; i < topoNodeCount; i++)
|
||||
{
|
||||
for (uint32 i = 0; i < topoNodeCount; i++) {
|
||||
switch (topology[i].type) {
|
||||
case B_TOPOLOGY_ROOT:
|
||||
platform = topology[i].data.root.platform;
|
||||
@@ -48,15 +49,18 @@ const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPURe
|
||||
}
|
||||
}
|
||||
|
||||
const char *model = get_cpu_model_string(platform, cpuVendor, cpuModel);
|
||||
if (model)
|
||||
const char* model = get_cpu_model_string(platform, cpuVendor, cpuModel);
|
||||
if (model) {
|
||||
ffStrbufSetS(&cpu->name, model);
|
||||
else
|
||||
} else {
|
||||
ffStrbufSetF(&cpu->name, "(Unknown %" B_PRIx32 ")", cpuModel);
|
||||
}
|
||||
ffStrbufSetS(&cpu->vendor, get_cpu_vendor_string(cpuVendor));
|
||||
|
||||
ffCPUDetectByCpuid(cpu);
|
||||
if (cpu->frequencyBase < frequency) cpu->frequencyBase = frequency;
|
||||
if (cpu->frequencyBase < frequency) {
|
||||
cpu->frequencyBase = frequency;
|
||||
}
|
||||
cpu->packages = packages;
|
||||
cpu->coresPhysical = cores;
|
||||
cpu->coresOnline = cpu->coresLogical = (uint16_t) sysInfo.cpu_count;
|
||||
|
||||
+517
-379
File diff suppressed because it is too large
Load Diff
@@ -9,66 +9,78 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static void freePropDict(prop_dictionary_t* pdict)
|
||||
{
|
||||
static void freePropDict(prop_dictionary_t* pdict) {
|
||||
assert(pdict != NULL);
|
||||
if (*pdict == NULL) return;
|
||||
if (*pdict == NULL) {
|
||||
return;
|
||||
}
|
||||
prop_object_release(*pdict);
|
||||
}
|
||||
|
||||
static const char* detectCpuTemp(const FFCPUOptions* options, double* current)
|
||||
{
|
||||
static const char* detectCpuTemp(const FFCPUOptions* options, double* current) {
|
||||
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC) failed";
|
||||
if (fd < 0) {
|
||||
return "open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC) failed";
|
||||
}
|
||||
|
||||
__attribute__((__cleanup__(freePropDict))) prop_dictionary_t root = NULL;
|
||||
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
|
||||
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0) {
|
||||
return "prop_dictionary_recv_ioctl(ENVSYS_GETDICTIONARY) failed";
|
||||
}
|
||||
|
||||
prop_array_t array;
|
||||
|
||||
if (options->tempSensor.length > 0)
|
||||
{
|
||||
if (options->tempSensor.length > 0) {
|
||||
array = prop_dictionary_get(root, options->tempSensor.chars);
|
||||
if (!array) return "No temp data found in specified sensor";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!array) {
|
||||
return "No temp data found in specified sensor";
|
||||
}
|
||||
} else {
|
||||
array = prop_dictionary_get(root, "coretemp0");
|
||||
if (!array) array = prop_dictionary_get(root, "amdzentemp0");
|
||||
if (!array) array = prop_dictionary_get(root, "viac7temp0");
|
||||
if (!array) array = prop_dictionary_get(root, "acpitz0"); // Thermal Zones
|
||||
if (!array) return "No temp data found in root dictionary";
|
||||
if (!array) {
|
||||
array = prop_dictionary_get(root, "amdzentemp0");
|
||||
}
|
||||
if (!array) {
|
||||
array = prop_dictionary_get(root, "viac7temp0");
|
||||
}
|
||||
if (!array) {
|
||||
array = prop_dictionary_get(root, "acpitz0"); // Thermal Zones
|
||||
}
|
||||
if (!array) {
|
||||
return "No temp data found in root dictionary";
|
||||
}
|
||||
}
|
||||
|
||||
if (prop_array_count(array) != 2)
|
||||
if (prop_array_count(array) != 2) {
|
||||
return "Unexpected `xtemp0` data";
|
||||
}
|
||||
|
||||
prop_dictionary_t dict = prop_array_get(array, 0);
|
||||
if (prop_object_type(dict) != PROP_TYPE_DICTIONARY)
|
||||
if (prop_object_type(dict) != PROP_TYPE_DICTIONARY) {
|
||||
return "Unexpected `xtemp0[0]`";
|
||||
}
|
||||
|
||||
int temp = 0; // in µK
|
||||
if (!prop_dictionary_get_int(dict, "cur-value", &temp))
|
||||
if (!prop_dictionary_get_int(dict, "cur-value", &temp)) {
|
||||
return "Failed to get temperature";
|
||||
}
|
||||
|
||||
*current = temp / 1e6 - 273.15;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
|
||||
if (ffSysctlGetString("machdep.cpu_brand", &cpu->name) != NULL &&
|
||||
ffSysctlGetString("machdep.dmi.processor-version", &cpu->name) != NULL &&
|
||||
ffSysctlGetString("hw.cpu0.name", &cpu->name) != NULL &&
|
||||
ffSysctlGetString("hw.model", &cpu->name) != NULL)
|
||||
{
|
||||
ffSysctlGetString("hw.model", &cpu->name) != NULL) {
|
||||
ffStrbufSetS(&cpu->name, "Unknown CPU");
|
||||
}
|
||||
|
||||
if (ffSysctlGetString("machdep.dmi.processor-vendor", &cpu->vendor) == NULL)
|
||||
if (ffSysctlGetString("machdep.dmi.processor-vendor", &cpu->vendor) == NULL) {
|
||||
ffStrbufTrimRightSpace(&cpu->vendor);
|
||||
}
|
||||
|
||||
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
|
||||
cpu->coresLogical = cpu->coresPhysical;
|
||||
@@ -77,13 +89,21 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
ffCPUDetectByCpuid(cpu);
|
||||
|
||||
uint32_t freq = (uint32_t) ffSysctlGetInt("machdep.cpu.frequency.target", 0);
|
||||
if (freq == 0) freq = (uint32_t) (ffSysctlGetInt64("hw.cpu0.clock_frequency", 0) / 1000000);
|
||||
if (freq == 0) freq = (uint32_t) ffSysctlGetInt("machdep.dmi.processor-frequency", 0);
|
||||
if (freq > cpu->frequencyBase) cpu->frequencyBase = freq;
|
||||
if (freq == 0) {
|
||||
freq = (uint32_t) (ffSysctlGetInt64("hw.cpu0.clock_frequency", 0) / 1000000);
|
||||
}
|
||||
if (freq == 0) {
|
||||
freq = (uint32_t) ffSysctlGetInt("machdep.dmi.processor-frequency", 0);
|
||||
}
|
||||
if (freq > cpu->frequencyBase) {
|
||||
cpu->frequencyBase = freq;
|
||||
}
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
if (options->temp) detectCpuTemp(options, &cpu->temperature);
|
||||
if (options->temp) {
|
||||
detectCpuTemp(options, &cpu->temperature);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "cpu.h"
|
||||
|
||||
const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FF_MAYBE_UNUSED FFCPUResult* cpu)
|
||||
{
|
||||
const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FF_MAYBE_UNUSED FFCPUResult* cpu) {
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
|
||||
@@ -6,48 +6,46 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/sensors.h>
|
||||
|
||||
static const char* detectCPUTemp(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
static const char* detectCPUTemp(const FFCPUOptions* options, FFCPUResult* cpu) {
|
||||
int mib[5] = {CTL_HW, HW_SENSORS, 0, SENSOR_TEMP, 0};
|
||||
|
||||
for (mib[2] = 0; mib[2] < 1024; mib[2]++)
|
||||
{
|
||||
for (mib[2] = 0; mib[2] < 1024; mib[2]++) {
|
||||
struct sensordev sensordev;
|
||||
size_t sdlen = sizeof(struct sensordev);
|
||||
if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) < 0) {
|
||||
if (errno == ENOENT) {
|
||||
break;
|
||||
if (errno == ENXIO)
|
||||
}
|
||||
if (errno == ENXIO) {
|
||||
continue;
|
||||
}
|
||||
return "sysctl(sensordev) failed";
|
||||
}
|
||||
|
||||
if (options->tempSensor.length > 0)
|
||||
{
|
||||
if (!ffStrbufEqualS(&options->tempSensor, sensordev.xname))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ffStrStartsWith(sensordev.xname, "cpu"))
|
||||
continue;
|
||||
}
|
||||
|
||||
for (mib[4] = 0; mib[4] < sensordev.maxnumt[SENSOR_TEMP]; mib[4]++)
|
||||
{
|
||||
struct sensor sensor;
|
||||
size_t slen = sizeof(struct sensor);
|
||||
if (sysctl(mib, 5, &sensor, &slen, NULL, 0) < 0)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
return "sysctl(sensor) failed";
|
||||
if (options->tempSensor.length > 0) {
|
||||
if (!ffStrbufEqualS(&options->tempSensor, sensordev.xname)) {
|
||||
continue;
|
||||
}
|
||||
if (sensor.flags & SENSOR_FINVALID)
|
||||
} else {
|
||||
if (!ffStrStartsWith(sensordev.xname, "cpu")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
cpu->temperature = (double)(sensor.value - 273150000) / 1E6;
|
||||
for (mib[4] = 0; mib[4] < sensordev.maxnumt[SENSOR_TEMP]; mib[4]++) {
|
||||
struct sensor sensor;
|
||||
size_t slen = sizeof(struct sensor);
|
||||
if (sysctl(mib, 5, &sensor, &slen, NULL, 0) < 0) {
|
||||
if (errno != ENOENT) {
|
||||
return "sysctl(sensor) failed";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (sensor.flags & SENSOR_FINVALID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cpu->temperature = (double) (sensor.value - 273150000) / 1E6;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -55,10 +53,10 @@ static const char* detectCPUTemp(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
return "No sensor for CPU temp found";
|
||||
}
|
||||
|
||||
const char *ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
if (ffSysctlGetString(CTL_HW, HW_MODEL, &cpu->name))
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
|
||||
if (ffSysctlGetString(CTL_HW, HW_MODEL, &cpu->name)) {
|
||||
return "sysctl(hw.model) failed";
|
||||
}
|
||||
|
||||
cpu->coresPhysical = (uint16_t) ffSysctlGetInt(CTL_HW, HW_NCPU, 1);
|
||||
cpu->coresLogical = cpu->coresPhysical;
|
||||
@@ -67,10 +65,14 @@ const char *ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
ffCPUDetectByCpuid(cpu);
|
||||
|
||||
uint32_t cpuspeed = (uint32_t) ffSysctlGetInt(CTL_HW, HW_CPUSPEED, 0);
|
||||
if (cpuspeed > cpu->frequencyBase) cpu->frequencyBase = cpuspeed;
|
||||
if (cpuspeed > cpu->frequencyBase) {
|
||||
cpu->frequencyBase = cpuspeed;
|
||||
}
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
if (options->temp) detectCPUTemp(options, cpu);
|
||||
if (options->temp) {
|
||||
detectCPUTemp(options, cpu);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
#include "common/stringUtils.h"
|
||||
#include <kstat.h>
|
||||
|
||||
static const char* detectCPUTempByKstat(const FFCPUOptions* options, kstat_ctl_t* kc, FFCPUResult* cpu)
|
||||
{
|
||||
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) {
|
||||
@@ -19,10 +18,10 @@ static const char* detectCPUTempByKstat(const FFCPUOptions* options, kstat_ctl_t
|
||||
if (kn) {
|
||||
switch (kn->data_type) {
|
||||
case KSTAT_DATA_INT32:
|
||||
cpu->temperature = (float)kn->value.i32;
|
||||
cpu->temperature = (float) kn->value.i32;
|
||||
return NULL;
|
||||
case KSTAT_DATA_UINT32:
|
||||
cpu->temperature = (float)kn->value.ui32;
|
||||
cpu->temperature = (float) kn->value.ui32;
|
||||
return NULL;
|
||||
case KSTAT_DATA_FLOAT:
|
||||
cpu->temperature = kn->value.f;
|
||||
@@ -35,61 +34,53 @@ static const char* detectCPUTempByKstat(const FFCPUOptions* options, kstat_ctl_t
|
||||
return "Failed to find CPU temperature using kstat";
|
||||
}
|
||||
|
||||
static const char* detectCPUTempByIpmiTool(FFCPUResult* cpu)
|
||||
{
|
||||
static const char* detectCPUTempByIpmiTool(FFCPUResult* cpu) {
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
const char* error = ffProcessAppendStdOut(&buffer, (char* const[]){
|
||||
"ipmitool",
|
||||
"-c",
|
||||
"sdr",
|
||||
"list",
|
||||
NULL
|
||||
});
|
||||
const char* error = ffProcessAppendStdOut(&buffer, (char* const[]) {"ipmitool", "-c", "sdr", "list", NULL});
|
||||
|
||||
if (error)
|
||||
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)
|
||||
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)
|
||||
{
|
||||
static inline void kstatFreeWrap(kstat_ctl_t** pkc) {
|
||||
assert(pkc);
|
||||
if (*pkc)
|
||||
if (*pkc) {
|
||||
kstat_close(*pkc);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint16_t countTypeId(kstat_ctl_t* kc, const char* type)
|
||||
{
|
||||
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)
|
||||
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)
|
||||
if (!stat) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t id = 0;
|
||||
switch (stat->data_type)
|
||||
{
|
||||
#ifdef _INT64_TYPE
|
||||
switch (stat->data_type) {
|
||||
#ifdef _INT64_TYPE
|
||||
case KSTAT_DATA_INT64:
|
||||
case KSTAT_DATA_UINT64:
|
||||
id = (uint32_t) stat->value.ui64;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
case KSTAT_DATA_INT32:
|
||||
case KSTAT_DATA_UINT32:
|
||||
id = stat->value.ui32;
|
||||
@@ -97,57 +88,66 @@ static inline uint16_t countTypeId(kstat_ctl_t* kc, const char* type)
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
if (__builtin_expect(id > 64, false))
|
||||
if (__builtin_expect(id > 64, false)) {
|
||||
high |= 1ULL << (id - 64);
|
||||
else
|
||||
} else {
|
||||
low |= 1ULL << id;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (uint16_t) (__builtin_popcountll(low) + __builtin_popcountll(high));
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
|
||||
__attribute__((__cleanup__(kstatFreeWrap))) kstat_ctl_t* kc = kstat_open();
|
||||
if (!kc)
|
||||
if (!kc) {
|
||||
return "kstat_open() failed";
|
||||
}
|
||||
|
||||
kstat_t* ks = kstat_lookup(kc, "cpu_info", -1, NULL);
|
||||
if (!ks)
|
||||
if (!ks) {
|
||||
return "kstat_lookup() failed";
|
||||
}
|
||||
|
||||
if (kstat_read(kc, ks, NULL) < 0)
|
||||
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));
|
||||
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));
|
||||
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)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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)
|
||||
if (options->temp) {
|
||||
if (detectCPUTempByKstat(options, kc, cpu) != NULL) {
|
||||
detectCPUTempByIpmiTool(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
+135
-123
@@ -9,26 +9,22 @@
|
||||
#include "common/windows/nt.h"
|
||||
#include <wchar.h>
|
||||
|
||||
static inline void ffPerfCloseQueryHandle(HANDLE* phQuery)
|
||||
{
|
||||
if (*phQuery != NULL)
|
||||
{
|
||||
static inline void ffPerfCloseQueryHandle(HANDLE* phQuery) {
|
||||
if (*phQuery != NULL) {
|
||||
PerfCloseQueryHandle(*phQuery);
|
||||
*phQuery = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char* detectThermalTemp(const FFCPUOptions* options, double* result)
|
||||
{
|
||||
struct FFPerfQuerySpec
|
||||
{
|
||||
const char* detectThermalTemp(const FFCPUOptions* options, double* result) {
|
||||
struct FFPerfQuerySpec {
|
||||
PERF_COUNTER_IDENTIFIER Identifier;
|
||||
WCHAR Name[16];
|
||||
} querySpec = {
|
||||
.Identifier = {
|
||||
// Thermal Zone Information
|
||||
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers\{383487a6-3676-4870-a4e7-d45b30c35629}\{52bc5412-dac2-449c-8bc2-96443888fe6b}
|
||||
.CounterSetGuid = { 0x52bc5412, 0xdac2, 0x449c, {0x8b, 0xc2, 0x96, 0x44, 0x38, 0x88, 0xfe, 0x6b} },
|
||||
.CounterSetGuid = {0x52bc5412, 0xdac2, 0x449c, {0x8b, 0xc2, 0x96, 0x44, 0x38, 0x88, 0xfe, 0x6b}},
|
||||
.Size = sizeof(querySpec),
|
||||
.CounterId = PERF_WILDCARD_COUNTER,
|
||||
.InstanceId = PERF_WILDCARD_COUNTER,
|
||||
@@ -36,43 +32,47 @@ const char* detectThermalTemp(const FFCPUOptions* options, double* result)
|
||||
.Name = L"\\_TZ.CPUZ", // The standard(?) instance name for CPU temperature in the thermal provider
|
||||
};
|
||||
|
||||
if (options->tempSensor.length > 0)
|
||||
{
|
||||
if (!NT_SUCCESS(RtlUTF8ToUnicodeN(querySpec.Name, (ULONG) sizeof(querySpec.Name), NULL, options->tempSensor.chars, (ULONG)options->tempSensor.length + 1)))
|
||||
if (options->tempSensor.length > 0) {
|
||||
if (!NT_SUCCESS(RtlUTF8ToUnicodeN(querySpec.Name, (ULONG) sizeof(querySpec.Name), NULL, options->tempSensor.chars, (ULONG) options->tempSensor.length + 1))) {
|
||||
return "Invalid temp sensor string";
|
||||
}
|
||||
}
|
||||
|
||||
DWORD dataSize = 0;
|
||||
if (PerfEnumerateCounterSetInstances(NULL, &querySpec.Identifier.CounterSetGuid, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY)
|
||||
if (PerfEnumerateCounterSetInstances(NULL, &querySpec.Identifier.CounterSetGuid, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY) {
|
||||
return "PerfEnumerateCounterSetInstances() failed";
|
||||
}
|
||||
|
||||
if (dataSize <= sizeof(PERF_INSTANCE_HEADER))
|
||||
if (dataSize <= sizeof(PERF_INSTANCE_HEADER)) {
|
||||
return "No `Thermal Zone Information` instances found";
|
||||
}
|
||||
|
||||
{
|
||||
FF_AUTO_FREE PERF_INSTANCE_HEADER* const pHead = malloc(dataSize);
|
||||
if (PerfEnumerateCounterSetInstances(NULL, &querySpec.Identifier.CounterSetGuid, pHead, dataSize, &dataSize) != ERROR_SUCCESS)
|
||||
if (PerfEnumerateCounterSetInstances(NULL, &querySpec.Identifier.CounterSetGuid, pHead, dataSize, &dataSize) != ERROR_SUCCESS) {
|
||||
return "PerfEnumerateCounterSetInstances() failed to get instance headers";
|
||||
|
||||
PERF_INSTANCE_HEADER* pInstanceHeader = pHead;
|
||||
while (1)
|
||||
{
|
||||
const wchar_t* instanceName = (const wchar_t*)((BYTE*)pInstanceHeader + sizeof(*pInstanceHeader));
|
||||
if (wcscmp(instanceName, querySpec.Name) == 0)
|
||||
break;
|
||||
|
||||
dataSize -= pInstanceHeader->Size;
|
||||
if (dataSize == 0)
|
||||
break;
|
||||
pInstanceHeader = (PERF_INSTANCE_HEADER*)((BYTE*)pInstanceHeader + pInstanceHeader->Size);
|
||||
}
|
||||
|
||||
if (dataSize == 0)
|
||||
{
|
||||
if (options->tempSensor.length > 0)
|
||||
return "Unable to find CPU sensor";
|
||||
PERF_INSTANCE_HEADER* pInstanceHeader = pHead;
|
||||
while (1) {
|
||||
const wchar_t* instanceName = (const wchar_t*) ((BYTE*) pInstanceHeader + sizeof(*pInstanceHeader));
|
||||
if (wcscmp(instanceName, querySpec.Name) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
const wchar_t* instanceName = (const wchar_t*)((BYTE*)pHead + sizeof(*pHead));
|
||||
dataSize -= pInstanceHeader->Size;
|
||||
if (dataSize == 0) {
|
||||
break;
|
||||
}
|
||||
pInstanceHeader = (PERF_INSTANCE_HEADER*) ((BYTE*) pInstanceHeader + pInstanceHeader->Size);
|
||||
}
|
||||
|
||||
if (dataSize == 0) {
|
||||
if (options->tempSensor.length > 0) {
|
||||
return "Unable to find CPU sensor";
|
||||
}
|
||||
|
||||
const wchar_t* instanceName = (const wchar_t*) ((BYTE*) pHead + sizeof(*pHead));
|
||||
wcscpy(querySpec.Name, instanceName); // Use the first instance name if the specific one is not found
|
||||
}
|
||||
}
|
||||
@@ -80,75 +80,80 @@ const char* detectThermalTemp(const FFCPUOptions* options, double* result)
|
||||
__attribute__((__cleanup__(ffPerfCloseQueryHandle)))
|
||||
HANDLE hQuery = NULL;
|
||||
|
||||
if (PerfOpenQueryHandle(NULL, &hQuery) != ERROR_SUCCESS)
|
||||
if (PerfOpenQueryHandle(NULL, &hQuery) != ERROR_SUCCESS) {
|
||||
return "PerfOpenQueryHandle() failed";
|
||||
}
|
||||
|
||||
if (PerfAddCounters(hQuery, &querySpec.Identifier, sizeof(querySpec)) != ERROR_SUCCESS)
|
||||
if (PerfAddCounters(hQuery, &querySpec.Identifier, sizeof(querySpec)) != ERROR_SUCCESS) {
|
||||
return "PerfAddCounters() failed";
|
||||
}
|
||||
|
||||
if (querySpec.Identifier.Status != ERROR_SUCCESS)
|
||||
if (querySpec.Identifier.Status != ERROR_SUCCESS) {
|
||||
return "PerfAddCounters() reports invalid identifier";
|
||||
}
|
||||
|
||||
if (PerfQueryCounterData(hQuery, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY)
|
||||
if (PerfQueryCounterData(hQuery, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY) {
|
||||
return "PerfQueryCounterData(NULL) failed";
|
||||
}
|
||||
|
||||
if (dataSize <= sizeof(PERF_DATA_HEADER) + sizeof(PERF_COUNTER_HEADER)) // PERF_ERROR_RETURN, should not happen
|
||||
if (dataSize <= sizeof(PERF_DATA_HEADER) + sizeof(PERF_COUNTER_HEADER)) { // PERF_ERROR_RETURN, should not happen
|
||||
return "instance doesn't exist";
|
||||
}
|
||||
|
||||
FF_AUTO_FREE PERF_DATA_HEADER* const pDataHeader = malloc(dataSize);
|
||||
|
||||
if (PerfQueryCounterData(hQuery, pDataHeader, dataSize, &dataSize) != ERROR_SUCCESS)
|
||||
if (PerfQueryCounterData(hQuery, pDataHeader, dataSize, &dataSize) != ERROR_SUCCESS) {
|
||||
return "PerfQueryCounterData(pDataHeader) failed";
|
||||
}
|
||||
|
||||
PERF_COUNTER_HEADER* pCounterHeader = (PERF_COUNTER_HEADER*)(pDataHeader + 1);
|
||||
if (pCounterHeader->dwType != PERF_MULTIPLE_COUNTERS)
|
||||
PERF_COUNTER_HEADER* pCounterHeader = (PERF_COUNTER_HEADER*) (pDataHeader + 1);
|
||||
if (pCounterHeader->dwType != PERF_MULTIPLE_COUNTERS) {
|
||||
return "Invalid counter type";
|
||||
}
|
||||
|
||||
PERF_MULTI_COUNTERS* pMultiCounters = (PERF_MULTI_COUNTERS*)(pCounterHeader + 1);
|
||||
PERF_COUNTER_DATA* pCounterData = (PERF_COUNTER_DATA*)((BYTE*)pMultiCounters + pMultiCounters->dwSize);
|
||||
PERF_MULTI_COUNTERS* pMultiCounters = (PERF_MULTI_COUNTERS*) (pCounterHeader + 1);
|
||||
PERF_COUNTER_DATA* pCounterData = (PERF_COUNTER_DATA*) ((BYTE*) pMultiCounters + pMultiCounters->dwSize);
|
||||
|
||||
for (ULONG iCounter = 0; iCounter != pMultiCounters->dwCounters; iCounter++)
|
||||
{
|
||||
if (pCounterData->dwDataSize == sizeof(int32_t))
|
||||
{
|
||||
DWORD* pCounterIds = (DWORD*)(pMultiCounters + 1);
|
||||
int32_t value = *(int32_t*)(pCounterData + 1);
|
||||
if (value == 0)
|
||||
for (ULONG iCounter = 0; iCounter != pMultiCounters->dwCounters; iCounter++) {
|
||||
if (pCounterData->dwDataSize == sizeof(int32_t)) {
|
||||
DWORD* pCounterIds = (DWORD*) (pMultiCounters + 1);
|
||||
int32_t value = *(int32_t*) (pCounterData + 1);
|
||||
if (value == 0) {
|
||||
return "Temperature data is zero";
|
||||
}
|
||||
|
||||
switch (pCounterIds[iCounter]) {
|
||||
case 0: // Temperature
|
||||
*result = value - 273;
|
||||
break;
|
||||
case 3: // High Precision Temperature
|
||||
*result = value / 10.0 - 273;
|
||||
break;
|
||||
case 0: // Temperature
|
||||
*result = value - 273;
|
||||
break;
|
||||
case 3: // High Precision Temperature
|
||||
*result = value / 10.0 - 273;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pCounterData = (PERF_COUNTER_DATA*)((BYTE*)pCounterData + pCounterData->dwSize);
|
||||
pCounterData = (PERF_COUNTER_DATA*) ((BYTE*) pCounterData + pCounterData->dwSize);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 7.5
|
||||
typedef struct FFSmbiosProcessorInfo
|
||||
{
|
||||
typedef struct FFSmbiosProcessorInfo {
|
||||
FFSmbiosHeader Header;
|
||||
|
||||
uint8_t SocketDesignation; // string
|
||||
uint8_t ProcessorType; // enum
|
||||
uint8_t ProcessorFamily; // enum
|
||||
uint8_t SocketDesignation; // string
|
||||
uint8_t ProcessorType; // enum
|
||||
uint8_t ProcessorFamily; // enum
|
||||
uint8_t ProcessorManufacturer; // string
|
||||
uint64_t ProcessorID; // varies
|
||||
uint8_t ProcessorVersion; // string
|
||||
uint8_t Voltage; // varies
|
||||
uint16_t ExternalClock; // varies
|
||||
uint16_t MaxSpeed; // varies
|
||||
uint16_t CurrentSpeed; // varies
|
||||
uint8_t Status; // varies
|
||||
uint8_t ProcessorUpgrade; // enum
|
||||
uint64_t ProcessorID; // varies
|
||||
uint8_t ProcessorVersion; // string
|
||||
uint8_t Voltage; // varies
|
||||
uint16_t ExternalClock; // varies
|
||||
uint16_t MaxSpeed; // varies
|
||||
uint16_t CurrentSpeed; // varies
|
||||
uint8_t Status; // varies
|
||||
uint8_t ProcessorUpgrade; // enum
|
||||
|
||||
// 2.1+
|
||||
uint16_t L1CacheHandle; // varies
|
||||
@@ -157,20 +162,20 @@ typedef struct FFSmbiosProcessorInfo
|
||||
|
||||
// 2.3+
|
||||
uint8_t SerialNumber; // string
|
||||
uint8_t AssertTag; // string
|
||||
uint8_t PartNumber; // string
|
||||
uint8_t AssertTag; // string
|
||||
uint8_t PartNumber; // string
|
||||
|
||||
// 2.5+
|
||||
uint8_t CoreCount; // varies
|
||||
uint8_t CoreEnabled; // varies
|
||||
uint8_t ThreadCount; // varies
|
||||
uint8_t CoreCount; // varies
|
||||
uint8_t CoreEnabled; // varies
|
||||
uint8_t ThreadCount; // varies
|
||||
uint16_t ProcessorCharacteristics; // bit field
|
||||
|
||||
// 2.6+
|
||||
uint16_t ProcessorFamily2; // enum
|
||||
|
||||
// 3.0+
|
||||
uint16_t CoreCount2; // varies
|
||||
uint16_t CoreCount2; // varies
|
||||
uint16_t CoreEnabled2; // varies
|
||||
uint16_t ThreadCount2; // varies
|
||||
|
||||
@@ -181,128 +186,135 @@ typedef struct FFSmbiosProcessorInfo
|
||||
static_assert(offsetof(FFSmbiosProcessorInfo, ThreadEnabled) == 0x30,
|
||||
"FFSmbiosProcessorInfo: Wrong struct alignment");
|
||||
|
||||
static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu)
|
||||
{
|
||||
static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu) {
|
||||
const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable();
|
||||
if (!smbiosTable)
|
||||
if (!smbiosTable) {
|
||||
return "Failed to get SMBIOS data";
|
||||
}
|
||||
|
||||
const FFSmbiosProcessorInfo* data = (const FFSmbiosProcessorInfo*) (*smbiosTable)[FF_SMBIOS_TYPE_PROCESSOR_INFO];
|
||||
|
||||
if (!data)
|
||||
if (!data) {
|
||||
return "Processor information is not found in SMBIOS data";
|
||||
}
|
||||
|
||||
while (data->ProcessorType != 0x03 /*Central Processor*/ || (data->Status & 0b00000111) != 1 /*Enabled*/)
|
||||
{
|
||||
while (data->ProcessorType != 0x03 /*Central Processor*/ || (data->Status & 0b00000111) != 1 /*Enabled*/) {
|
||||
data = (const FFSmbiosProcessorInfo*) ffSmbiosNextEntry(&data->Header);
|
||||
if (data->Header.Type != FF_SMBIOS_TYPE_PROCESSOR_INFO)
|
||||
if (data->Header.Type != FF_SMBIOS_TYPE_PROCESSOR_INFO) {
|
||||
return "No active CPU is found in SMBIOS data";
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t speed = data->MaxSpeed;
|
||||
// Sometimes SMBIOS reports invalid value. We assume that max speed is small than 2x of base
|
||||
if (speed < cpu->frequencyBase || speed > cpu->frequencyBase * 2)
|
||||
if (speed < cpu->frequencyBase || speed > cpu->frequencyBase * 2) {
|
||||
return "Possible invalid CPU max speed in SMBIOS data. See #800";
|
||||
}
|
||||
|
||||
cpu->frequencyMax = speed;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectNCores(FFCPUResult* cpu)
|
||||
{
|
||||
static const char* detectNCores(FFCPUResult* cpu) {
|
||||
LOGICAL_PROCESSOR_RELATIONSHIP lpr = RelationAll;
|
||||
ULONG length = 0;
|
||||
NtQuerySystemInformationEx(SystemLogicalProcessorAndGroupInformation, &lpr, sizeof(lpr), NULL, 0, &length);
|
||||
if (length == 0)
|
||||
if (length == 0) {
|
||||
return "GetLogicalProcessorInformationEx(RelationAll, NULL, &length) failed";
|
||||
}
|
||||
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* FF_AUTO_FREE
|
||||
pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
|
||||
pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) malloc(length);
|
||||
|
||||
if (!NT_SUCCESS(NtQuerySystemInformationEx(SystemLogicalProcessorAndGroupInformation, &lpr, sizeof(lpr), pProcessorInfo, length, &length)))
|
||||
if (!NT_SUCCESS(NtQuerySystemInformationEx(SystemLogicalProcessorAndGroupInformation, &lpr, sizeof(lpr), pProcessorInfo, length, &length))) {
|
||||
return "GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length) failed";
|
||||
}
|
||||
|
||||
for(
|
||||
for (
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pProcessorInfo;
|
||||
(uint8_t*)ptr < ((uint8_t*)pProcessorInfo) + length;
|
||||
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((uint8_t*)ptr) + ptr->Size)
|
||||
)
|
||||
{
|
||||
if (ptr->Relationship == RelationGroup)
|
||||
{
|
||||
for (uint32_t index = 0; index < ptr->Group.ActiveGroupCount; ++index)
|
||||
{
|
||||
(uint8_t*) ptr < ((uint8_t*) pProcessorInfo) + length;
|
||||
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) (((uint8_t*) ptr) + ptr->Size)) {
|
||||
if (ptr->Relationship == RelationGroup) {
|
||||
for (uint32_t index = 0; index < ptr->Group.ActiveGroupCount; ++index) {
|
||||
cpu->coresOnline += ptr->Group.GroupInfo[index].ActiveProcessorCount;
|
||||
cpu->coresLogical += ptr->Group.GroupInfo[index].MaximumProcessorCount;
|
||||
}
|
||||
}
|
||||
else if (ptr->Relationship == RelationProcessorCore)
|
||||
} else if (ptr->Relationship == RelationProcessorCore) {
|
||||
++cpu->coresPhysical;
|
||||
else if (ptr->Relationship == RelationProcessorPackage)
|
||||
} else if (ptr->Relationship == RelationProcessorPackage) {
|
||||
++cpu->packages;
|
||||
else if (ptr->Relationship == RelationNumaNode)
|
||||
} else if (ptr->Relationship == RelationNumaNode) {
|
||||
++cpu->numaNodes;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectByRegistry(FFCPUResult* cpu)
|
||||
{
|
||||
static const char* detectByRegistry(FFCPUResult* cpu) {
|
||||
FF_AUTO_CLOSE_FD HANDLE hKey = NULL;
|
||||
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL))
|
||||
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL)) {
|
||||
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed";
|
||||
}
|
||||
|
||||
if (ffRegReadValues(hKey, 3, (FFRegValueArg[]) {
|
||||
FF_ARG(cpu->name, L"ProcessorNameString"),
|
||||
FF_ARG(cpu->vendor, L"VendorIdentifier"),
|
||||
FF_ARG(cpu->frequencyBase, L"~MHz"),
|
||||
}, NULL))
|
||||
FF_ARG(cpu->name, L"ProcessorNameString"),
|
||||
FF_ARG(cpu->vendor, L"VendorIdentifier"),
|
||||
FF_ARG(cpu->frequencyBase, L"~MHz"),
|
||||
},
|
||||
NULL)) {
|
||||
ffStrbufTrimRightSpace(&cpu->vendor);
|
||||
else
|
||||
} else {
|
||||
return "ffRegReadValues() failed for CPU registry key";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectCoreTypes(FFCPUResult* cpu)
|
||||
{
|
||||
static const char* detectCoreTypes(FFCPUResult* cpu) {
|
||||
FF_AUTO_FREE PROCESSOR_POWER_INFORMATION* pinfo = calloc(cpu->coresLogical, sizeof(PROCESSOR_POWER_INFORMATION));
|
||||
if (!NT_SUCCESS(NtPowerInformation(ProcessorInformation, NULL, 0, pinfo, (ULONG) sizeof(PROCESSOR_POWER_INFORMATION) * cpu->coresLogical)))
|
||||
if (!NT_SUCCESS(NtPowerInformation(ProcessorInformation, NULL, 0, pinfo, (ULONG) sizeof(PROCESSOR_POWER_INFORMATION) * cpu->coresLogical))) {
|
||||
return "NtPowerInformation(ProcessorInformation, NULL, 0, pinfo, size) failed";
|
||||
}
|
||||
|
||||
for (uint32_t icore = 0; icore < cpu->coresLogical && pinfo[icore].MhzLimit; ++icore)
|
||||
{
|
||||
for (uint32_t icore = 0; icore < cpu->coresLogical && pinfo[icore].MhzLimit; ++icore) {
|
||||
uint32_t ifreq = 0;
|
||||
while (cpu->coreTypes[ifreq].freq != pinfo[icore].MhzLimit && cpu->coreTypes[ifreq].freq > 0)
|
||||
while (cpu->coreTypes[ifreq].freq != pinfo[icore].MhzLimit && cpu->coreTypes[ifreq].freq > 0) {
|
||||
++ifreq;
|
||||
if (cpu->coreTypes[ifreq].freq == 0)
|
||||
}
|
||||
if (cpu->coreTypes[ifreq].freq == 0) {
|
||||
cpu->coreTypes[ifreq].freq = pinfo[icore].MhzLimit;
|
||||
}
|
||||
++cpu->coreTypes[ifreq].count;
|
||||
}
|
||||
|
||||
if (cpu->frequencyBase == 0)
|
||||
if (cpu->frequencyBase == 0) {
|
||||
cpu->frequencyBase = pinfo->MaxMhz;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) {
|
||||
detectNCores(cpu);
|
||||
|
||||
const char* error = detectByRegistry(cpu);
|
||||
if (error)
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
ffCPUDetectByCpuid(cpu);
|
||||
if (options->showPeCoreCount) detectCoreTypes(cpu);
|
||||
if (options->showPeCoreCount) {
|
||||
detectCoreTypes(cpu);
|
||||
}
|
||||
|
||||
if (cpu->frequencyMax == 0)
|
||||
if (cpu->frequencyMax == 0) {
|
||||
detectMaxSpeedBySmbios(cpu);
|
||||
}
|
||||
|
||||
if(options->temp)
|
||||
if (options->temp) {
|
||||
detectThermalTemp(options, &cpu->temperature);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user