[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / ke / i386 / cpu.c
index 21d49c9..4b56a2b 100644 (file)
@@ -105,10 +105,28 @@ RDMSR(IN ULONG Register)
     return __readmsr(Register);
 }
 
+/* NSC/Cyrix CPU configuration register index */
+#define CX86_CCR1 0xc1
+
+/* NSC/Cyrix CPU indexed register access macros */
+static __inline
+ULONG
+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)
+
 /* FUNCTIONS *****************************************************************/
 
 VOID
 NTAPI
+INIT_FUNCTION
 KiSetProcessorType(VOID)
 {
     ULONG EFlags, NewEFlags;
@@ -175,6 +193,7 @@ KiSetProcessorType(VOID)
 
 ULONG
 NTAPI
+INIT_FUNCTION
 KiGetCpuVendor(VOID)
 {
     PKPRCB Prcb = KeGetCurrentPrcb();
@@ -236,12 +255,13 @@ KiGetCpuVendor(VOID)
 
 ULONG
 NTAPI
+INIT_FUNCTION
 KiGetFeatureBits(VOID)
 {
     PKPRCB Prcb = KeGetCurrentPrcb();
     ULONG Vendor;
     ULONG FeatureBits = KF_WORKING_PTE;
-    ULONG Reg[4], Dummy;
+    ULONG Reg[4], Dummy, Ccr1;
     BOOLEAN ExtendedCPUID = TRUE;
     ULONG CpuFeatures = 0;
 
@@ -283,10 +303,16 @@ KiGetFeatureBits(VOID)
                 /* Remove support for correct PTE support. */
                 FeatureBits &= ~KF_WORKING_PTE;
             }
+            
+            /* Virtualbox claims to have no SYSENTER support,
+             * which is false for processors >= Pentium Pro */
+            if(Prcb->CpuType >= 6)
+            {
+                Reg[3] |= 0x800;
+            }
 
             /* Check if the CPU is too old to support SYSENTER */
-            if ((Prcb->CpuType < 6) ||
-                ((Prcb->CpuType == 6) && (Prcb->CpuStep < 0x0303)))
+            if ((Reg[0] & 0x0FFF3FFF) < 0x00000633)
             {
                 /* Disable it */
                 Reg[3] &= ~0x800;
@@ -352,7 +378,22 @@ KiGetFeatureBits(VOID)
         /* Cyrix CPUs */
         case CPU_CYRIX:
 
-            /* FIXME: CMPXCGH8B */
+            /* Workaround the "COMA" bug on 6x family of Cyrix CPUs */
+            if (Prcb->CpuType == 6 &&
+                Prcb->CpuStep <= 1)
+            {
+                /* Get CCR1 value */
+                Ccr1 = getCx86(CX86_CCR1);
+
+                /* Enable the NO_LOCK bit */
+                Ccr1 |= 0x10;
+
+                /* Set the new CCR1 value */
+                setCx86(CX86_CCR1, Ccr1);
+            }
+
+            /* Set the current features */
+            CpuFeatures = Reg[3];
 
             break;
 
@@ -439,6 +480,32 @@ KiGetFeatureBits(VOID)
             }
         }
     }
