- Add the other CPU_* codes (got them from a PDB)
authorColin Finck <colin@reactos.org>
Thu, 2 Oct 2008 21:57:36 +0000 (21:57 +0000)
committerColin Finck <colin@reactos.org>
Thu, 2 Oct 2008 21:57:36 +0000 (21:57 +0000)
- Restructure the CPU vendor check in KiGetFeatureBits with a switch statement
- Enable experimental support for Cyrix, Transmeta, Centaur and Rise CPUs (experimental = mostly untested)
- Just add CMPXCHG8B support to the feature bits for Centaur CPUs like it's already done for Rise CPUs without touching any MSRs.
  The instruction already works properly by default according to two official Centaur datasheets. Also Geoz on IRC already reported that his C3 Nehemiah works with ReactOS after this patch.
- Enable the 3DNow detection code through extended CPUID also for Centaur CPUs (all CPUs from IDT WinChip C6 to VIA C3 Ezra-T supported it)
- Report the presence of AMD K6 MTRRs also for mobile AMD K6-2+/K6-III+ CPUs (model D)

svn path=/trunk/; revision=36630

reactos/include/ndk/asm.h
reactos/ntoskrnl/ke/i386/cpu.c

index dc7b3b2..09ccd1a 100644 (file)
@@ -40,8 +40,14 @@ Author:
 //
 // CPU Types
 //
+#define CPU_NONE                                0x0
 #define CPU_INTEL                               0x1
 #define CPU_AMD                                 0x2
+#define CPU_CYRIX                               0x3
+#define CPU_TRANSMETA                           0x4
+#define CPU_CENTAUR                             0x5
+#define CPU_RISE                                0x6
+#define CPU_UNKNOWN                             0x7
 
 //
 // Selector Names
index f74f2bb..819cec1 100644 (file)
@@ -216,23 +216,23 @@ KiGetCpuVendor(VOID)
     }
     else if (!strcmp(Prcb->VendorString, CmpCyrixID))
     {
-        DPRINT1("Cyrix CPUs not fully supported\n");
-        return 0;
+        DPRINT1("Cyrix CPU support not fully tested!\n");
+        return CPU_CYRIX;
     }
     else if (!strcmp(Prcb->VendorString, CmpTransmetaID))
     {
-        DPRINT1("Transmeta CPUs not fully supported\n");
-        return 0;
+        DPRINT1("Transmeta CPU support not fully tested!\n");
+        return CPU_TRANSMETA;
     }
     else if (!strcmp(Prcb->VendorString, CmpCentaurID))
     {
-        DPRINT1("VIA CPUs not fully supported\n");
-        return 0;
+        DPRINT1("Centaur CPU support not fully tested!\n");
+        return CPU_CENTAUR;
     }
     else if (!strcmp(Prcb->VendorString, CmpRiseID))
     {
-        DPRINT1("Rise CPUs not fully supported\n");
-        return 0;
+        DPRINT1("Rise CPU support not fully tested!\n");
+        return CPU_RISE;
     }
 
     /* Invalid CPU */
@@ -262,136 +262,121 @@ KiGetFeatureBits(VOID)
     /* Set the initial APIC ID */
     Prcb->InitialApicId = (UCHAR)(Reg[1] >> 24);
 
