{
PKPRCB Prcb = KeGetCurrentPrcb();
ULONG Vendor;
ULONG FeatureBits = KF_WORKING_PTE;
ULONG Reg[4], Dummy;
UCHAR Ccr1;
BOOLEAN ExtendedCPUID = TRUE;
ULONG CpuFeatures = 0;
/* Get the Vendor ID */
Vendor = KiGetCpuVendor();
/* Make sure we got a valid vendor ID at least. */if (!Vendor) return FeatureBits;
/* Get the CPUID Info. Features are in Reg[3]. */CPUID(1, &Reg[0], &Reg[1], &Dummy, &Reg[3]);
/* Set the initial APIC ID */
Prcb->InitialApicId = (UCHAR)(Reg[1] >> 24);
switch (Vendor)
{
/* Intel CPUs */caseCPU_INTEL:
/* Check if it's a P6 */if (Prcb->CpuType == 6)
{
/* Perform the special sequence to get the MicroCode Signature */WRMSR(0x8B, 0);
CPUID(1, &Dummy, &Dummy, &Dummy, &Dummy);
Prcb->UpdateSignature.QuadPart = RDMSR(0x8B);
}
elseif (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;
}
break;
/* AMD CPUs */caseCPU_AMD:
/* Check if this is a K5 or K6. (family 5) */if ((Reg[0] & 0x0F00) == 0x0500)
{
/* Get the Model Number */switch (Reg[0] & 0x00F0)
{
/* 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:
FeatureBits |= KF_AMDK6MTRR;
break;
}
}
elseif((Reg[0] & 0x0F00) < 0x0500)
{
/* 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;
}
break;
/* Cyrix CPUs */caseCPU_CYRIX:
/* 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);
}
break;
/* Transmeta CPUs */caseCPU_TRANSMETA:
/* Enable CMPXCHG8B if the family (>= 5), model and stepping (>= 4.2) support it */if ((Reg[0] & 0x0FFF) >= 0x0542)
{
WRMSR(0x80860004, RDMSR(0x80860004) | 0x0100);
FeatureBits |= KF_CMPXCHG8B;
}
break;
/* Centaur, IDT, Rise and VIA CPUs */caseCPU_CENTAUR:
caseCPU_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;
}
/* 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;
if (CpuFeatures & 0x00000010) FeatureBits |= KF_RDTSC;
if (CpuFeatures & 0x00000100) FeatureBits |= KF_CMPXCHG8B;
if (CpuFeatures & 0x00000800) FeatureBits |= KF_FAST_SYSCALL;
if (CpuFeatures & 0x00001000) FeatureBits |= KF_MTRR;
if (CpuFeatures & 0x00002000) FeatureBits |= KF_GLOBAL_PAGE | KF_CR4;
if (CpuFeatures & 0x00008000) FeatureBits |= KF_CMOV;
if (CpuFeatures & 0x00010000) FeatureBits |= KF_PAT;
if (CpuFeatures & 0x00200000) FeatureBits |= KF_DTS;
if (CpuFeatures & 0x00800000) FeatureBits |= KF_MMX;
if (CpuFeatures & 0x01000000) FeatureBits |= KF_FXSR;
if (CpuFeatures & 0x02000000) FeatureBits |= KF_XMMI;
if (CpuFeatures & 0x04000000) FeatureBits |= KF_XMMI64;
/* Check if the CPU has hyper-threading */if (CpuFeatures & 0x10000000)
{
/* Set the number of logical CPUs */
Prcb->LogicalProcessorsPerPhysicalProcessor = (UCHAR)(Reg[1] >> 16);
if (Prcb->LogicalProcessorsPerPhysicalProcessor > 1)
{
/* We're on dual-core */KiSMTProcessorsPresent = TRUE;
}
}
else
{
/* We only have a single CPU */
Prcb->LogicalProcessorsPerPhysicalProcessor = 1;
}
/* Check if CPUID 0x80000000 is supported */if (ExtendedCPUID)
{
/* Do the call */CPUID(0x80000000, &Reg[0], &Dummy, &Dummy, &Dummy);
if ((Reg[0] & 0xffffff00) == 0x80000000)
{
/* Check if CPUID 0x80000001 is supported */if (Reg[0] >= 0x80000001)
{
/* Check which extended features are available. */CPUID(0x80000001, &Dummy, &Dummy, &Dummy, &Reg[3]);
/* Check if NX-bit is supported */if (Reg[3] & 0x00100000) FeatureBits |= KF_NX_BIT;
/* Now handle each features for each CPU Vendor */switch (Vendor)
{
caseCPU_AMD:
caseCPU_CENTAUR:
if (Reg[3] & 0x80000000) FeatureBits |= KF_3DNOW;
break;
}
}
}
}
#define print_supported(kf_value) ((FeatureBits & kf_value) ? #kf_value : "")DPRINT1("Supported CPU features : %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\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;
}
Generated on Sat May 26 2012 06:07:03 for ReactOS by
1.7.6.1
ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.