+    
+    DPRINT1("Supported CPU features :\n");
+#define print_supported(kf_value) \
+    if(FeatureBits & kf_value) DPRINT1("\t" #kf_value "\n")
+    print_supported(KF_V86_VIS);
+    print_supported(KF_RDTSC);
+    print_supported(KF_CR4);
+    print_supported(KF_CMOV);
+    print_supported(KF_GLOBAL_PAGE);
+    print_supported(KF_LARGE_PAGE);
+    print_supported(KF_MTRR);
+    print_supported(KF_CMPXCHG8B);
+    print_supported(KF_MMX);
+    print_supported(KF_WORKING_PTE);
+    print_supported(KF_PAT);
+    print_supported(KF_FXSR);
+    print_supported(KF_FAST_SYSCALL);
+    print_supported(KF_XMMI);
+    print_supported(KF_3DNOW);
+    print_supported(KF_AMDK6MTRR);
+    print_supported(KF_XMMI64);
+    print_supported(KF_DTS);
+    print_supported(KF_NX_BIT);
+    print_supported(KF_NX_DISABLED);
+    print_supported(KF_NX_ENABLED);
+#undef print_supported
 
     /* Return the Feature Bits */
     return FeatureBits;
@@ -446,6 +513,7 @@ KiGetFeatureBits(VOID)
 
 VOID
 NTAPI
+INIT_FUNCTION
 KiGetCacheInformation(VOID)
 {
     PKIPCR Pcr = (PKIPCR)KeGetPcr();
@@ -748,6 +816,7 @@ KiGetCacheInformation(VOID)
 
 VOID
 NTAPI
+INIT_FUNCTION
 KiSetCR0Bits(VOID)
 {
     ULONG Cr0;
@@ -764,6 +833,7 @@ KiSetCR0Bits(VOID)
 
 VOID
 NTAPI
+INIT_FUNCTION
 KiInitializeTSS2(IN PKTSS Tss,
                  IN PKGDTENTRY TssEntry OPTIONAL)
 {
@@ -817,6 +887,7 @@ KiInitializeTSS(IN PKTSS Tss)
 
 VOID
 FASTCALL
+INIT_FUNCTION
 Ki386InitializeTss(IN PKTSS Tss,
                    IN PKIDTENTRY Idt,
                    IN PKGDTENTRY Gdt)
@@ -976,6 +1047,7 @@ KiSaveProcessorControlState(OUT PKPROCESSOR_STATE ProcessorState)
 
 VOID
 NTAPI
+INIT_FUNCTION
 KiInitializeMachineType(VOID)
 {
     /* Set the Machine Type we got from NTLDR */
@@ -984,6 +1056,7 @@ KiInitializeMachineType(VOID)
 
 ULONG_PTR
 NTAPI
+INIT_FUNCTION
 KiLoadFastSyscallMachineSpecificRegisters(IN ULONG_PTR Context)
 {
     /* Set CS and ESP */
@@ -997,56 +1070,7 @@ KiLoadFastSyscallMachineSpecificRegisters(IN ULONG_PTR Context)
 
 VOID
 NTAPI
-KiDisableFastSyscallReturn(VOID)
-{
-    /* Was it applied? */
-    if (KiSystemCallExitAdjusted)
-    {        
-        /* Restore the original value */
-        KiSystemCallExitBranch[1] = KiSystemCallExitBranch[1] - KiSystemCallExitAdjusted;
-                
-        /* It's not adjusted anymore */
-        KiSystemCallExitAdjusted = FALSE;
-    }
-}
-
-VOID
-NTAPI
-KiEnableFastSyscallReturn(VOID)
-{
-    /* Check if the patch has already been done */
-    if ((KiSystemCallExitAdjusted == KiSystemCallExitAdjust) &&
-        (KiFastCallCopyDoneOnce))
-    {
-        return;
-    }
-    
-    /* Make sure the offset is within the distance of a Jxx SHORT */
-    if ((KiSystemCallExitBranch[1] - KiSystemCallExitAdjust) < 0x80)
-    {
-        /* Remove any existing code patch */
-        KiDisableFastSyscallReturn();
-        
-        /* We should have a JNZ there */
-        ASSERT(KiSystemCallExitBranch[0] == 0x75);
-
-        /* Do the patch */        
-        KiSystemCallExitAdjusted = KiSystemCallExitAdjust;
-        KiSystemCallExitBranch[1] -= KiSystemCallExitAdjusted;
-        
-        /* Remember that we've done it */
-        KiFastCallCopyDoneOnce = TRUE;
-    }
-    else
-    {
-        /* This shouldn't happen unless we've messed the macros up */
-        DPRINT1("Your compiled kernel is broken!\n");
-        DbgBreakPoint();
-    }
-}
-
-VOID
-NTAPI
+INIT_FUNCTION
 KiRestoreFastSyscallReturnState(VOID)
 {
     /* Check if the CPU Supports fast system call */
@@ -1055,32 +1079,32 @@ KiRestoreFastSyscallReturnState(VOID)
         /* Check if it has been disabled */
         if (!KiFastSystemCallDisable)
         {
-            /* KiSystemCallExit2 should come BEFORE KiSystemCallExit */
-            ASSERT(KiSystemCallExit2 < KiSystemCallExit);
-            
-            /* It's enabled, so we'll have to do a code patch */
-            KiSystemCallExitAdjust = KiSystemCallExit - KiSystemCallExit2;
+            /* 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");
         }
     }
-    
-    /* Now check if all CPUs support fast system call, and the registry allows it */
-    if (KeFeatureBits & KF_FAST_SYSCALL)
+    else
     {
-        /* Do an IPI to enable it */
-        KeIpiGenericCall(KiLoadFastSyscallMachineSpecificRegisters, 0);
+        /* Use the IRET handler */
+        KiFastCallExitHandler = KiSystemCallTrapReturn;
+        DPRINT1("No support for SYSENTER detected.\n");
     }
-    
-    /* Perform the code patch that is required */
-    KiEnableFastSyscallReturn();
 }
 
 ULONG_PTR
 NTAPI
+INIT_FUNCTION
 Ki386EnableDE(IN ULONG_PTR Context)
 {
     /* Enable DE */
@@ -1090,6 +1114,7 @@ Ki386EnableDE(IN ULONG_PTR Context)
 
 ULONG_PTR
 NTAPI
+INIT_FUNCTION
 Ki386EnableFxsr(IN ULONG_PTR Context)
 {
     /* Enable FXSR */
@@ -1099,6 +1124,7 @@ Ki386EnableFxsr(IN ULONG_PTR Context)
 
 ULONG_PTR
 NTAPI
+INIT_FUNCTION
 Ki386EnableXMMIExceptions(IN ULONG_PTR Context)
 {
     PKIDTENTRY IdtEntry;
@@ -1121,6 +1147,7 @@ Ki386EnableXMMIExceptions(IN ULONG_PTR Context)
 
 VOID
 NTAPI
+INIT_FUNCTION
 KiI386PentiumLockErrataFixup(VOID)
 {
     KDESCRIPTOR IdtDescriptor;
@@ -1212,6 +1239,7 @@ KiSaveProcessorState(IN PKTRAP_FRAME TrapFrame,
 
 BOOLEAN
 NTAPI
+INIT_FUNCTION
 KiIsNpxPresent(VOID)
 {
     ULONG Cr0;
@@ -1224,7 +1252,12 @@ KiIsNpxPresent(VOID)
     Cr0 = __readcr0() & ~(CR0_MP | CR0_TS | CR0_EM | CR0_ET);
     
     /* Store on FPU stack */
+#ifdef _MSC_VER
+    __asm fninit;
+    __asm fnstsw Magic;
+#else
     asm volatile ("fninit;" "fnstsw %0" : "+m"(Magic));
+#endif
     
     /* Magic should now be cleared */
     if (Magic & 0xFF)
@@ -1247,6 +1280,7 @@ KiIsNpxPresent(VOID)
 
 BOOLEAN
 NTAPI
+INIT_FUNCTION
 KiIsNpxErrataPresent(VOID)
 {
     BOOLEAN ErrataPresent;
@@ -1261,7 +1295,7 @@ KiIsNpxErrataPresent(VOID)
     __writecr0(Cr0 & ~(CR0_MP | CR0_TS | CR0_EM));
     
     /* Initialize FPU state */
-    asm volatile ("fninit");
+    Ke386FnInit();
     
     /* Multiply the magic values and divide, we should get the result back */
     Value1 = 4195835.0;
@@ -1278,8 +1312,8 @@ KiIsNpxErrataPresent(VOID)
     return ErrataPresent;
 }
 
-NTAPI
 VOID
+NTAPI
 KiFlushNPXState(IN PFLOATING_SAVE_AREA SaveArea)
 {
     ULONG EFlags, Cr0;