https://git.reactos.org/?p=reactos.git;a=commitdiff;h=410b1030c02240e0a711b0006023451fdd46a6d1

commit 410b1030c02240e0a711b0006023451fdd46a6d1
Author:     Timo Kreuzer <timo.kreu...@reactos.org>
AuthorDate: Sun Aug 27 15:07:30 2023 +0300
Commit:     Timo Kreuzer <timo.kreu...@reactos.org>
CommitDate: Tue Oct 3 19:45:44 2023 +0300

    [NTOS:KE/x64] Implement detection of more KF_* feature flags
    
    - Detect KF_SSSE3, KF_SSE4_1, KF_SSE4_2, KF_RDRAND, KF_BRANCH, KF_SLAT, 
KF_GENUINE_INTEL, KF_AUTHENTICAMD, KF_ACNT2, KF_SMEP, KF_SMAP, KF_RDWRFSGSBASE, 
KF_XSAVEOPT, KF_XSAVES, KF_HUGEPAGE, KF_RDTSCP
---
 ntoskrnl/ke/amd64/cpu.c            | 159 +++++++++++++++++++++++++++++++++----
 sdk/include/ndk/amd64/ketypes.h    |   2 +-
 sdk/include/reactos/x86x64/Cpuid.h |  11 ++-
 sdk/include/reactos/x86x64/Msr.h   |   6 ++
 4 files changed, 156 insertions(+), 22 deletions(-)

diff --git a/ntoskrnl/ke/amd64/cpu.c b/ntoskrnl/ke/amd64/cpu.c
index f01784f5b07..b2b40b0bf62 100644
--- a/ntoskrnl/ke/amd64/cpu.c
+++ b/ntoskrnl/ke/amd64/cpu.c
@@ -11,6 +11,7 @@
 
 #include <ntoskrnl.h>
 #include <x86x64/Cpuid.h>
+#include <x86x64/Msr.h>
 #define NDEBUG
 #include <debug.h>
 
@@ -146,6 +147,19 @@ KiSetProcessorType(VOID)
     KeGetCurrentPrcb()->CpuStep = (USHORT)Stepping;
 }
 
+/*!
+    \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)
@@ -153,6 +167,7 @@ KiGetFeatureBits(VOID)
     PKPRCB Prcb = KeGetCurrentPrcb();
     ULONG Vendor;
     ULONG64 FeatureBits = 0;
+    CPUID_SIGNATURE_REGS signature;
     CPUID_VERSION_INFO_REGS VersionInfo;
     CPUID_EXTENDED_FUNCTION_REGS extendedFunction;
 
@@ -160,7 +175,10 @@ KiGetFeatureBits(VOID)
     Vendor = Prcb->CpuVendor;
 
     /* Make sure we got a valid vendor ID at least. */
-    if (!Vendor) return FeatureBits;
+    if (Vendor == CPU_UNKNOWN) return FeatureBits;
+
+    /* Get signature CPUID for the maximum function */
+    __cpuid(signature.AsInt32, CPUID_SIGNATURE);
 
     /* Get the CPUID Info. */
     __cpuid(VersionInfo.AsInt32, CPUID_VERSION_INFO);
@@ -189,6 +207,7 @@ KiGetFeatureBits(VOID)
     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 (VersionInfo.Edx.Bits.HTT)
