ULONG KeIcacheFlushCount = 0;
ULONG KiDmaIoCoherency = 0;
ULONG KePrefetchNTAGranularity = 32;
-CHAR KeNumberProcessors = 0;
KAFFINITY KeActiveProcessors = 1;
BOOLEAN KiI386PentiumLockErrataPresent;
BOOLEAN KiSMTProcessorsPresent;
/* Compute associativity */
Associativity = 4;
if (RegisterByte >= 0x79) Associativity = 8;
-
+
/* Mask out only the first nibble */
RegisterByte &= 0x07;
{
/* Set minimum cache line size */
if (CacheLine < 128) CacheLine = 128;
-
+
/* Hard-code size/associativity */
Associativity = 8;
switch (RegisterByte)
Size = 512 * 1024;
Associativity = 4;
break;
-
+
case 0x23:
Size = 1024 * 1024;
break;
-
+
case 0x25:
Size = 2048 * 1024;
break;
-
+
case 0x29:
Size = 4096 * 1024;
break;
-
+
default:
Size = 0;
break;
}
-
+
/* Check if this cache is bigger than the last */
if ((Size / Associativity) > CurrentSize)
{
{
/* Set minimum cache line size */
if (CacheLine < 64) CacheLine = 64;
-
+
/* Hard-code size/associativity */
switch (RegisterByte)
{
Size = 4 * 1024 * 1024;
Associativity = 8;
break;
-
+
case 0x4B:
Size = 6 * 1024 * 1024;
Associativity = 12;
break;
-
+
case 0x4C:
Size = 8 * 1024 * 1024;
Associativity = 16;
break;
-
+
case 0x78:
Size = 1 * 1024 * 1024;
Associativity = 4;
break;
-
+
case 0x7D:
Size = 2 * 1024 * 1024;
Associativity = 8;
break;
-
+
case 0x7F:
Size = 512 * 1024;
Associativity = 2;
break;
-
+
case 0x86:
Size = 512 * 1024;
Associativity = 4;
break;
-
+
case 0x87:
Size = 1 * 1024 * 1024;
Associativity = 8;
Size = 0;
break;
}
-
+
/* Check if this cache is bigger than the last */
if ((Size / Associativity) > CurrentSize)
{
/* Get L1 size first */
CPUID(0x80000005, &Data[0], &Data[1], &Data[2], &Data[3]);
KePrefetchNTAGranularity = Data[2] & 0xFF;
-
+
/* Check if we support CPUID 0x80000006 */
CPUID(0x80000000, &Data[0], &Data[1], &Data[2], &Data[3]);
if (Data[0] >= 0x80000006)
{
/* Get 2nd level cache and tlb size */
CPUID(0x80000006, &Data[0], &Data[1], &Data[2], &Data[3]);
-
+
/* Cache line size */
CacheLine = Data[2] & 0xFF;
-
+
/* Hardcode associativity */
RegisterByte = Data[2] >> 12;
switch (RegisterByte)
case 2:
Associativity = 2;
break;
-
+
case 4:
Associativity = 4;
break;
-
+
case 6:
Associativity = 8;
break;
-
+
case 8:
case 15:
Associativity = 16;
break;
-
+
default:
Associativity = 1;
break;
}
-
+
/* Compute size */
Size = (Data[2] >> 16) << 10;
-
+
/* Hack for Model 6, Steping 300 */
if ((KeGetCurrentPrcb()->CpuType == 6) &&
(KeGetCurrentPrcb()->CpuStep == 0x300))
/* FIXME */
break;
}
-
+
/* 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",
{
ULONG Cr0;
USHORT Magic;
-
+
/* Set magic */
Magic = 0xFFFF;
-
+
/* Read CR0 and mask out FPU flags */
Cr0 = __readcr0() & ~(CR0_MP | CR0_TS | CR0_EM | CR0_ET);
-
+
/* Store on FPU stack */
#ifdef _MSC_VER
__asm fninit;
#else
asm volatile ("fninit;" "fnstsw %0" : "+m"(Magic));
#endif
-
+
/* Magic should now be cleared */
if (Magic & 0xFF)
{
__writecr0(Cr0 | CR0_EM | CR0_TS);
return FALSE;
}
-
+
/* You have an FPU, enable it */
Cr0 |= CR0_ET;
-
+
/* Enable INT 16 on 486 and higher */
if (KeGetCurrentPrcb()->CpuType >= 3) Cr0 |= CR0_NE;
-
+
/* Set FPU state */
__writecr0(Cr0 | CR0_EM | CR0_TS);
return TRUE;
BOOLEAN ErrataPresent;
ULONG Cr0;
volatile double Value1, Value2;
-
+
/* Disable interrupts */
_disable();
-
+
/* Read CR0 and remove FPU flags */
Cr0 = __readcr0();
__writecr0(Cr0 & ~(CR0_MP | CR0_TS | CR0_EM));
-
+
/* Initialize FPU state */
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;
-
+
/* Restore CR0 */
__writecr0(Cr0);
-
+
/* Enable interrupts */
_enable();
-
+
/* Return if there's an errata */
return ErrataPresent;
}
ULONG EFlags, Cr0;
PKTHREAD Thread, NpxThread;
PFX_SAVE_AREA FxSaveArea;
-
+
/* Save volatiles and disable interrupts */
EFlags = __readeflags();
_disable();
-
+
/* Save the PCR and get the current thread */
Thread = KeGetCurrentThread();
-
+
/* Check if we're already loaded */
if (Thread->NpxState != NPX_STATE_LOADED)
{
/* If there's nothing to load, quit */
if (!SaveArea) return;
-
+
/* Need FXSR support for this */
ASSERT(KeI386FxsrPresent == TRUE);
-
+
/* Check for sane CR0 */
Cr0 = __readcr0();
if (Cr0 & (CR0_MP | CR0_TS | CR0_EM))
/* Mask out FPU flags */
__writecr0(Cr0 & ~(CR0_MP | CR0_TS | CR0_EM));
}
-
+
/* Get the NPX thread and check its FPU state */
NpxThread = KeGetCurrentPrcb()->NpxThread;
if ((NpxThread) && (NpxThread->NpxState == NPX_STATE_LOADED))
/* Get the FX frame and store the state there */
FxSaveArea = KiGetThreadNpxArea(NpxThread);
Ke386FxSave(FxSaveArea);
-
+
/* NPX thread has lost its state */
NpxThread->NpxState = NPX_STATE_NOT_LOADED;
}
-
+
/* Now load NPX state from the NPX area */
FxSaveArea = KiGetThreadNpxArea(Thread);
Ke386FxStore(FxSaveArea);
/* Mask out FPU flags */
__writecr0(Cr0 & ~(CR0_MP | CR0_TS | CR0_EM));
}
-
+
/* Get FX frame */
FxSaveArea = KiGetThreadNpxArea(Thread);
Thread->NpxState = NPX_STATE_NOT_LOADED;
-
+
/* Save state if supported by CPU */
if (KeI386FxsrPresent) Ke386FxSave(FxSaveArea);
}
/* Clear NPX thread */
KeGetCurrentPrcb()->NpxThread = NULL;
-
+
/* Add the CR0 from the NPX frame */
Cr0 |= NPX_STATE_NOT_LOADED;
Cr0 |= FxSaveArea->Cr0NpxState;
__writecr0(Cr0);
-
+
/* Restore interrupt state */
__writeeflags(EFlags);
}
KiCoprocessorError(VOID)
{
PFX_SAVE_AREA NpxArea;
-
+
/* Get the FPU area */
NpxArea = KiGetThreadNpxArea(KeGetCurrentThread());
-
+
/* Set CR0_TS */
NpxArea->Cr0NpxState = CR0_TS;
__writecr0(__readcr0() | CR0_TS);