Compare commits

...

10 Commits

Author SHA1 Message Date
Dr-Noob
8f2f3d3a16 [v0.97] Merge bugfix3 branch to support Rocket Lake processors 2021-04-09 20:06:05 +02:00
Dr-Noob
6dd041bf9f [v0.97] Fix macOS compilation issue as noted by #73 2021-04-09 18:32:34 +02:00
Dr-Noob
b45c09efff [v0.97] Add raw option to help. Disable raw option in ARM 2021-04-09 15:58:33 +02:00
Dr-Noob
ec5f80adc1 [v0.97] Fix compilation in macOS 2021-04-09 15:49:21 +02:00
Dr-Noob
ecca042d86 [v0.97] Manually merge bugfix branch with latest fixes 2021-04-09 15:37:17 +02:00
Dr-Noob
e8d2898ae3 [v0.96] Remove cache sizes check 2021-04-08 13:18:35 +02:00
Dr-Noob
044608f31f [v0.95] Add 0x8000001D sublevel query to --raw option 2021-04-07 14:35:45 +02:00
Dr-Noob
7420792ef5 [v0.95] Fetch topology extensions field in AMD processors 2021-03-30 10:39:27 +02:00
Dr-Noob
db32cccd91 [v0.95] Add --raw option 2021-03-15 21:49:47 +01:00
Dr-Noob
a8d8ac2e91 [v0.95] Temporarily disable cache sanity checks 2021-03-06 22:13:32 +01:00
8 changed files with 152 additions and 34 deletions

View File

@@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.2.
.TH CPUFETCH "1" "March 2021" "cpufetch v0.96 (x86_64 build)" "User Commands"
.TH CPUFETCH "1" "March 2021" "cpufetch v0.97 (x86_64 build)" "User Commands"
.SH NAME
cpufetch \- manual page for cpufetch v0.96 (x86_64 build)
cpufetch \- manual page for cpufetch v0.97 (x86_64 build)
.SH SYNOPSIS
.B cpufetch
[\fI\,OPTION\/\fR]...
@@ -21,6 +21,9 @@ Prints CPU model and cpuid levels (debug purposes)
\fB\-v\fR, \fB\-\-verbose\fR
Prints extra information (if available) about how cpufetch tried fetching information
.TP
\fB\-r\fR, \fB\-\-raw\fR
Prints raw cpuid data
.TP
\fB\-h\fR, \fB\-\-help\fR
Prints this help and exit
.TP

View File

