/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
+#include <x86x64/Cpuid.h>
+#include <x86x64/Msr.h>
#define NDEBUG
#include <debug.h>
-/* FIXME: Local EFLAGS defines not used anywhere else */
-#define EFLAGS_IOPL 0x3000
-#define EFLAGS_NF 0x4000
-#define EFLAGS_RF 0x10000
-#define EFLAGS_ID 0x200000
-
/* GLOBALS *******************************************************************/
/* The Boot TSS */
ULONG KiDmaIoCoherency = 0;
BOOLEAN KiSMTProcessorsPresent;
-/* Freeze data */
-KIRQL KiOldIrql;
-ULONG KiFreezeFlag;
-
/* Flush data */
volatile LONG KiTbFlushTimeStamp;
/* CPU Signatures */
static const CHAR CmpIntelID[] = "GenuineIntel";
static const CHAR CmpAmdID[] = "AuthenticAMD";
-static const CHAR CmpCyrixID[] = "CyrixInstead";
-static const CHAR CmpTransmetaID[] = "GenuineTMx86";
static const CHAR CmpCentaurID[] = "CentaurHauls";
-static const CHAR CmpRiseID[] = "RiseRiseRise";
-/* SUPPORT ROUTINES FOR MSVC COMPATIBILITY ***********************************/
-
-VOID
-NTAPI
-CPUID(IN ULONG InfoType,
- OUT PULONG CpuInfoEax,
- OUT PULONG CpuInfoEbx,
- OUT PULONG CpuInfoEcx,
- OUT PULONG CpuInfoEdx)
+typedef union _CPU_SIGNATURE
{
- ULONG CpuInfo[4];
-
- /* Perform the CPUID Operation */
- __cpuid((int*)CpuInfo, InfoType);
-
- /* Return the results */
- *CpuInfoEax = CpuInfo[0];
- *CpuInfoEbx = CpuInfo[1];
- *CpuInfoEcx = CpuInfo[2];
- *CpuInfoEdx = CpuInfo[3];
-}
+ struct
+ {
+ ULONG Step : 4;
+ ULONG Model : 4;
+ ULONG Family : 4;
+ ULONG Unused : 4;
+ ULONG ExtendedModel : 4;
+ ULONG ExtendedFamily : 8;
+ ULONG Unused2 : 4;
+ };
+ ULONG AsULONG;
+} CPU_SIGNATURE;
/* FUNCTIONS *****************************************************************/
-VOID
-NTAPI
-KiSetProcessorType(VOID)
-{
- ULONG64 EFlags;
- INT Reg[4];
- ULONG Stepping, Type;
-
- /* Start by assuming no CPUID data */
- KeGetCurrentPrcb()->CpuID = 0;
-
- /* Save EFlags */
- EFlags = __readeflags();
-
- /* Do CPUID 1 now */
- __cpuid(Reg, 1);
-
- /*
- * Get the Stepping and Type. The stepping contains both the
- * Model and the Step, while the Type contains the returned Type.
- * We ignore the family.
- *
- * For the stepping, we convert this: zzzzzzxy into this: x0y
- */
- Stepping = Reg[0] & 0xF0;
- Stepping <<= 4;
- Stepping += (Reg[0] & 0xFF);
- Stepping &= 0xF0F;
- Type = Reg[0] & 0xF00;
- Type >>= 8;
-
- /* Save them in the PRCB */
- KeGetCurrentPrcb()->CpuID = TRUE;
- KeGetCurrentPrcb()->CpuType = (UCHAR)Type;
- KeGetCurrentPrcb()->CpuStep = (USHORT)Stepping;
-
- /* Restore EFLAGS */
- __writeeflags(EFlags);
-}
-
ULONG
NTAPI
KiGetCpuVendor(VOID)
{
PKPRCB Prcb = KeGetCurrentPrcb();
- INT Vendor[5];
+ CPU_INFO CpuInfo;
/* Get the Vendor ID and null-terminate it */
- __cpuid(Vendor, 0);
+ KiCpuId(&CpuInfo, 0);
/* Copy it to the PRCB and null-terminate it */
- *(ULONG*)&Prcb->VendorString[0] = Vendor[1]; // ebx
- *(ULONG*)&Prcb->VendorString[4] = Vendor[3]; // edx
- *(ULONG*)&Prcb->VendorString[8] = Vendor[2]; // ecx
- *(ULONG*)&Prcb->VendorString[12] = 0;
+ *(ULONG*)&Prcb->VendorString[0] = CpuInfo.Ebx;
+ *(ULONG*)&Prcb->VendorString[4] = CpuInfo.Edx;
+ *(ULONG*)&Prcb->VendorString[8] = CpuInfo.Ecx;
+ Prcb->VendorString[12] = 0;
/* Now check the CPU Type */
if (!strcmp((PCHAR)Prcb->VendorString, CmpIntelID))
{
- return CPU_INTEL;
+ Prcb->CpuVendor = CPU_INTEL;
}
else if (!strcmp((PCHAR)Prcb->VendorString, CmpAmdID))
{
- return CPU_AMD;
+ Prcb->CpuVendor = CPU_AMD;
}
- else if (!strcmp((PCHAR)Prcb->VendorString, CmpCyrixID))
+ else if (!strcmp((PCHAR)Prcb->VendorString, CmpCentaurID))
{
- DPRINT1("Cyrix CPUs not fully supported\n");
- return 0;
+ DPRINT1("VIA CPUs not fully supported\n");
+ Prcb->CpuVendor = CPU_VIA;
}
- else if (!strcmp((PCHAR)Prcb->VendorString, CmpTransmetaID))
+ else
{
- DPRINT1("Transmeta CPUs not fully supported\n");
- return 0;
+ /* Invalid CPU */
+ DPRINT1("%s CPU support not fully tested!\n", Prcb->VendorString);
+ Prcb->CpuVendor = CPU_UNKNOWN;
}
- else if (!strcmp((PCHAR)Prcb->VendorString, CmpCentaurID))
+
+ return Prcb->CpuVendor;
+}
+
+VOID
+NTAPI
+KiSetProcessorType(VOID)
+{
+ CPU_INFO CpuInfo;
+ CPU_SIGNATURE CpuSignature;
+ BOOLEAN ExtendModel;
+ ULONG Stepping, Type, Vendor;
+
+ /* This initializes Prcb->CpuVendor */
+ Vendor = KiGetCpuVendor();
+
+ /* Do CPUID 1 now */
+ KiCpuId(&CpuInfo, 1);
+
+ /*
+ * Get the Stepping and Type. The stepping contains both the
+ * Model and the Step, while the Type contains the returned Family.
+ *
+ * For the stepping, we convert this: zzzzzzxy into this: x0y
+ */
+ CpuSignature.AsULONG = CpuInfo.Eax;
+ Stepping = CpuSignature.Model;
+ ExtendModel = (CpuSignature.Family == 15);
+#if ( (NTDDI_VERSION >= NTDDI_WINXPSP2) && (NTDDI_VERSION < NTDDI_WS03) ) || (NTDDI_VERSION >= NTDDI_WS03SP1)
+ if (CpuSignature.Family == 6)
{
- DPRINT1("VIA CPUs not fully supported\n");
- return 0;
+ ExtendModel |= (Vendor == CPU_INTEL);
+#if (NTDDI_VERSION >= NTDDI_WIN8)
+ ExtendModel |= (Vendor == CPU_CENTAUR);
+#endif
}
- else if (!strcmp((PCHAR)Prcb->VendorString, CmpRiseID))
+#endif
+ if (ExtendModel)
{
- DPRINT1("Rise CPUs not fully supported\n");
- return 0;
+ /* Add ExtendedModel to distinguish from non-extended values. */
+ Stepping |= (CpuSignature.ExtendedModel << 4);
+ }
+ Stepping = (Stepping << 8) | CpuSignature.Step;
+ Type = CpuSignature.Family;
+ if (CpuSignature.Family == 15)
+ {
+ /* Add ExtendedFamily to distinguish from non-extended values.
+ * It must not be larger than 0xF0 to avoid overflow. */
+ Type += min(CpuSignature.ExtendedFamily, 0xF0);
}
- /* Invalid CPU */
- return 0;
+ /* Save them in the PRCB */
+ KeGetCurrentPrcb()->CpuID = TRUE;
+ KeGetCurrentPrcb()->CpuType = (UCHAR)Type;
+ KeGetCurrentPrcb()->CpuStep = (USHORT)Stepping;
}
-ULONG
+/*!
+ \brief Evaluates the KeFeatureFlag bits for the current CPU.
+
+ \return The feature flags for this CPU.
+
+ \see https://www.geoffchappell.com/studies/windows/km/ntoskrnl/structs/kprcb/featurebits.htm
+
+ \todo
+ - KF_VIRT_FIRMWARE_ENABLED 0x08000000 (see notes from Geoff Chappell)
+ - KF_FPU_LEAKAGE 0x0000020000000000ULL
+ - KF_CAT 0x0000100000000000ULL
+ - KF_CET_SS 0x0000400000000000ULL
+*/
+ULONG64
NTAPI
KiGetFeatureBits(VOID)
{
PKPRCB Prcb = KeGetCurrentPrcb();
ULONG Vendor;
- ULONG FeatureBits = KF_WORKING_PTE;
- INT Reg[4];
- ULONG CpuFeatures = 0;
+ ULONG64 FeatureBits = 0;
+ CPUID_SIGNATURE_REGS signature;
+ CPUID_VERSION_INFO_REGS VersionInfo;
+ CPUID_EXTENDED_FUNCTION_REGS extendedFunction;
/* Get the Vendor ID */
- Vendor = KiGetCpuVendor();
+ Vendor = Prcb->CpuVendor;
/* Make sure we got a valid vendor ID at least. */
- if (!Vendor) return FeatureBits;
+ if (Vendor == CPU_UNKNOWN) return FeatureBits;
- /* Get the CPUID Info. Features are in Reg[3]. */
- __cpuid(Reg, 1);
+ /* Get signature CPUID for the maximum function */
+ __cpuid(signature.AsInt32, CPUID_SIGNATURE);
- /* Set the initial APIC ID */
- Prcb->InitialApicId = (UCHAR)(Reg[1] >> 24);
+ /* Get the CPUID Info. */
+ __cpuid(VersionInfo.AsInt32, CPUID_VERSION_INFO);
- /* Set the current features */
- CpuFeatures = Reg[3];
+ /* Set the initial APIC ID */
+ Prcb->InitialApicId = (UCHAR)VersionInfo.Ebx.Bits.InitialLocalApicId;
/* Convert all CPUID Feature bits into our format */
- if (CpuFeatures & 0x00000002) FeatureBits |= KF_V86_VIS | KF_CR4;
- if (CpuFeatures & 0x00000008) FeatureBits |= KF_LARGE_PAGE | KF_CR4;
- if (CpuFeatures & 0x00000010) FeatureBits |= KF_RDTSC;
- if (CpuFeatures & 0x00000100) FeatureBits |= KF_CMPXCHG8B;
- if (CpuFeatures & 0x00000800) FeatureBits |= KF_FAST_SYSCALL;
- if (CpuFeatures & 0x00001000) FeatureBits |= KF_MTRR;
- if (CpuFeatures & 0x00002000) FeatureBits |= KF_GLOBAL_PAGE | KF_CR4;
- if (CpuFeatures & 0x00008000) FeatureBits |= KF_CMOV;
- if (CpuFeatures & 0x00010000) FeatureBits |= KF_PAT;
- if (CpuFeatures & 0x00200000) FeatureBits |= KF_DTS;
- if (CpuFeatures & 0x00800000) FeatureBits |= KF_MMX;
- if (CpuFeatures & 0x01000000) FeatureBits |= KF_FXSR;
- if (CpuFeatures & 0x02000000) FeatureBits |= KF_XMMI;
- if (CpuFeatures & 0x04000000) FeatureBits |= KF_XMMI64;
-
-#if 0
- if (Reg[2] & 0x00000001) FeatureBits |= KF_SSE3NEW;
- if (Reg[2] & 0x00000008) FeatureBits |= KF_MONITOR;
- if (Reg[2] & 0x00000200) FeatureBits |= KF_SSE3SUP;
- if (Reg[2] & 0x00002000) FeatureBits |= KF_CMPXCHG16B;
- if (Reg[2] & 0x00080000) FeatureBits |= KF_SSE41;
- if (Reg[2] & 0x00800000) FeatureBits |= KF_POPCNT;
-#endif
+ if (VersionInfo.Edx.Bits.VME) FeatureBits |= KF_CR4;
+ if (VersionInfo.Edx.Bits.PSE) FeatureBits |= KF_LARGE_PAGE | KF_CR4;
+ if (VersionInfo.Edx.Bits.TSC) FeatureBits |= KF_RDTSC;
+ if (VersionInfo.Edx.Bits.CX8) FeatureBits |= KF_CMPXCHG8B;
+ if (VersionInfo.Edx.Bits.SEP) FeatureBits |= KF_FAST_SYSCALL;
+ if (VersionInfo.Edx.Bits.MTRR) FeatureBits |= KF_MTRR;
+ if (VersionInfo.Edx.Bits.PGE) FeatureBits |= KF_GLOBAL_PAGE | KF_CR4;
+ if (VersionInfo.Edx.Bits.CMOV) FeatureBits |= KF_CMOV;
+ if (VersionInfo.Edx.Bits.PAT) FeatureBits |= KF_PAT;
+ if (VersionInfo.Edx.Bits.DS) FeatureBits |= KF_DTS;
+ if (VersionInfo.Edx.Bits.MMX) FeatureBits |= KF_MMX;
+ if (VersionInfo.Edx.Bits.FXSR) FeatureBits |= KF_FXSR;
+ if (VersionInfo.Edx.Bits.SSE) FeatureBits |= KF_XMMI;
+ if (VersionInfo.Edx.Bits.SSE2) FeatureBits |= KF_XMMI64;
+
+ if (VersionInfo.Ecx.Bits.SSE3) FeatureBits |= KF_SSE3;
+ if (VersionInfo.Ecx.Bits.SSSE3) FeatureBits |= KF_SSSE3;
+ if (VersionInfo.Ecx.Bits.CMPXCHG16B) FeatureBits |= KF_CMPXCHG16B;
+ if (VersionInfo.Ecx.Bits.SSE4_1) FeatureBits |= KF_SSE4_1;
+ if (VersionInfo.Ecx.Bits.XSAVE) FeatureBits |= KF_XSTATE;
+ if (VersionInfo.Ecx.Bits.RDRAND) FeatureBits |= KF_RDRAND;
/* Check if the CPU has hyper-threading */
- if (CpuFeatures & 0x10000000)
+ if (VersionInfo.Edx.Bits.HTT)
{
/* Set the number of logical CPUs */
- Prcb->LogicalProcessorsPerPhysicalProcessor = (UCHAR)(Reg[1] >> 16);
+ Prcb->LogicalProcessorsPerPhysicalProcessor =
+ VersionInfo.Ebx.Bits.MaximumAddressableIdsForLogicalProcessors;
if (Prcb->LogicalProcessorsPerPhysicalProcessor > 1)
{
/* We're on dual-core */
Prcb->LogicalProcessorsPerPhysicalProcessor = 1;
}
+ /* Check if CPUID_THERMAL_POWER_MANAGEMENT (0x06) is supported */
+ if (signature.MaxLeaf >= CPUID_THERMAL_POWER_MANAGEMENT)
+ {
+ /* Read CPUID_THERMAL_POWER_MANAGEMENT */
+ CPUID_THERMAL_POWER_MANAGEMENT_REGS PowerInfo;
+ __cpuid(PowerInfo.AsInt32, CPUID_THERMAL_POWER_MANAGEMENT);
+
+ if (PowerInfo.Undoc.Ecx.ACNT2) FeatureBits |= KF_ACNT2;
+ }
+
+ /* Check if CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS (0x07) is supported */
+ if (signature.MaxLeaf >= CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS)
+ {
+ /* Read CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS */
+ CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_REGS ExtFlags;
+ __cpuidex(ExtFlags.AsInt32,
+ CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS,
+ CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO);
+
+ if (ExtFlags.Ebx.Bits.SMEP) FeatureBits |= KF_SMEP;
+ if (ExtFlags.Ebx.Bits.FSGSBASE) FeatureBits |= KF_RDWRFSGSBASE;
+ if (ExtFlags.Ebx.Bits.SMAP) FeatureBits |= KF_SMAP;
+ }
+
+ /* Check if CPUID_EXTENDED_STATE (0x0D) is supported */
+ if (signature.MaxLeaf >= CPUID_EXTENDED_STATE)
+ {
+ /* Read CPUID_EXTENDED_STATE */
+ CPUID_EXTENDED_STATE_SUB_LEAF_EAX_REGS ExtStateSub;
+ __cpuidex(ExtStateSub.AsInt32,
+ CPUID_EXTENDED_STATE,
+ CPUID_EXTENDED_STATE_SUB_LEAF);
+
+ if (ExtStateSub.Eax.Bits.XSAVEOPT) FeatureBits |= KF_XSAVEOPT;
+ if (ExtStateSub.Eax.Bits.XSAVES) FeatureBits |= KF_XSAVES;
+ }
+
/* Check extended cpuid features */
- __cpuid(Reg, 0x80000000);
- if ((Reg[0] & 0xffffff00) == 0x80000000)
+ __cpuid(extendedFunction.AsInt32, CPUID_EXTENDED_FUNCTION);
+ if ((extendedFunction.MaxLeaf & 0xffffff00) == 0x80000000)
{
- /* Check if CPUID 0x80000001 is supported */
- if (Reg[0] >= 0x80000001)
+ /* Check if CPUID_EXTENDED_CPU_SIG (0x80000001) is supported */
+ if (extendedFunction.MaxLeaf >= CPUID_EXTENDED_CPU_SIG)
{
- /* Check which extended features are available. */
- __cpuid(Reg, 0x80000001);
+ /* Read CPUID_EXTENDED_CPU_SIG */
+ CPUID_EXTENDED_CPU_SIG_REGS ExtSig;
+ __cpuid(ExtSig.AsInt32, CPUID_EXTENDED_CPU_SIG);
/* Check if NX-bit is supported */
- if (Reg[3] & 0x00100000) FeatureBits |= KF_NX_BIT;
+ if (ExtSig.Intel.Edx.Bits.NX) FeatureBits |= KF_NX_BIT;
+ if (ExtSig.Intel.Edx.Bits.Page1GB) FeatureBits |= KF_HUGEPAGE;
+ if (ExtSig.Intel.Edx.Bits.RDTSCP) FeatureBits |= KF_RDTSCP;
+
+ /* AMD specific */
+ if (Vendor == CPU_AMD)
+ {
+ if (ExtSig.Amd.Edx.Bits.ThreeDNow) FeatureBits |= KF_3DNOW;
+ }
+ }
+ }
+
+ /* Vendor specific */
+ if (Vendor == CPU_INTEL)
+ {
+ FeatureBits |= KF_GENUINE_INTEL;
+
+ /* Check for models that support LBR */
+ if (VersionInfo.Eax.Bits.FamilyId == 6)
+ {
+ if ((VersionInfo.Eax.Bits.Model == 15) ||
+ (VersionInfo.Eax.Bits.Model == 22) ||
+ (VersionInfo.Eax.Bits.Model == 23) ||
+ (VersionInfo.Eax.Bits.Model == 26))
+ {
+ FeatureBits |= KF_BRANCH;
+ }
+ }
- /* Now handle each features for each CPU Vendor */
- switch (Vendor)
+ /* Check if VMX is available */
+ if (VersionInfo.Ecx.Bits.VMX)
+ {
+ /* Read PROCBASED ctls and check if secondary are allowed */
+ MSR_IA32_VMX_PROCBASED_CTLS_REGISTER ProcBasedCtls;
+ ProcBasedCtls.Uint64 = __readmsr(MSR_IA32_VMX_PROCBASED_CTLS);
+ if (ProcBasedCtls.Bits.Allowed1.ActivateSecondaryControls)
{
- case CPU_AMD:
- if (Reg[3] & 0x80000000) FeatureBits |= KF_3DNOW;
- break;
+ /* Read secondary controls and check if EPT is allowed */
+ MSR_IA32_VMX_PROCBASED_CTLS2_REGISTER ProcBasedCtls2;
+ ProcBasedCtls2.Uint64 = __readmsr(MSR_IA32_VMX_PROCBASED_CTLS2);
+ if (ProcBasedCtls2.Bits.Allowed1.EPT)
+ FeatureBits |= KF_SLAT;
+ }
+ }
+ }
+ else if (Vendor == CPU_AMD)
+ {
+ FeatureBits |= KF_AUTHENTICAMD;
+ FeatureBits |= KF_BRANCH;
+
+ /* Check extended cpuid features */
+ if ((extendedFunction.MaxLeaf & 0xffffff00) == 0x80000000)
+ {
+ /* Check if CPUID_AMD_SVM_FEATURES (0x8000000A) is supported */
+ if (extendedFunction.MaxLeaf >= CPUID_AMD_SVM_FEATURES)
+ {
+ /* Read CPUID_AMD_SVM_FEATURES and check if Nested Paging is available */
+ CPUID_AMD_SVM_FEATURES_REGS SvmFeatures;
+ __cpuid(SvmFeatures.AsInt32, CPUID_AMD_SVM_FEATURES);
+ if (SvmFeatures.Edx.Bits.NP) FeatureBits |= KF_SLAT;
}
}
}
return FeatureBits;
}
+#if DBG
+VOID
+KiReportCpuFeatures(IN PKPRCB Prcb)
+{
+ ULONG CpuFeatures = 0;
+ CPU_INFO CpuInfo;
+
+ if (Prcb->CpuVendor)
+ {
+ KiCpuId(&CpuInfo, 1);
+ CpuFeatures = CpuInfo.Edx;
+ }
+
+ DPRINT1("Supported CPU features: ");
+
+#define print_kf_bit(kf_value) if (Prcb->FeatureBits & kf_value) DbgPrint(#kf_value " ")
+ print_kf_bit(KF_SMEP);
+ print_kf_bit(KF_RDTSC);
+ print_kf_bit(KF_CR4);
+ print_kf_bit(KF_CMOV);
+ print_kf_bit(KF_GLOBAL_PAGE);
+ print_kf_bit(KF_LARGE_PAGE);
+ print_kf_bit(KF_MTRR);
+ print_kf_bit(KF_CMPXCHG8B);
+ print_kf_bit(KF_MMX);
+ print_kf_bit(KF_DTS);
+ print_kf_bit(KF_PAT);
+ print_kf_bit(KF_FXSR);
+ print_kf_bit(KF_FAST_SYSCALL);
+ print_kf_bit(KF_XMMI);
+ print_kf_bit(KF_3DNOW);
+ print_kf_bit(KF_XSAVEOPT);
+ print_kf_bit(KF_XMMI64);
+ print_kf_bit(KF_BRANCH);
+ print_kf_bit(KF_00040000);
+ print_kf_bit(KF_SSE3);
+ print_kf_bit(KF_CMPXCHG16B);
+ print_kf_bit(KF_AUTHENTICAMD);
+ print_kf_bit(KF_ACNT2);
+ print_kf_bit(KF_XSTATE);
+ print_kf_bit(KF_GENUINE_INTEL);
+ print_kf_bit(KF_SLAT);
+ print_kf_bit(KF_VIRT_FIRMWARE_ENABLED);
+ print_kf_bit(KF_RDWRFSGSBASE);
+ print_kf_bit(KF_NX_BIT);
+ print_kf_bit(KF_NX_DISABLED);
+ print_kf_bit(KF_NX_ENABLED);
+ print_kf_bit(KF_RDRAND);
+ print_kf_bit(KF_SMAP);
+ print_kf_bit(KF_RDTSCP);
+ print_kf_bit(KF_HUGEPAGE);
+ print_kf_bit(KF_XSAVES);
+ print_kf_bit(KF_FPU_LEAKAGE);
+ print_kf_bit(KF_CAT);
+ print_kf_bit(KF_CET_SS);
+ print_kf_bit(KF_SSSE3);
+ print_kf_bit(KF_SSE4_1);
+ print_kf_bit(KF_SSE4_2);
+#undef print_kf_bit
+
+#define print_cf(cpu_flag) if (CpuFeatures & cpu_flag) DbgPrint(#cpu_flag " ")
+ print_cf(X86_FEATURE_PAE);
+ print_cf(X86_FEATURE_HT);
+#undef print_cf
+
+ DbgPrint("\n");
+}
+#endif // DBG
+
VOID
NTAPI
KiGetCacheInformation(VOID)
{
PKIPCR Pcr = (PKIPCR)KeGetPcr();
ULONG Vendor;
- INT Data[4];
ULONG CacheRequests = 0, i;
ULONG CurrentRegister;
UCHAR RegisterByte;
BOOLEAN FirstPass = TRUE;
+ CPU_INFO CpuInfo;
/* Set default L2 size */
Pcr->SecondLevelCacheSize = 0;
case CPU_INTEL:
/*Check if we support CPUID 2 */
- __cpuid(Data, 0);
- if (Data[0] >= 2)
+ KiCpuId(&CpuInfo, 0);
+ if (CpuInfo.Eax >= 2)
{
/* We need to loop for the number of times CPUID will tell us to */
do
{
/* Do the CPUID call */
- __cpuid(Data, 2);
+ KiCpuId(&CpuInfo, 2);
/* Check if it was the first call */
if (FirstPass)
* The number of times to loop is the first byte. Read
* it and then destroy it so we don't get confused.
*/
- CacheRequests = Data[0] & 0xFF;
- Data[0] &= 0xFFFFFF00;
+ CacheRequests = CpuInfo.Eax & 0xFF;
+ CpuInfo.Eax &= 0xFFFFFF00;
/* Don't go over this again */
FirstPass = FALSE;
for (i = 0; i < 4; i++)
{
/* Get the current register */
- CurrentRegister = Data[i];
+ CurrentRegister = CpuInfo.AsUINT32[i];
/*
* If the upper bit is set, then this register should
case CPU_AMD:
/* Check if we support CPUID 0x80000006 */
- __cpuid(Data, 0x80000000);
- if (Data[0] >= 6)
+ KiCpuId(&CpuInfo, 0x80000000);
+ if (CpuInfo.Eax >= 6)
{
/* Get 2nd level cache and tlb size */
- __cpuid(Data, 0x80000006);
+ KiCpuId(&CpuInfo, 0x80000006);
/* Set the L2 Cache Size */
- Pcr->SecondLevelCacheSize = (Data[2] & 0xFFFF0000) >> 6;
+ Pcr->SecondLevelCacheSize = (CpuInfo.Ecx & 0xFFFF0000) >> 6;
}
break;
}
// __ltr(&ProcessorState->SpecialRegisters.Tr);
__lidt(&ProcessorState->SpecialRegisters.Idtr.Limit);
-// __ldmxcsr(&ProcessorState->SpecialRegisters.MxCsr); // FIXME
+ _mm_setcsr(ProcessorState->SpecialRegisters.MxCsr);
// ProcessorState->SpecialRegisters.DebugControl
// ProcessorState->SpecialRegisters.LastBranchToRip
// ProcessorState->SpecialRegisters.LastBranchFromRip
__str(&ProcessorState->SpecialRegisters.Tr);
__sidt(&ProcessorState->SpecialRegisters.Idtr.Limit);
-// __stmxcsr(&ProcessorState->SpecialRegisters.MxCsr);
+ ProcessorState->SpecialRegisters.MxCsr = _mm_getcsr();
// ProcessorState->SpecialRegisters.DebugControl =
// ProcessorState->SpecialRegisters.LastBranchToRip =
// ProcessorState->SpecialRegisters.LastBranchFromRip =