Fix KeSaveFloatingPointState. It was working once upon a time, but the fix was lost...
[reactos.git] / reactos / ntoskrnl / ke / i386 / cpu.c
index fbe9ea8..b56414c 100644 (file)
@@ -23,11 +23,7 @@ UCHAR KiNMITSS[KTSS_IO_MAPS];
 /* CPU Features and Flags */
 ULONG KeI386CpuType;
 ULONG KeI386CpuStep;
-ULONG KeProcessorArchitecture;
-ULONG KeProcessorLevel;
-ULONG KeProcessorRevision;
-ULONG KeFeatureBits;
-ULONG KiFastSystemCallDisable = 1;
+ULONG KiFastSystemCallDisable = 0;
 ULONG KeI386NpxPresent = 0;
 ULONG KiMXCsrMask = 0;
 ULONG MxcsrFeatureMask = 0;
@@ -41,7 +37,6 @@ ULONG KeDcacheFlushCount = 0;
 ULONG KeIcacheFlushCount = 0;
 ULONG KiDmaIoCoherency = 0;
 ULONG KePrefetchNTAGranularity = 32;
-KAFFINITY KeActiveProcessors = 1;
 BOOLEAN KiI386PentiumLockErrataPresent;
 BOOLEAN KiSMTProcessorsPresent;
 
@@ -109,17 +104,21 @@ RDMSR(IN ULONG Register)
 
 /* NSC/Cyrix CPU indexed register access macros */
 static __inline
-ULONG
+UCHAR
 getCx86(UCHAR reg)
 {
     WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)0x22, reg);
     return READ_PORT_UCHAR((PUCHAR)(ULONG_PTR)0x23);
 }
 
-#define setCx86(reg, data) do { \
-   WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)0x22,(reg)); \
-   WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)0x23,(data)); \
-} while (0)
+static __inline
+void
+setCx86(UCHAR reg, UCHAR data)
+{
+    WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)0x22, reg);
+    WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)0x23, data);
+}
+
 
 /* FUNCTIONS *****************************************************************/
 
@@ -248,8 +247,9 @@ KiGetCpuVendor(VOID)
         return CPU_RISE;
     }
 
-    /* Invalid CPU */
-    return 0;
+    /* Unknown CPU */
+    DPRINT1("%s CPU support not fully tested!\n", Prcb->VendorString);
+    return CPU_UNKNOWN;
 }
 
 ULONG
@@ -260,7 +260,8 @@ KiGetFeatureBits(VOID)
     PKPRCB Prcb = KeGetCurrentPrcb();
     ULONG Vendor;
     ULONG FeatureBits = KF_WORKING_PTE;
-    ULONG Reg[4], Dummy, Ccr1;
+    ULONG Reg[4], Dummy;
+    UCHAR Ccr1;
     BOOLEAN ExtendedCPUID = TRUE;
     ULONG CpuFeatures = 0;
 
@@ -311,9 +312,6 @@ KiGetFeatureBits(VOID)
                 Reg[3] &= ~0x800;
             }
 
-            /* Set the current features */
-            CpuFeatures = Reg[3];
-
             break;
 
         /* AMD CPUs */
@@ -363,9 +361,6 @@ KiGetFeatureBits(VOID)
                 ExtendedCPUID = FALSE;
             }
 
-            /* Set the current features */
-            CpuFeatures = Reg[3];
-
             break;
 
         /* Cyrix CPUs */
@@ -385,9 +380,6 @@ KiGetFeatureBits(VOID)
                 setCx86(CX86_CCR1, Ccr1);
             }
 
-            /* Set the current features */
-            CpuFeatures = Reg[3];
-
             break;
 
         /* Transmeta CPUs */
@@ -413,6 +405,9 @@ KiGetFeatureBits(VOID)
             break;
     }
 
+    /* Set the current features */
+    CpuFeatures = Reg[3];
+
     /* Convert all CPUID Feature bits into our format */
     if (CpuFeatures & 0x00000002) FeatureBits |= KF_V86_VIS | KF_CR4;
     if (CpuFeatures & 0x00000008) FeatureBits |= KF_LARGE_PAGE | KF_CR4;
@@ -513,8 +508,8 @@ KiGetCacheInformation(VOID)
     ULONG Data[4], Dummy;
     ULONG CacheRequests = 0, i;
     ULONG CurrentRegister;
-    UCHAR RegisterByte;
-    ULONG Size, Associativity = 0, CacheLine = 64, CurrentSize = 0;
+    UCHAR RegisterByte, Associativity = 0;
+    ULONG Size, CacheLine = 64, CurrentSize = 0;
     BOOLEAN FirstPass = TRUE;
 
     /* Set default L2 size */
@@ -745,7 +740,7 @@ KiGetCacheInformation(VOID)
                     CacheLine = Data[2] & 0xFF;
 
                     /* Hardcode associativity */
