mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 21:00:17 +02:00
Just gets the feature bit handling stuff in place for various facilities, so it can be easily expanded in the future.
601 lines
23 KiB
C++
601 lines
23 KiB
C++
// SPDX-License-Identifier: MIT
|
|
#pragma once
|
|
|
|
#include <FEXCore/Core/CPUID.h>
|
|
#include <FEXCore/Config/Config.h>
|
|
#include <FEXCore/fextl/vector.h>
|
|
|
|
#include <cstdint>
|
|
#include <unordered_map>
|
|
#include <utility>
|
|
|
|
namespace FEXCore {
|
|
namespace Context {
|
|
class ContextImpl;
|
|
}
|
|
|
|
uint64_t GetCycleCounterFrequency();
|
|
|
|
// Debugging define to switch what family of CPU we execute as.
|
|
// Might be useful if an application makes an assumption about a CPU.
|
|
// #define CPUID_AMD
|
|
class CPUIDEmu final {
|
|
private:
|
|
constexpr static uint32_t CPUID_VENDOR_INTEL1 = 0x756E6547; // "Genu"
|
|
constexpr static uint32_t CPUID_VENDOR_INTEL2 = 0x49656E69; // "ineI"
|
|
constexpr static uint32_t CPUID_VENDOR_INTEL3 = 0x6C65746E; // "ntel"
|
|
|
|
constexpr static uint32_t CPUID_VENDOR_AMD1 = 0x68747541; // "Auth"
|
|
constexpr static uint32_t CPUID_VENDOR_AMD2 = 0x69746E65; // "enti"
|
|
constexpr static uint32_t CPUID_VENDOR_AMD3 = 0x444D4163; // "cAMD"
|
|
|
|
public:
|
|
CPUIDEmu(const FEXCore::Context::ContextImpl* ctx);
|
|
|
|
// X86 cacheline size effectively has to be hardcoded to 64
|
|
// if we report anything differently then applications are likely to break
|
|
constexpr static uint64_t CACHELINE_SIZE = 64;
|
|
|
|
FEXCore::CPUID::FunctionResults RunFunction(uint32_t Function, uint32_t Leaf) const {
|
|
if (Function < Primary.size()) {
|
|
const auto Handler = Primary[Function];
|
|
return (this->*Handler)(Leaf);
|
|
}
|
|
|
|
constexpr uint32_t HypervisorBase = 0x4000'0000;
|
|
if (Function >= HypervisorBase && Function < (HypervisorBase + Hypervisor.size())) {
|
|
const auto Handler = Hypervisor[Function - HypervisorBase];
|
|
return (this->*Handler)(Leaf);
|
|
}
|
|
|
|
constexpr uint32_t ExtendedBase = 0x8000'0000;
|
|
if (Function >= ExtendedBase && Function < (ExtendedBase + Extended.size())) {
|
|
const auto Handler = Extended[Function - ExtendedBase];
|
|
return (this->*Handler)(Leaf);
|
|
}
|
|
|
|
return Function_Reserved(Leaf);
|
|
}
|
|
|
|
FEXCore::CPUID::FunctionResults RunFunctionName(uint32_t Function, uint32_t Leaf, uint32_t CPU) const {
|
|
if (Function == 0x8000'0002U) {
|
|
return Function_8000_0002h(Leaf, CPU % PerCPUData.size());
|
|
} else if (Function == 0x8000'0003U) {
|
|
return Function_8000_0003h(Leaf, CPU % PerCPUData.size());
|
|
} else {
|
|
return Function_8000_0004h(Leaf, CPU % PerCPUData.size());
|
|
}
|
|
}
|
|
|
|
FEXCore::CPUID::XCRResults RunXCRFunction(uint32_t Function) const {
|
|
if (Function >= 1) {
|
|
// XCR function 1 is not yet supported.
|
|
return {};
|
|
}
|
|
|
|
return XCRFunction_0h();
|
|
}
|
|
|
|
bool DoesXCRFunctionReportConstantData(uint32_t Function) const {
|
|
// Every function currently returns constant data.
|
|
return true;
|
|
}
|
|
|
|
enum class SupportsConstant {
|
|
CONSTANT,
|
|
NONCONSTANT,
|
|
};
|
|
enum class NeedsLeafConstant {
|
|
NEEDSLEAFCONSTANT,
|
|
NOLEAFCONSTANT,
|
|
};
|
|
struct FunctionConstant {
|
|
SupportsConstant SupportsConstantFunction;
|
|
NeedsLeafConstant NeedsLeaf;
|
|
};
|
|
|
|
static constexpr FunctionConstant DoesFunctionReportConstantData(uint32_t Function) {
|
|
if (Function < Primary.size()) {
|
|
return Primary_Constant[Function];
|
|
}
|
|
|
|
constexpr uint32_t HypervisorBase = 0x4000'0000;
|
|
if (Function >= HypervisorBase && Function < (HypervisorBase + Hypervisor.size())) {
|
|
return Hypervisor_Constant[Function - HypervisorBase];
|
|
}
|
|
|
|
constexpr uint32_t ExtendedBase = 0x8000'0000;
|
|
if (Function >= ExtendedBase && Function < (ExtendedBase + Extended.size())) {
|
|
return Extended_Constant[Function - ExtendedBase];
|
|
}
|
|
|
|
// Anything unsupported is known constant return of reserved data.
|
|
return {SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT};
|
|
}
|
|
|
|
private:
|
|
const FEXCore::Context::ContextImpl* CTX;
|
|
[[maybe_unused]] bool SupportsCPUIndexInTPIDRRO {};
|
|
bool Hybrid {};
|
|
uint32_t Cores {};
|
|
FEX_CONFIG_OPT(HideHypervisorBit, HIDEHYPERVISORBIT);
|
|
|
|
// XFEATURE_ENABLED_MASK
|
|
// Mask that configures what features are enabled on the CPU.
|
|
// Affects XSAVE and XRSTOR when modified.
|
|
// Bit layout is as follows.
|
|
// [0] - x87 enabled
|
|
// [1] - SSE enabled
|
|
// [2] - YMM enabled (256-bit SSE)
|
|
// [8:3] - Reserved. MBZ.
|
|
// [9] - MPK
|
|
// [10] - Reserved. MBZ.
|
|
// [11] - CET_U
|
|
// [12] - CET_S
|
|
// [61:13] - Reserved. MBZ.
|
|
// [62] - LWP (Lightweight profiling)
|
|
// [63] - Reserved for XCR bit vector expansion. MBZ.
|
|
// Always enable x87 and SSE by default.
|
|
constexpr static uint64_t XCR0_X87 = 1ULL << 0;
|
|
constexpr static uint64_t XCR0_SSE = 1ULL << 1;
|
|
constexpr static uint64_t XCR0_AVX = 1ULL << 2;
|
|
|
|
struct FeaturesConfig {
|
|
uint64_t SHA : 1;
|
|
uint64_t _pad : 63;
|
|
};
|
|
|
|
FeaturesConfig Features {
|
|
.SHA = 1,
|
|
};
|
|
|
|
uint64_t XCR0 {XCR0_X87 | XCR0_SSE};
|
|
|
|
uint32_t SupportsAVX() const {
|
|
return (XCR0 & XCR0_AVX) ? 1 : 0;
|
|
}
|
|
|
|
using FunctionHandler = FEXCore::CPUID::FunctionResults (CPUIDEmu::*)(uint32_t Leaf) const;
|
|
|
|
struct CPUData {
|
|
const char* ProductName {};
|
|
#ifdef ARCHITECTURE_arm64
|
|
uint32_t MIDR {};
|
|
#endif
|
|
bool IsBig {};
|
|
};
|
|
fextl::vector<CPUData> PerCPUData {};
|
|
|
|
// Functions
|
|
FEXCore::CPUID::FunctionResults Function_0h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_01h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_02h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_04h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_06h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_07h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_0Dh(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_15h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_1Ah(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_24h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_4000_0000h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_4000_0001h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_8000_0000h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_8000_0001h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_8000_0002h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_8000_0003h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_8000_0004h(uint32_t Leaf) const;
|
|
|
|
FEXCore::CPUID::FunctionResults Function_8000_0002h(uint32_t Leaf, uint32_t CPU) const;
|
|
FEXCore::CPUID::FunctionResults Function_8000_0003h(uint32_t Leaf, uint32_t CPU) const;
|
|
FEXCore::CPUID::FunctionResults Function_8000_0004h(uint32_t Leaf, uint32_t CPU) const;
|
|
|
|
FEXCore::CPUID::FunctionResults Function_8000_0005h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_8000_0006h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_8000_0007h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_8000_0008h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_8000_0019h(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_8000_001Dh(uint32_t Leaf) const;
|
|
FEXCore::CPUID::FunctionResults Function_Reserved(uint32_t Leaf) const;
|
|
|
|
FEXCore::CPUID::XCRResults XCRFunction_0h() const;
|
|
|
|
void SetupHostHybridFlag();
|
|
void SetupFeatures();
|
|
static constexpr size_t PRIMARY_FUNCTION_COUNT = 37;
|
|
static constexpr size_t HYPERVISOR_FUNCTION_COUNT = 2;
|
|
static constexpr size_t EXTENDED_FUNCTION_COUNT = 32;
|
|
static constexpr std::array<FunctionHandler, PRIMARY_FUNCTION_COUNT> Primary = {
|
|
// 0: Highest function parameter and ID
|
|
&CPUIDEmu::Function_0h,
|
|
// 1: Processor info
|
|
&CPUIDEmu::Function_01h,
|
|
// 2: Cache and TLB info
|
|
&CPUIDEmu::Function_02h,
|
|
// 3: Serial Number(previously), now reserved
|
|
&CPUIDEmu::Function_Reserved,
|
|
#ifndef CPUID_AMD
|
|
// 4: Deterministic cache parameters for each level
|
|
&CPUIDEmu::Function_04h,
|
|
#else
|
|
&CPUIDEmu::Function_Reserved,
|
|
#endif
|
|
// 5: Monitor/mwait
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 6: Thermal and power management
|
|
&CPUIDEmu::Function_06h,
|
|
// 7: Extended feature flags
|
|
&CPUIDEmu::Function_07h,
|
|
// 0x08: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 9: Direct Cache Access information
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x0A: Architectural performance monitoring
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x0B: Extended topology enumeration
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x0C: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x0D: Processor extended state enumeration
|
|
&CPUIDEmu::Function_0Dh,
|
|
// 0x0E: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x0F: Intel RDT monitoring
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x10: Intel RDT allocation enumeration
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x12: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x12: Intel SGX capability enumeration
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x13: Reserved
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x14: Intel Processor trace
|
|
&CPUIDEmu::Function_Reserved,
|
|
#ifndef CPUID_AMD
|
|
// Timestamp counter information
|
|
// Doesn't exist on AMD hardware
|
|
&CPUIDEmu::Function_15h,
|
|
#else
|
|
&CPUIDEmu::Function_Reserved,
|
|
#endif
|
|
// 0x16: Processor frequency information
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x17: SoC vendor attribute enumeration
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x18: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x19: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
#ifndef CPUID_AMD
|
|
// 0x1A: Hybrid Information Sub-leaf
|
|
&CPUIDEmu::Function_1Ah,
|
|
// 0x1B: PCONFIG info
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x1C: Last Branch Records (LBR) info
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x1D: Tile info
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x1E: TMUL info
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x1F: V2 Extended topology
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x20: Processor History Reset info
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x21: Unimplemented
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x22: Reserved
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x23: Architectural Performance Monitoring Extended
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x24: Converged Vector ISA
|
|
&CPUIDEmu::Function_24h,
|
|
#else
|
|
// 0x1A: Reserved
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x1B: Reserved
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x1C: Reserved
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x1D: Reserved
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x1E: Reserved
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x1F: Reserved
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x20: Reserved
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x21: Reserved
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x22: Reserved
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x23: Reserved
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x24: Reserved
|
|
&CPUIDEmu::Function_Reserved,
|
|
#endif
|
|
};
|
|
|
|
static constexpr std::array<FunctionConstant, PRIMARY_FUNCTION_COUNT> Primary_Constant = {{
|
|
// 0: Highest function parameter and ID
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 1: Processor info
|
|
{SupportsConstant::NONCONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 2: Cache and TLB info
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 3: Serial Number(previously), now reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
#ifndef CPUID_AMD
|
|
// 4: Deterministic cache parameters for each level
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NEEDSLEAFCONSTANT},
|
|
#else
|
|
// 4: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
#endif
|
|
// 5: Monitor/mwait
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 6: Thermal and power management
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 7: Extended feature flags
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NEEDSLEAFCONSTANT},
|
|
// 0x08: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 9: Direct Cache Access information
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x0A: Architectural performance monitoring
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x0B: Extended topology enumeration
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x0C: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x0D: Processor extended state enumeration
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NEEDSLEAFCONSTANT},
|
|
// 0x0E: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x0F: Intel RDT monitoring
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x10: Intel RDT allocation enumeration
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x12: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x12: Intel SGX capability enumeration
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x13: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x14: Intel Processor trace
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
#ifndef CPUID_AMD
|
|
// 0x15: Timestamp counter information
|
|
// Doesn't exist on AMD hardware
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
#else
|
|
// 0x15: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
#endif
|
|
// 0x16: Processor frequency information
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x17: SoC vendor attribute enumeration
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x18: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x19: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
#ifndef CPUID_AMD
|
|
// 0x1A: Hybrid Information Sub-leaf
|
|
{SupportsConstant::NONCONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x1B: PCONFIG info
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x1C: Last Branch Records (LBR) info
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x1D: Tile info
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x1E: TMUL info
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x1F: V2 Extended topology
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x20: Processor History Reset info
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x21: Unimplemented/Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x22: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x23: Architectural Performance Monitoring Extended
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x24: Converged Vector ISA
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NEEDSLEAFCONSTANT},
|
|
#else
|
|
// 0x1A: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x1B: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x1C: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x1D: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x1E: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x1F: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x20: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x21: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x22: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x23: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x24: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
#endif
|
|
}};
|
|
|
|
static constexpr std::array<FunctionHandler, HYPERVISOR_FUNCTION_COUNT> Hypervisor = {
|
|
// Hypervisor CPUID information leaf
|
|
&CPUIDEmu::Function_4000_0000h,
|
|
// FEX-Emu specific leaf
|
|
&CPUIDEmu::Function_4000_0001h,
|
|
};
|
|
|
|
static constexpr std::array<FunctionConstant, HYPERVISOR_FUNCTION_COUNT> Hypervisor_Constant = {{
|
|
// Hypervisor CPUID information leaf
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// FEX-Emu specific leaf
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NEEDSLEAFCONSTANT},
|
|
}};
|
|
|
|
static constexpr std::array<FunctionHandler, EXTENDED_FUNCTION_COUNT> Extended = {
|
|
// Largest extended function number
|
|
&CPUIDEmu::Function_8000_0000h,
|
|
// Processor vendor
|
|
&CPUIDEmu::Function_8000_0001h,
|
|
// Processor brand string
|
|
&CPUIDEmu::Function_8000_0002h,
|
|
// Processor brand string continued
|
|
&CPUIDEmu::Function_8000_0003h,
|
|
// Processor brand string continued
|
|
&CPUIDEmu::Function_8000_0004h,
|
|
#ifdef CPUID_AMD
|
|
// 0x8000'0005: L1 Cache and TLB identifiers
|
|
&CPUIDEmu::Function_8000_0005h,
|
|
#else
|
|
&CPUIDEmu::Function_Reserved,
|
|
#endif
|
|
// 0x8000'0006: L2 Cache identifiers
|
|
&CPUIDEmu::Function_8000_0006h,
|
|
// 0x8000'0007: Advanced power management information
|
|
&CPUIDEmu::Function_8000_0007h,
|
|
// 0x8000'0008: Virtual and physical address sizes
|
|
&CPUIDEmu::Function_8000_0008h,
|
|
// 0x8000'0009: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'000A: SVM Revision
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'000B: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'000C: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'000D: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'000E: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'000F: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'0010: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'0011: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'0012: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'0013: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'0014: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'0015: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'0016: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'0017: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'0018: Reserved?
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'0019: TLB 1GB page identifiers
|
|
&CPUIDEmu::Function_8000_0019h,
|
|
// 0x8000'001A: Performance optimization identifiers
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'001B: Instruction based sampling identifiers
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'001C: Lightweight profiling capabilities
|
|
&CPUIDEmu::Function_Reserved,
|
|
#ifdef CPUID_AMD
|
|
// 0x8000'001D: Cache properties
|
|
&CPUIDEmu::Function_8000_001Dh,
|
|
#else
|
|
&CPUIDEmu::Function_Reserved,
|
|
#endif
|
|
// 0x8000'001E: Extended APIC ID
|
|
&CPUIDEmu::Function_Reserved,
|
|
// 0x8000'001F: AMD Secure Encryption
|
|
&CPUIDEmu::Function_Reserved,
|
|
};
|
|
|
|
static constexpr std::array<FunctionConstant, EXTENDED_FUNCTION_COUNT> Extended_Constant = {{
|
|
// Largest extended function number
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// Processor vendor
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// Processor brand string
|
|
{SupportsConstant::NONCONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// Processor brand string continued
|
|
{SupportsConstant::NONCONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// Processor brand string continued
|
|
{SupportsConstant::NONCONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
#ifdef CPUID_AMD
|
|
// 0x8000'0005: L1 Cache and TLB identifiers
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
#else
|
|
// 0x8000'0005: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
#endif
|
|
// 0x8000'0006: L2 Cache identifiers
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'0007: Advanced power management information
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'0008: Virtual and physical address sizes
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'0009: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'000A: SVM Revision
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'000B: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'000C: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'000D: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'000E: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'000F: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'0010: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'0011: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'0012: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'0013: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'0014: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'0015: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'0016: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'0017: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'0018: Reserved?
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'0019: TLB 1GB page identifiers
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'001A: Performance optimization identifiers
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'001B: Instruction based sampling identifiers
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'001C: Lightweight profiling capabilities
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
#ifdef CPUID_AMD
|
|
// 0x8000'001D: Cache properties
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NEEDSLEAFCONSTANT},
|
|
#else
|
|
// 0x8000'001D: Reserved
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
#endif
|
|
// 0x8000'001E: Extended APIC ID
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
// 0x8000'001F: AMD Secure Encryption
|
|
{SupportsConstant::CONSTANT, NeedsLeafConstant::NOLEAFCONSTANT},
|
|
}};
|
|
|
|
using GetCPUIDPtr = uint32_t (*)();
|
|
GetCPUIDPtr GetCPUID;
|
|
};
|
|
} // namespace FEXCore
|