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);