// Do all the needed CPUID calls here, and store the info for later use const std = @import("std"); const arch = @import("../root.zig"); pub const captured = struct { pub var vendor_str: [12]u8 = undefined; }; pub fn init() void { capture_vendor_str(); capture_cpu_features(); } fn capture_vendor_str() void { const res = cpuid(0, 0); @memcpy(captured.vendor_str[0..4], std.mem.asBytes(&res.ebx)); @memcpy(captured.vendor_str[4..8], std.mem.asBytes(&res.edx)); @memcpy(captured.vendor_str[8..12], std.mem.asBytes(&res.ecx)); } fn capture_cpu_features() void { const res = cpuid(1, 0); const feat_ecx: FeaturesEcx = @bitCast(res.ecx); arch.interrupts.apic.tsc_deadline_available = feat_ecx.tsc_deadline; arch.interrupts.apic.has_x2apic = feat_ecx.x2apic; } const FeaturesEcx = packed struct(u32) { sse3: bool, pclmulqdq: bool, dtes64: bool, monitor: bool, ds_cpl: bool, vmx: bool, smx: bool, est: bool, tm2: bool, ssse3: bool, cnxt_id: bool, sdbg: bool, fma: bool, cx16: bool, xtpr: bool, pdcm: bool, _reserved0: bool, pcid: bool, dca: bool, sse4_1: bool, sse4_2: bool, x2apic: bool, movbe: bool, popcnt: bool, tsc_deadline: bool, aesni: bool, xsave: bool, osxsave: bool, avx: bool, f16c: bool, rdrand: bool, hypervisor: bool, }; pub inline fn cpuid(leaf: u32, sub: u32) DefaultResults { var eax: u32 = undefined; var ebx: u32 = undefined; var edx: u32 = undefined; var ecx: u32 = undefined; asm volatile ( \\cpuid : [eax] "={eax}" (eax), [ebx] "={ebx}" (ebx), [edx] "={edx}" (edx), [ecx] "={ecx}" (ecx), : [leaf] "{eax}" (leaf), [sub] "{ecx}" (sub), ); return .{ .eax = eax, .ebx = ebx, .ecx = ecx, .edx = edx, }; } pub const DefaultResults = struct { eax: u32 = 0, ebx: u32 = 0, edx: u32 = 0, ecx: u32 = 0, };