- Add KF_XMMI64 feature flag for SSE2 and detect it.

- Detect Hyper-Threading and set Local APIC ID (put back Thomas's code that he added in an old revision and that I had accidentally removed and forgotten to re-convert into the new KiGetFeatureBits function).
- Add code to set the kernel MX Csr Mask in the FX Save Area.
- Startup the sysenter handler on the DPC stack.
- Detect and notify users with broken Pentiums.
- Do some NPX checks to forcefully disable any FPU flags that might be set (SSE, MMX, 3DNOW) if the NPX is disabled.

svn path=/trunk/; revision=24386
This commit is contained in:
Alex Ionescu 2006-10-04 05:29:30 +00:00
parent 917979cceb
commit 1e4f141555
7 changed files with 136 additions and 5 deletions

View file

@ -86,6 +86,7 @@ Author:
#define KF_XMMI 0x00002000
#define KF_3DNOW 0x00004000
#define KF_AMDK6MTRR 0x00008000
#define KF_XMMI64 0x00010000
//
// KPCR Access for non-IA64 builds

View file

@ -82,6 +82,7 @@ extern ULONG_PTR KERNEL_BASE;
extern ULONG KeI386NpxPresent;
extern ULONG KeI386XMMIPresent;
extern ULONG KeI386FxsrPresent;
extern ULONG KiMXCsrMask;
extern ULONG KeI386CpuType;
extern ULONG KeI386CpuStep;
extern ULONG KeProcessorArchitecture;
@ -89,6 +90,7 @@ extern ULONG KeProcessorLevel;
extern ULONG KeProcessorRevision;
extern ULONG KeFeatureBits;
extern ULONG Ke386GlobalPagesEnabled;
extern BOOLEAN KiI386PentiumLockErrataPresent;
extern KNODE KiNode0;
extern PKNODE KeNodeBlock[1];
extern UCHAR KeNumberNodes;
@ -119,6 +121,7 @@ extern ULONG KiIdealDpcRate;
extern BOOLEAN KeThreadDpcEnable;
extern LARGE_INTEGER KiTimeIncrementReciprocal;
extern UCHAR KiTimeIncrementShiftCount;
extern ULONG KiTimeLimitIsrMicroseconds;
extern LIST_ENTRY BugcheckCallbackListHead, BugcheckReasonCallbackListHead;
extern KSPIN_LOCK BugCheckCallbackLock;
extern KDPC KiExpireTimerDpc;
@ -860,6 +863,10 @@ VOID
NTAPI
KiInitMachineDependent(VOID);
VOID
NTAPI
KiI386PentiumLockErrataFixup(VOID);
VOID
WRMSR(
IN ULONG Register,

View file

@ -318,6 +318,7 @@ C_ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == K
C_ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
C_ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
C_ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
C_ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, DpcStack) == KPCR_PRCB_DPC_STACK);
C_ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
#endif /* INCLUDE_INTERNAL_NTOSKRNL_H */

View file

