diff --git a/Makefile b/Makefile index 2194934..463e90d 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC ?= gcc -CFLAGS+=-Wall -Wextra -pedantic -fstack-protector-all -pedantic -std=c99 +CFLAGS+=-Wall -Wextra -pedantic -fstack-protector-all -pedantic SANITY_FLAGS=-Wfloat-equal -Wshadow -Wpointer-arith PREFIX ?= /usr @@ -16,18 +16,18 @@ ifneq ($(OS),Windows_NT) SRC_DIR=src/x86/ SOURCE += $(COMMON_SRC) $(SRC_DIR)cpuid.c $(SRC_DIR)apic.c $(SRC_DIR)cpuid_asm.c $(SRC_DIR)uarch.c HEADERS += $(COMMON_HDR) $(SRC_DIR)cpuid.h $(SRC_DIR)apic.h $(SRC_DIR)cpuid_asm.h $(SRC_DIR)uarch.h - CFLAGS += -DARCH_X86 + CFLAGS += -DARCH_X86 -std=c99 else ifeq ($(arch), $(filter $(arch), ppc64el ppc64le ppc32)) SRC_DIR=src/ppc/ SOURCE += $(COMMON_SRC) $(SRC_DIR)ppc.c $(SRC_DIR)uarch.c $(SRC_DIR)udev.c HEADERS += $(COMMON_HDR) $(SRC_DIR)ppc.h $(SRC_DIR)uarch.h $(SRC_DIR)udev.c - CFLAGS += -DARCH_PPC + CFLAGS += -DARCH_PPC -std=gnu99 else # Assume ARM SRC_DIR=src/arm/ SOURCE += $(COMMON_SRC) $(SRC_DIR)midr.c $(SRC_DIR)uarch.c $(SRC_DIR)soc.c $(SRC_DIR)udev.c HEADERS += $(COMMON_HDR) $(SRC_DIR)midr.h $(SRC_DIR)uarch.h $(SRC_DIR)soc.h $(SRC_DIR)udev.c $(SRC_DIR)socs.h - CFLAGS += -DARCH_ARM -Wno-unused-parameter + CFLAGS += -DARCH_ARM -Wno-unused-parameter -std=c99 endif OUTPUT=cpufetch @@ -37,7 +37,7 @@ else SOURCE += $(COMMON_SRC) $(SRC_DIR)cpuid.c $(SRC_DIR)apic.c $(SRC_DIR)cpuid_asm.c $(SRC_DIR)uarch.c HEADERS += $(COMMON_HDR) $(SRC_DIR)cpuid.h $(SRC_DIR)apic.h $(SRC_DIR)cpuid_asm.h $(SRC_DIR)uarch.h CFLAGS += -DARCH_X86 - SANITY_FLAGS += -Wno-pedantic-ms-format + SANITY_FLAGS += -Wno-pedantic-ms-format -std=c99 OUTPUT=cpufetch.exe endif diff --git a/src/ppc/ppc.c b/src/ppc/ppc.c index 4216b62..513c321 100644 --- a/src/ppc/ppc.c +++ b/src/ppc/ppc.c @@ -105,6 +105,19 @@ struct topology* get_topology_info(struct cpuInfo* cpu, struct cache* cach) { return topo; } +static inline uint32_t mfpvr() { + uint32_t pvr; + + asm ("mfpvr %0" + : "=r"(pvr)); + return pvr; +} + +struct uarch* get_cpu_uarch() { + uint32_t pvr = mfpvr(); + return get_uarch_from_pvr(pvr); +} + struct cpuInfo* get_cpu_info() { struct cpuInfo* cpu = malloc(sizeof(struct cpuInfo)); struct features* feat = malloc(sizeof(struct features)); @@ -118,7 +131,7 @@ struct cpuInfo* get_cpu_info() { cpu->cpu_name = malloc(sizeof(char) * strlen(STRING_UNKNOWN) + 1); snprintf(cpu->cpu_name, strlen(STRING_UNKNOWN) + 1, STRING_UNKNOWN); - cpu->arch = get_uarch_from_auxval(cpu); + cpu->arch = get_cpu_uarch(); cpu->cach = get_cache_info(cpu); cpu->topo = get_topology_info(cpu, cpu->cach); diff --git a/src/ppc/pvr_kern_to_cpufetch.sh b/src/ppc/pvr_kern_to_cpufetch.sh new file mode 100755 index 0000000..2ad6a91 --- /dev/null +++ b/src/ppc/pvr_kern_to_cpufetch.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# This script takes as input cputable.c from linux kernel +# and generates a valid output for cpufetch in src/ppc/uarch.c + +CPUTABLE_PATH="linux-5.13.7/arch/powerpc/kernel/cputable.c" + +raw_values=$(grep '\.pvr_value' "$CPUTABLE_PATH" | grep -oP "= .*," | cut -d' ' -f2 | tr -d ',') +raw_masks=$(grep '\.pvr_mask' "$CPUTABLE_PATH" | grep -oE "0x........") + +raw_v_len=$(echo "$raw_values" | wc -l) +raw_m_len=$(echo "$raw_masks" | wc -l) + +if [ $raw_v_len -ne $raw_m_len ] +then + echo "Lengths do not match!" + echo "values length: $raw_v_len" + echo "masks length: $raw_m_len" + exit 1 +fi + +IFS=$'\n' read -r -d ' ' -a values <<< "$raw_values" +IFS=$'\n' read -r -d ' ' -a masks <<< "$raw_masks" + +for i in "${!values[@]}" +do + echo ' CHECK_UARCH(arch, pvr, '"${masks[i]}"', '"${values[i]}"', "POWERX", UARCH_POWERX, -1)' +done diff --git a/src/ppc/uarch.c b/src/ppc/uarch.c index e3e7b13..cf93314 100644 --- a/src/ppc/uarch.c +++ b/src/ppc/uarch.c @@ -21,7 +21,21 @@ typedef uint32_t MICROARCH; enum { UARCH_UNKNOWN, - UARCH_POWER9 + UARCH_PPC604, + UARCH_PPCG3, + UARCH_PPCG4, + UARCH_PPC405, + UARCH_PPC603, + UARCH_PPC440, + UARCH_PPC470, + UARCH_PPC970, + UARCH_CELLBE, + UARCH_POWER5, + UARCH_POWER6, + UARCH_POWER7, + UARCH_POWER8, + UARCH_POWER9, + UARCH_POWER10, }; struct uarch { @@ -31,9 +45,9 @@ struct uarch { }; #define UARCH_START if (false) {} -#define CHECK_UARCH(arch, auxv_plat_ret, auxv_plat, str, uarch, process) \ - else if (strcmp(auxv_plat_ret, auxv_plat) == 0) fill_uarch(arch, str, uarch, process); -#define UARCH_END else { printBug("Unknown microarchitecture detected: '%s'", platform); fill_uarch(arch, "Unknown", UARCH_UNKNOWN, 0); } +#define CHECK_UARCH(arch, cpu_pvr, pvr_mask, pvr_value, str, uarch, process) \ + else if ((cpu_pvr & pvr_mask) == pvr_value) fill_uarch(arch, str, uarch, process); +#define UARCH_END else { printBug("Unknown microarchitecture detected: 0x%.8X", pvr); fill_uarch(arch, "Unknown", UARCH_UNKNOWN, 0); } void fill_uarch(struct uarch* arch, char* str, MICROARCH u, uint32_t process) { arch->uarch_str = malloc(sizeof(char) * (strlen(str)+1)); @@ -42,19 +56,127 @@ void fill_uarch(struct uarch* arch, char* str, MICROARCH u, uint32_t process) { arch->process= process; } -struct uarch* get_uarch_from_auxval() { +/* + * PVR masks/values from arch/powerpc/kernel/cputable.c (Linux kernel) + * This list may be incorrect, incomplete or overly simplified, + * specially in the case of 32 bit entries + */ +struct uarch* get_uarch_from_pvr(uint32_t pvr) { struct uarch* arch = malloc(sizeof(struct uarch)); - unsigned long ret = getauxval(AT_PLATFORM); - if(ret == 0 && errno == ENOENT) { - printErr("Entry AT_PLATFORM not found in getauxval"); - perror("getauxval"); - } - - char* platform = (char *) ret; - UARCH_START - CHECK_UARCH(arch, platform, "power9", "POWER 9", UARCH_POWER9, 14) + // 64 bit + CHECK_UARCH(arch, pvr, 0xffff0000, 0x00390000, "PPC970", UARCH_PPC970, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x003c0000, "PPC970", UARCH_PPC970, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x00440100, "PPC970", UARCH_PPC970, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x00440000, "PPC970", UARCH_PPC970, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x00450000, "PPC970", UARCH_PPC970, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x003a0000, "POWER5", UARCH_POWER5, -1) + CHECK_UARCH(arch, pvr, 0xffffff00, 0x003b0300, "POWER5", UARCH_POWER5, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x003b0000, "POWER5", UARCH_POWER5, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x0f000001, "POWER5", UARCH_POWER5, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x003e0000, "POWER6", UARCH_POWER6, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x0f000002, "POWER6", UARCH_POWER6, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x0f000003, "POWER7", UARCH_POWER7, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x0f000004, "POWER8", UARCH_POWER8, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x0f000005, "POWER9", UARCH_POWER9, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x0f000006, "POWER10", UARCH_POWER10, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x003f0000, "POWER7", UARCH_POWER7, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x004A0000, "POWER7", UARCH_POWER7, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x004b0000, "POWER8", UARCH_POWER8, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x004c0000, "POWER8", UARCH_POWER8, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x004d0000, "POWER8", UARCH_POWER8, -1) + CHECK_UARCH(arch, pvr, 0xffffefff, 0x004e0200, "POWER9", UARCH_POWER9, -1) + CHECK_UARCH(arch, pvr, 0xffffefff, 0x004e0201, "POWER9", UARCH_POWER9, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x004e0000, "POWER9", UARCH_POWER9, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x00800000, "POWER10", UARCH_POWER10, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x00700000, "Cell BE", UARCH_CELLBE, -1) + // 32 bit + CHECK_UARCH(arch, pvr, 0xffff0000, 0x00040000, "PowerPC C604", UARCH_PPC604, -1) + CHECK_UARCH(arch, pvr, 0xfffff000, 0x00090000, "PowerPC C604", UARCH_PPC604, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x00090000, "PowerPC C604", UARCH_PPC604, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x000a0000, "PowerPC C604", UARCH_PPC604, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x00084202, "PowerPC G3", UARCH_PPCG3, -1) + CHECK_UARCH(arch, pvr, 0xfffffff0, 0x00080100, "PowerPC G3", UARCH_PPCG3, -1) + CHECK_UARCH(arch, pvr, 0xfffffff0, 0x00082200, "PowerPC G3", UARCH_PPCG3, -1) + CHECK_UARCH(arch, pvr, 0xfffffff0, 0x00082210, "PowerPC G3", UARCH_PPCG3, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x00083214, "PowerPC G3", UARCH_PPCG3, -1) + CHECK_UARCH(arch, pvr, 0xfffff0e0, 0x00087000, "PowerPC G3", UARCH_PPCG3, -1) + CHECK_UARCH(arch, pvr, 0xfffff000, 0x00083000, "PowerPC G3", UARCH_PPCG3, -1) + CHECK_UARCH(arch, pvr, 0xffffff00, 0x70000100, "PowerPC G3", UARCH_PPCG3, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x70000200, "PowerPC G3", UARCH_PPCG3, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x70000000, "PowerPC G3", UARCH_PPCG3, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x70020000, "PowerPC G3", UARCH_PPCG3, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x00080000, "PowerPC G3", UARCH_PPCG3, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x000c1101, "PowerPC G4", UARCH_PPCG4, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x000c0000, "PowerPC G4", UARCH_PPCG4, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x800c0000, "PowerPC G4", UARCH_PPCG4, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x80000200, "PowerPC G4", UARCH_PPCG4, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x80000201, "PowerPC G4", UARCH_PPCG4, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x80000000, "PowerPC G4", UARCH_PPCG4, -1) + CHECK_UARCH(arch, pvr, 0xffffff00, 0x80010100, "PowerPC G4", UARCH_PPCG4, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x80010200, "PowerPC G4", UARCH_PPCG4, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x80010000, "PowerPC G4", UARCH_PPCG4, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x80020100, "PowerPC G4", UARCH_PPCG4, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x80020101, "PowerPC G4", UARCH_PPCG4, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x80020000, "PowerPC G4", UARCH_PPCG4, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x80030000, "PowerPC G4", UARCH_PPCG4, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x80040000, "PowerPC G4", UARCH_PPCG4, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x00030000, "PowerPC 603", UARCH_PPC603, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x00060000, "PowerPC 603", UARCH_PPC603, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x00070000, "PowerPC 603", UARCH_PPC603, -1) + CHECK_UARCH(arch, pvr, 0x7fff0000, 0x00810000, "PowerPC 603", UARCH_PPC603, -1) + CHECK_UARCH(arch, pvr, 0x7fff0000, 0x00820000, "PowerPC 603", UARCH_PPC603, -1) + CHECK_UARCH(arch, pvr, 0x7fff0000, 0x00830000, "PowerPC 603", UARCH_PPC603, -1) + CHECK_UARCH(arch, pvr, 0x7fff0000, 0x00840000, "PowerPC 603", UARCH_PPC603, -1) + CHECK_UARCH(arch, pvr, 0x7fff0000, 0x00850000, "PowerPC 603", UARCH_PPC603, -1) + CHECK_UARCH(arch, pvr, 0x7fff0000, 0x00860000, "PowerPC 603", UARCH_PPC603, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x41810000, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x41610000, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x40B10000, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x41410000, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x50910000, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x51510000, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x41F10000, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x51210000, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff000f, 0x12910007, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff000f, 0x1291000d, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff000f, 0x1291000f, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff000f, 0x12910003, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff000f, 0x12910005, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff000f, 0x12910001, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff000f, 0x12910009, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff000f, 0x1291000b, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff000f, 0x12910000, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff000f, 0x12910002, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x41510000, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x7ff11432, "PowerPC 405", UARCH_PPC405, -1) + CHECK_UARCH(arch, pvr, 0xf0000fff, 0x40000850, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xf0000fff, 0x40000858, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xf0000fff, 0x400008d3, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xf0000ff7, 0x400008d4, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xf0000fff, 0x400008db, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xf0000ffb, 0x200008D0, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xf0000ffb, 0x200008D8, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xf0000fff, 0x40000440, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xf0000fff, 0x40000481, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xf0000fff, 0x50000850, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xf0000fff, 0x50000851, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xf0000fff, 0x50000892, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xf0000fff, 0x50000894, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xfff00fff, 0x53200891, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xfff00fff, 0x53400890, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xfff00fff, 0x53400891, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xffff0006, 0x13020002, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xffff0007, 0x13020004, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xffff0006, 0x13020000, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xffff0007, 0x13020005, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xffffff00, 0x13541800, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xfffffff0, 0x12C41C80, "PowerPC 440", UARCH_PPC440, -1) + CHECK_UARCH(arch, pvr, 0xffffffff, 0x11a52080, "PowerPC 470", UARCH_PPC470, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x7ff50000, "PowerPC 470", UARCH_PPC470, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x00050000, "PowerPC 470", UARCH_PPC470, -1) + CHECK_UARCH(arch, pvr, 0xffff0000, 0x11a50000, "PowerPC 470", UARCH_PPC470, -1) UARCH_END return arch; diff --git a/src/ppc/uarch.h b/src/ppc/uarch.h index 585409a..60c78b1 100644 --- a/src/ppc/uarch.h +++ b/src/ppc/uarch.h @@ -1,11 +1,12 @@ #ifndef __UARCH__ #define __UARCH__ +#include #include "ppc.h" struct uarch; -struct uarch* get_uarch_from_auxval(); +struct uarch* get_uarch_from_pvr(uint32_t pvr); char* get_str_uarch(struct cpuInfo* cpu); char* get_str_process(struct cpuInfo* cpu); void free_uarch_struct(struct uarch* arch);