- Add KF_XMMI64 feature flag for SSE2 and detect it.
authorAlex Ionescu <aionescu@gmail.com>
Wed, 4 Oct 2006 05:29:30 +0000 (05:29 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Wed, 4 Oct 2006 05:29:30 +0000 (05:29 +0000)
- Detect Hyper-Threading and set Local APIC ID (put back Thomas's code that he added in an old revision and that I had accidentally removed and forgotten to re-convert into the new KiGetFeatureBits function).
- Add code to set the kernel MX Csr Mask in the FX Save Area.
- Startup the sysenter handler on the DPC stack.
- Detect and notify users with broken Pentiums.
- Do some NPX checks to forcefully disable any FPU flags that might be set (SSE, MMX, 3DNOW) if the NPX is disabled.

svn path=/trunk/; revision=24386

reactos/include/ndk/ketypes.h
reactos/ntoskrnl/include/internal/ke.h
reactos/ntoskrnl/include/internal/ntoskrnl.h
reactos/ntoskrnl/ke/clock.c
reactos/ntoskrnl/ke/i386/cpu.c
reactos/ntoskrnl/ke/i386/kiinit.c
reactos/ntoskrnl/ke/i386/trap.s

index 9ed3830..5510e35 100644 (file)
@@ -86,6 +86,7 @@ Author:
 #define KF_XMMI                         0x00002000
 #define KF_3DNOW                        0x00004000
 #define KF_AMDK6MTRR                    0x00008000
+#define KF_XMMI64                       0x00010000
 
 //
 // KPCR Access for non-IA64 builds
index d36d301..24e5156 100644 (file)
@@ -82,6 +82,7 @@ extern ULONG_PTR KERNEL_BASE;
 extern ULONG KeI386NpxPresent;
 extern ULONG KeI386XMMIPresent;
 extern ULONG KeI386FxsrPresent;
+extern ULONG KiMXCsrMask;
 extern ULONG KeI386CpuType;
 extern ULONG KeI386CpuStep;
 extern ULONG KeProcessorArchitecture;
@@ -89,6 +90,7 @@ extern ULONG KeProcessorLevel;
 extern ULONG KeProcessorRevision;
 extern ULONG KeFeatureBits;
 extern ULONG Ke386GlobalPagesEnabled;
+extern BOOLEAN KiI386PentiumLockErrataPresent;
 extern KNODE KiNode0;
 extern PKNODE KeNodeBlock[1];
 extern UCHAR KeNumberNodes;
@@ -119,6 +121,7 @@ extern ULONG KiIdealDpcRate;
 extern BOOLEAN KeThreadDpcEnable;
 extern LARGE_INTEGER KiTimeIncrementReciprocal;
 extern UCHAR KiTimeIncrementShiftCount;
+extern ULONG KiTimeLimitIsrMicroseconds;
 extern LIST_ENTRY BugcheckCallbackListHead, BugcheckReasonCallbackListHead;
 extern KSPIN_LOCK BugCheckCallbackLock;
 extern KDPC KiExpireTimerDpc;
@@ -860,6 +863,10 @@ VOID
 NTAPI
 KiInitMachineDependent(VOID);
 
+VOID
+NTAPI
+KiI386PentiumLockErrataFixup(VOID);
+
 VOID
 WRMSR(
     IN ULONG Register,
index ba21d3f..de6d82e 100644 (file)
@@ -318,6 +318,7 @@ C_ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == K
 C_ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
 C_ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
 C_ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
+C_ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, DpcStack) == KPCR_PRCB_DPC_STACK);
 C_ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
 
 #endif /* INCLUDE_INTERNAL_NTOSKRNL_H */
index e294543..63ee0c0 100644 (file)
@@ -37,7 +37,7 @@ LARGE_INTEGER SystemBootTime = { 0 };
 
 KDPC KiExpireTimerDpc;
 BOOLEAN KiClockSetupComplete = FALSE;
-
+ULONG KiTimeLimitIsrMicroseconds;
 
 /*
  * Number of timer interrupts since initialisation
index 6516497..e8f88e0 100644 (file)
@@ -58,19 +58,21 @@ ULONG KeProcessorRevision;
 ULONG KeFeatureBits;\r
 ULONG KiFastSystemCallDisable = 1;\r
 ULONG KeI386NpxPresent = 0;\r
+ULONG KiMXCsrMask = 0;\r
 ULONG MxcsrFeatureMask = 0;\r
 ULONG KeI386XMMIPresent = 0;\r
 ULONG KeI386FxsrPresent = 0;\r
 ULONG KeI386MachineType;\r
 ULONG Ke386Pae = FALSE;\r
 ULONG Ke386NoExecute = FALSE;\r
-BOOLEAN KiI386PentiumLockErrataPresent;\r
 ULONG KeLargestCacheLine = 0x40;\r
 ULONG KeDcacheFlushCount = 0;\r
 ULONG KeIcacheFlushCount = 0;\r
 ULONG KiDmaIoCoherency = 0;\r
 CHAR KeNumberProcessors;\r
 KAFFINITY KeActiveProcessors = 1;\r
+BOOLEAN KiI386PentiumLockErrataPresent;\r
+BOOLEAN KiSMTProcessorsPresent;\r
 \r
 /* CPU Signatures */\r
 CHAR CmpIntelID[]       = "GenuineIntel";\r
@@ -255,6 +257,9 @@ KiGetFeatureBits(VOID)
     /* Get the CPUID Info. Features are in Reg[3]. */\r
     CPUID(Reg, 1);\r
 \r
+    /* Set the initial APIC ID */\r
+    Prcb->InitialApicId = (UCHAR)(Reg[1] >> 24);\r
+\r
     /* Check for AMD CPU */\r
     if (Vendor == CPU_AMD)\r
     {\r
@@ -351,6 +356,24 @@ KiGetFeatureBits(VOID)
     if (CpuFeatures & 0x00800000) FeatureBits |= KF_MMX;\r
     if (CpuFeatures & 0x01000000) FeatureBits |= KF_FXSR;\r
     if (CpuFeatures & 0x02000000) FeatureBits |= KF_XMMI;\r
+    if (CpuFeatures & 0x04000000) FeatureBits |= KF_XMMI64;\r
+\r
+    /* Check if the CPU has hyper-threading */\r
+    if (CpuFeatures & 0x10000000)\r
+    {\r
+        /* Set the number of logical CPUs */\r
+        Prcb->LogicalProcessorsPerPhysicalProcessor = (UCHAR)(Reg[1] >> 16);\r
+        if (Prcb->LogicalProcessorsPerPhysicalProcessor > 1)\r
+        {\r
+            /* We're on dual-core */\r
+            KiSMTProcessorsPresent = TRUE;\r
+        }\r
+    }\r
+    else\r
+    {\r
+        /* We only have a single CPU */\r
+        Prcb->LogicalProcessorsPerPhysicalProcessor = 1;\r
+    }\r
 \r
     /* Check if CPUID 0x80000000 is supported */\r
     if (ExtendedCPUID)\r
@@ -765,7 +788,7 @@ KiLoadFastSyscallMachineSpecificRegisters(IN ULONG_PTR Context)
 {\r
     /* Set CS and ESP */\r
     Ke386Wrmsr(0x174, KGDT_R0_CODE, 0);\r
-    Ke386Wrmsr(0x175, 0, 0);\r
+    Ke386Wrmsr(0x175, KeGetCurrentPrcb()->DpcStack, 0);\r
 \r
     /* Set LSTAR */\r
     Ke386Wrmsr(0x176, KiFastCallEntry, 0);\r
@@ -813,6 +836,14 @@ Ki386EnableXMMIExceptions(IN ULONG_PTR Context)
     return 0;\r
 }\r
 \r
+VOID\r
+NTAPI\r
+KiI386PentiumLockErrataFixup(VOID)\r
+{\r
+    /* FIXME: Support this */\r
+    DPRINT1("WARNING: Your machine has a CPU bug that ReactOS can't bypass!\n");\r
+}\r
+\r
 /* PUBLIC FUNCTIONS **********************************************************/\r
 \r
 /*\r
index a94815b..cf3a3b5 100644 (file)
@@ -30,6 +30,8 @@ KiInitMachineDependent(VOID)
     NTSTATUS Status;
     //ULONG ReturnLength;
     ULONG i, Affinity;
+    PFX_SAVE_AREA FxSaveArea;
+    ULONG MXCsrMask = 0xFFBF, NewMask;
 
     /* Check for large page support */
     if (KeFeatureBits & KF_LARGE_PAGE)
@@ -69,6 +71,30 @@ KiInitMachineDependent(VOID)
     /* Check for PAT support and enable it */
     if (KeFeatureBits & KF_PAT) KiInitializePAT();
 
+    /* Assume no errata for now */
+    SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = 0;
+
+    /* If there's no NPX, then we're emulating the FPU */
+    SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] =
+        !KeI386NpxPresent;
+
+    /* Check if there's no NPX, so that we can disable associated features */
+    if (!KeI386NpxPresent)
+    {
+        /* Remove NPX-related bits */
+        KeFeatureBits &= ~(KF_XMMI64 | KF_XMMI | KF_FXSR | KF_MMX);
+
+        /* Disable kernel flags */
+        KeI386FxsrPresent = KeI386XMMIPresent = FALSE;
+
+        /* Disable processor features that might've been set until now */
+        SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] =
+        SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE]   =
+        SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE]     =
+        SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE]    =
+        SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = 0;
+    }
+
     /* Check for CR4 support */
     if (KeFeatureBits & KF_CR4)
     {
@@ -143,12 +169,67 @@ KiInitMachineDependent(VOID)
             /* Check if we have AMD MTRR and initialize it for the CPU */
             if (KeFeatureBits & KF_AMDK6MTRR) KiAmdK6InitializeMTRR();
 
-            /* FIXME: Apply P5 LOCK Errata fixups */
+            /* Check if this is a buggy Pentium and apply the fixup if so */
+            if (KiI386PentiumLockErrataPresent) KiI386PentiumLockErrataFixup();
+
+            /* Get the current thread NPX state */
+            FxSaveArea = (PVOID)
+                         ((ULONG_PTR)KeGetCurrentThread()->InitialStack -
+                         NPX_FRAME_LENGTH);
+
+            /* Clear initial MXCsr mask */
+            FxSaveArea->U.FxArea.MXCsrMask = 0;
+
+            /* Save the current NPX State */
+#ifdef __GNUC__
+            asm volatile("fxsave %0\n\t" : "=m" (*FxSaveArea));
+#else
+            __asm fxsave [FxSaveArea]
+#endif
+            /* Check if the current mask doesn't match the reserved bits */
+            if (FxSaveArea->U.FxArea.MXCsrMask != MXCsrMask)
+            {
+                /* Then use whatever it's holding */
+                MXCsrMask = FxSaveArea->U.FxArea.MXCsrMask;
+            }
+
+            /* Check if nobody set the kernel-wide mask */
+            if (!KiMXCsrMask)
+            {
+                /* Then use the one we calculated above */
+                NewMask = MXCsrMask;
+            }
+            else
+            {
+                /* Use the existing mask */
+                NewMask = KiMXCsrMask;
+
+                /* Was it set to the same value we found now? */
+                if (NewMask != MXCsrMask)
+                {
+                    /* No, something is definitely wrong */
+                    KEBUGCHECKEX(MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED,
+                                 KF_FXSR,
+                                 NewMask,
+                                 MXCsrMask,
+                                 0);
+                }
+            }
+
+            /* Now set the kernel mask */
+            KiMXCsrMask = NewMask & MXCsrMask;
         }
     }
 
     /* Return affinity back to where it was */
     KeRevertToUserAffinityThread();
