https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1aca6937ff8a450bcc4681...
commit 1aca6937ff8a450bcc4681816a84cd4b1127f294 Author: Victor Perevertkin victor.perevertkin@reactos.org AuthorDate: Sat Jan 15 03:42:59 2022 +0300 Commit: Victor Perevertkin victor.perevertkin@reactos.org 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; }