- 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
#define KF_XMMI 0x00002000
#define KF_3DNOW 0x00004000
#define KF_AMDK6MTRR 0x00008000
+#define KF_XMMI64 0x00010000
//
// KPCR Access for non-IA64 builds
extern ULONG KeI386NpxPresent;
extern ULONG KeI386XMMIPresent;
extern ULONG KeI386FxsrPresent;
+extern ULONG KiMXCsrMask;
extern ULONG KeI386CpuType;
extern ULONG KeI386CpuStep;
extern ULONG KeProcessorArchitecture;
extern ULONG KeProcessorRevision;
extern ULONG KeFeatureBits;
extern ULONG Ke386GlobalPagesEnabled;
+extern BOOLEAN KiI386PentiumLockErrataPresent;
extern KNODE KiNode0;
extern PKNODE KeNodeBlock[1];
extern UCHAR KeNumberNodes;
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;
NTAPI
KiInitMachineDependent(VOID);
+VOID
+NTAPI
+KiI386PentiumLockErrataFixup(VOID);
+
VOID
WRMSR(
IN ULONG Register,
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 */
KDPC KiExpireTimerDpc;
BOOLEAN KiClockSetupComplete = FALSE;
-
+ULONG KiTimeLimitIsrMicroseconds;
/*
* Number of timer interrupts since initialisation
ULONG KeFeatureBits;\r
ULONG KiFastSystemCallDisable = 1;\r
ULONG KeI386NpxPresent = 0;\r
+ULONG KiMXCsrMask = 0;\r
ULONG MxcsrFeatureMask = 0;\r
ULONG KeI386XMMIPresent = 0;\r
ULONG KeI386FxsrPresent = 0;\r
ULONG KeI386MachineType;\r
ULONG Ke386Pae = FALSE;\r
ULONG Ke386NoExecute = FALSE;\r
-BOOLEAN KiI386PentiumLockErrataPresent;\r
ULONG KeLargestCacheLine = 0x40;\r
ULONG KeDcacheFlushCount = 0;\r
ULONG KeIcacheFlushCount = 0;\r
ULONG KiDmaIoCoherency = 0;\r
CHAR KeNumberProcessors;\r
KAFFINITY KeActiveProcessors = 1;\r
+BOOLEAN KiI386PentiumLockErrataPresent;\r
+BOOLEAN KiSMTProcessorsPresent;\r
\r
/* CPU Signatures */\r
CHAR CmpIntelID[] = "GenuineIntel";\r
/* Get the CPUID Info. Features are in Reg[3]. */\r
CPUID(Reg, 1);\r
\r
+ /* Set the initial APIC ID */\r
+ Prcb->InitialApicId = (UCHAR)(Reg[1] >> 24);\r
+\r
/* Check for AMD CPU */\r
if (Vendor == CPU_AMD)\r
{\r
if (CpuFeatures & 0x00800000) FeatureBits |= KF_MMX;\r
if (CpuFeatures & 0x01000000) FeatureBits |= KF_FXSR;\r
if (CpuFeatures & 0x02000000) FeatureBits |= KF_XMMI;\r
+ if (CpuFeatures & 0x04000000) FeatureBits |= KF_XMMI64;\r
+\r
+ /* Check if the CPU has hyper-threading */\r
+ if (CpuFeatures & 0x10000000)\r
+ {\r
+ /* Set the number of logical CPUs */\r
+ Prcb->LogicalProcessorsPerPhysicalProcessor = (UCHAR)(Reg[1] >> 16);\r
+ if (Prcb->LogicalProcessorsPerPhysicalProcessor > 1)\r
+ {\r
+ /* We're on dual-core */\r
+ KiSMTProcessorsPresent = TRUE;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* We only have a single CPU */\r
+ Prcb->LogicalProcessorsPerPhysicalProcessor = 1;\r
+ }\r
\r
/* Check if CPUID 0x80000000 is supported */\r
if (ExtendedCPUID)\r
{\r
/* Set CS and ESP */\r
Ke386Wrmsr(0x174, KGDT_R0_CODE, 0);\r
- Ke386Wrmsr(0x175, 0, 0);\r
+ Ke386Wrmsr(0x175, KeGetCurrentPrcb()->DpcStack, 0);\r
\r
/* Set LSTAR */\r
Ke386Wrmsr(0x176, KiFastCallEntry, 0);\r
return 0;\r
}\r
\r
+VOID\r
+NTAPI\r
+KiI386PentiumLockErrataFixup(VOID)\r
+{\r
+ /* FIXME: Support this */\r
+ DPRINT1("WARNING: Your machine has a CPU bug that ReactOS can't bypass!\n");\r
+}\r
+\r
/* PUBLIC FUNCTIONS **********************************************************/\r
\r
/*\r
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)
/* 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)
{
/* 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
/* 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,
/* Set FS to PCR */
mov ecx, KGDT_R0_PCR
mov fs, cx
+ //push KGDT_R0_PCR
+ //pop fs
- /* Set DS/ES to User Selector */
+ /* Set user selector */
mov ecx, KGDT_R3_DATA | RPL_MASK
+
+ /* Set DS/ES to User Selector */
mov ds, cx
mov es, cx