diff --git a/CMakeLists.txt b/CMakeLists.txt index b6d3569..83fb8cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,7 +54,7 @@ set(CMAKE_CXX_FLAGS "${SANITY_FLAGS} -Wall -Wextra -pedantic -fstack-protector-a if(ENABLE_INTEL_BACKEND) target_compile_definitions(gpufetch PUBLIC BACKEND_INTEL) - add_library(intel_backend STATIC ${INTEL_DIR}/intel.cpp ${INTEL_DIR}/pci.cpp ${INTEL_DIR}/uarch.cpp ${INTEL_DIR}/udev.cpp) + add_library(intel_backend STATIC ${INTEL_DIR}/intel.cpp ${INTEL_DIR}/pci.cpp ${INTEL_DIR}/uarch.cpp ${INTEL_DIR}/udev.cpp ${INTEL_DIR}/cpuid.cpp) if(NOT ${PCIUTILS_FOUND}) add_dependencies(intel_backend pciutils) diff --git a/src/intel/cpuid.cpp b/src/intel/cpuid.cpp new file mode 100644 index 0000000..441f8c1 --- /dev/null +++ b/src/intel/cpuid.cpp @@ -0,0 +1,71 @@ +#include "../common/global.hpp" +#include +#include +#include +#include + +#define CPU_VENDOR_MAX_LENGTH 13 +#define CPU_NAME_MAX_LENGTH 49 +#define CPU_VENDOR_INTEL_STRING "GenuineIntel" + +void cpuid(uint32_t level, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { + __asm volatile("cpuid" + : "=a" (*eax), + "=b" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "0" (level), "2" (*ecx)); +} + +char* get_cpu_vendor() { + uint32_t vendor[3]; + uint32_t dummy; + char * name = (char *) emalloc(sizeof(char) * CPU_VENDOR_MAX_LENGTH); + memset(name, 0, CPU_VENDOR_MAX_LENGTH); + + cpuid(0x00000000, &dummy, vendor+0x0, vendor+0x2, vendor+0x1); + + snprintf(name, CPU_VENDOR_MAX_LENGTH, "%s", (char *) vendor); + + return name; +} + +char* get_str_cpu_name_internal() { + uint32_t brand[12]; + char * name = (char *) emalloc(sizeof(char) * CPU_NAME_MAX_LENGTH); + memset(name, 0, CPU_NAME_MAX_LENGTH); + + cpuid(0x80000002, brand+0x0, brand+0x1, brand+0x2, brand+0x3); + cpuid(0x80000003, brand+0x4, brand+0x5, brand+0x6, brand+0x7); + cpuid(0x80000004, brand+0x8, brand+0x9, brand+0xa, brand+0xb); + + snprintf(name, CPU_NAME_MAX_LENGTH, "%s", (char *) brand); + + return name; +} + +bool is_corei5() { + uint32_t eax = 0; + uint32_t ebx = 0; + uint32_t ecx = 0; + uint32_t edx = 0; + + // Get CPU vendor + char* cpu_vendor = get_cpu_vendor(); + + if(strcmp(CPU_VENDOR_INTEL_STRING, cpu_vendor) != 0) { + printBug("is_corei5: invalid CPU vendor: %s", cpu_vendor); + return false; + } + + cpuid(0x80000000, &eax, &ebx, &ecx, &edx); + + if (eax < 0x80000004){ + printBug("is_corei5: unexpected max extended level: 0x%.8X", eax); + return false; + } + + // Get CPU name + char* cpu_name = get_str_cpu_name_internal(); + return strstr(cpu_name, "i5") != NULL; +} diff --git a/src/intel/cpuid.hpp b/src/intel/cpuid.hpp new file mode 100644 index 0000000..61cdf43 --- /dev/null +++ b/src/intel/cpuid.hpp @@ -0,0 +1,6 @@ +#ifndef __CPUID__ +#define __CPUID__ + +bool is_corei5(); + +#endif diff --git a/src/intel/uarch.cpp b/src/intel/uarch.cpp index 5888602..b3a1861 100644 --- a/src/intel/uarch.cpp +++ b/src/intel/uarch.cpp @@ -8,6 +8,7 @@ #include "../common/gpu.hpp" #include "chips.hpp" #include "pci.hpp" +#include "cpuid.hpp" // Data not available #define NA -1 @@ -239,7 +240,15 @@ struct topology_i* get_topology_info(struct uarch* arch) { CHECK_TOPO(topo, arch, UARCH_GEN11, GT2, 8, 8, 1) // Gen12 CHECK_TOPO(topo, arch, UARCH_GEN12_RKL, GT1, 16, 2, 1) - CHECK_TOPO(topo, arch, UARCH_GEN12_TGL, GT2, 16, 6, 1) // TODO: Check if is i5/i7 do know if has 80 or 96 EUs + else if(arch->uarch == UARCH_GEN12_TGL && arch->gt == GT2) { + // Special case: TigerLake GT2 needs to check if is i5/i7 to know the exact topology + if(is_corei5()) { + fill_topo(topo, 10, 8, 1); // Should be 80 EUs, but not sure about the organization + } + else { + fill_topo(topo, 16, 6, 1); + } + } CHECK_TOPO_END return topo; }