@@ -208,27 +227,115 @@ KiGetFeatureBits(VOID)
         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(extendedFunction.AsInt32, CPUID_EXTENDED_FUNCTION);
     if ((extendedFunction.MaxLeaf & 0xffffff00) == 0x80000000)
     {
-        /* Check if CPUID 0x80000001 is supported */
-        if (extendedFunction.MaxLeaf >= 0x80000001)
+        /* Check if CPUID_EXTENDED_CPU_SIG (0x80000001) is supported */
+        if (extendedFunction.MaxLeaf >= CPUID_EXTENDED_CPU_SIG)
         {
-            CPUID_EXTENDED_CPU_SIG_REGS extSig;
-
-            /* Check which extended features are available. */
-            __cpuid(extSig.AsInt32, CPUID_EXTENDED_CPU_SIG);
+            /* 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 (extSig.Intel.Edx.Bits.NX) 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;
 
-            /* Now handle each features for each CPU Vendor */
-            switch (Vendor)
+            /* AMD specific */
+            if (Vendor == CPU_AMD)
             {
-                case CPU_AMD:
-                    if (extSig.Amd.Edx.Bits.ThreeDNow) FeatureBits |= KF_3DNOW;
-                    break;
+                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;
+            }
+        }
+
+        /* 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)
+            {
+                /* 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;
             }
         }
     }
@@ -261,22 +368,40 @@ KiReportCpuFeatures(IN PKPRCB Prcb)
     print_kf_bit(KF_LARGE_PAGE);
     print_kf_bit(KF_MTRR);
     print_kf_bit(KF_CMPXCHG8B);
-    print_kf_bit(KF_CMPXCHG16B);
     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_DTS);
+    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_SSE3);
+    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_XSTATE);
+    print_kf_bit(KF_SSE4_2);
 #undef print_kf_bit
 
 #define print_cf(cpu_flag) if (CpuFeatures & cpu_flag) DbgPrint(#cpu_flag " ")
diff --git a/sdk/include/ndk/amd64/ketypes.h b/sdk/include/ndk/amd64/ketypes.h
index 1f306de1d2c..81219a73f82 100644
--- a/sdk/include/ndk/amd64/ketypes.h
+++ b/sdk/include/ndk/amd64/ketypes.h
@@ -249,7 +249,7 @@ typedef enum
 #define MSR_GS_SWAP             0xC0000102
 #define MSR_MCG_STATUS          0x017A
 #define MSR_AMD_ACCESS          0x9C5A203A
-#define MSR_IA32_MISC_ENABLE    0x01A0
+#define MSR_IA32_MISC_ENABLE    0x000001A0
 #define MSR_LAST_BRANCH_FROM    0x01DB
 #define MSR_LAST_BRANCH_TO      0x01DC
 #define MSR_LAST_EXCEPTION_FROM 0x01DD
diff --git a/sdk/include/reactos/x86x64/Cpuid.h 
b/sdk/include/reactos/x86x64/Cpuid.h
index 0a27d581e17..39ece442c99 100644
--- a/sdk/include/reactos/x86x64/Cpuid.h
+++ b/sdk/include/reactos/x86x64/Cpuid.h
@@ -1,3 +1,9 @@
+/*
+ * PROJECT:     ReactOS SDK
+ * LICENSE:     MIT (https://spdx.org/licenses/MIT)
+ * PURPOSE:     Provides CPUID structure definitions
+ * COPYRIGHT:   Copyright 2023 Timo Kreuzer <timo.kreu...@reactos.org>
+ */
 
 #define CHAR8 char
 
@@ -104,10 +110,7 @@ typedef union
             UINT32 XSaveAreaSize; // The size in bytes of the XSAVE area 
containing all states enabled by XCRO | IA32_XSS.
         } Ebx;
         CPUID_EXTENDED_STATE_SUB_LEAF_ECX Ecx;
-        struct
-        {
-            UINT32 Edx; // Reports the supported bits of the upper 32 bits of 
the IA32_XSS MSR.IA32_XSS[n + 32] can be set to 1 only if EDX[n] is 1.
-        } Edx;
+        UINT32 Edx; // Reports the supported bits of the upper 32 bits of the 
IA32_XSS MSR. IA32_XSS[n + 32] can be set to 1 only if EDX[n] is 1.
     };
 } CPUID_EXTENDED_STATE_SUB_LEAF_EAX_REGS;
 
diff --git a/sdk/include/reactos/x86x64/Msr.h b/sdk/include/reactos/x86x64/Msr.h
index 21e2a4df6ec..98b3e4d9ae1 100644
--- a/sdk/include/reactos/x86x64/Msr.h
+++ b/sdk/include/reactos/x86x64/Msr.h
@@ -1,3 +1,9 @@
+/*
+ * PROJECT:     ReactOS SDK
+ * LICENSE:     MIT (https://spdx.org/licenses/MIT)
+ * PURPOSE:     Provides CPUID structure definitions
+ * COPYRIGHT:   Copyright 2023 Timo Kreuzer <timo.kreu...@reactos.org>
+ */
 
 #define SIZE_2KB 2048
 

Reply via email to