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