mirror of
https://github.com/Dr-Noob/cpufetch.git
synced 2026-03-25 07:50:40 +01:00
518 lines
28 KiB
C
518 lines
28 KiB
C
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "uarch.h"
|
|
#include "../common/global.h"
|
|
|
|
/*
|
|
* - cpuid codes are based on Todd Allen's cpuid program
|
|
* http://www.etallen.com/cpuid.html
|
|
* - This should be updated from time to time, to support newer CPUs. A good reference to look at:
|
|
* https://en.wikichip.org/
|
|
* http://instlatx64.atw.hu/
|
|
*/
|
|
|
|
// From Todd Allen:
|
|
//
|
|
// MSR_CPUID_table* is a table that appears in Intel document 325462, "Intel 64
|
|
// and IA-32 Architectures Software Developer's Manual Combined Volumes: 1, 2A,
|
|
// 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4" (the name changes from version to version
|
|
// as more volumes are added). The table moves around from version to version,
|
|
// but in version 071US, was in "Volume 4: Model-Specific Registers", Table 2-1:
|
|
// "CPUID Signature Values of DisplayFamily_DisplayModel".
|
|
|
|
// MRG* is a table that forms the bulk of Intel Microcode Revision Guidance (or
|
|
// Microcode Update Guidance). Its purpose is not to list CPUID values, but
|
|
// it does so, and sometimes lists values that appear nowhere else.
|
|
|
|
// LX* indicates features that I have seen no documentation for, but which are
|
|
// used by the Linux kernel (which is good evidence that they're correct).
|
|
// The "hook" to find these generally is an X86_FEATURE_* flag in:
|
|
// arch/x86/include/asm/cpufeatures.h
|
|
// For (synth) and (uarch synth) decoding, it often indicates
|
|
// family/model/stepping value which are documented nowhere else. These usually
|
|
// can be found in:
|
|
// arch/x86/include/asm/intel-family.h
|
|
|
|
typedef uint32_t MICROARCH;
|
|
|
|
// Data not available
|
|
#define NA -1
|
|
|
|
// Unknown manufacturing process
|
|
#define UNK -1
|
|
|
|
enum {
|
|
UARCH_UNKNOWN,
|
|
// INTEL //
|
|
UARCH_P5,
|
|
UARCH_P6,
|
|
UARCH_DOTHAN,
|
|
UARCH_YONAH,
|
|
UARCH_MEROM,
|
|
UARCH_PENYR,
|
|
UARCH_NEHALEM,
|
|
UARCH_WESTMERE,
|
|
UARCH_BONNELL,
|
|
UARCH_SALTWELL,
|
|
UARCH_SANDY_BRIDGE,
|
|
UARCH_SILVERMONT,
|
|
UARCH_IVY_BRIDGE,
|
|
UARCH_HASWELL,
|
|
UARCH_BROADWELL,
|
|
UARCH_AIRMONT,
|
|
UARCH_KABY_LAKE,
|
|
UARCH_COMET_LAKE,
|
|
UARCH_ROCKET_LAKE,
|
|
UARCH_AMBER_LAKE,
|
|
UARCH_WHISKEY_LAKE,
|
|
UARCH_SKYLAKE,
|
|
UARCH_CASCADE_LAKE,
|
|
UARCH_COOPER_LAKE,
|
|
UARCH_KNIGHTS_LANDING,
|
|
UARCH_KNIGHTS_MILL,
|
|
UARCH_GOLDMONT,
|
|
UARCH_PALM_COVE,
|
|
UARCH_SUNNY_COVE,
|
|
UARCH_GOLDMONT_PLUS,
|
|
UARCH_TREMONT,
|
|
UARCH_LAKEMONT,
|
|
UARCH_COFFEE_LAKE,
|
|
UARCH_ITANIUM,
|
|
UARCH_KNIGHTS_FERRY,
|
|
UARCH_KNIGHTS_CORNER,
|
|
UARCH_WILLAMETTE,
|
|
UARCH_NORTHWOOD,
|
|
UARCH_PRESCOTT,
|
|
UARCH_CEDAR_MILL,
|
|
UARCH_ITANIUM2,
|
|
UARCH_ICE_LAKE,
|
|
UARCH_TIGER_LAKE,
|
|
UARCH_ALDER_LAKE,
|
|
UARCH_RAPTOR_LAKE,
|
|
// AMD //
|
|
UARCH_AM486,
|
|
UARCH_AM5X86,
|
|
UARCH_K6,
|
|
UARCH_K7,
|
|
UARCH_K8,
|
|
UARCH_K10,
|
|
UARCH_PUMA_2008,
|
|
UARCH_BOBCAT,
|
|
UARCH_BULLDOZER,
|
|
UARCH_PILEDRIVER,
|
|
UARCH_STEAMROLLER,
|
|
UARCH_EXCAVATOR,
|
|
UARCH_JAGUAR,
|
|
UARCH_PUMA_2014,
|
|
UARCH_ZEN,
|
|
UARCH_ZEN_PLUS,
|
|
UARCH_ZEN2,
|
|
UARCH_ZEN3,
|
|
UARCH_ZEN3_PLUS,
|
|
UARCH_ZEN4,
|
|
UARCH_ZEN4C
|
|
};
|
|
|
|
struct uarch {
|
|
MICROARCH uarch;
|
|
char* uarch_str;
|
|
int32_t process; // measured in nanometers
|
|
};
|
|
|
|
#define UARCH_START if (false) {}
|
|
#define CHECK_UARCH(arch, ef_, f_, em_, m_, s_, str, uarch, process) \
|
|
else if (ef_ == ef && f_ == f && (em_ == NA || em_ == em) && (m_ == NA || m_ == m) && (s_ == NA || s_ == s)) fill_uarch(arch, str, uarch, process);
|
|
#define UARCH_END else { printBug("Unknown microarchitecture detected: M=0x%.8X EM=0x%.8X F=0x%.8X EF=0x%.8X S=0x%.8X", m, em, f, ef, s); fill_uarch(arch, STRING_UNKNOWN, UARCH_UNKNOWN, 0); }
|
|
|
|
void fill_uarch(struct uarch* arch, char* str, MICROARCH u, uint32_t process) {
|
|
arch->uarch_str = emalloc(sizeof(char) * (strlen(str)+1));
|
|
strcpy(arch->uarch_str, str);
|
|
arch->uarch = u;
|
|
arch->process= process;
|
|
}
|
|
|
|
// Inspired in Todd Allen's decode_uarch_intel
|
|
struct uarch* get_uarch_from_cpuid_intel(uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s) {
|
|
struct uarch* arch = emalloc(sizeof(struct uarch));
|
|
|
|
// EF: Extended Family //
|
|
// F: Family //
|
|
// EM: Extended Model //
|
|
// M: Model //
|
|
// S: Stepping //
|
|
// ----------------------------------------------------------------------------- //
|
|
// EF F EM M S //
|
|
UARCH_START
|
|
CHECK_UARCH(arch, 0, 5, 0, 0, NA, "P5", UARCH_P5, 800)
|
|
CHECK_UARCH(arch, 0, 5, 0, 1, NA, "P5", UARCH_P5, 800)
|
|
CHECK_UARCH(arch, 0, 5, 0, 2, NA, "P5", UARCH_P5, UNK)
|
|
CHECK_UARCH(arch, 0, 5, 0, 3, NA, "P5", UARCH_P5, 600)
|
|
CHECK_UARCH(arch, 0, 5, 0, 4, NA, "P5 MMX", UARCH_P5, UNK)
|
|
CHECK_UARCH(arch, 0, 5, 0, 7, NA, "P5 MMX", UARCH_P5, UNK)
|
|
CHECK_UARCH(arch, 0, 5, 0, 8, NA, "P5 MMX", UARCH_P5, 250)
|
|
CHECK_UARCH(arch, 0, 5, 0, 9, 0, "Lakemont", UARCH_LAKEMONT, 32)
|
|
CHECK_UARCH(arch, 0, 5, 0, 9, NA, "P5 MMX", UARCH_P5, UNK)
|
|
CHECK_UARCH(arch, 0, 5, 0, 10, 0, "Lakemont", UARCH_LAKEMONT, 32)
|
|
CHECK_UARCH(arch, 0, 6, 0, 0, NA, "P6 Pentium II", UARCH_P6, UNK)
|
|
CHECK_UARCH(arch, 0, 6, 0, 1, NA, "P6 Pentium II", UARCH_P6, UNK) // process depends on core
|
|
CHECK_UARCH(arch, 0, 6, 0, 2, NA, "P6 Pentium II", UARCH_P6, UNK)
|
|
CHECK_UARCH(arch, 0, 6, 0, 3, NA, "P6 Pentium II", UARCH_P6, 350)
|
|
CHECK_UARCH(arch, 0, 6, 0, 4, NA, "P6 Pentium II", UARCH_P6, UNK)
|
|
CHECK_UARCH(arch, 0, 6, 0, 5, NA, "P6 Pentium II", UARCH_P6, 250)
|
|
CHECK_UARCH(arch, 0, 6, 0, 6, NA, "P6 Pentium II", UARCH_P6, UNK)
|
|
CHECK_UARCH(arch, 0, 6, 0, 7, NA, "P6 Pentium III", UARCH_P6, 250)
|
|
CHECK_UARCH(arch, 0, 6, 0, 8, NA, "P6 Pentium III", UARCH_P6, 180)
|
|
CHECK_UARCH(arch, 0, 6, 0, 9, NA, "P6 Pentium M", UARCH_P6, 130)
|
|
CHECK_UARCH(arch, 0, 6, 0, 10, NA, "P6 Pentium III", UARCH_P6, 180)
|
|
CHECK_UARCH(arch, 0, 6, 0, 11, NA, "P6 Pentium III", UARCH_P6, 130)
|
|
CHECK_UARCH(arch, 0, 6, 0, 13, NA, "Dothan", UARCH_DOTHAN, UNK) // process depends on core
|
|
CHECK_UARCH(arch, 0, 6, 0, 14, NA, "Yonah", UARCH_YONAH, 65)
|
|
CHECK_UARCH(arch, 0, 6, 0, 15, NA, "Merom", UARCH_MEROM, 65)
|
|
CHECK_UARCH(arch, 0, 6, 1, 5, NA, "Dothan", UARCH_DOTHAN, 90)
|
|
CHECK_UARCH(arch, 0, 6, 1, 6, NA, "Merom", UARCH_MEROM, 65)
|
|
CHECK_UARCH(arch, 0, 6, 1, 7, NA, "Penryn", UARCH_PENYR, 45)
|
|
CHECK_UARCH(arch, 0, 6, 1, 10, NA, "Nehalem", UARCH_NEHALEM, 45)
|
|
CHECK_UARCH(arch, 0, 6, 1, 12, NA, "Bonnell", UARCH_BONNELL, 45)
|
|
CHECK_UARCH(arch, 0, 6, 1, 13, NA, "Penryn", UARCH_PENYR, 45)
|
|
CHECK_UARCH(arch, 0, 6, 1, 14, NA, "Nehalem", UARCH_NEHALEM, 45)
|
|
CHECK_UARCH(arch, 0, 6, 1, 15, NA, "Nehalem", UARCH_NEHALEM, 45)
|
|
CHECK_UARCH(arch, 0, 6, 2, 5, NA, "Westmere", UARCH_WESTMERE, 32)
|
|
CHECK_UARCH(arch, 0, 6, 2 , 6, NA, "Bonnell", UARCH_BONNELL, 45)
|
|
CHECK_UARCH(arch, 0, 6, 2, 7, NA, "Saltwell", UARCH_SALTWELL, 32)
|
|
CHECK_UARCH(arch, 0, 6, 2, 10, NA, "Sandy Bridge", UARCH_SANDY_BRIDGE, 32)
|
|
CHECK_UARCH(arch, 0, 6, 2, 12, NA, "Westmere", UARCH_WESTMERE, 32)
|
|
CHECK_UARCH(arch, 0, 6, 2, 13, NA, "Sandy Bridge", UARCH_SANDY_BRIDGE, 32)
|
|
CHECK_UARCH(arch, 0, 6, 2, 14, NA, "Nehalem", UARCH_NEHALEM, 45)
|
|
CHECK_UARCH(arch, 0, 6, 2, 15, NA, "Westmere", UARCH_WESTMERE, 32)
|
|
CHECK_UARCH(arch, 0, 6, 3, 5, NA, "Saltwell", UARCH_SALTWELL, 14)
|
|
CHECK_UARCH(arch, 0, 6, 3, 6, NA, "Saltwell", UARCH_SALTWELL, 32)
|
|
CHECK_UARCH(arch, 0, 6, 3, 7, NA, "Silvermont", UARCH_SILVERMONT, 22)
|
|
CHECK_UARCH(arch, 0, 6, 3, 10, NA, "Ivy Bridge", UARCH_IVY_BRIDGE, 22)
|
|
CHECK_UARCH(arch, 0, 6, 3, 12, NA, "Haswell", UARCH_HASWELL, 22)
|
|
CHECK_UARCH(arch, 0, 6, 3, 13, NA, "Broadwell", UARCH_BROADWELL, 14)
|
|
CHECK_UARCH(arch, 0, 6, 3, 14, NA, "Ivy Bridge", UARCH_IVY_BRIDGE, 22)
|
|
CHECK_UARCH(arch, 0, 6, 3, 15, NA, "Haswell", UARCH_HASWELL, 22)
|
|
CHECK_UARCH(arch, 0, 6, 4, 5, NA, "Haswell", UARCH_HASWELL, 22)
|
|
CHECK_UARCH(arch, 0, 6, 4, 6, NA, "Haswell", UARCH_HASWELL, 22)
|
|
CHECK_UARCH(arch, 0, 6, 4, 7, NA, "Broadwell", UARCH_BROADWELL, 14)
|
|
CHECK_UARCH(arch, 0, 6, 4, 10, NA, "Silvermont", UARCH_SILVERMONT, 22) // no docs, but /proc/cpuinfo seen in wild
|
|
CHECK_UARCH(arch, 0, 6, 4, 12, NA, "Airmont", UARCH_AIRMONT, 14)
|
|
CHECK_UARCH(arch, 0, 6, 4, 13, NA, "Silvermont", UARCH_SILVERMONT, 22)
|
|
CHECK_UARCH(arch, 0, 6, 4, 14, 8, "Kaby Lake", UARCH_KABY_LAKE, 14)
|
|
CHECK_UARCH(arch, 0, 6, 4, 14, NA, "Skylake", UARCH_SKYLAKE, 14)
|
|
CHECK_UARCH(arch, 0, 6, 4, 15, NA, "Broadwell", UARCH_BROADWELL, 14)
|
|
CHECK_UARCH(arch, 0, 6, 5, 5, 6, "Cascade Lake", UARCH_CASCADE_LAKE, 14) // no docs, but example from Greg Stewart
|
|
CHECK_UARCH(arch, 0, 6, 5, 5, 7, "Cascade Lake", UARCH_CASCADE_LAKE, 14)
|
|
CHECK_UARCH(arch, 0, 6, 5, 5, 10, "Cooper Lake", UARCH_COOPER_LAKE, 14)
|
|
CHECK_UARCH(arch, 0, 6, 5, 5, NA, "Skylake", UARCH_SKYLAKE, 14)
|
|
CHECK_UARCH(arch, 0, 6, 5, 6, NA, "Broadwell", UARCH_BROADWELL, 14)
|
|
CHECK_UARCH(arch, 0, 6, 5, 7, NA, "Knights Landing", UARCH_KNIGHTS_LANDING, 14)
|
|
CHECK_UARCH(arch, 0, 6, 5, 10, NA, "Silvermont", UARCH_SILVERMONT, 22) // no spec update; only MSR_CPUID_table* so far
|
|
CHECK_UARCH(arch, 0, 6, 5, 12, NA, "Goldmont", UARCH_GOLDMONT, 14)
|
|
CHECK_UARCH(arch, 0, 6, 5, 13, NA, "Silvermont", UARCH_SILVERMONT, 22) // no spec update; only MSR_CPUID_table* so far
|
|
CHECK_UARCH(arch, 0, 6, 5, 14, 8, "Kaby Lake", UARCH_KABY_LAKE, 14)
|
|
CHECK_UARCH(arch, 0, 6, 5, 14, NA, "Skylake", UARCH_SKYLAKE, 14)
|
|
CHECK_UARCH(arch, 0, 6, 5, 15, NA, "Goldmont", UARCH_GOLDMONT, 14)
|
|
CHECK_UARCH(arch, 0, 6, 6, 6, NA, "Palm Cove", UARCH_PALM_COVE, 10) // no spec update; only MSR_CPUID_table* so far
|
|
CHECK_UARCH(arch, 0, 6, 6, 10, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // no spec update; only MSR_CPUID_table* so far
|
|
CHECK_UARCH(arch, 0, 6, 6, 12, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // no spec update; only MSR_CPUID_table* so far
|
|
CHECK_UARCH(arch, 0, 6, 7, 5, NA, "Airmont", UARCH_AIRMONT, 14) // no spec update; whispers & rumors
|
|
CHECK_UARCH(arch, 0, 6, 7, 10, NA, "Goldmont Plus", UARCH_GOLDMONT_PLUS, 14)
|
|
CHECK_UARCH(arch, 0, 6, 7, 13, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // no spec update; only MSR_CPUID_table* so far
|
|
CHECK_UARCH(arch, 0, 6, 7, 14, NA, "Ice Lake", UARCH_ICE_LAKE, 10)
|
|
CHECK_UARCH(arch, 0, 6, 8, 5, NA, "Knights Mill", UARCH_KNIGHTS_MILL, 14) // no spec update; only MSR_CPUID_table* so far
|
|
CHECK_UARCH(arch, 0, 6, 8, 6, NA, "Tremont", UARCH_TREMONT, 10) // LX*
|
|
CHECK_UARCH(arch, 0, 6, 8, 10, NA, "Tremont", UARCH_TREMONT, 10) // no spec update; only geekbench.com example
|
|
CHECK_UARCH(arch, 0, 6, 8, 12, NA, "Tiger Lake", UARCH_TIGER_LAKE, 10) // instlatx64
|
|
CHECK_UARCH(arch, 0, 6, 8, 13, NA, "Tiger Lake", UARCH_TIGER_LAKE, 10) // instlatx64
|
|
// CHECK_UARCH(arch, 0, 6, 8, 14, 9, ...) It is not possible to determine uarch only from CPUID dump (can be Kaby Lake or Amber Lake)
|
|
// CHECK_UARCH(arch, 0, 6, 8, 14, 10, ...) It is not possible to determine uarch only from CPUID dump (can be Kaby Lake R or Coffee Lake U)
|
|
CHECK_UARCH(arch, 0, 6, 8, 14, 11, "Whiskey Lake", UARCH_WHISKEY_LAKE, 14) // wikichip
|
|
CHECK_UARCH(arch, 0, 6, 8, 14, 12, "Comet Lake", UARCH_COMET_LAKE, 14) // wikichip
|
|
CHECK_UARCH(arch, 0, 6, 9, 6, NA, "Tremont", UARCH_TREMONT, 10) // LX*
|
|
CHECK_UARCH(arch, 0, 6, 9, 7, NA, "Alder Lake", UARCH_ALDER_LAKE, 10) // instlatx64 (Alder Lake-S)
|
|
CHECK_UARCH(arch, 0, 6, 9, 10, NA, "Alder Lake", UARCH_ALDER_LAKE, 10) // instlatx64 (Alder Lake-P)
|
|
CHECK_UARCH(arch, 0, 6, 9, 12, NA, "Tremont", UARCH_TREMONT, 10) // LX*
|
|
CHECK_UARCH(arch, 0, 6, 9, 13, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // LX*
|
|
CHECK_UARCH(arch, 0, 6, 9, 14, 9, "Kaby Lake", UARCH_KABY_LAKE, 14)
|
|
CHECK_UARCH(arch, 0, 6, 9, 14, 10, "Coffee Lake", UARCH_COFFEE_LAKE, 14)
|
|
CHECK_UARCH(arch, 0, 6, 9, 14, 11, "Coffee Lake", UARCH_COFFEE_LAKE, 14)
|
|
CHECK_UARCH(arch, 0, 6, 9, 14, 12, "Coffee Lake", UARCH_COFFEE_LAKE, 14)
|
|
CHECK_UARCH(arch, 0, 6, 9, 14, 13, "Coffee Lake", UARCH_COFFEE_LAKE, 14)
|
|
CHECK_UARCH(arch, 0, 6, 10, 5, NA, "Comet Lake", UARCH_COMET_LAKE, 14) // wikichip
|
|
CHECK_UARCH(arch, 0, 6, 10, 6, NA, "Comet Lake", UARCH_COMET_LAKE, 14) // instlatx64.atw.hu (i7-10710U)
|
|
CHECK_UARCH(arch, 0, 6, 10, 7, NA, "Rocket Lake", UARCH_ROCKET_LAKE, 14) // instlatx64.atw.hu (i7-11700K)
|
|
CHECK_UARCH(arch, 0, 6, 11, 7, NA, "Raptor Lake", UARCH_RAPTOR_LAKE, 10) // instlatx64.atw.hu (i5-13600K)
|
|
CHECK_UARCH(arch, 0, 6, 11, 10, NA, "Raptor Lake", UARCH_RAPTOR_LAKE, 10) // instlatx64.atw.hu (i7-1370P)
|
|
CHECK_UARCH(arch, 0, 6, 11, 14, NA, "Alder Lake", UARCH_ALDER_LAKE, 10) // instlatx64.atw.hu (Alder Lake-N)
|
|
CHECK_UARCH(arch, 0, 6, 11, 15, NA, "Raptor Lake", UARCH_RAPTOR_LAKE, 10) // instlatx64.atw.hu (i5-13500)
|
|
CHECK_UARCH(arch, 0, 11, 0, 0, NA, "Knights Ferry", UARCH_KNIGHTS_FERRY, 45) // found only on en.wikichip.org
|
|
CHECK_UARCH(arch, 0, 11, 0, 1, NA, "Knights Corner", UARCH_KNIGHTS_CORNER, 22)
|
|
CHECK_UARCH(arch, 0, 15, 0, 0, NA, "Willamette", UARCH_WILLAMETTE, 180)
|
|
CHECK_UARCH(arch, 0, 15, 0, 1, NA, "Willamette", UARCH_WILLAMETTE, 180)
|
|
CHECK_UARCH(arch, 0, 15, 0, 2, NA, "Northwood", UARCH_NORTHWOOD, 130)
|
|
CHECK_UARCH(arch, 0, 15, 0, 3, NA, "Prescott", UARCH_PRESCOTT, 90)
|
|
CHECK_UARCH(arch, 0, 15, 0, 4, NA, "Prescott", UARCH_PRESCOTT, 90)
|
|
CHECK_UARCH(arch, 0, 15, 0, 6, NA, "Cedar Mill", UARCH_CEDAR_MILL, 65)
|
|
CHECK_UARCH(arch, 1, 15, 0, 0, NA, "Itanium2", UARCH_ITANIUM2, 180)
|
|
CHECK_UARCH(arch, 1, 15, 0, 1, NA, "Itanium2", UARCH_ITANIUM2, 130)
|
|
CHECK_UARCH(arch, 1, 15, 0, 2, NA, "Itanium2", UARCH_ITANIUM2, 130)
|
|
UARCH_END
|
|
return arch;
|
|
}
|
|
|
|
// Inspired in Todd Allen's decode_uarch_amd
|
|
struct uarch* get_uarch_from_cpuid_amd(uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s) {
|
|
struct uarch* arch = emalloc(sizeof(struct uarch));
|
|
|
|
// EF: Extended Family //
|
|
// F: Family //
|
|
// EM: Extended Model //
|
|
// M: Model //
|
|
// S: Stepping //
|
|
// ----------------------------------------------------------------------------- //
|
|
// EF F EM M S //
|
|
UARCH_START
|
|
CHECK_UARCH(arch, 0, 4, 0, 3, NA, "Am486", UARCH_AM486, UNK)
|
|
CHECK_UARCH(arch, 0, 4, 0, 7, NA, "Am486", UARCH_AM486, UNK)
|
|
CHECK_UARCH(arch, 0, 4, 0, 8, NA, "Am486", UARCH_AM486, UNK)
|
|
CHECK_UARCH(arch, 0, 4, 0, 9, NA, "Am486", UARCH_AM486, UNK)
|
|
CHECK_UARCH(arch, 0, 4, NA, NA, NA, "Am5x86", UARCH_AM5X86, UNK)
|
|
CHECK_UARCH(arch, 0, 5, 0, 6, NA, "K6", UARCH_K6, 300)
|
|
CHECK_UARCH(arch, 0, 5, 0, 7, NA, "K6", UARCH_K6, 250) // *p from sandpile.org
|
|
CHECK_UARCH(arch, 0, 5, 0, 10, NA, "K7", UARCH_K7, 130) // Geode NX
|
|
CHECK_UARCH(arch, 0, 5, 0, 13, NA, "K6", UARCH_K6, 80) // *p from sandpile.org
|
|
CHECK_UARCH(arch, 0, 5, NA, NA, NA, "K6", UARCH_K6, UNK)
|
|
CHECK_UARCH(arch, 0, 6, 0, 1, NA, "K7", UARCH_K7, 250)
|
|
CHECK_UARCH(arch, 0, 6, 0, 2, NA, "K7", UARCH_K7, 180)
|
|
CHECK_UARCH(arch, 0, 6, NA, NA, NA, "K7", UARCH_K7, UNK)
|
|
CHECK_UARCH(arch, 0, 15, 0, 4, 8, "K8", UARCH_K8, 130)
|
|
CHECK_UARCH(arch, 0, 15, 0, 4, NA, "K8", UARCH_K8, 130)
|
|
CHECK_UARCH(arch, 0, 15, 0, 5, NA, "K8", UARCH_K8, 130)
|
|
CHECK_UARCH(arch, 0, 15, 0, 7, NA, "K8", UARCH_K8, 130)
|
|
CHECK_UARCH(arch, 0, 15, 0, 8, NA, "K8", UARCH_K8, 130)
|
|
CHECK_UARCH(arch, 0, 15, 0, 11, NA, "K8", UARCH_K8, 130)
|
|
CHECK_UARCH(arch, 0, 15, 0, 12, NA, "K8", UARCH_K8, 130)
|
|
CHECK_UARCH(arch, 0, 15, 0, 14, NA, "K8", UARCH_K8, 130)
|
|
CHECK_UARCH(arch, 0, 15, 0, 15, NA, "K8", UARCH_K8, 130)
|
|
CHECK_UARCH(arch, 0, 15, 1, 4, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 1, 5, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 1, 7, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 1, 8, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 1, 11, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 1, 12, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 1, 15, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 2, 1, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 2, 3, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 2, 4, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 2, 5, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 2, 7, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 2, 11, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 2, 12, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 2, 15, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 4, 1, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 4, 3, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 4, 8, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 4, 11, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 4, 12, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 4, 15, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 5, 13, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 5, 15, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 0, 15, 6, 8, NA, "K8", UARCH_K8, 65)
|
|
CHECK_UARCH(arch, 0, 15, 6, 11, NA, "K8", UARCH_K8, 65)
|
|
CHECK_UARCH(arch, 0, 15, 6, 12, NA, "K8", UARCH_K8, 65)
|
|
CHECK_UARCH(arch, 0, 15, 6, 15, NA, "K8", UARCH_K8, 65)
|
|
CHECK_UARCH(arch, 0, 15, 7, 12, NA, "K8", UARCH_K8, 65)
|
|
CHECK_UARCH(arch, 0, 15, 7, 15, NA, "K8", UARCH_K8, 65)
|
|
CHECK_UARCH(arch, 0, 15, 12, 1, NA, "K8", UARCH_K8, 90)
|
|
CHECK_UARCH(arch, 1, 15, 0, 0, NA, "K10", UARCH_K10, 65) // sandpile.org
|
|
CHECK_UARCH(arch, 1, 15, 0, 2, NA, "K10", UARCH_K10, 65)
|
|
CHECK_UARCH(arch, 1, 15, 0, 4, NA, "K10", UARCH_K10, 45)
|
|
CHECK_UARCH(arch, 1, 15, 0, 5, NA, "K10", UARCH_K10, 45)
|
|
CHECK_UARCH(arch, 1, 15, 0, 6, NA, "K10", UARCH_K10, 45)
|
|
CHECK_UARCH(arch, 1, 15, 0, 8, NA, "K10", UARCH_K10, 45)
|
|
CHECK_UARCH(arch, 1, 15, 0, 9, NA, "K10", UARCH_K10, 45)
|
|
CHECK_UARCH(arch, 1, 15, 0, 10, NA, "K10", UARCH_K10, 45)
|
|
CHECK_UARCH(arch, 2, 15, NA, NA, NA, "Puma 2008", UARCH_PUMA_2008, 65)
|
|
CHECK_UARCH(arch, 3, 15, NA, NA, NA, "K10", UARCH_K10, 32)
|
|
CHECK_UARCH(arch, 5, 15, NA, NA, NA, "Bobcat", UARCH_BOBCAT, 40)
|
|
CHECK_UARCH(arch, 6, 15, 0, 0, NA, "Bulldozer", UARCH_BULLDOZER, 32) // instlatx64 engr sample
|
|
CHECK_UARCH(arch, 6, 15, 0, 1, NA, "Bulldozer", UARCH_BULLDOZER, 32)
|
|
CHECK_UARCH(arch, 6, 15, 0, 2, NA, "Piledriver", UARCH_PILEDRIVER, 32)
|
|
CHECK_UARCH(arch, 6, 15, 1, 0, NA, "Piledriver", UARCH_PILEDRIVER, 32)
|
|
CHECK_UARCH(arch, 6, 15, 1, 3, NA, "Piledriver", UARCH_PILEDRIVER, 32)
|
|
CHECK_UARCH(arch, 6, 15, 3, 0, NA, "Steamroller", UARCH_STEAMROLLER, 28)
|
|
CHECK_UARCH(arch, 6, 15, 3, 8, NA, "Steamroller", UARCH_STEAMROLLER, 28)
|
|
CHECK_UARCH(arch, 6, 15, 4, 0, NA, "Steamroller", UARCH_STEAMROLLER, 28) // Software Optimization Guide (15h) says it has the same iNAt latencies as (6,15),(3,x).
|
|
CHECK_UARCH(arch, 6, 15, 6, 0, NA, "Excavator", UARCH_EXCAVATOR, 28) // undocumented, but instlatx64 samples
|
|
CHECK_UARCH(arch, 6, 15, 6, 5, NA, "Excavator", UARCH_EXCAVATOR, 28) // undocumented, but sample from Alexandros Couloumbis
|
|
CHECK_UARCH(arch, 6, 15, 7, 0, NA, "Excavator", UARCH_EXCAVATOR, 28)
|
|
CHECK_UARCH(arch, 7, 15, 0, 0, NA, "Jaguar", UARCH_JAGUAR, 28)
|
|
CHECK_UARCH(arch, 7, 15, 1, NA, NA, "Jaguar", UARCH_JAGUAR, 14) // instlatx64 (PS4) Normal PS4 is 28nm, Slim and Pro are 16nm
|
|
CHECK_UARCH(arch, 7, 15, 2, 6, NA, "Jaguar", UARCH_JAGUAR, 28) // AMD Cato (Xbox One?)
|
|
CHECK_UARCH(arch, 7, 15, 3, 0, NA, "Puma 2014", UARCH_PUMA_2014, 28)
|
|
CHECK_UARCH(arch, 8, 15, 0, 0, NA, "Zen", UARCH_ZEN, 14) // instlatx64 engr sample
|
|
CHECK_UARCH(arch, 8, 15, 0, 1, NA, "Zen", UARCH_ZEN, 14)
|
|
CHECK_UARCH(arch, 8, 15, 0, 8, NA, "Zen+", UARCH_ZEN_PLUS, 12)
|
|
CHECK_UARCH(arch, 8, 15, 1, 1, NA, "Zen", UARCH_ZEN, 14) // found only on en.wikichip.org & instlatx64 examples
|
|
CHECK_UARCH(arch, 8, 15, 1, 8, NA, "Zen+", UARCH_ZEN_PLUS, 12) // found only on en.wikichip.org
|
|
CHECK_UARCH(arch, 8, 15, 2, 0, NA, "Zen", UARCH_ZEN, 14) // Dali, found on instlatx64 and en.wikichip.org
|
|
CHECK_UARCH(arch, 8, 15, 3, 1, NA, "Zen 2", UARCH_ZEN2, 7) // found only on en.wikichip.org
|
|
CHECK_UARCH(arch, 8, 15, 4, 7, NA, "Zen 2", UARCH_ZEN2, 7) // instlatx64 example (AMD 4700S)
|
|
CHECK_UARCH(arch, 8, 15, 5, 0, NA, "Zen", UARCH_ZEN, 14) // instlatx64 example (Subor Z+)
|
|
CHECK_UARCH(arch, 8, 15, 6, 0, NA, "Zen 2", UARCH_ZEN2, 7) // undocumented, geekbench.com example
|
|
CHECK_UARCH(arch, 8, 15, 6, 8, NA, "Zen 2", UARCH_ZEN2, 7) // found on instlatx64
|
|
CHECK_UARCH(arch, 8, 15, 7, 1, NA, "Zen 2", UARCH_ZEN2, 7) // samples from Steven Noonan and instlatx64
|
|
CHECK_UARCH(arch, 8, 15, 8, 4, NA, "Zen 2", UARCH_ZEN2, 7) // instlatx64 (Xbox Series X?)
|
|
CHECK_UARCH(arch, 8, 15, 9, 0, 2, "Zen 2", UARCH_ZEN2, 7) // Steam Deck (instlatx64)
|
|
CHECK_UARCH(arch, 8, 15, 10, 0, NA, "Zen 2", UARCH_ZEN2, 6) // instlatx64
|
|
CHECK_UARCH(arch, 10, 15, 0, 1, NA, "Zen 3", UARCH_ZEN3, 7) // instlatx64
|
|
CHECK_UARCH(arch, 10, 15, 0, 8, NA, "Zen 3", UARCH_ZEN3, 7) // instlatx64
|
|
CHECK_UARCH(arch, 10, 15, 1, 1, NA, "Zen 4", UARCH_ZEN4, 5) // instlatx64
|
|
CHECK_UARCH(arch, 10, 15, 1, 8, NA, "Zen 4", UARCH_ZEN4, 5) // instlatx64
|
|
CHECK_UARCH(arch, 10, 15, 2, 1, NA, "Zen 3", UARCH_ZEN3, 7) // instlatx64
|
|
CHECK_UARCH(arch, 10, 15, 3, NA, NA, "Zen 3", UARCH_ZEN3, 7) // instlatx64
|
|
CHECK_UARCH(arch, 10, 15, 4, 4, NA, "Zen 3+", UARCH_ZEN3_PLUS, 6) // instlatx64 (they say it is Zen3...)
|
|
CHECK_UARCH(arch, 10, 15, 5, 0, NA, "Zen 3", UARCH_ZEN3, 7) // instlatx64
|
|
CHECK_UARCH(arch, 10, 15, 6, 1, 2, "Zen 4", UARCH_ZEN4, 5) // instlatx64
|
|
CHECK_UARCH(arch, 10, 15, 7, 4, 1, "Zen 4", UARCH_ZEN4, 4) // instlatx64
|
|
CHECK_UARCH(arch, 10, 15, 7, 8, 0, "Zen 4", UARCH_ZEN4, 4) // instlatx64
|
|
CHECK_UARCH(arch, 10, 15, 8, NA, NA, "Zen 4", UARCH_ZEN4, 5) // instlatx64 (AMD MI300C)
|
|
CHECK_UARCH(arch, 10, 15, 9, NA, NA, "Zen 4", UARCH_ZEN4, 5) // instlatx64 (AMD MI300A)
|
|
CHECK_UARCH(arch, 10, 15, 10, NA, NA, "Zen 4c", UARCH_ZEN4C, 5) // instlatx64
|
|
UARCH_END
|
|
|
|
return arch;
|
|
}
|
|
|
|
struct uarch* get_uarch_from_cpuid(struct cpuInfo* cpu, uint32_t dump, uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s) {
|
|
if(cpu->cpu_vendor == CPU_VENDOR_INTEL) {
|
|
if(dump == 0x000806E9) {
|
|
// It is not possible to determine uarch only from CPUID dump (can be Kaby Lake or Amber Lake)
|
|
// See issue https://github.com/Dr-Noob/cpufetch/issues/122
|
|
struct uarch* arch = emalloc(sizeof(struct uarch));
|
|
|
|
if(strstr(cpu->cpu_name, "Y") != NULL) {
|
|
fill_uarch(arch, "Amber Lake", UARCH_AMBER_LAKE, 14);
|
|
}
|
|
else {
|
|
fill_uarch(arch, "Kaby Lake", UARCH_KABY_LAKE, 14);
|
|
}
|
|
|
|
return arch;
|
|
}
|
|
else if (dump == 0x000806EA) {
|
|
// It is not possible to determine uarch only from CPUID dump (can be Kaby Lake R or Coffee Lake U)
|
|
// See issue https://github.com/Dr-Noob/cpufetch/issues/149
|
|
struct uarch* arch = emalloc(sizeof(struct uarch));
|
|
|
|
if(strstr(cpu->cpu_name, "i5-8250U") != NULL ||
|
|
strstr(cpu->cpu_name, "i5-8350U") != NULL ||
|
|
strstr(cpu->cpu_name, "i7-8550U") != NULL ||
|
|
strstr(cpu->cpu_name, "i7-8650U") != NULL) {
|
|
fill_uarch(arch, "Kaby Lake", UARCH_KABY_LAKE, 14);
|
|
}
|
|
else {
|
|
fill_uarch(arch, "Coffee Lake", UARCH_COFFEE_LAKE, 14);
|
|
}
|
|
|
|
return arch;
|
|
}
|
|
return get_uarch_from_cpuid_intel(ef, f, em, m, s);
|
|
}
|
|
else
|
|
return get_uarch_from_cpuid_amd(ef, f, em, m, s);
|
|
}
|
|
|
|
bool vpus_are_AVX512(struct cpuInfo* cpu) {
|
|
return cpu->arch->uarch != UARCH_ICE_LAKE &&
|
|
cpu->arch->uarch != UARCH_TIGER_LAKE &&
|
|
cpu->arch->uarch != UARCH_ZEN4 &&
|
|
cpu->arch->uarch != UARCH_ZEN4C;
|
|
}
|
|
|
|
bool is_knights_landing(struct cpuInfo* cpu) {
|
|
return cpu->arch->uarch == UARCH_KNIGHTS_LANDING;
|
|
}
|
|
|
|
int get_number_of_vpus(struct cpuInfo* cpu) {
|
|
switch(cpu->arch->uarch) {
|
|
// Intel
|
|
case UARCH_HASWELL:
|
|
case UARCH_BROADWELL:
|
|
|
|
case UARCH_SKYLAKE:
|
|
case UARCH_CASCADE_LAKE:
|
|
case UARCH_KABY_LAKE:
|
|
case UARCH_COMET_LAKE:
|
|
case UARCH_ROCKET_LAKE:
|
|
case UARCH_AMBER_LAKE:
|
|
case UARCH_WHISKEY_LAKE:
|
|
case UARCH_COFFEE_LAKE:
|
|
case UARCH_PALM_COVE:
|
|
|
|
case UARCH_KNIGHTS_LANDING:
|
|
case UARCH_KNIGHTS_MILL:
|
|
|
|
case UARCH_ICE_LAKE:
|
|
case UARCH_TIGER_LAKE:
|
|
case UARCH_ALDER_LAKE:
|
|
case UARCH_RAPTOR_LAKE:
|
|
|
|
// AMD
|
|
case UARCH_ZEN2:
|
|
case UARCH_ZEN3:
|
|
case UARCH_ZEN3_PLUS:
|
|
case UARCH_ZEN4:
|
|
case UARCH_ZEN4C:
|
|
return 2;
|
|
default:
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
bool choose_new_intel_logo_uarch(struct cpuInfo* cpu) {
|
|
switch(cpu->arch->uarch) {
|
|
case UARCH_ALDER_LAKE:
|
|
case UARCH_ROCKET_LAKE:
|
|
case UARCH_TIGER_LAKE:
|
|
case UARCH_RAPTOR_LAKE:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
char* get_str_uarch(struct cpuInfo* cpu) {
|
|
return cpu->arch->uarch_str;
|
|
}
|
|
|
|
char* get_str_process(struct cpuInfo* cpu) {
|
|
char* str = emalloc(sizeof(char) * (strlen(STRING_UNKNOWN)+1));
|
|
int32_t process = cpu->arch->process;
|
|
|
|
if(process == UNK) {
|
|
snprintf(str, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN);
|
|
}
|
|
else if(process > 100) {
|
|
sprintf(str, "%.2fum", (double)process/100);
|
|
}
|
|
else if(process > 0){
|
|
sprintf(str, "%dnm", process);
|
|
}
|
|
else {
|
|
snprintf(str, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN);
|
|
printBug("Found invalid process: '%d'", process);
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
void free_uarch_struct(struct uarch* arch) {
|
|
free(arch->uarch_str);
|
|
free(arch);
|
|
}
|