@ -37,7 +37,7 @@ LARGE_INTEGER SystemBootTime = { 0 };
KDPC KiExpireTimerDpc;
BOOLEAN KiClockSetupComplete = FALSE;
ULONG KiTimeLimitIsrMicroseconds;
/*
* Number of timer interrupts since initialisation

View file

@ -58,19 +58,21 @@ ULONG KeProcessorRevision;
ULONG KeFeatureBits;
ULONG KiFastSystemCallDisable = 1;
ULONG KeI386NpxPresent = 0;
ULONG KiMXCsrMask = 0;
ULONG MxcsrFeatureMask = 0;
ULONG KeI386XMMIPresent = 0;
ULONG KeI386FxsrPresent = 0;
ULONG KeI386MachineType;
ULONG Ke386Pae = FALSE;
ULONG Ke386NoExecute = FALSE;
BOOLEAN KiI386PentiumLockErrataPresent;
ULONG KeLargestCacheLine = 0x40;
ULONG KeDcacheFlushCount = 0;
ULONG KeIcacheFlushCount = 0;
ULONG KiDmaIoCoherency = 0;
CHAR KeNumberProcessors;
KAFFINITY KeActiveProcessors = 1;
BOOLEAN KiI386PentiumLockErrataPresent;
BOOLEAN KiSMTProcessorsPresent;
/* CPU Signatures */
CHAR CmpIntelID[] = "GenuineIntel";
@ -255,6 +257,9 @@ KiGetFeatureBits(VOID)
/* Get the CPUID Info. Features are in Reg[3]. */
CPUID(Reg, 1);
/* Set the initial APIC ID */
Prcb->InitialApicId = (UCHAR)(Reg[1] >> 24);
/* Check for AMD CPU */
if (Vendor == CPU_AMD)
{
@ -351,6 +356,24 @@ KiGetFeatureBits(VOID)
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)
@ -765,7 +788,7 @@ KiLoadFastSyscallMachineSpecificRegisters(IN ULONG_PTR Context)
{
/* Set CS and ESP */
Ke386Wrmsr(0x174, KGDT_R0_CODE, 0);
Ke386Wrmsr(0x175, 0, 0);
Ke386Wrmsr(0x175, KeGetCurrentPrcb()->DpcStack, 0);
/* Set LSTAR */
Ke386Wrmsr(0x176, KiFastCallEntry, 0);
@ -813,6 +836,14 @@ Ki386EnableXMMIExceptions(IN ULONG_PTR Context)
return 0;
}
VOID
NTAPI
KiI386PentiumLockErrataFixup(VOID)
{
/* FIXME: Support this */
DPRINT1("WARNING: Your machine has a CPU bug that ReactOS can't bypass!\n");
}
/* PUBLIC FUNCTIONS **********************************************************/
/*

View file

@ -30,6 +30,8 @@ KiInitMachineDependent(VOID)
NTSTATUS Status;
//ULONG ReturnLength;
ULONG i, Affinity;
PFX_SAVE_AREA FxSaveArea;
ULONG MXCsrMask = 0xFFBF, NewMask;
/* Check for large page support */
if (KeFeatureBits & KF_LARGE_PAGE)
@ -69,6 +71,30 @@ KiInitMachineDependent(VOID)
/* Check for PAT support and enable it */
if (KeFeatureBits & KF_PAT) KiInitializePAT();
/* Assume no errata for now */
SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = 0;
/* If there's no NPX, then we're emulating the FPU */
SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] =
!KeI386NpxPresent;
/* Check if there's no NPX, so that we can disable associated features */
if (!KeI386NpxPresent)
{
/* Remove NPX-related bits */
KeFeatureBits &= ~(KF_XMMI64 | KF_XMMI | KF_FXSR | KF_MMX);
/* Disable kernel flags */
KeI386FxsrPresent = KeI386XMMIPresent = FALSE;
/* Disable processor features that might've been set until now */
SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] =
SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] =
SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] =
SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] =
SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = 0;
}
/* Check for CR4 support */
if (KeFeatureBits & KF_CR4)
{
@ -143,12 +169,67 @@ KiInitMachineDependent(VOID)
/* Check if we have AMD MTRR and initialize it for the CPU */
if (KeFeatureBits & KF_AMDK6MTRR) KiAmdK6InitializeMTRR();
/* FIXME: Apply P5 LOCK Errata fixups */
/* Check if this is a buggy Pentium and apply the fixup if so */
if (KiI386PentiumLockErrataPresent) KiI386PentiumLockErrataFixup();
/* Get the current thread NPX state */
FxSaveArea = (PVOID)
((ULONG_PTR)KeGetCurrentThread()->InitialStack -
NPX_FRAME_LENGTH);
/* Clear initial MXCsr mask */
FxSaveArea->U.FxArea.MXCsrMask = 0;
/* Save the current NPX State */
#ifdef __GNUC__
asm volatile("fxsave %0\n\t" : "=m" (*FxSaveArea));
#else
__asm fxsave [FxSaveArea]
#endif
/* Check if the current mask doesn't match the reserved bits */
if (FxSaveArea->U.FxArea.MXCsrMask != MXCsrMask)
{
/* Then use whatever it's holding */
MXCsrMask = FxSaveArea->U.FxArea.MXCsrMask;
}
/* Check if nobody set the kernel-wide mask */
if (!KiMXCsrMask)
{
/* Then use the one we calculated above */
NewMask = MXCsrMask;
}
else
{
/* Use the existing mask */
NewMask = KiMXCsrMask;
/* Was it set to the same value we found now? */
if (NewMask != MXCsrMask)
{
/* No, something is definitely wrong */
KEBUGCHECKEX(MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED,
KF_FXSR,
NewMask,
MXCsrMask,
0);
}
}
/* Now set the kernel mask */
KiMXCsrMask = NewMask & MXCsrMask;
}
}
/* Return affinity back to where it was */
KeRevertToUserAffinityThread();
/* NT allows limiting the duration of an ISR with a registry key */
if (KiTimeLimitIsrMicroseconds)
{
/* FIXME: TODO */
DPRINT1("ISR Time Limit not yet supported\n");
}
}
VOID
@ -519,11 +600,17 @@ AppCpuInit:
/* Align stack and make space for the trap frame and NPX frame */
InitialStack &= ~KTRAP_FRAME_ALIGN;
#ifdef __GNUC__
__asm__ __volatile__("movl %0,%%esp" : :"r" (InitialStack));
__asm__ __volatile__("subl %0,%%esp" : :"r" (NPX_FRAME_LENGTH +
KTRAP_FRAME_LENGTH +
KTRAP_FRAME_ALIGN));
__asm__ __volatile__("push %0" : :"r" (CR0_EM + CR0_TS + CR0_MP));
#else
__asm mov esp, InitialStack;
__asm sub esp, NPX_FRAME_LENGTH + KTRAP_FRAME_ALIGN + KTRAP_FRAME_LENGTH;
__asm push CR0_EM + CR0_TS + CR0_MP
#endif
/* Call main kernel initialization */
KiInitializeKernel(&KiInitialProcess.Pcb,

View file

@ -111,9 +111,13 @@ _KiFastCallEntry:
/* Set FS to PCR */
mov ecx, KGDT_R0_PCR
mov fs, cx
//push KGDT_R0_PCR
//pop fs
/* Set user selector */
mov ecx, KGDT_R3_DATA | RPL_MASK
/* Set DS/ES to User Selector */
mov ecx, KGDT_R3_DATA | RPL_MASK
mov ds, cx
mov es, cx