cosmopolitan/tool/viz/cpuid.c

321 lines
8.8 KiB
C

/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2020 Justine Alexandra Roberts Tunney │
│ │
│ This program is free software; you can redistribute it and/or modify │
│ it under the terms of the GNU General Public License as published by │
│ the Free Software Foundation; version 2 of the License. │
│ │
│ This program is distributed in the hope that it will be useful, but │
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
│ General Public License for more details. │
│ │
│ You should have received a copy of the GNU General Public License │
│ along with this program; if not, write to the Free Software │
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
│ 02110-1301 USA │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/log/color.internal.h"
#include "libc/log/log.h"
#include "libc/nexgen32e/cpuid4.internal.h"
#include "libc/nexgen32e/nexgen32e.h"
#include "libc/nexgen32e/rdtscp.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/nexgen32e/x86info.h"
#include "libc/runtime/gc.h"
#include "libc/stdio/stdio.h"
#include "libc/time/time.h"
#include "libc/x/x.h"
#include "tool/decode/lib/idname.h"
#include "tool/decode/lib/x86idnames.h"
#define CANIUSE(FEATURE) caniuse(#FEATURE, X86_HAVE(FEATURE))
#define SHOW(CONSTANT) show(#CONSTANT, CONSTANT)
static void caniuse(const char *feature, bool present) {
printf("%-20s%s%s%s\n", feature, present ? GREEN : RED,
present ? "present" : "unavailable", RESET);
}
static void show(const char *constant, long value) {
printf("%-20s%#lx\n", constant, value);
}
static void showvendor(void) {
printf("%.*s%.*s%.*s", 4, &KCPUIDS(0H, EBX), 4, &KCPUIDS(0H, EDX), 4,
&KCPUIDS(0H, ECX));
}
static void showmodel(void) {
if (getx86processormodel(kX86ProcessorModelKey)) {
printf(" %s",
findnamebyid(kX86MarchNames,
getx86processormodel(kX86ProcessorModelKey)->march));
}
}
static void showspeed(void) {
if (KCPUIDS(16H, EAX)) {
printf(" %.1f%s", KCPUIDS(16H, EAX) / 1000.0, "ghz");
}
}
static void showstrata(void) {
if (getx86processormodel(kX86ProcessorModelKey)) {
printf(" (%s %s)",
findnamebyid(kX86GradeNames,
getx86processormodel(kX86ProcessorModelKey)->grade),
"Grade");
}
}
void showcachesizes(void) {
unsigned i;
CPUID4_ITERATE(i, {
printf("%-19s%s%s %u-way %,7u byte cache w/%s %,5u sets of %u byte lines "
"shared across %u threads\n",
gc(xasprintf("Level %u%s", CPUID4_CACHE_LEVEL,
CPUID4_CACHE_TYPE == 1
? " data"
: CPUID4_CACHE_TYPE == 2 ? " code" : "")),
CPUID4_IS_FULLY_ASSOCIATIVE ? " fully-associative" : "",
CPUID4_COMPLEX_INDEXING ? " complexly-indexed" : "",
CPUID4_WAYS_OF_ASSOCIATIVITY, CPUID4_CACHE_SIZE_IN_BYTES,
CPUID4_PHYSICAL_LINE_PARTITIONS > 1
? gc(xasprintf(" %u physically partitioned"))
: "",
CPUID4_NUMBER_OF_SETS, CPUID4_SYSTEM_COHERENCY_LINE_SIZE,
CPUID4_MAX_THREADS_SHARING_CACHE);
});
}
int main(int argc, char *argv[]) {
long tsc_aux;
showvendor();
showmodel();
showspeed();
showstrata();
printf("\n");
if (X86_HAVE(HYPERVISOR)) {
unsigned eax, ebx, ecx, edx;
asm("push\t%%rbx\n\t"
"cpuid\n\t"
"mov\t%%ebx,%1\n\t"
"pop\t%%rbx"
: "=a"(eax), "=rm"(ebx), "=c"(ecx), "=d"(edx)
: "0"(0x40000000), "2"(0));
printf("Running inside %.4s%.4s%.4s (eax=%#x)\n", &ebx, &ecx, &edx, eax);
}
printf("\n");
SHOW(kX86CpuStepping);
SHOW(kX86CpuModelid);
SHOW(kX86CpuFamilyid);
SHOW(kX86CpuType);
SHOW(kX86CpuExtmodelid);
SHOW(kX86CpuExtfamilyid);
printf("\n");
tsc_aux = rdpid();
show("TSC_AUX", tsc_aux);
show(" → core", TSC_AUX_CORE(tsc_aux));
show(" → node", TSC_AUX_NODE(tsc_aux));
printf("\n");
printf("Caches\n");
printf("──────\n");
showcachesizes();
printf("\n");
printf("Features\n");
printf("────────\n");
CANIUSE(ACC);
CANIUSE(ACPI);
CANIUSE(ADX);
CANIUSE(AES);
CANIUSE(APIC);
CANIUSE(ARCH_CAPABILITIES);
CANIUSE(AVX);
printf("%-20s%s%s%s%s\n", "AVX2", X86_HAVE(AVX2) ? GREEN : RED,
X86_HAVE(AVX2) ? "present" : "unavailable", RESET,
(!X86_HAVE(AVX2) && ({
unsigned eax, ebx, ecx, edx;
asm("push\t%%rbx\n\t"
"cpuid\n\t"
"mov\t%%ebx,%1\n\t"
"pop\t%%rbx"
: "=a"(eax), "=rm"(ebx), "=c"(ecx), "=d"(edx)
: "0"(7), "2"(0));
(void)eax;
(void)ecx;
(void)edx;
!!(ebx & (1u << 5));
}))
? " (disabled by operating system)"
: "");
CANIUSE(AVX512BW);
CANIUSE(AVX512CD);
CANIUSE(AVX512DQ);
CANIUSE(AVX512ER);
CANIUSE(AVX512F);
CANIUSE(AVX512IFMA);
CANIUSE(AVX512PF);
CANIUSE(AVX512VBMI);
CANIUSE(AVX512VL);
CANIUSE(AVX512_4FMAPS);
CANIUSE(AVX512_4VNNIW);
CANIUSE(AVX512_BF16);
CANIUSE(AVX512_BITALG);
CANIUSE(AVX512_VBMI2);
CANIUSE(AVX512_VNNI);
CANIUSE(AVX512_VP2INTERSECT);
CANIUSE(AVX512_VPOPCNTDQ);
CANIUSE(BMI);
CANIUSE(BMI2);
CANIUSE(CID);
CANIUSE(CLDEMOTE);
CANIUSE(CLFLUSH);
CANIUSE(CLFLUSHOPT);
CANIUSE(CLWB);
CANIUSE(CMOV);
CANIUSE(CQM);
CANIUSE(CX16);
CANIUSE(CX8);
CANIUSE(DCA);
CANIUSE(DE);
CANIUSE(DS);
CANIUSE(DSCPL);
CANIUSE(DTES64);
CANIUSE(ERMS);
CANIUSE(EST);
CANIUSE(F16C);
CANIUSE(FDP_EXCPTN_ONLY);
CANIUSE(FLUSH_L1D);
CANIUSE(FMA);
CANIUSE(FPU);
CANIUSE(FSGSBASE);
CANIUSE(FXSR);
CANIUSE(GBPAGES);
CANIUSE(GFNI);
CANIUSE(HLE);
CANIUSE(HT);
CANIUSE(HYPERVISOR);
CANIUSE(IA64);
CANIUSE(INTEL_PT);
CANIUSE(INTEL_STIBP);
CANIUSE(INVPCID);
CANIUSE(LA57);
CANIUSE(LM);
CANIUSE(MCA);
CANIUSE(MCE);
CANIUSE(MD_CLEAR);
CANIUSE(MMX);
CANIUSE(MOVBE);
CANIUSE(MOVDIR64B);
CANIUSE(MOVDIRI);
CANIUSE(MP);
CANIUSE(MPX);
CANIUSE(MSR);
CANIUSE(MTRR);
CANIUSE(MWAIT);
CANIUSE(NX);
CANIUSE(OSPKE);
CANIUSE(OSXSAVE);
CANIUSE(PAE);
CANIUSE(PAT);
CANIUSE(PBE);
CANIUSE(PCID);
CANIUSE(PCLMUL);
CANIUSE(PCONFIG);
CANIUSE(PDCM);
CANIUSE(PGE);
CANIUSE(PKU);
CANIUSE(PN);
CANIUSE(POPCNT);
CANIUSE(PSE);
CANIUSE(PSE36);
CANIUSE(RDPID);
CANIUSE(RDRND);
CANIUSE(RDSEED);
CANIUSE(RDTSCP);
CANIUSE(RDT_A);
CANIUSE(RTM);
CANIUSE(SDBG);
CANIUSE(SELFSNOOP);
CANIUSE(SEP);
CANIUSE(SHA);
CANIUSE(SMAP);
CANIUSE(SMEP);
CANIUSE(SMX);
CANIUSE(SPEC_CTRL);
CANIUSE(SPEC_CTRL_SSBD);
CANIUSE(SSE);
CANIUSE(SSE2);
CANIUSE(SSE3);
CANIUSE(SSE4_1);
CANIUSE(SSE4_2);
CANIUSE(SSSE3);
CANIUSE(SYSCALL);
CANIUSE(TM2);
CANIUSE(TME);
CANIUSE(TSC);
CANIUSE(TSC_ADJUST);
CANIUSE(TSC_DEADLINE_TIMER);
CANIUSE(TSX_FORCE_ABORT);
CANIUSE(UMIP);
CANIUSE(VAES);
CANIUSE(VME);
CANIUSE(VMX);
CANIUSE(VPCLMULQDQ);
CANIUSE(WAITPKG);
CANIUSE(X2APIC);
CANIUSE(XSAVE);
CANIUSE(XTPR);
CANIUSE(ZERO_FCS_FDS);
printf("\n");
printf("AMD Stuff\n");
printf("─────────\n");
CANIUSE(3DNOW);
CANIUSE(3DNOWEXT);
CANIUSE(3DNOWPREFETCH);
CANIUSE(ABM);
CANIUSE(BPEXT);
CANIUSE(CMP_LEGACY);
CANIUSE(CR8_LEGACY);
CANIUSE(EXTAPIC);
CANIUSE(FMA4);
CANIUSE(FXSR_OPT);
CANIUSE(IBS);
CANIUSE(LAHF_LM);
CANIUSE(LWP);
CANIUSE(MISALIGNSSE);
CANIUSE(MMXEXT);
CANIUSE(MWAITX);
CANIUSE(NODEID_MSR);
CANIUSE(OSVW);
CANIUSE(OVERFLOW_RECOV);
CANIUSE(PERFCTR_CORE);
CANIUSE(PERFCTR_LLC);
CANIUSE(PERFCTR_NB);
CANIUSE(PTSC);
CANIUSE(SKINIT);
CANIUSE(SMCA);
CANIUSE(SSE4A);
CANIUSE(SUCCOR);
CANIUSE(SVM);
CANIUSE(TBM);
CANIUSE(TCE);
CANIUSE(TOPOEXT);
CANIUSE(WDT);
CANIUSE(XOP);
return 0;
}