@@ -20,6 +20,7 @@ static const char *SYTLES_STR_LIST[] = {
struct args_struct {
bool debug_flag;
bool help_flag;
bool raw_flag;
bool verbose_flag;
bool version_flag;
STYLE style;
@@ -30,6 +31,7 @@ const char args_chr[] = {
/* [ARG_CHAR_STYLE] = */ 's',
/* [ARG_CHAR_COLOR] = */ 'c',
/* [ARG_CHAR_HELP] = */ 'h',
/* [ARG_CHAR_RAW] = */ 'r',
/* [ARG_CHAR_DEBUG] = */ 'd',
/* [ARG_CHAR_VERBOSE] = */ 'v',
/* [ARG_CHAR_VERSION] = */ 'V',
@@ -39,6 +41,7 @@ const char *args_str[] = {
/* [ARG_CHAR_STYLE] = */ "style",
/* [ARG_CHAR_COLOR] = */ "color",
/* [ARG_CHAR_HELP] = */ "help",
/* [ARG_CHAR_RAW] = */ "raw",
/* [ARG_CHAR_DEBUG] = */ "debug",
/* [ARG_CHAR_VERBOSE] = */ "verbose",
/* [ARG_CHAR_VERSION] = */ "version",
@@ -66,6 +69,10 @@ bool show_debug() {
return args.debug_flag;
}
bool show_raw() {
return args.raw_flag;
}
bool verbose_enabled() {
return args.verbose_flag;
}
@@ -182,9 +189,15 @@ char* build_short_options() {
char* str = (char *) malloc(sizeof(char) * (len*2 + 1));
memset(str, 0, sizeof(char) * (len*2 + 1));
#ifdef ARCH_X86
sprintf(str, "%c:%c:%c%c%c%c%c",
c[ARG_STYLE], c[ARG_COLOR], c[ARG_HELP], c[ARG_RAW],
c[ARG_DEBUG], c[ARG_VERBOSE], c[ARG_VERSION]);
#else
sprintf(str, "%c:%c:%c%c%c%c",
c[ARG_STYLE], c[ARG_COLOR], c[ARG_HELP],
c[ARG_DEBUG], c[ARG_VERBOSE], c[ARG_VERSION]);
#endif
return str;
}
@@ -196,6 +209,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;
@@ -205,6 +219,9 @@ bool parse_args(int argc, char* argv[]) {
{args_str[ARG_STYLE], required_argument, 0, args_chr[ARG_STYLE] },
{args_str[ARG_COLOR], required_argument, 0, args_chr[ARG_COLOR] },
{args_str[ARG_HELP], no_argument, 0, args_chr[ARG_HELP] },
#ifdef ARCH_X86
{args_str[ARG_RAW], no_argument, 0, args_chr[ARG_RAW] },
#endif
{args_str[ARG_DEBUG], no_argument, 0, args_chr[ARG_DEBUG] },
{args_str[ARG_VERBOSE], no_argument, 0, args_chr[ARG_VERBOSE] },
{args_str[ARG_VERSION], no_argument, 0, args_chr[ARG_VERSION] },
@@ -241,6 +258,9 @@ bool parse_args(int argc, char* argv[]) {
else if(opt == args_chr[ARG_HELP]) {
args.help_flag = true;
}
else if(opt == args_chr[ARG_RAW]) {
args.raw_flag = true;
}
else if(opt == args_chr[ARG_VERBOSE]) {
args.verbose_flag = true;
}

View File

@@ -30,6 +30,7 @@ enum {
ARG_STYLE,
ARG_COLOR,
ARG_HELP,
ARG_RAW,
ARG_DEBUG,
ARG_VERBOSE,
ARG_VERSION
@@ -43,6 +44,7 @@ extern const char *args_str[];
int max_arg_str_length();
bool parse_args(int argc, char* argv[]);
bool show_help();
bool show_raw();
bool show_debug();
bool show_version();
bool verbose_enabled();

View File

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

View File

@@ -14,7 +14,7 @@
#include "../arm/midr.h"
#endif
static const char* VERSION = "0.96";
static const char* VERSION = "0.97";
void print_help(char *argv[]) {
const char **t = args_str;
@@ -33,6 +33,9 @@ void print_help(char *argv[]) {
printf(" -%c, --%s %*s Prints main ID register values for all cores (debug purposes)\n", c[ARG_DEBUG], t[ARG_DEBUG], (int) (max_len-strlen(t[ARG_DEBUG])), "");
#endif
printf(" -%c, --%s %*s Prints extra information (if available) about how cpufetch tried fetching information\n", c[ARG_VERBOSE], t[ARG_VERBOSE], (int) (max_len-strlen(t[ARG_VERBOSE])), "");
#ifdef ARCH_X86
printf(" -%c, --%s %*s Prints raw cpuid data\n", c[ARG_RAW], t[ARG_RAW], (int) (max_len-strlen(t[ARG_RAW])), "");
#endif
printf(" -%c, --%s %*s Prints this help and exit\n", c[ARG_HELP], t[ARG_HELP], (int) (max_len-strlen(t[ARG_HELP])), "");
printf(" -%c, --%s %*s Prints cpufetch version and exit\n", c[ARG_VERSION], t[ARG_VERSION], (int) (max_len-strlen(t[ARG_VERSION])), "");
@@ -95,6 +98,17 @@ int main(int argc, char* argv[]) {
return EXIT_SUCCESS;
}
if(show_raw()) {
#ifdef ARCH_X86
print_version();
print_raw(cpu);
return EXIT_SUCCESS;
#else
printErr("raw option is valid only in x86_64");
return EXIT_FAILURE;
#endif
}
if(print_cpufetch(cpu, get_style(), get_colors()))
return EXIT_SUCCESS;
else

View File

@@ -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

View File

@@ -310,6 +310,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);
@@ -322,7 +329,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;
}
}
@@ -610,8 +617,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) {
printWarn("Can't read cache information from cpuid using old method (needed extended level is 0x%.8X, max is 0x%.8X)", level, cpu->maxExtendedLevels);
@@ -625,29 +632,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);
}
if(cach->L1d->size > 64 * 1024) {
printBug("Invalid L1d size: %dKB", cach->L1d->size/1024);
}
if(cach->L2->exists) {
if(cach->L3->exists && cach->L2->size > 2 * 1048576) {
printBug("Invalid L2 size: %dMB", cach->L2->size/(1048576));
}
else if(cach->L2->size > 100 * 1048576) {
printBug("Invalid L2 size: %dMB", cach->L2->size/(1048576));
}
}
if(cach->L3->exists && cach->L3->size > 100 * 1048576) {
printBug("Invalid L3 size: %dMB", cach->L3->size/(1048576));
}
if(!cach->L2->exists) {
printBug("Could not find L2 cache");
}
return cach;
}
@@ -890,14 +874,102 @@ 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);
}
// 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++) {
#ifndef __APPLE__
if(!bind_to_cpu(c)) {
printErr("Failed binding to CPU %d", c);
return;
}
#endif
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++) {
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);
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);
}
}
}
}
void free_topo_struct(struct topology* topo) {
free(topo->apic->cache_select_mask);
free(topo->apic->cache_id_apic);

View File

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