Created
August 14, 2019 19:38
-
-
Save alphaKAI/bc482de585c3728b84773fc95f405992 to your computer and use it in GitHub Desktop.
manipulate CPUID instruction
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import std.stdio; | |
import std.conv; | |
import std.string; | |
struct Regs { | |
uint a, b, c, d; | |
} | |
Regs cpuid(uint eax) { | |
Regs r; | |
asm { | |
mov EAX, eax; | |
cpuid; | |
mov r, EAX; | |
mov r + 4, EBX; | |
mov r + 8, ECX; | |
mov r + 12, EDX; | |
} | |
return r; | |
} | |
string getVenderID() { | |
auto r = cpuid(0); | |
char[12] buf = 0; | |
foreach (i, v; [r.b, r.d, r.c]) { | |
foreach (j; 0 .. 4) { | |
buf[i * 4 + j] = (v >> (j * 8)) & 0xFF; | |
} | |
} | |
return buf.to!string; | |
} | |
string getCPUName() { | |
char[48] buf; | |
foreach (t, eax; [0x80000002, 0x80000003, 0x80000004]) { | |
auto r = cpuid(eax); | |
foreach (i, v; [r.a, r.b, r.c, r.d]) { | |
foreach (j; 0 .. 4) { | |
char c = (v >> (j * 8)) & 0xFF; | |
buf[t * 16 + i * 4 + j] = c; | |
} | |
} | |
} | |
return (cast(char*)&buf).fromStringz.to!string; | |
} | |
struct TypeModelFamily { | |
ubyte stepping; | |
ubyte model; | |
ubyte family; | |
ubyte type; | |
} | |
struct AdditionalInfo { | |
ubyte brand_index; | |
ubyte CLFLUSH_line_size; | |
ubyte max_logical_cpus; | |
ubyte local_apic_id; | |
} | |
struct FeatureInfo { | |
bool fpu, vme, de, pse, tsc, msr, pae, mce, cx8, apic, sep, mttr, pge, mca, | |
cmov, pat, pse_36, psn, clfsh, ds, acpi, mmx, fxsr, sse, sse2, ss, htt, tm, ia64, pbe; | |
bool sse3, pclmulqdq, dtes64, monitor, ds_cpl, vmx, smx, est, tm2, ssse3, | |
cnxt_id, sdbg, fma, cx16, xtpr, pdcm, pcid, dca, sse4_1, sse4_2, x2apic, | |
movbe, popcnt, tsc_deadline, aes, xsave, osxsave, avx, f16c, rdrnd, hypervisor; | |
} | |
struct CPUInfo { | |
TypeModelFamily tmf; | |
AdditionalInfo add_info; | |
FeatureInfo feature_info; | |
} | |
CPUInfo getCPUInfo() { | |
auto r = cpuid(1); | |
ubyte stepping = (r.a) & 0b1111; | |
ubyte model = (r.a >> 4) & 0b1111; | |
ubyte family = (r.a >> 8) & 0b1111; | |
ubyte type = (r.a >> 12) & 0b11; | |
ubyte emodel = (r.a >> 16) & 0b1111; | |
ubyte efamily = cast(byte)((r.a >> 20) & 0xFF); | |
/* | |
writefln("stepping : %d(%b)", stepping, stepping); | |
writefln("model : %d(%b)", model, model); | |
writefln("family : %d(%b)", family, family); | |
writefln("type : %d(%b)", type, type); | |
writefln("emodel : %d(%b)", emodel, emodel); | |
writefln("efamily : %d(%b)", efamily, efamily); | |
writeln("actual...:"); | |
*/ | |
ubyte amodel = (family == 6 || family == 15) ? cast(ubyte)(emodel << 4 | model) : model; | |
//writefln("amodel : %d(%x)", amodel, amodel); | |
ubyte afamily = family == 15 ? cast(ubyte)(efamily + family) : family; | |
//writefln("family : %d(%x)", afamily, afamily); | |
auto tmf = TypeModelFamily(stepping, amodel, afamily, type); | |
ubyte brand_index = r.b & 0xFF; | |
ubyte CLFLUSH_line_size = (r.b >> 8) & 0xFF; | |
ubyte max_logical_cpus = (r.b >> 16) & 0xFF; | |
ubyte local_apic_id = (r.b >> 24) & 0xFF; | |
auto add_info = AdditionalInfo(brand_index, CLFLUSH_line_size, max_logical_cpus, local_apic_id); | |
bool fpu = r.d & 1; | |
bool vme = (r.d >> 1) & 1; | |
bool de = (r.d >> 2) & 1; | |
bool pse = (r.d >> 3) & 1; | |
bool tsc = (r.d >> 4) & 1; | |
bool msr = (r.d >> 5) & 1; | |
bool pae = (r.d >> 6) & 1; | |
bool mce = (r.d >> 7) & 1; | |
bool cx8 = (r.d >> 8) & 1; | |
bool apic = (r.d >> 9) & 1; | |
bool sep = (r.d >> 11) & 1; | |
bool mttr = (r.d >> 12) & 1; | |
bool pge = (r.d >> 13) & 1; | |
bool mca = (r.d >> 14) & 1; | |
bool cmov = (r.d >> 15) & 1; | |
bool pat = (r.d >> 16) & 1; | |
bool pse_36 = (r.d >> 17) & 1; | |
bool psn = (r.d >> 18) & 1; | |
bool clfsh = (r.d >> 19) & 1; | |
bool ds = (r.d >> 21) & 1; | |
bool acpi = (r.d >> 22) & 1; | |
bool mmx = (r.d >> 23) & 1; | |
bool fxsr = (r.d >> 24) & 1; | |
bool sse = (r.d >> 25) & 1; | |
bool sse2 = (r.d >> 26) & 1; | |
bool ss = (r.d >> 27) & 1; | |
bool htt = (r.d >> 28) & 1; | |
bool tm = (r.d >> 29) & 1; | |
bool ia64 = (r.d >> 30) & 1; | |
bool pbe = (r.d >> 31) & 1; | |
bool sse3 = r.c & 1, pclmulqdq = (r.c >> 1) & 1, dtes64 = (r.c >> 2) & 1, | |
monitor = (r.c >> 3) & 1, ds_cpl = (r.c >> 4) & 1, vmx = (r.c >> 5) & 1, | |
smx = (r.c >> 6) & 1, est = (r.c >> 7) & 1, tm2 = (r.c >> 8) & 1, | |
ssse3 = (r.c >> 9) & 1, cnxt_id = (r.c >> 10) & 1, sdbg = (r.c >> 11) & 1, | |
fma = (r.c >> 12) & 1, cx16 = (r.c >> 13) & 1, xtpr = (r.c >> 14) & 1, | |
pdcm = (r.c >> 15) & 1, pcid = (r.c >> 17) & 1, dca = (r.c >> 18) & 1, | |
sse4_1 = (r.c >> 19) & 1, sse4_2 = (r.c >> 20) & 1, x2apic = (r.c >> 21) & 1, | |
movbe = (r.c >> 22) & 1, popcnt = (r.c >> 23) & 1, | |
tsc_deadline = (r.c >> 24) & 1, aes = (r.c >> 25) & 1, xsave = (r.c >> 26) & 1, | |
osxsave = (r.c >> 27) & 1, avx = (r.c >> 28) & 1, f16c = (r.c >> 29) & 1, | |
rdrnd = (r.c >> 30) & 1, hypervisor = (r.c >> 31) & 1; | |
auto feature_info = FeatureInfo(fpu, vme, de, pse, tsc, msr, pae, mce, cx8, | |
apic, sep, mttr, pge, mca, cmov, pat, pse_36, psn, clfsh, ds, acpi, | |
mmx, fxsr, sse, sse2, ss, htt, tm, ia64, pbe, sse3, pclmulqdq, dtes64, | |
monitor, ds_cpl, vmx, smx, est, tm2, ssse3, cnxt_id, sdbg, fma, cx16, | |
xtpr, pdcm, pcid, dca, sse4_1, sse4_2, x2apic, movbe, popcnt, | |
tsc_deadline, aes, xsave, osxsave, avx, f16c, rdrnd, hypervisor); | |
return CPUInfo(tmf, add_info, feature_info); | |
} | |
void printCPUInfo(const ref CPUInfo info) { | |
with (info) { | |
with (tmf) { | |
writefln("stepping : %d(%b)", stepping, stepping); | |
writefln("model : %d(%b)", model, model); | |
writefln("family : %d(%b)", family, family); | |
writefln("type : %d(%b)", type, type); | |
} | |
with (add_info) { | |
writefln("brand_index : %d(%b)", brand_index, brand_index); | |
writefln("CLFLUSH_line_size : %d(%b)", CLFLUSH_line_size, CLFLUSH_line_size); | |
writefln("max_logical_cpus : %d(%b)", max_logical_cpus, max_logical_cpus); | |
writefln("local_apic_id : %d(%b)", local_apic_id, local_apic_id); | |
} | |
with (feature_info) { | |
writeln("Onboard x87 FPU : ", fpu); | |
writeln("Virtual 8086 mode extensions : ", vme); | |
writeln("Debugging extensions : ", de); | |
writeln("Page Size Extension : ", pse); | |
writeln("Time Stamp Counter : ", tsc); | |
writeln("Model-specific registers : ", msr); | |
writeln("Pysical Address Extension : ", pae); | |
writeln("Machine Check Exception : ", mce); | |
writeln("CMPXCHG8 (compare-and-swap) instruction : ", cx8); | |
writeln("Onboard Advanced Programmable Interrupt Controller : ", apic); | |
writeln("SYSENTER and SYSEXIT instructions : ", sep); | |
writeln("Memory Type Range Registers : ", mttr); | |
writeln("Page Global Enable bit in CR4 : ", pge); | |
writeln("Machine check architecture : ", mca); | |
writeln("Conditional move and FCMOV instructions : ", cmov); | |
writeln("Page Attribute Table : ", pat); | |
writeln("36-bit page size extension : ", pse_36); | |
writeln("Processor Serial Number : ", psn); | |
writeln("CLFLUSH instruction (SSE2) : ", clfsh); | |
writeln("Debug store: save trace of executed jumps : ", ds); | |
writeln("Onboard thermal control MSRs for ACPI : ", acpi); | |
writeln("MMX instructions : ", mmx); | |
writeln("FXSAVE, FXRESTOR instructions, CR4 bit 9 : ", fxsr); | |
writeln("SSE instructions : ", sse); | |
writeln("SSE2 instructions : ", sse2); | |
writeln("CPU cache implements self-snoop : ", ss); | |
writeln("Hyper-threading : ", htt); | |
writeln("Thermal monitor automatically limits temperature : ", tm); | |
writeln("IA64 processor emulating x86 : ", ia64); | |
writeln("Pending Break Enable (PBE# pin) wakeup capability : ", pbe); | |
writeln("Prescott New Instructions-SSE3 (PNI) : ", sse3); | |
writeln("PCLMULQDQ : ", pclmulqdq); | |
writeln("64-bit debug store (edx bit 21) : ", dtes64); | |
writeln("MONITOR and MWAIT instructions (SSE3) : ", monitor); | |
writeln("CPL qualified debug store : ", ds_cpl); | |
writeln("Virtual Machine eXtensions : ", vmx); | |
writeln("Safer Mode Extensions (LaGrande) : ", smx); | |
writeln("Enhanced SpeedStep : ", est); | |
writeln("Thermal Monitor 2 : ", tm2); | |
writeln("Supplemental SSE3 instructions : ", ssse3); | |
writeln("L1 Context ID : ", cnxt_id); | |
writeln("Silicon Debug interface : ", sdbg); | |
writeln("Fused multiply-add (FMA3) : ", fma); | |
writeln("CMPXCHG16B instruction : ", cx16); | |
writeln("Can disable sending task priority messages : ", xtpr); | |
writeln("Perfmon & debug capability : ", pdcm); | |
writeln("pcid Process context identifiers (CR4 bit 17) : ", pcid); | |
writeln("Direct cache access for DMA writes : ", dca); | |
writeln("SSE4.1 instructions : ", sse4_1); | |
writeln("SSE4.2 instructions : ", sse4_2); | |
writeln("x2APIC : ", x2apic); | |
writeln("MOVBE instruction (big-endian) : ", movbe); | |
writeln("POPCNT instruction : ", popcnt); | |
writeln("APIC implements one-shot operation using a TSC deadline value : ", tsc_deadline); | |
writeln("AES instruction set : ", aes); | |
writeln("XSAVE, XRESTOR, XSETBV, XGETBV : ", xsave); | |
writeln("XSAVE enabled by OS : ", osxsave); | |
writeln("Advanced Vector Extensions : ", avx); | |
writeln("F16C (half-precision) FP feature : ", f16c); | |
writeln("RDRAND (on-chip random number generator) feature : ", rdrnd); | |
writeln("Hypervisor present (always zero on physical CPUs) : ", hypervisor); | |
} | |
} | |
} | |
void main() { | |
writeln("VenderID : ", getVenderID); | |
writeln("CPU Name : ", getCPUName); | |
auto cpu_info = getCPUInfo; | |
cpu_info.printCPUInfo; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment