#include "Interface/Core/CPUID.h" namespace FEXCore { CPUIDEmu::FunctionResults CPUIDEmu::Function_0h() { CPUIDEmu::FunctionResults Res{}; Res.Res[0] = 0x16; // Let's say we are a Skylake // EBX, EDX, ECX become the manufacturer id string Res.Res[1] = 0x756E6547; // "Genu" Res.Res[2] = 0x49656E69; // "ineI" Res.Res[3] = 0x6C65746E; // "ntel" return Res; } // Processor Info and Features bits CPUIDEmu::FunctionResults CPUIDEmu::Function_01h() { CPUIDEmu::FunctionResults Res{}; Res.Res[0] = 0 | // Stepping (0 << 4) | // Model (0 << 8) | // Family ID (0 << 12) | // Processor type (0 << 16) | // Extended model ID (0 << 20); // Extended family ID Res.Res[1] = 0 | // Brand index (8 << 8) | // Cache line size in bytes (8 << 16) | // Number of addressable IDs for the logical cores in the physical CPU (0 << 24); // Local APIC ID Res.Res[2] = ~0U; // Let's say we support every feature for fun Res.Res[3] = ~0U; // Let's say we support every feature for fun Res.Res[3] &= ~( (3 << 26) | // Let's say that XSAVE isn't enabled by the OS. Prevents glibc from using XSAVE/XGETBV (1 << 19) | // Remove SSE4.1 (1 << 20) | // Remove SSE4.2 (1 << 28) | // Remove AVX (1 << 30) // Remove RDRAND ); return Res; } CPUIDEmu::FunctionResults CPUIDEmu::Function_07h() { CPUIDEmu::FunctionResults Res{}; // Number of subfunctions Res.Res[0] = 0x0; Res.Res[1] = (1 << 0) | // FS/GS support (1 << 3) | // BMI 1 support (1 << 5) | // AVX2 support (1 << 7) | // SMEP support (1 << 8) // BMI2 support ; Res.Res[2] = ~0U; Res.Res[3] = ~0U; Res.Res[2] &= ~( (1 << 2) | // Remove AVX5124VNNIW (1 << 3) | // Remove AVX5124FMAPS (1 << 8) | // Remove AVX512VP2INTERSECT (1 << 20) // we don't support CET indirect branch tracking ); Res.Res[3] &= ~( (1 << 1) | // Remove AVX512VBMI (1 << 6) | // Remove AVX512VBMI2 (1 << 7) | // we don't support CET shadow stack features (1 << 11) | // Remove AVX512VNNI (1 << 12) | // Remove AVX512BITALG (1 << 14) // Remove AVX512VPOPCNTDQ ); return Res; } // Highest extended function implemented CPUIDEmu::FunctionResults CPUIDEmu::Function_8000_0000h() { CPUIDEmu::FunctionResults Res{}; Res.Res[0] = 0x8000001F; return Res; } // Extended processor and feature bits CPUIDEmu::FunctionResults CPUIDEmu::Function_8000_0001h() { CPUIDEmu::FunctionResults Res{}; Res.Res[2] = ~0U; // Let's say we support every feature for fun Res.Res[3] = ~0U; // Let's say we support every feature for fun Res.Res[3] &= ~( (1 << 6) | // Remove SSE4a (1 << 11) | // Remove XOP (1 << 16) // Remove FMA4 ); return Res; } // Advanced power management CPUIDEmu::FunctionResults CPUIDEmu::Function_8000_0007h() { CPUIDEmu::FunctionResults Res{}; Res.Res[0] = (1 << 2); // APIC timer not affected by p-state return Res; } CPUIDEmu::FunctionResults CPUIDEmu::Function_Reserved() { CPUIDEmu::FunctionResults Res{}; return Res; } void CPUIDEmu::Init() { RegisterFunction(0, std::bind(&CPUIDEmu::Function_0h, this)); RegisterFunction(1, std::bind(&CPUIDEmu::Function_01h, this)); // Cache and TLB information RegisterFunction(2, std::bind(&CPUIDEmu::Function_Reserved, this)); // Serial Number(previously), now reserved RegisterFunction(3, std::bind(&CPUIDEmu::Function_Reserved, this)); // Deterministic cache parameters for each level RegisterFunction(4, std::bind(&CPUIDEmu::Function_Reserved, this)); // Monitor/mwait RegisterFunction(5, std::bind(&CPUIDEmu::Function_Reserved, this)); // Thermal and power management RegisterFunction(6, std::bind(&CPUIDEmu::Function_Reserved, this)); // Extended feature flags RegisterFunction(7, std::bind(&CPUIDEmu::Function_07h, this)); // Reserved RegisterFunction(8, std::bind(&CPUIDEmu::Function_Reserved, this)); // Direct Cache Access information RegisterFunction(9, std::bind(&CPUIDEmu::Function_Reserved, this)); // Architectural performance monitoring RegisterFunction(0x0A, std::bind(&CPUIDEmu::Function_Reserved, this)); // Extended topology enumeration RegisterFunction(0x0B, std::bind(&CPUIDEmu::Function_Reserved, this)); // Reserved RegisterFunction(0x0C, std::bind(&CPUIDEmu::Function_Reserved, this)); // Processor extended state enumeration RegisterFunction(0x0D, std::bind(&CPUIDEmu::Function_Reserved, this)); // Reserved RegisterFunction(0x0E, std::bind(&CPUIDEmu::Function_Reserved, this)); // Intel RDT monitoring RegisterFunction(0x0F, std::bind(&CPUIDEmu::Function_Reserved, this)); // Intel RDT allocation enumeration RegisterFunction(0x10, std::bind(&CPUIDEmu::Function_Reserved, this)); // Reserved RegisterFunction(0x11, std::bind(&CPUIDEmu::Function_Reserved, this)); // Intel SGX capability enumeration RegisterFunction(0x12, std::bind(&CPUIDEmu::Function_Reserved, this)); // Reserved RegisterFunction(0x13, std::bind(&CPUIDEmu::Function_Reserved, this)); // Intel Processor trace RegisterFunction(0x14, std::bind(&CPUIDEmu::Function_Reserved, this)); // Timestamp counter information RegisterFunction(0x15, std::bind(&CPUIDEmu::Function_Reserved, this)); // Processor frequency information RegisterFunction(0x16, std::bind(&CPUIDEmu::Function_Reserved, this)); // SoC vendor attribute enumeration RegisterFunction(0x17, std::bind(&CPUIDEmu::Function_Reserved, this)); // Largest extended function number RegisterFunction(0x8000'0000, std::bind(&CPUIDEmu::Function_8000_0000h, this)); // Processor vendor RegisterFunction(0x8000'0001, std::bind(&CPUIDEmu::Function_8000_0001h, this)); // Processor brand string RegisterFunction(0x8000'0002, std::bind(&CPUIDEmu::Function_Reserved, this)); // Processor brand string continued RegisterFunction(0x8000'0003, std::bind(&CPUIDEmu::Function_Reserved, this)); // Processor brand string continued RegisterFunction(0x8000'0004, std::bind(&CPUIDEmu::Function_Reserved, this)); // L1 Cache and TLB identifiers RegisterFunction(0x8000'0005, std::bind(&CPUIDEmu::Function_Reserved, this)); // L2 Cache identifiers RegisterFunction(0x8000'0006, std::bind(&CPUIDEmu::Function_Reserved, this)); // Advanced power management information RegisterFunction(0x8000'0007, std::bind(&CPUIDEmu::Function_8000_0007h, this)); // Virtual and physical address sizes RegisterFunction(0x8000'0008, std::bind(&CPUIDEmu::Function_Reserved, this)); // Reserved RegisterFunction(0x8000'0009, std::bind(&CPUIDEmu::Function_Reserved, this)); // SVM Revision RegisterFunction(0x8000'000A, std::bind(&CPUIDEmu::Function_Reserved, this)); // Reserved RegisterFunction(0x8000'000B, std::bind(&CPUIDEmu::Function_Reserved, this)); RegisterFunction(0x8000'000C, std::bind(&CPUIDEmu::Function_Reserved, this)); RegisterFunction(0x8000'000D, std::bind(&CPUIDEmu::Function_Reserved, this)); RegisterFunction(0x8000'000E, std::bind(&CPUIDEmu::Function_Reserved, this)); RegisterFunction(0x8000'000F, std::bind(&CPUIDEmu::Function_Reserved, this)); RegisterFunction(0x8000'0010, std::bind(&CPUIDEmu::Function_Reserved, this)); RegisterFunction(0x8000'0011, std::bind(&CPUIDEmu::Function_Reserved, this)); RegisterFunction(0x8000'0012, std::bind(&CPUIDEmu::Function_Reserved, this)); RegisterFunction(0x8000'0013, std::bind(&CPUIDEmu::Function_Reserved, this)); RegisterFunction(0x8000'0014, std::bind(&CPUIDEmu::Function_Reserved, this)); RegisterFunction(0x8000'0015, std::bind(&CPUIDEmu::Function_Reserved, this)); RegisterFunction(0x8000'0016, std::bind(&CPUIDEmu::Function_Reserved, this)); RegisterFunction(0x8000'0017, std::bind(&CPUIDEmu::Function_Reserved, this)); RegisterFunction(0x8000'0018, std::bind(&CPUIDEmu::Function_Reserved, this)); // TLB 1GB page identifiers RegisterFunction(0x8000'0019, std::bind(&CPUIDEmu::Function_Reserved, this)); // Performance optimization identifiers RegisterFunction(0x8000'001A, std::bind(&CPUIDEmu::Function_Reserved, this)); // Instruction based sampling identifiers RegisterFunction(0x8000'001B, std::bind(&CPUIDEmu::Function_Reserved, this)); // Lightweight profiling capabilities RegisterFunction(0x8000'001C, std::bind(&CPUIDEmu::Function_Reserved, this)); // Cache properties RegisterFunction(0x8000'001D, std::bind(&CPUIDEmu::Function_Reserved, this)); // Extended APIC ID RegisterFunction(0x8000'001E, std::bind(&CPUIDEmu::Function_Reserved, this)); } }