Compare commits

..

12 Commits
testk ... hygon

17 changed files with 540 additions and 142 deletions

View File

@@ -32,8 +32,8 @@ ifneq ($(OS),Windows_NT)
CFLAGS += -DARCH_PPC -std=gnu99 -fstack-protector-all -Wno-language-extension-token
else ifeq ($(arch), $(filter $(arch), arm aarch64_be aarch64 arm64 armv8b armv8l armv7l armv6l))
SRC_DIR=src/arm/
SOURCE += $(COMMON_SRC) $(SRC_DIR)midr.c $(SRC_DIR)uarch.c $(SRC_COMMON)soc.c $(SRC_DIR)soc.c $(SRC_DIR)udev.c
HEADERS += $(COMMON_HDR) $(SRC_DIR)midr.h $(SRC_DIR)uarch.h $(SRC_COMMON)soc.h $(SRC_DIR)soc.h $(SRC_DIR)udev.c $(SRC_DIR)socs.h
SOURCE += $(COMMON_SRC) $(SRC_DIR)midr.c $(SRC_DIR)uarch.c $(SRC_COMMON)soc.c $(SRC_DIR)soc.c $(SRC_COMMON)pci.c $(SRC_DIR)udev.c
HEADERS += $(COMMON_HDR) $(SRC_DIR)midr.h $(SRC_DIR)uarch.h $(SRC_COMMON)soc.h $(SRC_DIR)soc.h $(SRC_COMMON)pci.h $(SRC_DIR)udev.c $(SRC_DIR)socs.h
CFLAGS += -DARCH_ARM -Wno-unused-parameter -std=c99 -fstack-protector-all
os := $(shell uname -s)

View File

@@ -8,6 +8,7 @@
#include "udev.h"
#include "uarch.h"
#include "../common/global.h"
#include "../common/pci.h"
#if defined(__APPLE__) || defined(__MACH__)
#include "sysctl.h"
@@ -834,6 +835,43 @@ struct system_on_chip* guess_soc_from_uarch(struct system_on_chip* soc, struct c
return soc;
}
struct system_on_chip* guess_soc_from_pci(struct system_on_chip* soc, struct cpuInfo* cpu) {
struct pci_devices * pci = get_pci_devices();
if (pci == NULL) {
printWarn("guess_soc_from_pci: Unable to find suitable PCI devices");
return soc;
}
typedef struct {
uint16_t vendor_id;
uint16_t device_id;
struct system_on_chip soc;
} pciToSoC;
pciToSoC socFromPCI[] = {
{PCI_VENDOR_NVIDIA, PCI_DEVICE_TEGRA_X1, {SOC_TEGRA_X1, SOC_VENDOR_NVIDIA, 20, "Tegra X1", NULL} },
// {PCI_VENDOR_NVIDIA, PCI_DEVICE_GH_200,{SOC_GH_200, SOC_VENDOR_NVIDIA, ?, "Grace Hopper", NULL} },
{0x0000, 0x0000, {UNKNOWN, SOC_VENDOR_UNKNOWN, -1, "", NULL} }
};
int index = 0;
while (socFromPCI[index].vendor_id != 0x0) {
for (int i=0; i < pci->num_devices; i++) {
struct pci_device * dev = pci->devices[i];
if (socFromPCI[index].vendor_id == dev->vendor_id &&
socFromPCI[index].device_id == dev->device_id) {
fill_soc(soc, socFromPCI[index].soc.soc_name, socFromPCI[index].soc.soc_model, socFromPCI[index].soc.process);
return soc;
}
}
index++;
}
printWarn("guess_soc_from_pci: No PCI device matched the list");
return soc;
}
int hex2int(char c) {
if (c >= '0' && c <= '9')
return c - '0';
@@ -1004,14 +1042,18 @@ struct system_on_chip* get_soc(struct cpuInfo* cpu) {
printWarn("SoC detection failed using Android: Found '%s' string", soc->raw_name);
}
#endif // ifdef __ANDROID__
// If cpufinfo/Android (if available) detection fails, try with nvmem
// If previous steps failed, try with nvmem
if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) {
soc = guess_soc_from_nvmem(soc);
}
// If everything else failed, try infering it from the microarchitecture
// If previous steps failed, try infering it from the microarchitecture
if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) {
soc = guess_soc_from_uarch(soc, cpu);
}
// If previous steps failed, try infering it from the pci device id
if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) {
soc = guess_soc_from_pci(soc, cpu);
}
}
#elif defined __APPLE__ || __MACH__
soc = guess_soc_apple(soc);