-                    RegisterByte = Data[2] >> 12;
+                    RegisterByte = (Data[2] >> 12) & 0xFF;
                     switch (RegisterByte)
                     {
                         case 2:
@@ -799,7 +794,7 @@ KiGetCacheInformation(VOID)
 
     /* Set the cache line */
     if (CacheLine > KeLargestCacheLine) KeLargestCacheLine = CacheLine;
-    DPRINT1("Prefetch Cache: %d bytes\tL2 Cache: %d bytes\tL2 Cache Line: %d bytes\tL2 Cache Associativity: %d\n",
+    DPRINT1("Prefetch Cache: %lu bytes\tL2 Cache: %lu bytes\tL2 Cache Line: %lu bytes\tL2 Cache Associativity: %lu\n",
             KePrefetchNTAGranularity,
             Pcr->SecondLevelCacheSize,
             KeLargestCacheLine,
@@ -1069,21 +1064,21 @@ KiRestoreFastSyscallReturnState(VOID)
     if (KeFeatureBits & KF_FAST_SYSCALL)
     {
         /* Check if it has been disabled */
-        if (!KiFastSystemCallDisable)
+        if (KiFastSystemCallDisable)
+        {
+            /* Disable fast system call */
+            KeFeatureBits &= ~KF_FAST_SYSCALL;
+            KiFastCallExitHandler = KiSystemCallTrapReturn;
+            DPRINT1("Support for SYSENTER disabled.\n");
+        }
+        else
         {
             /* Do an IPI to enable it */
             KeIpiGenericCall(KiLoadFastSyscallMachineSpecificRegisters, 0);
 
             /* It's enabled, so use the proper exit stub */
             KiFastCallExitHandler = KiSystemCallSysExitReturn;
-            DPRINT1("Support for SYSENTER detected.\n");
-        }
-        else
-        {
-            /* Disable fast system call */
-            KeFeatureBits &= ~KF_FAST_SYSCALL;
-            KiFastCallExitHandler = KiSystemCallTrapReturn;
-            DPRINT1("Support for SYSENTER disabled.\n");
+            DPRINT("Support for SYSENTER detected.\n");
         }
     }
     else
@@ -1142,7 +1137,7 @@ NTAPI
 INIT_FUNCTION
 KiI386PentiumLockErrataFixup(VOID)
 {
-    KDESCRIPTOR IdtDescriptor;
+    KDESCRIPTOR IdtDescriptor = {0, 0, 0};
     PKIDTENTRY NewIdt, NewIdt2;
 
     /* Allocate memory for a new IDT */
@@ -1259,9 +1254,9 @@ NTAPI
 INIT_FUNCTION
 KiIsNpxErrataPresent(VOID)
 {
-    BOOLEAN ErrataPresent;
+    static double Value1 = 4195835.0, Value2 = 3145727.0;
+    INT ErrataPresent;
     ULONG Cr0;
-    volatile double Value1, Value2;
 
     /* Disable interrupts */
     _disable();
@@ -1274,9 +1269,30 @@ KiIsNpxErrataPresent(VOID)
     Ke386FnInit();
 
     /* Multiply the magic values and divide, we should get the result back */
-    Value1 = 4195835.0;
-    Value2 = 3145727.0;
-    ErrataPresent = (Value1 * Value2 / 3145727.0) != 4195835.0;
+#ifdef __GNUC__
+    __asm__ __volatile__
+    (
+        "fldl %1\n\t"
+        "fdivl %2\n\t"
+        "fmull %2\n\t"
+        "fldl %1\n\t"
+        "fsubp\n\t"
+        "fistpl %0\n\t"
+        : "=m" (ErrataPresent)
+        : "m" (Value1),
+          "m" (Value2)
+    );
+#else
+    __asm
+    {
+        fld Value1
+        fdiv Value2
+        fmul Value2
+        fld Value1
+        fsubp st(1), st(0)
+        fistp ErrataPresent
+    };
+#endif
 
     /* Restore CR0 */
     __writecr0(Cr0);
@@ -1285,7 +1301,7 @@ KiIsNpxErrataPresent(VOID)
     _enable();
 
     /* Return if there's an errata */
-    return ErrataPresent;
+    return ErrataPresent != 0;
 }
 
 VOID
@@ -1307,7 +1323,12 @@ KiFlushNPXState(IN PFLOATING_SAVE_AREA SaveArea)
     if (Thread->NpxState != NPX_STATE_LOADED)
     {
         /* If there's nothing to load, quit */
-        if (!SaveArea) return;
+        if (!SaveArea)
+        {
+            /* Restore interrupt state and return */
+            __writeeflags(EFlags);
+            return;
+        }
 
         /* Need FXSR support for this */
         ASSERT(KeI386FxsrPresent == TRUE);
@@ -1411,11 +1432,12 @@ KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save)
 #else
     __asm
     {
-        fnsave [FpState]
+        mov eax, [FpState]
+        fnsave [eax]
     };
 #endif
 
-    KeGetCurrentThread()->DispatcherHeader.NpxIrql = KeGetCurrentIrql();
+    KeGetCurrentThread()->Header.NpxIrql = KeGetCurrentIrql();
     return STATUS_SUCCESS;
 }
 
@@ -1427,7 +1449,7 @@ NTAPI
 KeRestoreFloatingPointState(IN PKFLOATING_SAVE Save)
 {
     PFNSAVE_FORMAT FpState = *((PVOID *) Save);
-    ASSERT(KeGetCurrentThread()->DispatcherHeader.NpxIrql == KeGetCurrentIrql());
+    ASSERT(KeGetCurrentThread()->Header.NpxIrql == KeGetCurrentIrql());
     DPRINT1("%s is not really implemented\n", __FUNCTION__);
 
 #ifdef __GNUC__
@@ -1514,7 +1536,7 @@ KeFlushEntireTb(IN BOOLEAN Invalid,
     if (TargetAffinity)
     {
         /* Sanity check */
-        ASSERT(Prcb == (volatile PKPRCB)KeGetCurrentPrcb());
+        ASSERT(Prcb == KeGetCurrentPrcb());
 
         /* FIXME: TODO */
         ASSERTMSG("Not yet implemented\n", FALSE);