https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1aca6937ff8a450bcc4681816a84cd4b1127f294

commit 1aca6937ff8a450bcc4681816a84cd4b1127f294
Author:     Victor Perevertkin <[email protected]>
AuthorDate: Sat Jan 15 03:42:59 2022 +0300
Commit:     Victor Perevertkin <[email protected]>
CommitDate: Tue Jan 25 02:12:33 2022 +0300

    [NTOS:KE] Add a check for unsupported CPU features on i586
    
    Currently, these features are vital for the kernel:
    - CPUID instruction
    - CMPXCHG8B instruction
    - TSC aka Time Stamp Counter
    
    All of that have to be present on i586
---
 ntoskrnl/ke/i386/kiinit.c | 69 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 50 insertions(+), 19 deletions(-)

diff --git a/ntoskrnl/ke/i386/kiinit.c b/ntoskrnl/ke/i386/kiinit.c
index 5c24902d2e5..10889c0195c 100644
--- a/ntoskrnl/ke/i386/kiinit.c
+++ b/ntoskrnl/ke/i386/kiinit.c
@@ -397,38 +397,69 @@ CODE_SEG("INIT")
 VOID
 KiVerifyCpuFeatures(PKPRCB Prcb)
 {
-    ULONG FeatureBits;
+    CPU_INFO CpuInfo;
 
-    /* Detect and set the CPU Type */
-    KiSetProcessorType();
+    // 1. Check CPUID support
+    ULONG EFlags = __readeflags();
+
+    /* XOR out the ID bit and update EFlags */
+    ULONG NewEFlags = EFlags ^ EFLAGS_ID;
+    __writeeflags(NewEFlags);
 
-    /* Check if an FPU is present */
-    KeI386NpxPresent = KiIsNpxPresent();
+    /* Get them back and see if they were modified */
+    NewEFlags = __readeflags();
+
+    if (NewEFlags == EFlags)
+    {
+        /* The modification did not work, so CPUID is not supported. */
+        KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x1, 0, 0, 0);
+    }
+    else
+    {
+        /* CPUID is supported. Set the ID Bit again. */
+        EFlags |= EFLAGS_ID;
+        __writeeflags(EFlags);
+    }
+
+    /* Peform CPUID 0 to see if CPUID 1 is supported */
+    KiCpuId(&CpuInfo, 0);
+    if (CpuInfo.Eax == 0)
+    {
+        // 0x1 - missing CPUID instruction
+        KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x1, 0, 0, 0);
+    }
+
+    // 2. Detect and set the CPU Type
+    KiSetProcessorType();
 
-    /* Bugcheck if this is a 386 CPU */
     if (Prcb->CpuType == 3)
         KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x386, 0, 0, 0);
 
-    /* Get the processor features for the CPU */
-    FeatureBits = KiGetFeatureBits();
+    // 3. Finally, obtain CPU features.
+    ULONG FeatureBits = KiGetFeatureBits();
+
+    // 4. Verify it supports everything we need.
+    if (!(FeatureBits & KF_RDTSC))
+    {
+        // 0x2 - missing CPUID features
+        // second paramenter - edx flag which is missing
+        KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x2, 0x00000010, 0, 0);
+    }
 
-    /* Detect 8-byte compare exchange support */
     if (!(FeatureBits & KF_CMPXCHG8B))
     {
-        ULONG Vendor[3];
+        KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x2, 0x00000100, 0, 0);
+    }
 
-        /* Copy the vendor string */
-        RtlCopyMemory(Vendor, Prcb->VendorString, sizeof(Vendor));
+    // Check x87 FPU is present. FIXME: put this into FeatureBits?
+    KiCpuId(&CpuInfo, 1);
 
-        /* Bugcheck the system. Windows *requires* this */
-        KeBugCheckEx(UNSUPPORTED_PROCESSOR,
-                     (1 << 24 ) | (Prcb->CpuType << 16) | Prcb->CpuStep,
-                     Vendor[0],
-                     Vendor[1],
-                     Vendor[2]);
+    if (!(CpuInfo.Edx & 0x00000001))
+    {
+        KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x2, 0x00000001, 0, 0);
     }
 
-    /* Save feature bits */
+    // 5. Save feature bits.
     Prcb->FeatureBits = FeatureBits;
 }
 

Reply via email to