Compare commits

...

14 Commits

Author SHA1 Message Date
Dr-Noob
2c4a2a0253 [v0.97] Automatically adjust text to the width of the terminal, as suggested by #65 2021-04-10 15:41:44 +02:00
Dr-Noob
61cd0783ac [v0.97] Make loop option work on ARM too 2021-04-10 14:33:45 +02:00
Dr-Noob
5242adf4ac [v0.97] Fix compilation in macOS 2021-04-10 13:34:28 +02:00
Dr-Noob
3a2b04de1e [v0.97] Add loop option as suggested by #75 2021-04-10 13:22:45 +02:00
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
11 changed files with 304 additions and 62 deletions

View File

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

View File

@@ -20,6 +20,8 @@ static const char *SYTLES_STR_LIST[] = {
struct args_struct { struct args_struct {
bool debug_flag; bool debug_flag;
bool help_flag; bool help_flag;
bool loop_flag;
bool raw_flag;
bool verbose_flag; bool verbose_flag;
bool version_flag; bool version_flag;
STYLE style; STYLE style;
@@ -29,7 +31,9 @@ struct args_struct {
const char args_chr[] = { const char args_chr[] = {
/* [ARG_CHAR_STYLE] = */ 's', /* [ARG_CHAR_STYLE] = */ 's',
/* [ARG_CHAR_COLOR] = */ 'c', /* [ARG_CHAR_COLOR] = */ 'c',
/* [ARG_CHAR_LOPP] = */ 'l',
/* [ARG_CHAR_HELP] = */ 'h', /* [ARG_CHAR_HELP] = */ 'h',
/* [ARG_CHAR_RAW] = */ 'r',
/* [ARG_CHAR_DEBUG] = */ 'd', /* [ARG_CHAR_DEBUG] = */ 'd',
/* [ARG_CHAR_VERBOSE] = */ 'v', /* [ARG_CHAR_VERBOSE] = */ 'v',
/* [ARG_CHAR_VERSION] = */ 'V', /* [ARG_CHAR_VERSION] = */ 'V',
@@ -38,7 +42,9 @@ const char args_chr[] = {
const char *args_str[] = { const char *args_str[] = {
/* [ARG_CHAR_STYLE] = */ "style", /* [ARG_CHAR_STYLE] = */ "style",
/* [ARG_CHAR_COLOR] = */ "color", /* [ARG_CHAR_COLOR] = */ "color",
/* [ARG_CHAR_LOOP] = */ "loop",
/* [ARG_CHAR_HELP] = */ "help", /* [ARG_CHAR_HELP] = */ "help",
/* [ARG_CHAR_RAW] = */ "raw",
/* [ARG_CHAR_DEBUG] = */ "debug", /* [ARG_CHAR_DEBUG] = */ "debug",
/* [ARG_CHAR_VERBOSE] = */ "verbose", /* [ARG_CHAR_VERBOSE] = */ "verbose",
/* [ARG_CHAR_VERSION] = */ "version", /* [ARG_CHAR_VERSION] = */ "version",
@@ -62,10 +68,18 @@ bool show_version() {
return args.version_flag; return args.version_flag;
} }
bool loop_mode() {
return args.loop_flag;
}
bool show_debug() { bool show_debug() {
return args.debug_flag; return args.debug_flag;
} }
bool show_raw() {
return args.raw_flag;
}
bool verbose_enabled() { bool verbose_enabled() {
return args.verbose_flag; return args.verbose_flag;
} }
@@ -182,9 +196,15 @@ char* build_short_options() {
char* str = (char *) malloc(sizeof(char) * (len*2 + 1)); char* str = (char *) malloc(sizeof(char) * (len*2 + 1));
memset(str, 0, sizeof(char) * (len*2 + 1)); memset(str, 0, sizeof(char) * (len*2 + 1));
sprintf(str, "%c:%c:%c%c%c%c", #ifdef ARCH_X86
sprintf(str, "%c:%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], c[ARG_LOOP]);
#else
sprintf(str, "%c:%c:%c%c%c%c%c",
c[ARG_STYLE], c[ARG_COLOR], c[ARG_HELP], c[ARG_STYLE], c[ARG_COLOR], c[ARG_HELP],
c[ARG_DEBUG], c[ARG_VERBOSE], c[ARG_VERSION]); c[ARG_DEBUG], c[ARG_VERBOSE], c[ARG_VERSION], c[ARG_LOOP]);
#endif
return str; return str;
} }
@@ -196,6 +216,8 @@ bool parse_args(int argc, char* argv[]) {
bool color_flag = false; bool color_flag = false;
args.debug_flag = false; args.debug_flag = false;
args.raw_flag = false;
args.loop_flag = false;
args.verbose_flag = false; args.verbose_flag = false;
args.help_flag = false; args.help_flag = false;
args.style = STYLE_EMPTY; args.style = STYLE_EMPTY;
@@ -205,7 +227,11 @@ bool parse_args(int argc, char* argv[]) {
{args_str[ARG_STYLE], required_argument, 0, args_chr[ARG_STYLE] }, {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_COLOR], required_argument, 0, args_chr[ARG_COLOR] },
{args_str[ARG_HELP], no_argument, 0, args_chr[ARG_HELP] }, {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_DEBUG], no_argument, 0, args_chr[ARG_DEBUG] },
{args_str[ARG_LOOP], no_argument, 0, args_chr[ARG_LOOP] },
{args_str[ARG_VERBOSE], no_argument, 0, args_chr[ARG_VERBOSE] }, {args_str[ARG_VERBOSE], no_argument, 0, args_chr[ARG_VERBOSE] },
{args_str[ARG_VERSION], no_argument, 0, args_chr[ARG_VERSION] }, {args_str[ARG_VERSION], no_argument, 0, args_chr[ARG_VERSION] },
{0, 0, 0, 0} {0, 0, 0, 0}
@@ -238,9 +264,15 @@ bool parse_args(int argc, char* argv[]) {
} }
break; break;
} }
else if(opt == args_chr[ARG_LOOP]) {
args.loop_flag = true;
}
else if(opt == args_chr[ARG_HELP]) { else if(opt == args_chr[ARG_HELP]) {
args.help_flag = true; args.help_flag = true;
} }
else if(opt == args_chr[ARG_RAW]) {
args.raw_flag = true;
}
else if(opt == args_chr[ARG_VERBOSE]) { else if(opt == args_chr[ARG_VERBOSE]) {
args.verbose_flag = true; args.verbose_flag = true;
} }

View File

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

View File

@@ -119,6 +119,8 @@ struct cpuInfo {
uint32_t maxLevels; uint32_t maxLevels;
// Max cpuids extended levels // Max cpuids extended levels
uint32_t maxExtendedLevels; uint32_t maxExtendedLevels;
// Topology Extensions (AMD only)
bool topology_extensions;
#elif ARCH_ARM #elif ARCH_ARM
// Main ID register // Main ID register
uint32_t midr; uint32_t midr;

View File

@@ -68,3 +68,7 @@ void set_log_level(bool verbose) {
int max(int a, int b) { int max(int a, int b) {
return a > b ? a : b; return a > b ? a : b;
} }
int min(int a, int b) {
return a < b ? a : b;
}

View File

@@ -8,5 +8,6 @@ void printWarn(const char *fmt, ...);
void printErr(const char *fmt, ...); void printErr(const char *fmt, ...);
void printBug(const char *fmt, ...); void printBug(const char *fmt, ...);
int max(int a, int b); int max(int a, int b);
int min(int a, int b);
#endif #endif

View File

@@ -14,7 +14,7 @@
#include "../arm/midr.h" #include "../arm/midr.h"
#endif #endif
static const char* VERSION = "0.96"; static const char* VERSION = "0.97";
void print_help(char *argv[]) { void print_help(char *argv[]) {
const char **t = args_str; const char **t = args_str;
@@ -27,12 +27,16 @@ void print_help(char *argv[]) {
printf("Options: \n"); printf("Options: \n");
printf(" -%c, --%s %*s Set the color scheme (by default, cpufetch uses the system color scheme)\n", c[ARG_COLOR], t[ARG_COLOR], (int) (max_len-strlen(t[ARG_COLOR])), ""); printf(" -%c, --%s %*s Set the color scheme (by default, cpufetch uses the system color scheme)\n", c[ARG_COLOR], t[ARG_COLOR], (int) (max_len-strlen(t[ARG_COLOR])), "");
printf(" -%c, --%s %*s Set the style of CPU art\n", c[ARG_STYLE], t[ARG_STYLE], (int) (max_len-strlen(t[ARG_STYLE])), ""); printf(" -%c, --%s %*s Set the style of CPU art\n", c[ARG_STYLE], t[ARG_STYLE], (int) (max_len-strlen(t[ARG_STYLE])), "");
printf(" -%c, --%s %*s Runs cpufetch in a loop\n", c[ARG_LOOP], t[ARG_LOOP], (int) (max_len-strlen(t[ARG_LOOP])), "");
#ifdef ARCH_X86 #ifdef ARCH_X86
printf(" -%c, --%s %*s Prints CPU model and cpuid levels (debug purposes)\n", c[ARG_DEBUG], t[ARG_DEBUG], (int) (max_len-strlen(t[ARG_DEBUG])), ""); printf(" -%c, --%s %*s Prints CPU model and cpuid levels (debug purposes)\n", c[ARG_DEBUG], t[ARG_DEBUG], (int) (max_len-strlen(t[ARG_DEBUG])), "");
#elif ARCH_ARM #elif ARCH_ARM
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])), ""); 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 #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])), ""); 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 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])), ""); 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 +99,17 @@ int main(int argc, char* argv[]) {
return EXIT_SUCCESS; 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())) if(print_cpufetch(cpu, get_style(), get_colors()))
return EXIT_SUCCESS; return EXIT_SUCCESS;
else else

View File

@@ -1,3 +1,15 @@
#ifdef _WIN32
#define NOMINMAX
#include <Windows.h>
#else
#ifdef __linux__
#define _POSIX_C_SOURCE 199309L
#endif
#include <sys/ioctl.h>
#include <unistd.h>
#endif
#include <signal.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@@ -17,11 +29,6 @@
#include "../arm/soc.h" #include "../arm/soc.h"
#endif #endif
#ifdef _WIN32
#define NOMINMAX
#include <Windows.h>
#endif
#define max(a,b) (((a)>(b))?(a):(b)) #define max(a,b) (((a)>(b))?(a):(b))
#define MAX_ATTRIBUTES 100 #define MAX_ATTRIBUTES 100
@@ -118,6 +125,29 @@ struct ascii {
STYLE style; STYLE style;
}; };
struct terminal {
int w;
int h;
};
volatile sig_atomic_t loop = 1;
#ifdef _WIN32
BOOL WINAPI loop_mode_handler(DWORD signum) {
if (signum == CTRL_C_EVENT) {
loop = 0;
}
return TRUE;
}
#else
void loop_mode_handler(int signum) {
if(signum == SIGINT) {
loop = 0;
}
}
#endif
void setAttribute(struct ascii* art, int type, char* value) { void setAttribute(struct ascii* art, int type, char* value) {
art->attributes[art->n_attributes_set]->value = value; art->attributes[art->n_attributes_set]->value = value;
art->attributes[art->n_attributes_set]->type = type; art->attributes[art->n_attributes_set]->type = type;
@@ -345,6 +375,33 @@ uint32_t longest_attribute_length(struct ascii* art) {
return max; return max;
} }
bool run_loop_mode() {
#ifdef _WIN32
if (!SetConsoleCtrlHandler(loop_mode_handler, TRUE)) {
printErr("SetConsoleCtrlHandler failed");
return false;
}
#else
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = loop_mode_handler;
if(sigaction(SIGINT, &act, NULL) == -1) {
perror("sigaction");
return false;
}
#endif
while (loop) {
#ifdef _WIN32
Sleep(1000);
#else
sleep(1);
#endif
}
return true;
}
#ifdef ARCH_X86 #ifdef ARCH_X86
void print_algorithm_intel(struct ascii* art, int n, bool* flag) { void print_algorithm_intel(struct ascii* art, int n, bool* flag) {
for(int i=0; i < LINE_SIZE; i++) { for(int i=0; i < LINE_SIZE; i++) {
@@ -382,46 +439,59 @@ void print_algorithm_amd(struct ascii* art, int n, bool* flag) {
} }
} }
void print_ascii_x86(struct ascii* art, uint32_t la, void (*callback_print_algorithm)(struct ascii* art, int i, bool* flag)) { void print_ascii_x86(struct ascii* art, struct terminal* term, uint32_t la, void (*callback_print_algorithm)(struct ascii* art, int i, bool* flag)) {
int attr_to_print = 0; int attr_to_print = 0;
int attr_type; int attr_type;
char* attr_value; char* attr_value;
int attr_print_len;
uint32_t attr_space_left;
uint32_t space_right; uint32_t space_right;
uint32_t space_up = (NUMBER_OF_LINES - art->n_attributes_set)/2; uint32_t space_up = (NUMBER_OF_LINES - art->n_attributes_set)/2;
uint32_t space_down = NUMBER_OF_LINES - art->n_attributes_set - space_up; uint32_t space_down = NUMBER_OF_LINES - art->n_attributes_set - space_up;
bool flag = false; bool flag = false;
bool print_ascii_art;
if(term->w - LINE_SIZE - 1 - (int) la > 0) {
print_ascii_art = true;
attr_space_left = term->w - LINE_SIZE - 1 - la;
}
else {
print_ascii_art = false;
attr_space_left = term->w - 1 - la;
}
printf("\n"); printf("\n");
for(uint32_t n=0;n<NUMBER_OF_LINES;n++) { for(uint32_t n=0;n<NUMBER_OF_LINES;n++) {
callback_print_algorithm(art, n, &flag); if(print_ascii_art) callback_print_algorithm(art, n, &flag);
if(n > space_up-1 && n < NUMBER_OF_LINES-space_down) { if(n > space_up-1 && n < NUMBER_OF_LINES-space_down) {
attr_type = art->attributes[attr_to_print]->type; attr_type = art->attributes[attr_to_print]->type;
attr_value = art->attributes[attr_to_print]->value; attr_value = art->attributes[attr_to_print]->value;
attr_to_print++; attr_to_print++;
attr_print_len = min(strlen(attr_value), attr_space_left);
attr_print_len = max(attr_print_len, 0);
space_right = 1 + (la - strlen(ATTRIBUTE_FIELDS[attr_type])); space_right = 1 + (la - strlen(ATTRIBUTE_FIELDS[attr_type]));
printf("%s%s%s%*s%s%s%s\n", art->color1_text, ATTRIBUTE_FIELDS[attr_type], art->reset, space_right, "", art->color2_text, attr_value, art->reset); printf("%s%s%s%*s%s%.*s%s\n", art->color1_text, ATTRIBUTE_FIELDS[attr_type], art->reset, space_right, "", art->color2_text, attr_print_len, attr_value, art->reset);
} }
else printf("\n"); else printf("\n");
} }
printf("\n"); printf("\n");
} }
void print_ascii(struct ascii* art) { void print_ascii(struct ascii* art, struct terminal* term) {
uint32_t longest_attribute = longest_attribute_length(art); uint32_t longest_attribute = longest_attribute_length(art);
if(art->vendor == CPU_VENDOR_INTEL) if(art->vendor == CPU_VENDOR_INTEL)
print_ascii_x86(art, longest_attribute, &print_algorithm_intel); print_ascii_x86(art, term, longest_attribute, &print_algorithm_intel);
else if(art->vendor == CPU_VENDOR_AMD) else if(art->vendor == CPU_VENDOR_AMD)
print_ascii_x86(art, longest_attribute, &print_algorithm_amd); print_ascii_x86(art, term, longest_attribute, &print_algorithm_amd);
else { else {
printBug("Invalid CPU vendor: %d\n", art->vendor); printBug("Invalid CPU vendor: %d\n", art->vendor);
} }
} }
bool print_cpufetch_x86(struct cpuInfo* cpu, STYLE s, struct colors* cs) { bool print_cpufetch_x86(struct cpuInfo* cpu, STYLE s, struct colors* cs, struct terminal* term) {
struct ascii* art = set_ascii(get_cpu_vendor(cpu), s, cs); struct ascii* art = set_ascii(get_cpu_vendor(cpu), s, cs);
if(art == NULL) if(art == NULL)
return false; return false;
@@ -436,7 +506,6 @@ bool print_cpufetch_x86(struct cpuInfo* cpu, STYLE s, struct colors* cs) {
char* avx = get_str_avx(cpu); char* avx = get_str_avx(cpu);
char* fma = get_str_fma(cpu); char* fma = get_str_fma(cpu);
char* l1i = get_str_l1i(cpu->cach); char* l1i = get_str_l1i(cpu->cach);
char* l1d = get_str_l1d(cpu->cach); char* l1d = get_str_l1d(cpu->cach);
char* l2 = get_str_l2(cpu->cach); char* l2 = get_str_l2(cpu->cach);
@@ -474,7 +543,11 @@ bool print_cpufetch_x86(struct cpuInfo* cpu, STYLE s, struct colors* cs) {
return false; return false;
} }
print_ascii(art); print_ascii(art, term);
if(loop_mode()) {
return run_loop_mode();
}
free(manufacturing_process); free(manufacturing_process);
free(max_frequency); free(max_frequency);
@@ -542,7 +615,7 @@ void print_algorithm_arm(struct ascii* art, int n) {
} }
} }
void print_ascii_arm(struct ascii* art, uint32_t la, void (*callback_print_algorithm)(struct ascii* art, int n)) { void print_ascii_arm(struct ascii* art, struct terminal* term, uint32_t la, void (*callback_print_algorithm)(struct ascii* art, int n)) {
int attr_to_print = 0; int attr_to_print = 0;
int attr_type; int attr_type;
char* attr_value; char* attr_value;
@@ -601,18 +674,18 @@ void print_ascii(struct ascii* art) {
uint32_t longest_attribute = longest_attribute_length(art); uint32_t longest_attribute = longest_attribute_length(art);
if(art->vendor == SOC_VENDOR_SNAPDRAGON || art->vendor == SOC_VENDOR_MEDIATEK || art->vendor == SOC_VENDOR_KIRIN || art->vendor == SOC_VENDOR_BROADCOM) if(art->vendor == SOC_VENDOR_SNAPDRAGON || art->vendor == SOC_VENDOR_MEDIATEK || art->vendor == SOC_VENDOR_KIRIN || art->vendor == SOC_VENDOR_BROADCOM)
print_ascii_arm(art, longest_attribute, &print_algorithm_snapd_mtk); print_ascii_arm(art, term, longest_attribute, &print_algorithm_snapd_mtk);
else if(art->vendor == SOC_VENDOR_EXYNOS) else if(art->vendor == SOC_VENDOR_EXYNOS)
print_ascii_arm(art, longest_attribute, &print_algorithm_samsung); print_ascii_arm(art, term, longest_attribute, &print_algorithm_samsung);
else { else {
if(art->vendor != SOC_VENDOR_UNKNOWN) if(art->vendor != SOC_VENDOR_UNKNOWN)
printWarn("Invalid SOC vendor: %d\n", art->vendor); printWarn("Invalid SOC vendor: %d\n", art->vendor);
print_ascii_arm(art, longest_attribute, &print_algorithm_arm); print_ascii_arm(art, term, longest_attribute, &print_algorithm_arm);
} }
} }
bool print_cpufetch_arm(struct cpuInfo* cpu, STYLE s, struct colors* cs) { bool print_cpufetch_arm(struct cpuInfo* cpu, STYLE s, struct colors* cs, struct terminal* term) {
struct ascii* art = set_ascii(get_soc_vendor(cpu->soc), s, cs); struct ascii* art = set_ascii(get_soc_vendor(cpu->soc), s, cs);
if(art == NULL) if(art == NULL)
return false; return false;
@@ -680,7 +753,11 @@ bool print_cpufetch_arm(struct cpuInfo* cpu, STYLE s, struct colors* cs) {
if(cpu->hv->present) if(cpu->hv->present)
setAttribute(art, ATTRIBUTE_HYPERVISOR, cpu->hv->hv_name); setAttribute(art, ATTRIBUTE_HYPERVISOR, cpu->hv->hv_name);
print_ascii(art); print_ascii(art, term);
if(loop_mode()) {
return run_loop_mode();
}
free(manufacturing_process); free(manufacturing_process);
free(pp); free(pp);
@@ -697,6 +774,31 @@ bool print_cpufetch_arm(struct cpuInfo* cpu, STYLE s, struct colors* cs) {
} }
#endif #endif
struct terminal* get_terminal_size() {
struct terminal* term = malloc(sizeof(struct terminal));
memset(term, 0, sizeof(struct terminal));
#ifdef _WIN32
CONSOLE_SCREEN_BUFFER_INFO csbi;
if(GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) == 0) {
printWarn("GetConsoleScreenBufferInfo failed");
return term;
}
term->w = csbi.srWindow.Right - csbi.srWindow.Left + 1;
term->h = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
#else
struct winsize w;
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == -1) {
perror("ioctl");
return term;
}
term->h = w.ws_row;
term->w = w.ws_col;
#endif
return term;
}
bool print_cpufetch(struct cpuInfo* cpu, STYLE s, struct colors* cs) { bool print_cpufetch(struct cpuInfo* cpu, STYLE s, struct colors* cs) {
// Sanity check of ASCII arts // Sanity check of ASCII arts
int len = sizeof(ASCII_ARRAY) / sizeof(ASCII_ARRAY[0]); int len = sizeof(ASCII_ARRAY) / sizeof(ASCII_ARRAY[0]);
@@ -707,10 +809,12 @@ bool print_cpufetch(struct cpuInfo* cpu, STYLE s, struct colors* cs) {
return false; return false;
} }
} }
struct terminal* term = get_terminal_size();
#ifdef ARCH_X86 #ifdef ARCH_X86
return print_cpufetch_x86(cpu, s, cs); return print_cpufetch_x86(cpu, s, cs, term);
#elif ARCH_ARM #elif ARCH_ARM
return print_cpufetch_arm(cpu, s, cs); return print_cpufetch_arm(cpu, s, cs, term);
#endif #endif
} }

View File

@@ -17,4 +17,8 @@ struct apic {
bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo); bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo);
uint32_t is_smt_enabled_amd(struct topology* topo); uint32_t is_smt_enabled_amd(struct topology* topo);
#ifndef __APPLE__
bool bind_to_cpu(int cpu_id);
#endif
#endif #endif

View File

@@ -310,11 +310,18 @@ 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); 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->arch = get_cpu_uarch(cpu);
cpu->freq = get_frequency_info(cpu); cpu->freq = get_frequency_info(cpu);
cpu->cach = get_cache_info(cpu); cpu->cach = get_cache_info(cpu);
cpu->topo = get_topology_info(cpu, cpu->cach); cpu->topo = get_topology_info(cpu, cpu->cach);
if(cpu->cach == NULL || cpu->topo == NULL) { if(cpu->cach == NULL || cpu->topo == NULL) {
return NULL; return NULL;
} }
@@ -322,7 +329,7 @@ struct cpuInfo* get_cpu_info() {
} }
bool get_cache_topology_amd(struct cpuInfo* cpu, struct topology* topo) { 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; uint32_t i, eax, ebx, ecx, edx, num_sharing_cache, cache_type, cache_level;
i = 0; i = 0;
@@ -379,7 +386,7 @@ bool get_cache_topology_amd(struct cpuInfo* cpu, struct topology* topo) {
} while (cache_type > 0); } while (cache_type > 0);
} }
else { 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->L1i->num_caches = topo->physical_cores;
topo->cach->L1d->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); cpuid(&eax, &ebx, &ecx, &edx);
topo->logical_cores = (ecx & 0xFF) + 1; topo->logical_cores = (ecx & 0xFF) + 1;
if (cpu->maxExtendedLevels >= 0x8000001E) { if (cpu->maxExtendedLevels >= 0x8000001E && cpu->topology_extensions) {
eax = 0x8000001E; eax = 0x8000001E;
cpuid(&eax, &ebx, &ecx, &edx); cpuid(&eax, &ebx, &ecx, &edx);
topo->smt_supported = ((ebx >> 8) & 0x03) + 1; topo->smt_supported = ((ebx >> 8) & 0x03) + 1;
} }
else { 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; topo->smt_supported = 1;
} }
} }
@@ -610,8 +617,8 @@ struct cache* get_cache_info(struct cpuInfo* cpu) {
} }
else { else {
level = 0x8000001D; level = 0x8000001D;
if(cpu->maxExtendedLevels < level) { 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)", level, cpu->maxExtendedLevels); 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; level = 0x80000006;
if(cpu->maxExtendedLevels < level) { 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); 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; return cach;
} }
@@ -890,14 +874,102 @@ void print_debug(struct cpuInfo* cpu) {
cpuid(&eax, &ebx, &ecx, &edx); cpuid(&eax, &ebx, &ecx, &edx);
printf("%s\n", cpu->cpu_name); 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 standard level: 0x%.8X\n", cpu->maxLevels);
printf("- Max extended level: 0x%.8X\n", cpu->maxExtendedLevels); 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); printf("- CPUID dump: 0x%.8X\n", eax);
free_cpuinfo_struct(cpu); 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) { void free_topo_struct(struct topology* topo) {
free(topo->apic->cache_select_mask); free(topo->apic->cache_select_mask);
free(topo->apic->cache_id_apic); 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); char* get_str_peak_performance(struct cpuInfo* cpu, struct topology* topo, int64_t freq);
void print_debug(struct cpuInfo* cpu); void print_debug(struct cpuInfo* cpu);
void print_raw(struct cpuInfo* cpu);
void free_topo_struct(struct topology* topo); void free_topo_struct(struct topology* topo);