Author: ion
Date: Wed Oct 4 09:29:30 2006
New Revision: 24386
URL:
http://svn.reactos.org/svn/reactos?rev=24386&view=rev
Log:
- 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.
Modified:
trunk/reactos/include/ndk/ketypes.h
trunk/reactos/ntoskrnl/include/internal/ke.h
trunk/reactos/ntoskrnl/include/internal/ntoskrnl.h
trunk/reactos/ntoskrnl/ke/clock.c
trunk/reactos/ntoskrnl/ke/i386/cpu.c
trunk/reactos/ntoskrnl/ke/i386/kiinit.c
trunk/reactos/ntoskrnl/ke/i386/trap.s
Modified: trunk/reactos/include/ndk/ketypes.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/ketypes.h?rev=…
==============================================================================
--- trunk/reactos/include/ndk/ketypes.h (original)
+++ trunk/reactos/include/ndk/ketypes.h Wed Oct 4 09:29:30 2006
@@ -86,6 +86,7 @@
#define KF_XMMI 0x00002000
#define KF_3DNOW 0x00004000
#define KF_AMDK6MTRR 0x00008000
+#define KF_XMMI64 0x00010000
//
// KPCR Access for non-IA64 builds
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ke.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h Wed Oct 4 09:29:30 2006
@@ -82,6 +82,7 @@
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 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 BOOLEAN KeThreadDpcEnable;
extern LARGE_INTEGER KiTimeIncrementReciprocal;
extern UCHAR KiTimeIncrementShiftCount;
+extern ULONG KiTimeLimitIsrMicroseconds;
extern LIST_ENTRY BugcheckCallbackListHead, BugcheckReasonCallbackListHead;
extern KSPIN_LOCK BugCheckCallbackLock;
extern KDPC KiExpireTimerDpc;
@@ -861,6 +864,10 @@
KiInitMachineDependent(VOID);
VOID
+NTAPI
+KiI386PentiumLockErrataFixup(VOID);
+
+VOID
WRMSR(
IN ULONG Register,
IN LONGLONG Value
Modified: trunk/reactos/ntoskrnl/include/internal/ntoskrnl.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ntoskrnl.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ntoskrnl.h Wed Oct 4 09:29:30 2006
@@ -318,6 +318,7 @@
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 */
Modified: trunk/reactos/ntoskrnl/ke/clock.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/clock.c?rev=24…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/clock.c (original)
+++ trunk/reactos/ntoskrnl/ke/clock.c Wed Oct 4 09:29:30 2006
@@ -37,7 +37,7 @@
KDPC KiExpireTimerDpc;
BOOLEAN KiClockSetupComplete = FALSE;
-
+ULONG KiTimeLimitIsrMicroseconds;
/*
* Number of timer interrupts since initialisation
Modified: trunk/reactos/ntoskrnl/ke/i386/cpu.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/cpu.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/cpu.c (original)
+++ trunk/reactos/ntoskrnl/ke/i386/cpu.c Wed Oct 4 09:29:30 2006
@@ -58,19 +58,21 @@
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 @@
/* 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 @@
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 @@
{
/* 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);
@@ -811,6 +834,14 @@
/* FIXME: Support this */
DPRINT1("Your machine supports XMMI exceptions but ReactOS
doesn't\n");
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 **********************************************************/
Modified: trunk/reactos/ntoskrnl/ke/i386/kiinit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/kiinit.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/kiinit.c (original)
+++ trunk/reactos/ntoskrnl/ke/i386/kiinit.c Wed Oct 4 09:29:30 2006
@@ -30,6 +30,8 @@
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 @@
/* 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 @@
/* 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 @@
/* 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,
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/trap.s?re…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/trap.s (original)
+++ trunk/reactos/ntoskrnl/ke/i386/trap.s Wed Oct 4 09:29:30 2006
@@ -111,9 +111,13 @@
/* 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