mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 07:56:59 +00:00
- 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:
parent
917979cceb
commit
1e4f141555
7 changed files with 136 additions and 5 deletions
|
@ -86,6 +86,7 @@ Author:
|
||||||
#define KF_XMMI 0x00002000
|
#define KF_XMMI 0x00002000
|
||||||
#define KF_3DNOW 0x00004000
|
#define KF_3DNOW 0x00004000
|
||||||
#define KF_AMDK6MTRR 0x00008000
|
#define KF_AMDK6MTRR 0x00008000
|
||||||
|
#define KF_XMMI64 0x00010000
|
||||||
|
|
||||||
//
|
//
|
||||||
// KPCR Access for non-IA64 builds
|
// KPCR Access for non-IA64 builds
|
||||||
|
|
|
@ -82,6 +82,7 @@ extern ULONG_PTR KERNEL_BASE;
|
||||||
extern ULONG KeI386NpxPresent;
|
extern ULONG KeI386NpxPresent;
|
||||||
extern ULONG KeI386XMMIPresent;
|
extern ULONG KeI386XMMIPresent;
|
||||||
extern ULONG KeI386FxsrPresent;
|
extern ULONG KeI386FxsrPresent;
|
||||||
|
extern ULONG KiMXCsrMask;
|
||||||
extern ULONG KeI386CpuType;
|
extern ULONG KeI386CpuType;
|
||||||
extern ULONG KeI386CpuStep;
|
extern ULONG KeI386CpuStep;
|
||||||
extern ULONG KeProcessorArchitecture;
|
extern ULONG KeProcessorArchitecture;
|
||||||
|
@ -89,6 +90,7 @@ extern ULONG KeProcessorLevel;
|
||||||
extern ULONG KeProcessorRevision;
|
extern ULONG KeProcessorRevision;
|
||||||
extern ULONG KeFeatureBits;
|
extern ULONG KeFeatureBits;
|
||||||
extern ULONG Ke386GlobalPagesEnabled;
|
extern ULONG Ke386GlobalPagesEnabled;
|
||||||
|
extern BOOLEAN KiI386PentiumLockErrataPresent;
|
||||||
extern KNODE KiNode0;
|
extern KNODE KiNode0;
|
||||||
extern PKNODE KeNodeBlock[1];
|
extern PKNODE KeNodeBlock[1];
|
||||||
extern UCHAR KeNumberNodes;
|
extern UCHAR KeNumberNodes;
|
||||||
|
@ -119,6 +121,7 @@ extern ULONG KiIdealDpcRate;
|
||||||
extern BOOLEAN KeThreadDpcEnable;
|
extern BOOLEAN KeThreadDpcEnable;
|
||||||
extern LARGE_INTEGER KiTimeIncrementReciprocal;
|
extern LARGE_INTEGER KiTimeIncrementReciprocal;
|
||||||
extern UCHAR KiTimeIncrementShiftCount;
|
extern UCHAR KiTimeIncrementShiftCount;
|
||||||
|
extern ULONG KiTimeLimitIsrMicroseconds;
|
||||||
extern LIST_ENTRY BugcheckCallbackListHead, BugcheckReasonCallbackListHead;
|
extern LIST_ENTRY BugcheckCallbackListHead, BugcheckReasonCallbackListHead;
|
||||||
extern KSPIN_LOCK BugCheckCallbackLock;
|
extern KSPIN_LOCK BugCheckCallbackLock;
|
||||||
extern KDPC KiExpireTimerDpc;
|
extern KDPC KiExpireTimerDpc;
|
||||||
|
@ -860,6 +863,10 @@ VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
KiInitMachineDependent(VOID);
|
KiInitMachineDependent(VOID);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
KiI386PentiumLockErrataFixup(VOID);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
WRMSR(
|
WRMSR(
|
||||||
IN ULONG Register,
|
IN ULONG Register,
|
||||||
|
|
|
@ -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(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
|
||||||
C_ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
|
C_ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
|
||||||
C_ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
|
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);
|
C_ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
|
||||||
|
|
||||||
#endif /* INCLUDE_INTERNAL_NTOSKRNL_H */
|
#endif /* INCLUDE_INTERNAL_NTOSKRNL_H */
|
||||||
|
|
|
@ -37,7 +37,7 @@ LARGE_INTEGER SystemBootTime = { 0 };
|
||||||
|
|
||||||
KDPC KiExpireTimerDpc;
|
KDPC KiExpireTimerDpc;
|
||||||
BOOLEAN KiClockSetupComplete = FALSE;
|
BOOLEAN KiClockSetupComplete = FALSE;
|
||||||
|
ULONG KiTimeLimitIsrMicroseconds;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Number of timer interrupts since initialisation
|
* Number of timer interrupts since initialisation
|
||||||
|
|
|
@ -58,19 +58,21 @@ ULONG KeProcessorRevision;
|
||||||
ULONG KeFeatureBits;
|
ULONG KeFeatureBits;
|
||||||
ULONG KiFastSystemCallDisable = 1;
|
ULONG KiFastSystemCallDisable = 1;
|
||||||
ULONG KeI386NpxPresent = 0;
|
ULONG KeI386NpxPresent = 0;
|
||||||
|
ULONG KiMXCsrMask = 0;
|
||||||
ULONG MxcsrFeatureMask = 0;
|
ULONG MxcsrFeatureMask = 0;
|
||||||
ULONG KeI386XMMIPresent = 0;
|
ULONG KeI386XMMIPresent = 0;
|
||||||
ULONG KeI386FxsrPresent = 0;
|
ULONG KeI386FxsrPresent = 0;
|
||||||
ULONG KeI386MachineType;
|
ULONG KeI386MachineType;
|
||||||
ULONG Ke386Pae = FALSE;
|
ULONG Ke386Pae = FALSE;
|
||||||
ULONG Ke386NoExecute = FALSE;
|
ULONG Ke386NoExecute = FALSE;
|
||||||
BOOLEAN KiI386PentiumLockErrataPresent;
|
|
||||||
ULONG KeLargestCacheLine = 0x40;
|
ULONG KeLargestCacheLine = 0x40;
|
||||||
ULONG KeDcacheFlushCount = 0;
|
ULONG KeDcacheFlushCount = 0;
|
||||||
ULONG KeIcacheFlushCount = 0;
|
ULONG KeIcacheFlushCount = 0;
|
||||||
ULONG KiDmaIoCoherency = 0;
|
ULONG KiDmaIoCoherency = 0;
|
||||||
CHAR KeNumberProcessors;
|
CHAR KeNumberProcessors;
|
||||||
KAFFINITY KeActiveProcessors = 1;
|
KAFFINITY KeActiveProcessors = 1;
|
||||||
|
BOOLEAN KiI386PentiumLockErrataPresent;
|
||||||
|
BOOLEAN KiSMTProcessorsPresent;
|
||||||
|
|
||||||
/* CPU Signatures */
|
/* CPU Signatures */
|
||||||
CHAR CmpIntelID[] = "GenuineIntel";
|
CHAR CmpIntelID[] = "GenuineIntel";
|
||||||
|
@ -255,6 +257,9 @@ KiGetFeatureBits(VOID)
|
||||||
/* Get the CPUID Info. Features are in Reg[3]. */
|
/* Get the CPUID Info. Features are in Reg[3]. */
|
||||||
CPUID(Reg, 1);
|
CPUID(Reg, 1);
|
||||||
|
|
||||||
|
/* Set the initial APIC ID */
|
||||||
|
Prcb->InitialApicId = (UCHAR)(Reg[1] >> 24);
|
||||||
|
|
||||||
/* Check for AMD CPU */
|
/* Check for AMD CPU */
|
||||||
if (Vendor == CPU_AMD)
|
if (Vendor == CPU_AMD)
|
||||||
{
|
{
|
||||||
|
@ -351,6 +356,24 @@ KiGetFeatureBits(VOID)
|
||||||
if (CpuFeatures & 0x00800000) FeatureBits |= KF_MMX;
|
if (CpuFeatures & 0x00800000) FeatureBits |= KF_MMX;
|
||||||
if (CpuFeatures & 0x01000000) FeatureBits |= KF_FXSR;
|
if (CpuFeatures & 0x01000000) FeatureBits |= KF_FXSR;
|
||||||
if (CpuFeatures & 0x02000000) FeatureBits |= KF_XMMI;
|
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 */
|
/* Check if CPUID 0x80000000 is supported */
|
||||||
if (ExtendedCPUID)
|
if (ExtendedCPUID)
|
||||||
|
@ -765,7 +788,7 @@ KiLoadFastSyscallMachineSpecificRegisters(IN ULONG_PTR Context)
|
||||||
{
|
{
|
||||||
/* Set CS and ESP */
|
/* Set CS and ESP */
|
||||||
Ke386Wrmsr(0x174, KGDT_R0_CODE, 0);
|
Ke386Wrmsr(0x174, KGDT_R0_CODE, 0);
|
||||||
Ke386Wrmsr(0x175, 0, 0);
|
Ke386Wrmsr(0x175, KeGetCurrentPrcb()->DpcStack, 0);
|
||||||
|
|
||||||
/* Set LSTAR */
|
/* Set LSTAR */
|
||||||
Ke386Wrmsr(0x176, KiFastCallEntry, 0);
|
Ke386Wrmsr(0x176, KiFastCallEntry, 0);
|
||||||
|
@ -813,6 +836,14 @@ Ki386EnableXMMIExceptions(IN ULONG_PTR Context)
|
||||||
return 0;
|
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 **********************************************************/
|
/* PUBLIC FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -30,6 +30,8 @@ KiInitMachineDependent(VOID)
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
//ULONG ReturnLength;
|
//ULONG ReturnLength;
|
||||||
ULONG i, Affinity;
|
ULONG i, Affinity;
|
||||||
|
PFX_SAVE_AREA FxSaveArea;
|
||||||
|
ULONG MXCsrMask = 0xFFBF, NewMask;
|
||||||
|
|
||||||
/* Check for large page support */
|
/* Check for large page support */
|
||||||
if (KeFeatureBits & KF_LARGE_PAGE)
|
if (KeFeatureBits & KF_LARGE_PAGE)
|
||||||
|
@ -69,6 +71,30 @@ KiInitMachineDependent(VOID)
|
||||||
/* Check for PAT support and enable it */
|
/* Check for PAT support and enable it */
|
||||||
if (KeFeatureBits & KF_PAT) KiInitializePAT();
|
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 */
|
/* Check for CR4 support */
|
||||||
if (KeFeatureBits & KF_CR4)
|
if (KeFeatureBits & KF_CR4)
|
||||||
{
|
{
|
||||||
|
@ -143,12 +169,67 @@ KiInitMachineDependent(VOID)
|
||||||
/* Check if we have AMD MTRR and initialize it for the CPU */
|
/* Check if we have AMD MTRR and initialize it for the CPU */
|
||||||
if (KeFeatureBits & KF_AMDK6MTRR) KiAmdK6InitializeMTRR();
|
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 */
|
/* Return affinity back to where it was */
|
||||||
KeRevertToUserAffinityThread();
|
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
|
VOID
|
||||||
|
@ -519,11 +600,17 @@ AppCpuInit:
|
||||||
|
|
||||||
/* Align stack and make space for the trap frame and NPX frame */
|
/* Align stack and make space for the trap frame and NPX frame */
|
||||||
InitialStack &= ~KTRAP_FRAME_ALIGN;
|
InitialStack &= ~KTRAP_FRAME_ALIGN;
|
||||||
|
#ifdef __GNUC__
|
||||||
__asm__ __volatile__("movl %0,%%esp" : :"r" (InitialStack));
|
__asm__ __volatile__("movl %0,%%esp" : :"r" (InitialStack));
|
||||||
__asm__ __volatile__("subl %0,%%esp" : :"r" (NPX_FRAME_LENGTH +
|
__asm__ __volatile__("subl %0,%%esp" : :"r" (NPX_FRAME_LENGTH +
|
||||||
KTRAP_FRAME_LENGTH +
|
KTRAP_FRAME_LENGTH +
|
||||||
KTRAP_FRAME_ALIGN));
|
KTRAP_FRAME_ALIGN));
|
||||||
__asm__ __volatile__("push %0" : :"r" (CR0_EM + CR0_TS + CR0_MP));
|
__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 */
|
/* Call main kernel initialization */
|
||||||
KiInitializeKernel(&KiInitialProcess.Pcb,
|
KiInitializeKernel(&KiInitialProcess.Pcb,
|
||||||
|
|
|
@ -111,9 +111,13 @@ _KiFastCallEntry:
|
||||||
/* Set FS to PCR */
|
/* Set FS to PCR */
|
||||||
mov ecx, KGDT_R0_PCR
|
mov ecx, KGDT_R0_PCR
|
||||||
mov fs, cx
|
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 */
|
/* Set DS/ES to User Selector */
|
||||||
mov ecx, KGDT_R3_DATA | RPL_MASK
|
|
||||||
mov ds, cx
|
mov ds, cx
|
||||||
mov es, cx
|
mov es, cx
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue