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=2... ============================================================================== --- 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/k... ============================================================================== --- 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/n... ============================================================================== --- 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=243... ============================================================================== --- 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?r... ============================================================================== --- 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?rev... ============================================================================== --- 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