+
+    /* NT allows limiting the duration of an ISR with a registry key */
+    if (KiTimeLimitIsrMicroseconds)
+    {
+        /* FIXME: TODO */
+        DPRINT1("ISR Time Limit not yet supported\n");
+    }
 }
 
 VOID
@@ -519,11 +600,17 @@ AppCpuInit:
 
     /* Align stack and make space for the trap frame and NPX frame */
     InitialStack &= ~KTRAP_FRAME_ALIGN;
+#ifdef __GNUC__
     __asm__ __volatile__("movl %0,%%esp" : :"r" (InitialStack));
     __asm__ __volatile__("subl %0,%%esp" : :"r" (NPX_FRAME_LENGTH +
                                                  KTRAP_FRAME_LENGTH +
                                                  KTRAP_FRAME_ALIGN));
     __asm__ __volatile__("push %0" : :"r" (CR0_EM + CR0_TS + CR0_MP));
+#else
+    __asm mov esp, InitialStack;
+    __asm sub esp, NPX_FRAME_LENGTH + KTRAP_FRAME_ALIGN + KTRAP_FRAME_LENGTH;
+    __asm push CR0_EM + CR0_TS + CR0_MP
+#endif
 
     /* Call main kernel initialization */
     KiInitializeKernel(&KiInitialProcess.Pcb,
index f2ad0f7..85bfd88 100644 (file)
@@ -111,9 +111,13 @@ _KiFastCallEntry:
     /* Set FS to PCR */
     mov ecx, KGDT_R0_PCR
     mov fs, cx
+    //push KGDT_R0_PCR
+    //pop fs
 
-    /* Set DS/ES to User Selector */
+    /* Set user selector */
     mov ecx, KGDT_R3_DATA | RPL_MASK
+
+    /* Set DS/ES to User Selector */
     mov ds, cx
     mov es, cx