View File

@@ -363,6 +363,8 @@ enum {
SOC_GOOGLE_TENSOR,
SOC_GOOGLE_TENSOR_G2,
SOC_GOOGLE_TENSOR_G3,
// NVIDIA,
SOC_TEGRA_X1,
// UNKNOWN
SOC_MODEL_UNKNOWN
};
@@ -378,6 +380,7 @@ inline static VENDOR get_soc_vendor_from_soc(SOC soc) {
else if(soc >= SOC_ALLWINNER_A10 && soc <= SOC_ALLWINNER_R328) return SOC_VENDOR_ALLWINNER;
else if(soc >= SOC_ROCKCHIP_3288 && soc <= SOC_ROCKCHIP_3588) return SOC_VENDOR_ROCKCHIP;
else if(soc >= SOC_GOOGLE_TENSOR && soc <= SOC_GOOGLE_TENSOR_G3) return SOC_VENDOR_GOOGLE;
else if(soc >= SOC_TEGRA_X1 && soc <= SOC_TEGRA_X1) return SOC_VENDOR_NVIDIA;
return SOC_VENDOR_UNKNOWN;
}

View File

@@ -324,6 +324,8 @@ int get_number_of_vpus(struct cpuInfo* cpu) {
return 3;
case UARCH_ICESTORM: // [https://dougallj.github.io/applecpu/icestorm-simd.html]
case UARCH_BLIZZARD: // [https://en.wikipedia.org/wiki/Comparison_of_ARM_processors]
case UARCH_TAISHAN_V110:// [https://www-file.huawei.com/-/media/corp2020/pdf/publications/huawei-research/2022/huawei-research-issue1-en.pdf]: "128-bit x 2 for single precision"
case UARCH_TAISHAN_V200:// Not confirmed, asssuming same as v110
case UARCH_CORTEX_A57: // [https://www.anandtech.com/show/8718/the-samsung-galaxy-note-4-exynos-review/5]
case UARCH_CORTEX_A72: // [https://www.anandtech.com/show/10347/arm-cortex-a73-artemis-unveiled/2]
case UARCH_CORTEX_A73: // [https://www.anandtech.com/show/10347/arm-cortex-a73-artemis-unveiled/2]

View File

@@ -105,6 +105,19 @@ $C1 MMM :MMM NMM dMMK dMMX MMN \
$C1 MMM :MMM NMM dMMMoo OMM0....:Nx. MMN \
$C1 MMM :WWW XWW lONMM 'xXMMMMNOc MMN "
#define ASCII_HYGON \
"$C1 \
$C1 \
$C1 \
$C1 ## ## ## ## ###### ###### ## # \
$C1 ##....## ## ## ## ## ## #### # \
$C1 ######## ## ## ##. ## ## # #### \
$C1 ## ## ## *######. ###### # ## \
$C1 \
$C1 \
$C1 \
$C1 "
#define ASCII_SNAPD \
" $C1@@$C2######## \
$C1@@@@@$C2########### \
@@ -360,6 +373,27 @@ $C1##########@@@@@@@@@@@@@@@@############## \
$C1######################################## \
$C1 #################################### "
#define ASCII_NVIDIA \
"$C1 'cccccccccccccccccccccccccc \
$C1 ;oooooooooooooooooooooooool \
$C1 .:::. .oooooooooooooooooool \
$C1 .:cll; ,c:::. cooooooooooooool \
$C1 ,clo' ;. oolc: ooooooooooool \
$C1.cloo ;cclo . .olc. coooooooool \
$C1oooo :lo, ;ll; looc :oooooooool \
$C1 oooc ool. ;oooc;clol :looooooooool \
$C1 :ooc ,ol; ;oooooo. .cloo; loool \
$C1 ool; .olc. ,:lool .lool \
$C1 ool:. ,::::ccloo. :clooool \
$C1 oolc::. ':cclooooooool \
$C1 ;oooooooooooooooooooooooool \
$C1 \
$C1 \
$C2######. ## ## ## ###### ## ### \
$C2## ## ## ## ## ## ## ## #: :# \
$C2## ## ## ## ## ## ## ## ####### \
$C2## ## ### ## ###### ## ## ## "
// --------------------- LONG LOGOS ------------------------- //
#define ASCII_AMD_L \
"$C1 \
@@ -492,6 +526,23 @@ $C1 ###########. ############ \
$C1 ################ \
$C1 ####### "
#define ASCII_NVIDIA_L \
"$C1 MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM \
$C1 MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM \
$C1 .:: 'MMMMMMMMMMMMMMMMMMMMMMMMM \
$C1 ccllooo;:;. ;MMMMMMMMMMMMMMMMMM \
$C1 cloc :ooollcc: :MMMMMMMMMMMMMMM \
$C1 cloc :ccl; lolc, ;MMMMMMMMMMMM \
$C1.cloo: :clo ;c: .ool; MMMMMMMMMMM \
$C1 ooo: ooo :ool, .cloo. ;lMMMMMMMMMMM \
$C1 ooo: ooc :ooooccooo. :MMMM lMMMMMMM \
$C1 ooc. ool: :oooooo' ,cloo. MMMM \
$C1 ool:. olc: .:cloo. :MMMM \
$C1 olc, ;:::cccloo. :MMMMMMMM \
$C1 olcc::; ,:ccloMMMMMMMMM \
$C1 :......oMMMMMMMMMMMMMMMMMMMMMM \
$C1 :lllMMMMMMMMMMMMMMMMMMMMMMMMMM "
typedef struct ascii_logo asciiL;
// +-----------------------------------------------------------------------------------------------------------------+
@@ -500,6 +551,7 @@ typedef struct ascii_logo asciiL;
asciiL logo_amd = { ASCII_AMD, 39, 15, false, {C_FG_WHITE, C_FG_GREEN}, {C_FG_WHITE, C_FG_GREEN} };
asciiL logo_intel = { ASCII_INTEL, 48, 14, false, {C_FG_CYAN}, {C_FG_CYAN, C_FG_WHITE} };
asciiL logo_intel_new = { ASCII_INTEL_NEW, 51, 9, false, {C_FG_CYAN}, {C_FG_CYAN, C_FG_WHITE} };
asciiL logo_hygon = { ASCII_HYGON, 51, 11, false, {C_FG_RED}, {C_FG_RED, C_FG_WHITE} };
asciiL logo_snapd = { ASCII_SNAPD, 39, 16, false, {C_FG_RED, C_FG_WHITE}, {C_FG_RED, C_FG_WHITE} };
asciiL logo_mtk = { ASCII_MTK, 59, 5, false, {C_FG_BLUE, C_FG_YELLOW}, {C_FG_BLUE, C_FG_YELLOW} };
asciiL logo_exynos = { ASCII_EXYNOS, 22, 13, true, {C_BG_BLUE, C_FG_WHITE}, {C_FG_BLUE, C_FG_WHITE} };
@@ -516,6 +568,7 @@ asciiL logo_riscv = { ASCII_RISCV, 63, 18, false, {C_FG_CYAN, C_FG_Y
asciiL logo_sifive = { ASCII_SIFIVE, 48, 19, true, {C_BG_WHITE, C_BG_BLACK}, {C_FG_WHITE, C_FG_BLUE} };
asciiL logo_starfive = { ASCII_STARFIVE, 33, 17, false, {C_FG_WHITE}, {C_FG_WHITE, C_FG_BLUE} };
asciiL logo_sipeed = { ASCII_SIPEED, 41, 16, true, {C_BG_RED, C_BG_WHITE}, {C_FG_RED, C_FG_WHITE} };
asciiL logo_nvidia = { ASCII_NVIDIA, 45, 19, false, {C_FG_GREEN, C_FG_WHITE}, {C_FG_WHITE, C_FG_GREEN} };
// Long variants | ----------------------------------------------------------------------------------------------------------------|
asciiL logo_amd_l = { ASCII_AMD_L, 62, 19, true, {C_BG_WHITE, C_BG_GREEN}, {C_FG_WHITE, C_FG_GREEN} };
@@ -525,6 +578,7 @@ asciiL logo_arm_l = { ASCII_ARM_L, 60, 8, true, {C_BG_CYAN},
asciiL logo_ibm_l = { ASCII_IBM_L, 62, 13, true, {C_BG_CYAN, C_FG_WHITE}, {C_FG_CYAN, C_FG_WHITE} };
asciiL logo_starfive_l = { ASCII_STARFIVE_L, 50, 22, false, {C_FG_WHITE}, {C_FG_WHITE, C_FG_BLUE} };
asciiL logo_sifive_l = { ASCII_SIFIVE_L, 53, 21, true, {C_BG_WHITE, C_BG_BLACK}, {C_FG_WHITE, C_FG_CYAN} };
asciiL logo_nvidia_l = { ASCII_NVIDIA_L, 50, 15, false, {C_FG_GREEN, C_FG_WHITE}, {C_FG_WHITE, C_FG_GREEN} };
asciiL logo_unknown = { NULL, 0, 0, false, {COLOR_NONE}, {COLOR_NONE, COLOR_NONE} };
#endif

View File

@@ -8,6 +8,7 @@ enum {
// ARCH_X86
CPU_VENDOR_INTEL,
CPU_VENDOR_AMD,
CPU_VENDOR_HYGON,
// ARCH_ARM
CPU_VENDOR_ARM,
CPU_VENDOR_APPLE,
@@ -32,6 +33,7 @@ enum {
enum {
HV_VENDOR_KVM,
HV_VENDOR_QEMU,
HV_VENDOR_VBOX,
HV_VENDOR_HYPERV,
HV_VENDOR_VMWARE,
HV_VENDOR_XEN,

View File

@@ -21,7 +21,7 @@
#endif
#ifdef ARCH_X86
static const char* ARCH_STR = "x86_64 build";
static const char* ARCH_STR = "x86 / x86_64 build";
#include "../x86/cpuid.h"
#elif ARCH_PPC
static const char* ARCH_STR = "PowerPC build";

178
src/common/pci.c Normal file
View File

@@ -0,0 +1,178 @@
#define _GNU_SOURCE
#include <sys/stat.h>
#include <dirent.h>
#include "udev.h"
#include "global.h"
#include "pci.h"
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
#define PCI_PATH "/sys/bus/pci/devices/"
#define MAX_LENGTH_PCI_DIR_NAME 1024
/*
* doc: https://wiki.osdev.org/PCI#Class_Codes
* https://pci-ids.ucw.cz/read/PC
*/
#define PCI_VENDOR_ID_AMD 0x1002
#define CLASS_VGA_CONTROLLER 0x0300
#define CLASS_3D_CONTROLLER 0x0302
// Return a list of PCI devices containing only
// the sysfs path
struct pci_devices * get_pci_paths(void) {
DIR *dirp;
if ((dirp = opendir(PCI_PATH)) == NULL) {
perror("opendir");
return NULL;
}
struct dirent *dp;
int numDirs = 0;
errno = 0;
while ((dp = readdir(dirp)) != NULL) {
if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0)
numDirs++;
}
if (errno != 0) {
perror("readdir");
return NULL;
}
rewinddir(dirp);
struct pci_devices * pci = emalloc(sizeof(struct pci_devices));
pci->num_devices = numDirs;
pci->devices = emalloc(sizeof(struct pci_device) * pci->num_devices);
char * full_path = emalloc(PATH_MAX * sizeof(char));
struct stat stbuf;
int i = 0;
while ((dp = readdir(dirp)) != NULL) {
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
continue;
if (strlen(dp->d_name) > MAX_LENGTH_PCI_DIR_NAME) {
printErr("Directory name is too long: %s", dp->d_name);
return NULL;
}
memset(full_path, 0, PATH_MAX * sizeof(char));
snprintf(full_path, min(strlen(PCI_PATH) + strlen(dp->d_name) + 1, PATH_MAX), "%s%s", PCI_PATH, dp->d_name);
if (stat(full_path, &stbuf) == -1) {
perror("stat");
return NULL;
}
if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
int strLen = min(MAX_LENGTH_PCI_DIR_NAME, strlen(dp->d_name)) + 1;
pci->devices[i] = emalloc(sizeof(struct pci_device));
pci->devices[i]->path = ecalloc(sizeof(char), strLen);
strncpy(pci->devices[i]->path, dp->d_name, strLen);
i++;
}
}
if (errno != 0) {
perror("readdir");
return NULL;
}
return pci;
}
// For each PCI device in the list pci, fetch its vendor and
// device id using sysfs (e.g., /sys/bus/pci/devices/XXX/{vendor/device})
void populate_pci_devices(struct pci_devices * pci) {
int filelen;
char* buf;
for (int i=0; i < pci->num_devices; i++) {
struct pci_device* dev = pci->devices[i];
int path_size = strlen(PCI_PATH) + strlen(dev->path) + 2;
// Read vendor_id
char *vendor_id_path = emalloc(sizeof(char) * (path_size + strlen("vendor")));
sprintf(vendor_id_path, "%s/%s/%s", PCI_PATH, dev->path, "vendor");
if ((buf = read_file(vendor_id_path, &filelen)) == NULL) {
printWarn("read_file: %s: %s\n", vendor_id_path, strerror(errno));
dev->vendor_id = 0;
}
else {
dev->vendor_id = strtol(buf, NULL, 16);
}
// Read device_id
char *device_id_path = emalloc(sizeof(char) * (path_size + strlen("device")));
sprintf(device_id_path, "%s/%s/%s", PCI_PATH, dev->path, "device");
if ((buf = read_file(device_id_path, &filelen)) == NULL) {
printWarn("read_file: %s: %s\n", device_id_path, strerror(errno));
dev->device_id = 0;
}
else {
dev->device_id = strtol(buf, NULL, 16);
}
free(vendor_id_path);
free(device_id_path);
}
}
// Right now, we are interested in PCI devices which
// vendor is NVIDIA (to be extended in the future).
// Should we also restrict to VGA controllers only?
bool pci_device_is_useful(struct pci_device* dev) {
return dev->vendor_id == PCI_VENDOR_NVIDIA;
}
// Filter the input list in order to get only those PCI devices which
// we are interested in (decided by pci_device_is_useful)
// and return the filtered result.
struct pci_devices * filter_pci_devices(struct pci_devices * pci) {
int * devices_to_get = emalloc(sizeof(int) * pci->num_devices);
int dev_ptr = 0;
for (int i=0; i < pci->num_devices; i++) {
if (pci_device_is_useful(pci->devices[i])) {
devices_to_get[dev_ptr] = i;
dev_ptr++;
}
}
struct pci_devices * pci_filtered = emalloc(sizeof(struct pci_devices));
pci_filtered->num_devices = dev_ptr;
if (pci_filtered->num_devices == 0) {
pci_filtered->devices = NULL;
}
else {
pci_filtered->devices = emalloc(sizeof(struct pci_device) * pci_filtered->num_devices);
for (int i=0; i < pci_filtered->num_devices; i++)
pci_filtered->devices[i] = pci->devices[devices_to_get[i]];
}
return pci_filtered;
}
// Return a list of PCI devices that could be used to infer the SoC.
// The criteria to determine which devices are suitable for this task
// is decided in filter_pci_devices.
struct pci_devices * get_pci_devices(void) {
struct pci_devices * pci = get_pci_paths();
if (pci == NULL)
return NULL;
populate_pci_devices(pci);
return filter_pci_devices(pci);
}

20
src/common/pci.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef __PCI__
#define __PCI__
#define PCI_VENDOR_NVIDIA 0x10de
#define PCI_DEVICE_TEGRA_X1 0x0faf
struct pci_device {
char * path;
uint16_t vendor_id;
uint16_t device_id;
};
struct pci_devices {
struct pci_device ** devices;
int num_devices;
};
struct pci_devices * get_pci_devices(void);
#endif

View File

@@ -336,6 +336,13 @@ struct ascii_logo* choose_ascii_art_aux(struct ascii_logo* logo_long, struct asc
}
}
// https://no-color.org/
bool is_color_enabled(void) {
const char *var_name = "NO_COLOR";
char *no_color = getenv(var_name);
return no_color == NULL || no_color[0] == '\0';
}
void choose_ascii_art(struct ascii* art, struct color** cs, struct terminal* term, int lf) {
// 1. Choose logo
#ifdef ARCH_X86
@@ -350,6 +357,9 @@ void choose_ascii_art(struct ascii* art, struct color** cs, struct terminal* ter
else if(art->vendor == CPU_VENDOR_AMD) {
art->art = choose_ascii_art_aux(&logo_amd_l, &logo_amd, term, lf);
}
else if(art->vendor == CPU_VENDOR_HYGON) {
art->art = &logo_hygon;
}
else {
art->art = &logo_unknown;
}
@@ -376,6 +386,8 @@ void choose_ascii_art(struct ascii* art, struct color** cs, struct terminal* ter
art->art = &logo_allwinner;
else if(art->vendor == SOC_VENDOR_ROCKCHIP)
art->art = &logo_rockchip;
else if(art->vendor == SOC_VENDOR_NVIDIA)
art->art = choose_ascii_art_aux(&logo_nvidia_l, &logo_nvidia, term, lf);
else {
art->art = choose_ascii_art_aux(&logo_arm_l, &logo_arm, term, lf);
}
@@ -394,6 +406,9 @@ void choose_ascii_art(struct ascii* art, struct color** cs, struct terminal* ter
// 2. Choose colors
struct ascii_logo* logo = art->art;
bool color = is_color_enabled();
if (!color)
art->style = STYLE_LEGACY;
switch(art->style) {
case STYLE_LEGACY:

View File

@@ -20,6 +20,7 @@ static char* soc_trademark_string[] = {
[SOC_VENDOR_APPLE] = "Apple ",
[SOC_VENDOR_ROCKCHIP] = "Rockchip ",
[SOC_VENDOR_GOOGLE] = "Google ",
[SOC_VENDOR_NVIDIA] = "NVIDIA ",
// RISC-V
[SOC_VENDOR_SIFIVE] = "SiFive ",
[SOC_VENDOR_STARFIVE] = "StarFive ",

View File

@@ -24,6 +24,7 @@ enum {
SOC_VENDOR_APPLE,
SOC_VENDOR_ROCKCHIP,
SOC_VENDOR_GOOGLE,
SOC_VENDOR_NVIDIA,
// RISC-V
SOC_VENDOR_SIFIVE,
SOC_VENDOR_STARFIVE,

View File

@@ -14,6 +14,7 @@
static char *hv_vendors_name[] = {
[HV_VENDOR_KVM] = "KVM",
[HV_VENDOR_QEMU] = "QEMU",
[HV_VENDOR_VBOX] = "VirtualBox",
[HV_VENDOR_HYPERV] = "Microsoft Hyper-V",
[HV_VENDOR_VMWARE] = "VMware",
[HV_VENDOR_XEN] = "Xen",

View File

@@ -280,9 +280,6 @@ char* get_str_process(struct cpuInfo* cpu) {
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);
}

View File

@@ -22,10 +22,12 @@
#define CPU_VENDOR_INTEL_STRING "GenuineIntel"
#define CPU_VENDOR_AMD_STRING "AuthenticAMD"
#define CPU_VENDOR_HYGON_STRING "HygonGenuine"
static const char *hv_vendors_string[] = {
[HV_VENDOR_KVM] = "KVMKVMKVM",
[HV_VENDOR_QEMU] = "TCGTCGTCGTCG",
[HV_VENDOR_VBOX] = "VBoxVBoxVBox",
[HV_VENDOR_HYPERV] = "Microsoft Hv",
[HV_VENDOR_VMWARE] = "VMwareVMware",
[HV_VENDOR_XEN] = "XenVMMXenVMM",
@@ -38,6 +40,7 @@ static const char *hv_vendors_string[] = {
static char *hv_vendors_name[] = {
[HV_VENDOR_KVM] = "KVM",
[HV_VENDOR_QEMU] = "QEMU",
[HV_VENDOR_VBOX] = "VirtualBox",
[HV_VENDOR_HYPERV] = "Microsoft Hyper-V",
[HV_VENDOR_VMWARE] = "VMware",
[HV_VENDOR_XEN] = "Xen",
@@ -468,6 +471,8 @@ struct cpuInfo* get_cpu_info(void) {
cpu->cpu_vendor = CPU_VENDOR_INTEL;
else if (strcmp(CPU_VENDOR_AMD_STRING,name) == 0)
cpu->cpu_vendor = CPU_VENDOR_AMD;
else if (strcmp(CPU_VENDOR_HYGON_STRING,name) == 0)
cpu->cpu_vendor = CPU_VENDOR_HYGON;
else {
cpu->cpu_vendor = CPU_VENDOR_INVALID;
printErr("Unknown CPU vendor: %s", name);
@@ -486,9 +491,8 @@ struct cpuInfo* get_cpu_info(void) {
cpu->cpu_name = get_str_cpu_name_internal();
}
else {
cpu->cpu_name = emalloc(sizeof(char) * (strlen(STRING_UNKNOWN) + 1));
strcpy(cpu->cpu_name, STRING_UNKNOWN);
printWarn("Can't read cpu name from cpuid (needed extended level is 0x%.8X, max is 0x%.8X)", 0x80000004, cpu->maxExtendedLevels);
cpu->cpu_name = NULL;
printWarn("Can't read CPU name from cpuid (needed extended level is 0x%.8X, max is 0x%.8X)", 0x80000004, cpu->maxExtendedLevels);
}
cpu->topology_extensions = false;
@@ -538,12 +542,17 @@ struct cpuInfo* get_cpu_info(void) {
ptr->first_core_id = first_core;
ptr->feat = get_features_info(ptr);
// If any field of the struct is NULL,
// return inmideately, as further functions
// require valid fields (cach, topo, etc)
ptr->arch = get_cpu_uarch(ptr);
ptr->freq = get_frequency_info(ptr);
if (cpu->cpu_name == NULL && ptr == cpu) {
// If we couldnt read CPU name from cpuid, infer it now
cpu->cpu_name = infer_cpu_name_from_uarch(cpu->arch);
}
// If any field of the struct is NULL,
// return early, as next functions
// require non NULL fields in cach and topo
ptr->cach = get_cache_info(ptr);
if(ptr->cach == NULL) return cpu;
@@ -712,6 +721,7 @@ struct topology* get_topology_info(struct cpuInfo* cpu, struct cache* cach, int
}
break;
case CPU_VENDOR_AMD:
case CPU_VENDOR_HYGON:
if (cpu->maxExtendedLevels >= 0x80000008) {
eax = 0x80000008;
cpuid(&eax, &ebx, &ecx, &edx);

View File

@@ -48,7 +48,9 @@ enum {
UARCH_UNKNOWN,
// INTEL //
UARCH_P5,
UARCH_P6,
UARCH_P5_MMX,
UARCH_P6_PENTIUM_II,
UARCH_P6_PENTIUM_III,
UARCH_DOTHAN,
UARCH_YONAH,
UARCH_MEROM,
@@ -139,128 +141,128 @@ void fill_uarch(struct uarch* arch, char* str, MICROARCH u, uint32_t process) {
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 //
// 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, 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_MMX, UNK)
CHECK_UARCH(arch, 0, 5, 0, 7, NA, "P5 (MMX)", UARCH_P5_MMX, UNK)
CHECK_UARCH(arch, 0, 5, 0, 8, NA, "P5 (MMX)", UARCH_P5_MMX, 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_MMX, 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_PENTIUM_II, UNK)
CHECK_UARCH(arch, 0, 6, 0, 1, NA, "P6 (Pentium II)", UARCH_P6_PENTIUM_II, UNK) // process depends on core
CHECK_UARCH(arch, 0, 6, 0, 2, NA, "P6 (Pentium II)", UARCH_P6_PENTIUM_II, UNK)
CHECK_UARCH(arch, 0, 6, 0, 3, NA, "P6 (Klamath)", UARCH_P6_PENTIUM_II, 350) // http://instlatx64.atw.hu.
CHECK_UARCH(arch, 0, 6, 0, 4, NA, "P6 (Pentium II)", UARCH_P6_PENTIUM_II, UNK)
CHECK_UARCH(arch, 0, 6, 0, 5, NA, "P6 (Deschutes)", UARCH_P6_PENTIUM_II, 250) // http://instlatx64.atw.hu.
CHECK_UARCH(arch, 0, 6, 0, 6, NA, "P6 (Dixon)", UARCH_P6_PENTIUM_II, UNK) // http://instlatx64.atw.hu.
CHECK_UARCH(arch, 0, 6, 0, 7, NA, "P6 (Katmai)", UARCH_P6_PENTIUM_III, 250) // Core names from: https://en.wikichip.org/wiki/intel/cpuid. NOTE: Xeon core names are different! https://www.techpowerup.com/cpu-specs/?generation=Intel+Pentium+III+Xeon
CHECK_UARCH(arch, 0, 6, 0, 8, NA, "P6 (Coppermine)", UARCH_P6_PENTIUM_III, 180) // Also: https://en.wikipedia.org/wiki/Pentium_III
CHECK_UARCH(arch, 0, 6, 0, 9, NA, "P6 (Pentium M)", UARCH_P6_PENTIUM_III, 130)
CHECK_UARCH(arch, 0, 6, 0, 10, NA, "P6 (Coppermine T)", UARCH_P6_PENTIUM_III, 180)
CHECK_UARCH(arch, 0, 6, 0, 11, NA, "P6 (Tualatin)", UARCH_P6_PENTIUM_III, 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)
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;
}
@@ -380,6 +382,7 @@ struct uarch* get_uarch_from_cpuid_amd(uint32_t ef, uint32_t f, uint32_t em, uin
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, 5, 2, "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)
@@ -389,13 +392,37 @@ struct uarch* get_uarch_from_cpuid_amd(uint32_t ef, uint32_t f, uint32_t em, uin
return arch;
}
struct uarch* get_uarch_from_cpuid_hygon(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
// https://www.phoronix.com/news/Hygon-Dhyana-AMD-China-CPUs
CHECK_UARCH(arch, 9, 15, 0, 1, NA, "Zen", UARCH_ZEN, UNK) // https://github.com/Dr-Noob/cpufetch/issues/244
// CHECK_UARCH(arch, 9, 15, 0, 2, NA, "???", ?????????, UNK) // http://instlatx64.atw.hu/
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) {
struct uarch* arch = emalloc(sizeof(struct uarch));
if(dump == 0x000806E9) {
if (cpu->cpu_name == NULL) {
printErr("Unable to find uarch without CPU name");
fill_uarch(arch, STRING_UNKNOWN, UARCH_UNKNOWN, UNK);
return arch;
}
// 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);
}
@@ -406,10 +433,14 @@ struct uarch* get_uarch_from_cpuid(struct cpuInfo* cpu, uint32_t dump, uint32_t
return arch;
}
else if (dump == 0x000806EA) {
if (cpu->cpu_name == NULL) {
printErr("Unable to find uarch without CPU name");
fill_uarch(arch, STRING_UNKNOWN, UARCH_UNKNOWN, UNK);
return arch;
}
// 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 ||
@@ -424,8 +455,51 @@ struct uarch* get_uarch_from_cpuid(struct cpuInfo* cpu, uint32_t dump, uint32_t
}
return get_uarch_from_cpuid_intel(ef, f, em, m, s);
}
else
else if(cpu->cpu_vendor == CPU_VENDOR_AMD) {
return get_uarch_from_cpuid_amd(ef, f, em, m, s);
}
else if(cpu->cpu_vendor == CPU_VENDOR_HYGON) {
return get_uarch_from_cpuid_hygon(ef, f, em, m, s);
}
else {
printBug("Invalid CPU vendor: %d", cpu->cpu_vendor);
return NULL;
}
}
// If we cannot get the CPU name from CPUID, try to infer it from uarch
char* infer_cpu_name_from_uarch(struct uarch* arch) {
char* cpu_name = NULL;
if (arch == NULL) {
printErr("infer_cpu_name_from_uarch: Unable to find CPU name");
cpu_name = ecalloc(strlen(STRING_UNKNOWN) + 1, sizeof(char));
strcpy(cpu_name, STRING_UNKNOWN);
return cpu_name;
}
char *str = NULL;
if (arch->uarch == UARCH_P5)
str = "Intel Pentium";
else if (arch->uarch == UARCH_P5_MMX)
str = "Intel Pentium MMX";
else if (arch->uarch == UARCH_P6_PENTIUM_II)
str = "Intel Pentium II";
else if (arch->uarch == UARCH_P6_PENTIUM_III)
str = "Intel Pentium III";
else
printErr("Unable to find name from uarch: %d", arch->uarch);
if (str == NULL) {
cpu_name = ecalloc(strlen(STRING_UNKNOWN) + 1, sizeof(char));
strcpy(cpu_name, STRING_UNKNOWN);
}
else {
cpu_name = ecalloc(strlen(str) + 1, sizeof(char));
strcpy(cpu_name, str);
}
return cpu_name;
}
bool vpus_are_AVX512(struct cpuInfo* cpu) {
@@ -498,9 +572,6 @@ char* get_str_process(struct cpuInfo* cpu) {
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);
}

View File

@@ -8,6 +8,7 @@
struct uarch;
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);
char* infer_cpu_name_from_uarch(struct uarch* arch);
bool vpus_are_AVX512(struct cpuInfo* cpu);
bool is_knights_landing(struct cpuInfo* cpu);
int get_number_of_vpus(struct cpuInfo* cpu);