From a8d8ac2e91cc55bf888465c4342faa41d2e56cb3 Mon Sep 17 00:00:00 2001 From: Dr-Noob Date: Sat, 6 Mar 2021 22:13:32 +0100 Subject: [PATCH 1/5] [v0.95] Temporarily disable cache sanity checks --- src/x86/cpuid.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/x86/cpuid.c b/src/x86/cpuid.c index 3609149..8d41a15 100755 --- a/src/x86/cpuid.c +++ b/src/x86/cpuid.c @@ -313,7 +313,10 @@ struct cpuInfo* get_cpu_info() { cpu->freq = get_frequency_info(cpu); cpu->cach = get_cache_info(cpu); cpu->topo = get_topology_info(cpu, cpu->cach); - + + if(cpu->cach == NULL || cpu->topo == NULL) { + return NULL; + } return cpu; } @@ -622,36 +625,36 @@ struct cache* get_cache_info(struct cpuInfo* cpu) { cach = get_cache_info_general(cach, level); } } - + // Sanity checks. If we read values greater than this, they can't be valid ones // The values were chosen by me if(cach->L1i->size > 64 * 1024) { printBug("Invalid L1i size: %dKB", cach->L1i->size/1024); - return NULL; + //return NULL; } if(cach->L1d->size > 64 * 1024) { printBug("Invalid L1d size: %dKB", cach->L1d->size/1024); - return NULL; + //return NULL; } if(cach->L2->exists) { if(cach->L3->exists && cach->L2->size > 2 * 1048576) { printBug("Invalid L2 size: %dMB", cach->L2->size/(1048576)); - return NULL; + //return NULL; } else if(cach->L2->size > 100 * 1048576) { printBug("Invalid L2 size: %dMB", cach->L2->size/(1048576)); - return NULL; + //return NULL; } } if(cach->L3->exists && cach->L3->size > 100 * 1048576) { printBug("Invalid L3 size: %dMB", cach->L3->size/(1048576)); - return NULL; + //return NULL; } if(!cach->L2->exists) { printBug("Could not find L2 cache"); - return NULL; + //return NULL; } - + return cach; } From db32cccd91964ba9720ea388ba054820baefac9b Mon Sep 17 00:00:00 2001 From: Dr-Noob Date: Mon, 15 Mar 2021 21:49:47 +0100 Subject: [PATCH 2/5] [v0.95] Add --raw option --- src/common/args.c | 15 +++++++++++ src/common/args.h | 1 + src/common/main.c | 11 ++++++-- src/x86/apic.h | 4 +++ src/x86/cpuid.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++ src/x86/cpuid.h | 1 + 6 files changed, 98 insertions(+), 2 deletions(-) diff --git a/src/common/args.c b/src/common/args.c index 577d931..74b738e 100644 --- a/src/common/args.c +++ b/src/common/args.c @@ -20,6 +20,7 @@ static const char *SYTLES_STR_LIST[] = { enum { ARG_CHAR_STYLE, ARG_CHAR_COLOR, + ARG_CHAR_RAW, ARG_CHAR_HELP, ARG_CHAR_DEBUG, ARG_CHAR_VERBOSE, @@ -29,6 +30,7 @@ enum { struct args_struct { bool debug_flag; bool help_flag; + bool raw_flag; bool verbose_flag; bool version_flag; STYLE style; @@ -57,6 +59,10 @@ bool show_debug() { return args.debug_flag; } +bool show_raw() { + return args.raw_flag; +} + bool verbose_enabled() { return args.verbose_flag; } @@ -165,6 +171,7 @@ bool parse_args(int argc, char* argv[]) { bool color_flag = false; args.debug_flag = false; + args.raw_flag = false; args.verbose_flag = false; args.help_flag = false; args.style = STYLE_EMPTY; @@ -173,6 +180,7 @@ bool parse_args(int argc, char* argv[]) { static struct option long_options[] = { {"style", required_argument, 0, ARG_CHAR_STYLE }, {"color", required_argument, 0, ARG_CHAR_COLOR }, + {"raw", no_argument, 0, ARG_CHAR_RAW }, {"help", no_argument, 0, ARG_CHAR_HELP }, {"debug", no_argument, 0, ARG_CHAR_DEBUG }, {"verbose", no_argument, 0, ARG_CHAR_VERBOSE }, @@ -205,6 +213,13 @@ bool parse_args(int argc, char* argv[]) { return false; } } + else if(c == ARG_CHAR_RAW) { + if(args.raw_flag) { + printErr("Raw option specified more than once"); + return false; + } + args.raw_flag = true; + } else if(c == ARG_CHAR_HELP) { if(args.help_flag) { printErr("Help option specified more than once"); diff --git a/src/common/args.h b/src/common/args.h index 7c25925..c4586ec 100644 --- a/src/common/args.h +++ b/src/common/args.h @@ -30,6 +30,7 @@ enum { bool parse_args(int argc, char* argv[]); bool show_help(); +bool show_raw(); bool show_debug(); bool show_version(); bool verbose_enabled(); diff --git a/src/common/main.c b/src/common/main.c index 7831463..3192153 100644 --- a/src/common/main.c +++ b/src/common/main.c @@ -16,7 +16,7 @@ static const char* VERSION = "0.95"; void print_help(char *argv[]) { - printf("Usage: %s [--version] [--help] [--debug] [--style \"fancy\"|\"retro\"|\"legacy\"] [--color \"intel\"|\"amd\"|'R,G,B:R,G,B:R,G,B:R,G,B']\n\n", argv[0]); + printf("Usage: %s [--version] [--help] [--debug] [--raw] [--style \"fancy\"|\"retro\"|\"legacy\"] [--color \"intel\"|\"amd\"|'R,G,B:R,G,B:R,G,B:R,G,B']\n\n", argv[0]); printf("Options: \n\ --color Set the color scheme. By default, cpufetch uses the system color scheme. This option \n\ @@ -31,7 +31,8 @@ void print_help(char *argv[]) { --style Set the style of CPU art: \n\ * \"fancy\": Default style \n\ * \"retro\": Old cpufetch style \n\ - * \"legacy\": Fallback style for terminals that does not support colors \n\n"); + * \"legacy\": Fallback style for terminals that does not support colors \n\n\ + --raw Dump raw cpuid information \n\n"); #ifdef ARCH_X86 printf(" --debug Prints CPU model and cpuid levels (debug purposes)\n\n"); @@ -81,6 +82,12 @@ int main(int argc, char* argv[]) { return EXIT_SUCCESS; } + if(show_raw()) { + print_version(); + print_raw(cpu); + return EXIT_SUCCESS; + } + if(print_cpufetch(cpu, get_style(), get_colors())) return EXIT_SUCCESS; else diff --git a/src/x86/apic.h b/src/x86/apic.h index 7e2b907..1b183b4 100644 --- a/src/x86/apic.h +++ b/src/x86/apic.h @@ -17,4 +17,8 @@ struct apic { bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo); uint32_t is_smt_enabled_amd(struct topology* topo); +#ifndef __APPLE__ +bool bind_to_cpu(int cpu_id); +#endif + #endif diff --git a/src/x86/cpuid.c b/src/x86/cpuid.c index 8d41a15..d5d0571 100755 --- a/src/x86/cpuid.c +++ b/src/x86/cpuid.c @@ -914,6 +914,74 @@ void print_debug(struct cpuInfo* cpu) { free_cpuinfo_struct(cpu); } +// TODO: Fix on macOS +// TODO: Query HV and Xeon Phi levels +void print_raw(struct cpuInfo* cpu) { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + printf("%s\n\n", cpu->cpu_name); + printf(" CPUID leaf sub EAX EBX ECX EDX \n"); + printf("--------------------------------------------------------------\n"); + + for(int c=0; c < cpu->topo->total_cores; c++) { + if(!bind_to_cpu(c)) { + printErr("Failed binding to CPU %d", c); + return; + } + + printf("CPU %d:\n", c); + + for(uint32_t reg=0x00000000; reg <= cpu->maxLevels; reg++) { + if(reg == 0x00000004) { + for(uint32_t reg2=0x00000000; reg2 < cpu->cach->max_cache_level; reg2++) { + eax = reg; + ebx = 0; + ecx = reg2; + edx = 0; + + cpuid(&eax, &ebx, &ecx, &edx); + + printf(" 0x%.8X 0x%.2X: 0x%.8X 0x%.8X 0x%.8X 0x%.8X\n", reg, reg2, eax, ebx, ecx, edx); + } + } + else if(reg == 0x0000000B) { + for(uint32_t reg2=0x00000000; reg2 < cpu->topo->smt_supported; reg2++) { + eax = reg; + ebx = 0; + ecx = reg2; + edx = 0; + + cpuid(&eax, &ebx, &ecx, &edx); + + printf(" 0x%.8X 0x%.2X: 0x%.8X 0x%.8X 0x%.8X 0x%.8X\n", reg, reg2, eax, ebx, ecx, edx); + } + } + else { + eax = reg; + ebx = 0; + ecx = 0; + edx = 0; + + cpuid(&eax, &ebx, &ecx, &edx); + + printf(" 0x%.8X 0x%.2X: 0x%.8X 0x%.8X 0x%.8X 0x%.8X\n", reg, 0x00, eax, ebx, ecx, edx); + } + } + for(uint32_t reg=0x80000000; reg <= cpu->maxExtendedLevels; reg++) { + eax = reg; + ebx = 0; + ecx = 0; + edx = 0; + + cpuid(&eax, &ebx, &ecx, &edx); + + printf(" 0x%.8X 0x%.2X: 0x%.8X 0x%.8X 0x%.8X 0x%.8X\n", reg, 0x00, eax, ebx, ecx, edx); + } + } +} + void free_topo_struct(struct topology* topo) { free(topo->apic->cache_select_mask); free(topo->apic->cache_id_apic); diff --git a/src/x86/cpuid.h b/src/x86/cpuid.h index 4025f64..743ae39 100644 --- a/src/x86/cpuid.h +++ b/src/x86/cpuid.h @@ -15,6 +15,7 @@ char* get_str_topology(struct cpuInfo* cpu, struct topology* topo, bool dual_soc char* get_str_peak_performance(struct cpuInfo* cpu, struct topology* topo, int64_t freq); void print_debug(struct cpuInfo* cpu); +void print_raw(struct cpuInfo* cpu); void free_topo_struct(struct topology* topo); From 7420792ef5395f4136227e0552d97be09e34e3c7 Mon Sep 17 00:00:00 2001 From: Dr-Noob Date: Tue, 30 Mar 2021 10:39:27 +0200 Subject: [PATCH 3/5] [v0.95] Fetch topology extensions field in AMD processors --- src/common/cpu.h | 2 ++ src/x86/cpuid.c | 26 +++++++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/common/cpu.h b/src/common/cpu.h index 77507f1..b107257 100644 --- a/src/common/cpu.h +++ b/src/common/cpu.h @@ -119,6 +119,8 @@ struct cpuInfo { uint32_t maxLevels; // Max cpuids extended levels uint32_t maxExtendedLevels; + // Topology Extensions (AMD only) + bool topology_extensions; #elif ARCH_ARM // Main ID register uint32_t midr; diff --git a/src/x86/cpuid.c b/src/x86/cpuid.c index d5d0571..5e89364 100755 --- a/src/x86/cpuid.c +++ b/src/x86/cpuid.c @@ -309,6 +309,13 @@ struct cpuInfo* get_cpu_info() { 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; + if(cpu->cpu_vendor == CPU_VENDOR_AMD && cpu->maxExtendedLevels >= 0x80000001) { + eax = 0x80000001; + cpuid(&eax, &ebx, &ecx, &edx); + cpu->topology_extensions = (ecx >> 22) & 1; + } + cpu->arch = get_cpu_uarch(cpu); cpu->freq = get_frequency_info(cpu); cpu->cach = get_cache_info(cpu); @@ -321,7 +328,7 @@ struct cpuInfo* get_cpu_info() { } bool get_cache_topology_amd(struct cpuInfo* cpu, struct topology* topo) { - if(cpu->maxExtendedLevels >= 0x8000001D) { + if(cpu->maxExtendedLevels >= 0x8000001D && cpu->topology_extensions) { uint32_t i, eax, ebx, ecx, edx, num_sharing_cache, cache_type, cache_level; i = 0; @@ -379,7 +386,7 @@ bool get_cache_topology_amd(struct cpuInfo* cpu, struct topology* topo) { } while (cache_type > 0); } else { - printWarn("Can't read topology information from cpuid (needed extended level is 0x%.8X, max is 0x%.8X). Guessing cache sizes", 0x8000001D, cpu->maxExtendedLevels); + printWarn("Can't read topology information from cpuid (needed extended level is 0x%.8X, max is 0x%.8X and topology_extensions=%s). Guessing cache topology", 0x8000001D, cpu->maxExtendedLevels, cpu->topology_extensions ? "true" : "false"); topo->cach->L1i->num_caches = topo->physical_cores; topo->cach->L1d->num_caches = topo->physical_cores; @@ -440,13 +447,13 @@ struct topology* get_topology_info(struct cpuInfo* cpu, struct cache* cach) { cpuid(&eax, &ebx, &ecx, &edx); topo->logical_cores = (ecx & 0xFF) + 1; - if (cpu->maxExtendedLevels >= 0x8000001E) { + if (cpu->maxExtendedLevels >= 0x8000001E && cpu->topology_extensions) { eax = 0x8000001E; cpuid(&eax, &ebx, &ecx, &edx); topo->smt_supported = ((ebx >> 8) & 0x03) + 1; } else { - printWarn("Can't read topology information from cpuid (needed extended level is 0x%.8X, max is 0x%.8X)", 0x8000001E, cpu->maxExtendedLevels); + printWarn("Can't read topology information from cpuid (needed extended level is 0x%.8X, max is 0x%.8X and topology_extensions=%s)", 0x8000001E, cpu->maxExtendedLevels, cpu->topology_extensions ? "true" : "false"); topo->smt_supported = 1; } } @@ -611,8 +618,8 @@ struct cache* get_cache_info(struct cpuInfo* cpu) { } else { level = 0x8000001D; - if(cpu->maxExtendedLevels < level) { - printWarn("Can't read cache information from cpuid (needed extended level is 0x%.8X, max is 0x%.8X)", level, cpu->maxExtendedLevels); + if(cpu->maxExtendedLevels < level || !cpu->topology_extensions) { + printWarn("Can't read cache information from cpuid (needed extended level is 0x%.8X, max is 0x%.8X and topology_extensions=%s)", level, cpu->maxExtendedLevels, cpu->topology_extensions ? "true" : "false"); level = 0x80000006; if(cpu->maxExtendedLevels < level) { printErr("Can't read cache information from cpuid using old method (needed extended level is 0x%.8X, max is 0x%.8X)", level, cpu->maxExtendedLevels); @@ -906,9 +913,14 @@ void print_debug(struct cpuInfo* cpu) { cpuid(&eax, &ebx, &ecx, &edx); printf("%s\n", cpu->cpu_name); - if(cpu->hv->present) printf("- Hypervisor: %s\n", cpu->hv->hv_name); + if(cpu->hv->present) { + printf("- Hypervisor: %s\n", cpu->hv->hv_name); + } printf("- Max standard level: 0x%.8X\n", cpu->maxLevels); printf("- Max extended level: 0x%.8X\n", cpu->maxExtendedLevels); + if(cpu->cpu_vendor == CPU_VENDOR_AMD) { + printf("- AMD topology extensions: %d\n", cpu->topology_extensions); + } printf("- CPUID dump: 0x%.8X\n", eax); free_cpuinfo_struct(cpu); From 044608f31f55943f9ee2cb3ed893ded5ac043d25 Mon Sep 17 00:00:00 2001 From: Dr-Noob Date: Wed, 7 Apr 2021 14:35:45 +0200 Subject: [PATCH 4/5] [v0.95] Add 0x8000001D sublevel query to --raw option --- src/x86/cpuid.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/x86/cpuid.c b/src/x86/cpuid.c index 5e89364..29aa211 100755 --- a/src/x86/cpuid.c +++ b/src/x86/cpuid.c @@ -982,14 +982,28 @@ void print_raw(struct cpuInfo* cpu) { } } for(uint32_t reg=0x80000000; reg <= cpu->maxExtendedLevels; reg++) { - eax = reg; - ebx = 0; - ecx = 0; - edx = 0; + if(reg == 0x8000001D) { + for(uint32_t reg2=0x00000000; reg2 < cpu->cach->max_cache_level; reg2++) { + eax = reg; + ebx = 0; + ecx = reg2; + edx = 0; - cpuid(&eax, &ebx, &ecx, &edx); + cpuid(&eax, &ebx, &ecx, &edx); - printf(" 0x%.8X 0x%.2X: 0x%.8X 0x%.8X 0x%.8X 0x%.8X\n", reg, 0x00, eax, ebx, ecx, edx); + printf(" 0x%.8X 0x%.2X: 0x%.8X 0x%.8X 0x%.8X 0x%.8X\n", reg, reg2, eax, ebx, ecx, edx); + } + } + else { + eax = reg; + ebx = 0; + ecx = 0; + edx = 0; + + cpuid(&eax, &ebx, &ecx, &edx); + + printf(" 0x%.8X 0x%.2X: 0x%.8X 0x%.8X 0x%.8X 0x%.8X\n", reg, 0x00, eax, ebx, ecx, edx); + } } } } From e8d2898ae3c5f5d87a5917468c24707c368e66b4 Mon Sep 17 00:00:00 2001 From: Dr-Noob Date: Thu, 8 Apr 2021 13:18:35 +0200 Subject: [PATCH 5/5] [v0.96] Remove cache sizes check --- src/x86/cpuid.c | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/src/x86/cpuid.c b/src/x86/cpuid.c index 29aa211..2845d01 100755 --- a/src/x86/cpuid.c +++ b/src/x86/cpuid.c @@ -633,35 +633,6 @@ struct cache* get_cache_info(struct cpuInfo* cpu) { } } - // Sanity checks. If we read values greater than this, they can't be valid ones - // The values were chosen by me - if(cach->L1i->size > 64 * 1024) { - printBug("Invalid L1i size: %dKB", cach->L1i->size/1024); - //return NULL; - } - if(cach->L1d->size > 64 * 1024) { - printBug("Invalid L1d size: %dKB", cach->L1d->size/1024); - //return NULL; - } - if(cach->L2->exists) { - if(cach->L3->exists && cach->L2->size > 2 * 1048576) { - printBug("Invalid L2 size: %dMB", cach->L2->size/(1048576)); - //return NULL; - } - else if(cach->L2->size > 100 * 1048576) { - printBug("Invalid L2 size: %dMB", cach->L2->size/(1048576)); - //return NULL; - } - } - if(cach->L3->exists && cach->L3->size > 100 * 1048576) { - printBug("Invalid L3 size: %dMB", cach->L3->size/(1048576)); - //return NULL; - } - if(!cach->L2->exists) { - printBug("Could not find L2 cache"); - //return NULL; - } - return cach; }