-    /* Check for AMD CPU */
-    if (Vendor == CPU_AMD)
+    switch (Vendor)
     {
-        /* Check if this is a K5 or higher. */
-        if ((Reg[0] & 0x0F00) >= 0x0500)
-        {
-            /* Check if this is a K5 specifically. */
+        /* Intel CPUs */
+        case CPU_INTEL:
+            /* Check if it's a P6 */
+            if (Prcb->CpuType == 6)
+            {
+                /* Perform the special sequence to get the MicroCode Signature */
+                WRMSR(0x8B, 0);
+                CPUID(Reg, 1);
+                Prcb->UpdateSignature.QuadPart = RDMSR(0x8B);
+            }
+            else if (Prcb->CpuType == 5)
+            {
+                /* On P5, enable workaround for the LOCK errata. */
+                KiI386PentiumLockErrataPresent = TRUE;
+            }
+
+            /* Check for broken P6 with bad SMP PTE implementation */
+            if (((Reg[0] & 0x0FF0) == 0x0610 && (Reg[0] & 0x000F) <= 0x9) ||
+                ((Reg[0] & 0x0FF0) == 0x0630 && (Reg[0] & 0x000F) <= 0x4))
+            {
+                /* Remove support for correct PTE support. */
+                FeatureBits &= ~KF_WORKING_PTE;
+            }
+
+            /* Check if the CPU is too old to support SYSENTER */
+            if ((Prcb->CpuType < 6) ||
+                ((Prcb->CpuType == 6) && (Prcb->CpuStep < 0x0303)))
+            {
+                /* Disable it */
+                Reg[3] &= ~0x800;
+            }
+
+            /* Set the current features */
+            CpuFeatures = Reg[3];
+
+            break;
+
+        /* AMD CPUs */
+        case CPU_AMD:
+
+            /* Check if this is a K5 or K6. (family 5) */
             if ((Reg[0] & 0x0F00) == 0x0500)
             {
                 /* Get the Model Number */
                 switch (Reg[0] & 0x00F0)
                 {
-                    /* Check if this is the Model 1 */
+                    /* Model 1: K5 - 5k86 (initial models) */
                     case 0x0010:
 
                         /* Check if this is Step 0 or 1. They don't support PGE */
                         if ((Reg[0] & 0x000F) > 0x03) break;
 
+                    /* Model 0: K5 - SSA5 */
                     case 0x0000:
 
                         /* Model 0 doesn't support PGE at all. */
                         Reg[3] &= ~0x2000;
                         break;
 
+                    /* Model 8: K6-2 */
                     case 0x0080:
 
                         /* K6-2, Step 8 and over have support for MTRR. */
                         if ((Reg[0] & 0x000F) >= 0x8) FeatureBits |= KF_AMDK6MTRR;
                         break;
 
+                    /* Model 9: K6-III
+                       Model D: K6-2+, K6-III+ */
                     case 0x0090:
+                    case 0x00D0:
 
-                        /* As does the K6-3 */
                         FeatureBits |= KF_AMDK6MTRR;
                         break;
-
-                    default:
-                        break;
                 }
             }
-        }
-        else
-        {
-            /* Families below 5 don't support PGE, PSE or CMOV at all */
-            Reg[3] &= ~(0x08 | 0x2000 | 0x8000);
-
-            /* They also don't support advanced CPUID functions. */
-            ExtendedCPUID = FALSE;
-        }
-
-        /* Set the current features */
-        CpuFeatures = Reg[3];
-    }
-
-    /* Now check if this is Intel */
-    if (Vendor == CPU_INTEL)
-    {
-        /* Check if it's a P6 */
-        if (Prcb->CpuType == 6)
-        {
-            /* Perform the special sequence to get the MicroCode Signature */
-            WRMSR(0x8B, 0);
-            CPUID(Reg, 1);
-            Prcb->UpdateSignature.QuadPart = RDMSR(0x8B);
-        }
-        else if (Prcb->CpuType == 5)
-        {
-            /* On P5, enable workaround for the LOCK errata. */
-            KiI386PentiumLockErrataPresent = TRUE;
-        }
+            else if((Reg[0] & 0x0F00) < 0x0500)
+            {
+                /* Families below 5 don't support PGE, PSE or CMOV at all */
+                Reg[3] &= ~(0x08 | 0x2000 | 0x8000);
 
-        /* Check for broken P6 with bad SMP PTE implementation */
-        if (((Reg[0] & 0x0FF0) == 0x0610 && (Reg[0] & 0x000F) <= 0x9) ||
-            ((Reg[0] & 0x0FF0) == 0x0630 && (Reg[0] & 0x000F) <= 0x4))
-        {
-            /* Remove support for correct PTE support. */
-            FeatureBits &= ~KF_WORKING_PTE;
-        }
+                /* They also don't support advanced CPUID functions. */
+                ExtendedCPUID = FALSE;
+            }
 
-        /* Check if the CPU is too old to support SYSENTER */
-        if ((Prcb->CpuType < 6) ||
-            ((Prcb->CpuType == 6) && (Prcb->CpuStep < 0x0303)))
-        {
-            /* Disable it */
-            Reg[3] &= ~0x800;
-        }
+            /* Set the current features */
+            CpuFeatures = Reg[3];
 
-        /* Set the current features */
-        CpuFeatures = Reg[3];
-    }
+            break;
 
-#ifdef CPU_TRANSMETA
-    if (Vendor == CPU_TRANSMETA)
-    {
-        /* Enable CMPXCHG8B if the family (>= 5), model and stepping (>= 4.2) support it */
-        if ((Reg[0] & 0x0F00) >= 0x0500 && (Reg[0] & 0x00FF) >= 0x0042)
-        {
-            WRMSR(0x80860004, RDMSR(0x80860004) | 0x0100);
-            FeatureBits |= KF_CMPXCHG8B;
-        }
-    }
-#endif
+        /* Cyrix CPUs */
+        case CPU_CYRIX:
+            break;
 
-#ifdef CPU_CENTAUR
-    if (Vendor == CPU_CENTAUR)
-    {
-        /* If CMPXCHG8B is not detected, try to enable it */
-        if (!(CpuFeatures & 0x00000100))
-        {
-            if ((Reg[0] & 0x0F00) == 0x0500)
-            {
-                WRMSR(0x0107, RDMSR(0x0107) | 0x02);
-                FeatureBits |= KF_CMPXCHG8B;
-            }
-            else if ((Reg[0] & 0x0F00) >= 0x0600)
+        /* Transmeta CPUs */
+        case CPU_TRANSMETA:
+            /* Enable CMPXCHG8B if the family (>= 5), model and stepping (>= 4.2) support it */
+            if ((Reg[0] & 0x0FFF) >= 0x0542)
             {
-                WRMSR(0x1107, (RDMSR(0x1107) | 0x02) & ~((LONGLONG)0x01));
+                WRMSR(0x80860004, RDMSR(0x80860004) | 0x0100);
                 FeatureBits |= KF_CMPXCHG8B;
             }
-        }
-    }
-#endif
 
-#ifdef CPU_RISE
-    if (Vendor == CPU_RISE)
-    {
-        /* Windows Vista assumes CMPXCHG8B is always supported on Rise */
-        FeatureBits |= KF_CMPXCHG8B;
+            break;
+
+        /* Centaur, IDT, Rise and VIA CPUs */
+        case CPU_CENTAUR:
+        case CPU_RISE:
+            /* These CPUs don't report the presence of CMPXCHG8B through CPUID.
+               However, this feature exists and operates properly without any additional steps. */
+            FeatureBits |= KF_CMPXCHG8B;
+
+            break;
     }
-#endif
 
     /* Convert all CPUID Feature bits into our format */
     if (CpuFeatures & 0x00000002) FeatureBits |= KF_V86_VIS | KF_CR4;
@@ -446,6 +431,7 @@ KiGetFeatureBits(VOID)
                 switch (Vendor)
                 {
                     case CPU_AMD:
+                    case CPU_CENTAUR:
                         if (Reg[3] & 0x80000000) FeatureBits |= KF_3DNOW;
                         break;
                 }