Author: ion
Date: Thu Jan 18 09:23:14 2007
New Revision: 25503
URL: 
http://svn.reactos.org/svn/reactos?rev=25503&view=rev
Log:
- Fix __rdtsc so it's considered volatile by GCC instead of caching it.
- Add NtInitialUserProcessBuffer settings and validate/user them when launching smss.
- Use SePublicDefaultUnrestrictedSd for the root system link.
- Make enough space for the smss process parameters, there's 6 strings, not 4.
- Fix incorrect length of NtSystemRoot string.
- Disable SYSENTER on CPUs that don't support it.
- Detect and enable NX feature bit.
- Detect and enable DTS support.
- Implement Ki386EnableXMMIExceptions (the XMMI handler still needs to be done, however).
- Implement KiI386PentiumLockErrataFixup to work around the F00F bug.
- Implement KiIsNpxErrataPresent to detect the FDIV bug.
- Implement CPU Speed detection.
- Only setup Initial FX State if the CPU supports FXSR.
- Setup some more PCR fields during init.
- Use NX_SUPPORT_POLICY flags documented in ntddk.h
- Don't boot if CMPXCHG8B is not supported by the CPU. This is the same requirement as
Windows.
- Don't overwrite all the PRCB locks in KiInitSpinlocks due to a stupid bug in the
timer spinlock initialization.
Modified:
    trunk/reactos/include/ddk/winddk.h
    trunk/reactos/include/ndk/ketypes.h
    trunk/reactos/include/psdk/intrin.h
    trunk/reactos/ntoskrnl/KrnlFun.c
    trunk/reactos/ntoskrnl/ex/init.c
    trunk/reactos/ntoskrnl/include/internal/i386/ke.h
    trunk/reactos/ntoskrnl/include/internal/ke.h
    trunk/reactos/ntoskrnl/ke/dpc.c
    trunk/reactos/ntoskrnl/ke/i386/cpu.c
    trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
    trunk/reactos/ntoskrnl/ke/i386/kiinit.c
    trunk/reactos/ntoskrnl/ke/i386/patpge.c
    trunk/reactos/ntoskrnl/ke/krnlinit.c
Modified: trunk/reactos/include/ddk/winddk.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ddk/winddk.h?rev=2…
==============================================================================
--- trunk/reactos/include/ddk/winddk.h (original)
+++ trunk/reactos/include/ddk/winddk.h Thu Jan 18 09:23:14 2007
@@ -426,6 +426,11 @@
 } KSYSTEM_TIME, *PKSYSTEM_TIME;
 extern volatile KSYSTEM_TIME KeTickCount;
+
+#define NX_SUPPORT_POLICY_ALWAYSOFF 0
+#define NX_SUPPORT_POLICY_ALWAYSON 1
+#define NX_SUPPORT_POLICY_OPTIN 2
+#define NX_SUPPORT_POLICY_OPTOUT 3
 typedef struct _KUSER_SHARED_DATA
 {
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 Thu Jan 18 09:23:14 2007
@@ -38,6 +38,11 @@
 // Maximum System Descriptor Table Entries
 //
 #define SSDT_MAX_ENTRIES                2
+
+//
+// Processor Architectures
+//
+#define PROCESSOR_ARCHITECTURE_INTEL    0
 //
 // Object Type Mask for Kernel Dispatcher Objects
@@ -87,8 +92,10 @@
 #define KF_3DNOW                        0x00004000
 #define KF_AMDK6MTRR                    0x00008000
 #define KF_XMMI64                       0x00010000
-#define KF_NX_DISABLED                  0x00400000
-#define KF_NX_ENABLED                   0x00800000
+#define KF_DTS                          0x00020000
+#define KF_NX_BIT                       0x20000000
+#define KF_NX_DISABLED                  0x40000000
+#define KF_NX_ENABLED                   0x80000000
 //
 // KPCR Access for non-IA64 builds
Modified: trunk/reactos/include/psdk/intrin.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/psdk/intrin.h?rev=…
==============================================================================
--- trunk/reactos/include/psdk/intrin.h (original)
+++ trunk/reactos/include/psdk/intrin.h Thu Jan 18 09:23:14 2007
@@ -930,7 +930,7 @@
        unsigned long lo32;
        unsigned long hi32;
-       __asm__("rdtsc" : "=a" (lo32), "=d" (hi32));
+       __asm__ __volatile__("rdtsc" : "=a" (lo32), "=d"
(hi32));
        {
                union u_
Modified: trunk/reactos/ntoskrnl/KrnlFun.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/KrnlFun.c?rev=255…
==============================================================================
--- trunk/reactos/ntoskrnl/KrnlFun.c (original)
+++ trunk/reactos/ntoskrnl/KrnlFun.c Thu Jan 18 09:23:14 2007
@@ -9,7 +9,6 @@
 //              Failure to respect this will *ACHIEVE NOTHING*.
 //
 // Ke1:
-//  - Implement KiInitMachineDependent.
 //  - Implement Privileged Instruction Handler in Umode GPF.
 //
 // Ex:
@@ -27,10 +26,6 @@
 //
 // Kd:
 //  - Implement KD Kernel Debugging and WinDBG support.
-//
-// Native:
-//  - Rewrite loader.
-//  - Make smss NT-compatible.
 //
 ///////////////////////////////////////////////////////////////////////////////
Modified: trunk/reactos/ntoskrnl/ex/init.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/init.c?rev=255…
==============================================================================
--- trunk/reactos/ntoskrnl/ex/init.c (original)
+++ trunk/reactos/ntoskrnl/ex/init.c Thu Jan 18 09:23:14 2007
@@ -38,6 +38,12 @@
 /* NT Boot Path */
 UNICODE_STRING NtSystemRoot;
+
+/* NT Initial User Application */
+WCHAR NtInitialUserProcessBuffer[128] = L"\\SystemRoot\\System32\\smss.exe";
+ULONG NtInitialUserProcessBufferLength = sizeof(NtInitialUserProcessBuffer) -
+                                         sizeof(WCHAR);
+ULONG NtInitialUserProcessBufferType = REG_SZ;
 /* Boot NLS information */
 PVOID ExpNlsTableBase;
@@ -68,7 +74,7 @@
                                &LinkName,
                                OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
                                NULL,
-                               SePublicDefaultSd);
+                               SePublicDefaultUnrestrictedSd);
     /* Create it */
     Status = NtCreateDirectoryObject(&LinkHandle,
@@ -88,7 +94,7 @@
                                &LinkName,
                                OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
                                NULL,
-                               SePublicDefaultSd);
+                               SePublicDefaultUnrestrictedSd);
     /* Create it */
     Status = NtCreateDirectoryObject(&LinkHandle,
@@ -115,7 +121,7 @@
                                &LinkName,
                                OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
                                NULL,
-                               SePublicDefaultSd);
+                               SePublicDefaultUnrestrictedSd);
     /* Build the ARC name */
     sprintf(Buffer,
@@ -353,10 +359,11 @@
     PWSTR p;
     UNICODE_STRING NullString = RTL_CONSTANT_STRING(L"");
     UNICODE_STRING SmssName, Environment, SystemDriveString;
+    PVOID EnvironmentPtr = NULL;
     /* Allocate memory for the process parameters */
     Size = sizeof(RTL_USER_PROCESS_PARAMETERS) +
-           ((MAX_PATH * 4) * sizeof(WCHAR));
+           ((MAX_PATH * 6) * sizeof(WCHAR));
     Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
                                      (PVOID)&ProcessParameters,
                                      0,
@@ -378,7 +385,7 @@
     /* Allocate a page for the environment */
     Size = PAGE_SIZE;
     Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
-                                     (PVOID)&ProcessParameters->Environment,
+                                     &EnvironmentPtr,
                                      0,
                                      &Size,
                                      MEM_COMMIT,
@@ -388,6 +395,9 @@
         /* Failed */
         KeBugCheckEx(SESSION2_INITIALIZATION_FAILED, Status, 0, 0, 0);
     }
+
+    /* Write the pointer */
+    ProcessParameters->Environment = EnvironmentPtr;
     /* Make a buffer for the DOS path */
     p = (PWSTR)(ProcessParameters + 1);
@@ -416,11 +426,48 @@
     ProcessParameters->ImagePathName.Buffer = p;
     ProcessParameters->ImagePathName.MaximumLength = MAX_PATH * sizeof(WCHAR);
-    /* Append the system path and session manager name */
-    RtlAppendUnicodeToString(&ProcessParameters->ImagePathName,
-                             L"\\SystemRoot\\System32");
-    RtlAppendUnicodeToString(&ProcessParameters->ImagePathName,
-                             L"\\smss.exe");
+    /* Make sure the buffer is a valid string which within the given length */
+    if ((NtInitialUserProcessBufferType != REG_SZ) ||
+        ((NtInitialUserProcessBufferLength != -1) &&
+         ((NtInitialUserProcessBufferLength < sizeof(WCHAR)) ||
+          (NtInitialUserProcessBufferLength >
+           sizeof(NtInitialUserProcessBuffer) - sizeof(WCHAR)))))
+    {
+        /* Invalid initial process string, bugcheck */
+        KeBugCheckEx(SESSION2_INITIALIZATION_FAILED,
+                     (ULONG_PTR)STATUS_INVALID_PARAMETER,
+                     NtInitialUserProcessBufferType,
+                     NtInitialUserProcessBufferLength,
+                     sizeof(NtInitialUserProcessBuffer));
+    }
+
+    /* Cut out anything after a space */
+    p = NtInitialUserProcessBuffer;
+    while (*p && *p != L' ') p++;
+
+    /* Set the image path length */
+    ProcessParameters->ImagePathName.Length =
+        (USHORT)((PCHAR)p - (PCHAR)NtInitialUserProcessBuffer);
+
+    /* Copy the actual buffer */
+    RtlCopyMemory(ProcessParameters->ImagePathName.Buffer,
+                  NtInitialUserProcessBuffer,
+                  ProcessParameters->ImagePathName.Length);
+
+    /* Null-terminate it */
+    ProcessParameters->
+        ImagePathName.Buffer[ProcessParameters->ImagePathName.Length /
+                             sizeof(WCHAR)] = UNICODE_NULL;
+
+    /* Make a buffer for the command line */
+    p = (PWSTR)((PCHAR)ProcessParameters->ImagePathName.Buffer +
+                ProcessParameters->ImagePathName.MaximumLength);
+    ProcessParameters->CommandLine.Buffer = p;
+    ProcessParameters->CommandLine.MaximumLength = MAX_PATH * sizeof(WCHAR);
+
+    /* Add the image name to the command line */
+    RtlAppendUnicodeToString(&ProcessParameters->CommandLine,
+                             NtInitialUserProcessBuffer);
     /* Create the environment string */
     RtlInitEmptyUnicodeString(&Environment,
@@ -446,11 +493,8 @@
     RtlAppendUnicodeStringToString(&Environment, &NtSystemRoot);
     RtlAppendUnicodeStringToString(&Environment, &NullString);
-    /* Get and set the command line equal to the image path */
-    ProcessParameters->CommandLine = ProcessParameters->ImagePathName;
+    /* Create SMSS process */
     SmssName = ProcessParameters->ImagePathName;
-
-    /* Create SMSS process */
     Status = RtlCreateUserProcess(&SmssName,
                                   OBJ_CASE_INSENSITIVE,
                                   RtlDeNormalizeProcessParams(
@@ -731,9 +775,9 @@
     Buffer[--AnsiPath.Length] = ANSI_NULL;
     /* Get the string from KUSER_SHARED_DATA's buffer */
-    NtSystemRoot.Buffer = SharedUserData->NtSystemRoot;
-    NtSystemRoot.MaximumLength = sizeof(SharedUserData->NtSystemRoot) / sizeof(WCHAR);
-    NtSystemRoot.Length = 0;
+    RtlInitEmptyUnicodeString(&NtSystemRoot,
+                              SharedUserData->NtSystemRoot,
+                              sizeof(SharedUserData->NtSystemRoot));
     /* Now fill it in */
     Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &AnsiPath, FALSE);
@@ -960,19 +1004,17 @@
         /* Bugcheck the system if SMSS couldn't initialize */
         KeBugCheck(SESSION5_INITIALIZATION_FAILED);
     }
-    else
-    {
-        /* Close process handles */
-        ZwClose(ThreadHandle);
-        ZwClose(ProcessHandle);
-
-        /* FIXME: We should free the initial process' memory!*/
-
-        /* Increase init phase */
-        ExpInitializationPhase += 1;
-
-        /* Jump into zero page thread */
-        MmZeroPageThreadMain(NULL);
-    }
+
+    /* Close process handles */
+    ZwClose(ThreadHandle);
+    ZwClose(ProcessHandle);
+
+    /* FIXME: We should free the initial process' memory!*/
+
+    /* Increase init phase */
+    ExpInitializationPhase += 1;
+
+    /* Jump into zero page thread */
+    MmZeroPageThreadMain(NULL);
 }
 /* EOF */
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/i386/ke.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/i386/ke.h Thu Jan 18 09:23:14 2007
@@ -92,6 +92,12 @@
     VOID
 );
+BOOLEAN
+NTAPI
+KiIsNpxErrataPresent(
+    VOID
+);
+
 VOID
 NTAPI
 KiSetProcessorType(VOID);
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 Thu Jan 18 09:23:14 2007
@@ -36,6 +36,18 @@
     PKINTERRUPT_ROUTINE ChainedDispatch;
     PKINTERRUPT_ROUTINE *FlatDispatch;
 } DISPATCH_INFO, *PDISPATCH_INFO;
+
+typedef struct _KI_SAMPLE_MAP
+{
+    LARGE_INTEGER PerfStart;
+    LARGE_INTEGER PerfEnd;
+    LONGLONG PerfDelta;
+    LARGE_INTEGER PerfFreq;
+    LONGLONG TSCStart;
+    LONGLONG TSCEnd;
+    LONGLONG TSCDelta;
+    ULONG MHz;
+} KI_SAMPLE_MAP, *PKI_SAMPLE_MAP;
 typedef struct _KTIMER_TABLE_ENTRY
 {
@@ -113,7 +125,7 @@
 extern KDPC KiExpireTimerDpc;
 extern KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE];
 extern LIST_ENTRY KiTimerListHead;
-extern KMUTEX KiGenericCallDpcMutex;
+extern FAST_MUTEX KiGenericCallDpcMutex;
 extern LIST_ENTRY KiProfileListHead, KiProfileSourceListHead;
 extern KSPIN_LOCK KiProfileLock;
 extern LIST_ENTRY KiProcessListHead;
@@ -235,6 +247,13 @@
     IN PKPRCB Prcb
 );
+VOID
+NTAPI
+CPUID(
+    OUT ULONG CpuInfo[4],
+    IN ULONG InfoType
+);
+
 /* gmutex.c ********************************************************************/
 VOID
Modified: trunk/reactos/ntoskrnl/ke/dpc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/dpc.c?rev=2550…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/dpc.c (original)
+++ trunk/reactos/ntoskrnl/ke/dpc.c Thu Jan 18 09:23:14 2007
@@ -23,7 +23,7 @@
 ULONG KiAdjustDpcThreshold = 20;
 ULONG KiIdealDpcRate = 20;
 BOOLEAN KeThreadDpcEnable;
-KMUTEX KiGenericCallDpcMutex;
+FAST_MUTEX KiGenericCallDpcMutex;
 /* PRIVATE FUNCTIONS *********************************************************/
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 Thu Jan 18 09:23:14 2007
@@ -340,6 +340,14 @@
             FeatureBits &= ~KF_WORKING_PTE;
         }
+        /* Check if the CPU is too old to support SYSENTER */
+        if ((Prcb->CpuType < 6) ||
+            ((Prcb->CpuType == 6) && (Prcb->CpuStep < 0x0303)))
+        {
+            /* Disable it */
+            Reg[3] &= ~0x800;
+        }
+
         /* Set the current features */
         CpuFeatures = Reg[3];
     }
@@ -354,6 +362,7 @@
     if (CpuFeatures & 0x00002000) FeatureBits |= KF_GLOBAL_PAGE | KF_CR4;
     if (CpuFeatures & 0x00008000) FeatureBits |= KF_CMOV;
     if (CpuFeatures & 0x00010000) FeatureBits |= KF_PAT;
+    if (CpuFeatures & 0x00200000) FeatureBits |= KF_DTS;
     if (CpuFeatures & 0x00800000) FeatureBits |= KF_MMX;
     if (CpuFeatures & 0x01000000) FeatureBits |= KF_FXSR;
     if (CpuFeatures & 0x02000000) FeatureBits |= KF_XMMI;
@@ -388,6 +397,9 @@
             {
                 /* Check which extended features are available. */
                 CPUID(Reg, 0x80000001);
+
+                /* Check if NX-bit is supported */
+                if (Reg[3] & 0x00100000) FeatureBits |= KF_NX_BIT;
                 /* Now handle each features for each CPU Vendor */
                 switch (Vendor)
@@ -741,8 +753,23 @@
 NTAPI
 Ki386EnableXMMIExceptions(IN ULONG_PTR Context)
 {
-    /* FIXME: Support this */
-    DPRINT1("Your machine supports XMMI exceptions but ReactOS doesn't\n");
+#if 0 // needs kitrap13
+    PKIDTENTRY IdtEntry;
+
+    /* Get the IDT Entry for Interrupt 19 */
+    IdtEntry = ((PKIPCR)KeGetPcr())->IDT[19];
+
+    /* Set it up */
+    IdtEntry->Selector = KGDT_R0_CODE;
+    IdtEntry->Offset = (KiTrap13 & 0xFFFF);
+    IdtEntry->ExtendedOffset = (KiTrap13 >> 16) & 0xFFFF;
+    ((PKIDT_ACCESS)&IdtEntry->Access)->Dpl = 0;
+    ((PKIDT_ACCESS)&IdtEntry->Access)->Present = 1;
+    ((PKIDT_ACCESS)&IdtEntry->Access)->SegmentType = I386_INTERRUPT_GATE;
+#endif
+
+    /* Enable XMMI exceptions */
+    __writecr4(__readcr4() | CR4_XMMEXCPT);
     return 0;
 }
@@ -750,8 +777,34 @@
 NTAPI
 KiI386PentiumLockErrataFixup(VOID)
 {
-    /* FIXME: Support this */
-    DPRINT1("WARNING: Your machine has a CPU bug that ReactOS can't
bypass!\n");
+    KDESCRIPTOR IdtDescriptor;
+    PKIDTENTRY NewIdt, NewIdt2;
+
+    /* Allocate memory for a new IDT */
+    NewIdt = ExAllocatePool(NonPagedPool, 2 * PAGE_SIZE);
+
+    /* Put everything after the first 7 entries on a new page */
+    NewIdt2 = (PVOID)((ULONG_PTR)NewIdt + PAGE_SIZE - (7 * sizeof(KIDTENTRY)));
+
+    /* Disable interrupts */
+    _disable();
+
+    /* Get the current IDT and copy it */
+    Ke386GetInterruptDescriptorTable(IdtDescriptor);
+    RtlCopyMemory(NewIdt2,
+                  (PVOID)IdtDescriptor.Base,
+                  IdtDescriptor.Limit + 1);
+    IdtDescriptor.Base = (ULONG)NewIdt2;
+
+    /* Set the new IDT */
+    Ke386SetInterruptDescriptorTable(IdtDescriptor);
+    ((PKIPCR)KeGetPcr())->IDT = NewIdt2;
+
+    /* Restore interrupts */
+    _enable();
+
+    /* Set the first 7 entries as read-only to produce a fault */
+    MmSetPageProtect(NULL, NewIdt, PAGE_READONLY);
 }
 /* PUBLIC FUNCTIONS **********************************************************/
Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/ctxswitch…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S (original)
+++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S Thu Jan 18 09:23:14 2007
@@ -17,7 +17,55 @@
 #define Running 2
 #define WrDispatchInt 0x1F
+Dividend: .float 4195835.0
+Divisor:  .float 3145727.0
+Result1:  .float 0
+Result2:  .float 0
+
 /* FUNCTIONS ****************************************************************/
+
+.globl _KiIsNpxErrataPresent@0
+.func KiIsNpxErrataPresent@0
+_KiIsNpxErrataPresent@0:
+
+    /* Disable interrupts */
+    cli
+
+    /* Get CR0 and mask out FPU flags */
+    mov eax, cr0
+    mov ecx, eax
+    and eax, ~(CR0_MP + CR0_TS + CR0_EM)
+    mov cr0, eax
+
+    /* Initialize the FPU */
+    fninit
+
+    /* Do the divison and inverse multiplication */
+    fld qword ptr Dividend
+    fstp qword ptr Result1
+    fld qword ptr Divisor
+    fstp qword ptr Result2
+    fld qword ptr Result1
+    fdiv qword ptr Result2
+    fmul qword ptr Result2
+
+    /* Do the compare and check flags */
+    fcomp qword ptr Result1
+    fstsw ax
+    sahf
+
+    /* Restore CR0 and interrupts */
+    mov cr0, ecx
+    sti
+
+    /* Return errata status */
+    xor eax, eax
+    jz NoErrata
+    inc eax
+
+NoErrata:
+    ret
+.endfunc
 .globl _KiIsNpxPresent@0
 .func KiIsNpxPresent@0
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 Thu Jan 18 09:23:14 2007
@@ -30,15 +30,18 @@
     BOOLEAN FbCaching = FALSE;
     NTSTATUS Status;
     ULONG ReturnLength;
-    ULONG i, Affinity;
+    ULONG i, Affinity, Sample = 0;
     PFX_SAVE_AREA FxSaveArea;
-    ULONG MXCsrMask = 0xFFBF, NewMask;
+    ULONG MXCsrMask = 0xFFBF;
+    ULONG Dummy[4];
+    KI_SAMPLE_MAP Samples[4];
+    PKI_SAMPLE_MAP CurrentSample = Samples;
     /* Check for large page support */
     if (KeFeatureBits & KF_LARGE_PAGE)
     {
         /* FIXME: Support this */
-        DPRINT1("Your machine supports PGE but ReactOS doesn't yet.\n");
+        DPRINT1("Large Page support detected but not yet taken advantage
of!\n");
     }
     /* Check for global page support */
@@ -70,6 +73,34 @@
     /* Assume no errata for now */
     SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = 0;
+    /* Check if we have an NPX */
+    if (KeI386NpxPresent)
+    {
+        /* Loop every CPU */
+        i = KeActiveProcessors;
+        for (Affinity = 1; i; Affinity <<= 1)
+        {
+            /* Check if this is part of the set */
+            if (i & Affinity)
+            {
+                /* Run on this CPU */
+                i &= ~Affinity;
+                KeSetSystemAffinityThread(Affinity);
+
+                /* Detect FPU errata */
+                if (KiIsNpxErrataPresent())
+                {
+                    /* Disable NPX support */
+                    KeI386NpxPresent = FALSE;
+                    SharedUserData->
+                        ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] =
+                        TRUE;
+                    break;
+                }
+            }
+        }
+    }
+
     /* If there's no NPX, then we're emulating the FPU */
     SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] =
         !KeI386NpxPresent;
@@ -148,18 +179,66 @@
                 /* Start sampling loop */
                 for (;;)
                 {
-                    //
-                    // FIXME: TODO
-                    //
-                    break;
+                    /* Do a dummy CPUID to start the sample */
+                    CPUID(Dummy, 0);
+
+                    /* Fill out the starting data */
+                    CurrentSample->PerfStart = KeQueryPerformanceCounter(NULL);
+                    CurrentSample->TSCStart = __rdtsc();
+                    CurrentSample->PerfFreq.QuadPart = -50000;
+
+                    /* Sleep for this sample */
+                    KeDelayExecutionThread(KernelMode,
+                                           FALSE,
+                                           &CurrentSample->PerfFreq);
+
+                    /* Do another dummy CPUID */
+                    CPUID(Dummy, 0);
+
+                    /* Fill out the ending data */
+                    CurrentSample->PerfEnd =
+                        KeQueryPerformanceCounter(&CurrentSample->PerfFreq);
+                    CurrentSample->TSCEnd = __rdtsc();
+
+                    /* Calculate the differences */
+                    CurrentSample->PerfDelta = CurrentSample->PerfEnd.QuadPart -
+                                               CurrentSample->PerfStart.QuadPart;
+                    CurrentSample->TSCDelta = CurrentSample->TSCEnd -
+                                              CurrentSample->TSCStart;
+
+                    /* Compute CPU Speed */
+                    CurrentSample->MHz = ((CurrentSample->TSCDelta *
+                                           CurrentSample->PerfFreq.QuadPart +
+                                           500000) /
+                                          (CurrentSample->PerfDelta * 1000000));
+
+                    /* Check if this isn't the first sample */
+                    if (Sample)
+                    {
+                        /* Check if we got a good precision within 1MHz */
+                        if ((CurrentSample->MHz == CurrentSample[-1].MHz) ||
+                            (CurrentSample->MHz == CurrentSample[-1].MHz + 1) ||
+                            (CurrentSample->MHz == CurrentSample[-1].MHz - 1))
+                        {
+                            /* We did, stop sampling */
+                            break;
+                        }
+                    }
+
+                    /* Move on */
+                    CurrentSample++;
+                    Sample++;
                 }
+
+                /* Save the CPU Speed */
+                KeGetCurrentPrcb()->MHz = CurrentSample[-1].MHz;
             }
-            /* Check if we have MTRR without PAT */
-            if (!(KeFeatureBits & KF_PAT) && (KeFeatureBits & KF_MTRR))
+            /* Check if we have MTRR */
+            if (KeFeatureBits & KF_MTRR)
             {
                 /* Then manually initialize MTRR for the CPU */
-                KiInitializeMTRR((BOOLEAN)i);
+                KiInitializeMTRR((BOOLEAN)i ? FALSE : TRUE);
             }
             /* Check if we have AMD MTRR and initialize it for the CPU */
@@ -168,52 +247,53 @@
             /* 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 */
+            /* Check if the CPU supports FXSR */
+            if (KeFeatureBits & KF_FXSR)
+            {
+                /* 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));
+                asm volatile("fxsave %0\n\t" : "=m" (*FxSaveArea));
 #else
-            __asm fxsave [FxSaveArea]
+                __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 the current mask doesn't match the reserved bits */
+                if (FxSaveArea->U.FxArea.MXCsrMask != 0)
+                {
+                    /* 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 */
+                    KiMXCsrMask = MXCsrMask;
+                }
+                else
+                {
+                    /* Was it set to the same value we found now? */
+                    if (KiMXCsrMask != MXCsrMask)
+                    {
+                        /* No, something is definitely wrong */
+                        KEBUGCHECKEX(MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED,
+                                     KF_FXSR,
+                                     KiMXCsrMask,
+                                     MXCsrMask,
+                                     0);
+                    }
+                }
+
+                /* Now set the kernel mask */
+                KiMXCsrMask &= 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;
         }
     }
@@ -242,7 +322,7 @@
     Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
     Pcr->NtTib.StackBase = 0;
     Pcr->NtTib.StackLimit = 0;
-    Pcr->NtTib.Self = 0;
+    Pcr->NtTib.Self = NULL;
     /* Set the Current Thread */
     Pcr->PrcbData.CurrentThread = IdleThread;
@@ -282,7 +362,11 @@
     Pcr->GDT = (PVOID)Gdt;
     Pcr->IDT = Idt;
     Pcr->TSS = Tss;
+    Pcr->TssCopy = Tss;
     Pcr->PrcbData.DpcStack = DpcStack;
+
+    /* Setup the processor set */
+    Pcr->PrcbData.MultiThreadProcessorSet = Pcr->PrcbData.SetMember;
 }
 VOID
@@ -299,6 +383,7 @@
     LARGE_INTEGER PageDirectory;
     PVOID DpcStack;
     ULONG NXSupportPolicy;
+    ULONG Vendor[3];
     /* Detect and set the CPU Type */
     KiSetProcessorType();
@@ -319,19 +404,19 @@
     FeatureBits = KiGetFeatureBits();
     /* Set the default NX policy (opt-in) */
-    NXSupportPolicy = 2;
+    NXSupportPolicy = NX_SUPPORT_POLICY_OPTIN;
     /* Check if NPX is always on */
     if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSON"))
     {
         /* Set it always on */
-        NXSupportPolicy = 1;
+        NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSON;
         FeatureBits |= KF_NX_ENABLED;
     }
     else if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTOUT"))
     {
         /* Set it in opt-out mode */
-        NXSupportPolicy = 3;
+        NXSupportPolicy = NX_SUPPORT_POLICY_OPTOUT;
         FeatureBits |= KF_NX_ENABLED;
     }
     else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTIN")) ||
@@ -344,7 +429,7 @@
              (strstr(KeLoaderBlock->LoadOptions, "EXECUTE")))
     {
         /* Set disabled mode */
-        NXSupportPolicy = 0;
+        NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSOFF;
         FeatureBits |= KF_NX_DISABLED;
     }
@@ -372,18 +457,32 @@
         KeI386NpxPresent = NpxPresent;
         KeI386CpuType = Prcb->CpuType;
         KeI386CpuStep = Prcb->CpuStep;
-        KeProcessorArchitecture = 0;
+        KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
         KeProcessorLevel = (USHORT)Prcb->CpuType;
         if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep;
         KeFeatureBits = FeatureBits;
         KeI386FxsrPresent = (KeFeatureBits & KF_FXSR) ? TRUE : FALSE;
         KeI386XMMIPresent = (KeFeatureBits & KF_XMMI) ? TRUE : FALSE;
+        /* Detect 8-byte compare exchange support */
+        if (!(KeFeatureBits & KF_CMPXCHG8B))
+        {
+            /* Copy the vendor string */
+            RtlCopyMemory(Vendor, Prcb->VendorString, sizeof(Vendor));
+
+            /* Bugcheck the system. Windows *requires* this */
+            KeBugCheckEx(0x5D,
+                         (1 << 24 ) | (Prcb->CpuType << 16) |
Prcb->CpuStep,
+                         Vendor[0],
+                         Vendor[1],
+                         Vendor[2]);
+        }
+
         /* Set the current MP Master KPRCB to the Boot PRCB */
         Prcb->MultiThreadSetMaster = Prcb;
         /* Lower to APC_LEVEL */
-        KfLowerIrql(APC_LEVEL);
+        KeLowerIrql(APC_LEVEL);
         /* Initialize some spinlocks */
         KeInitializeSpinLock(&KiFreezeExecutionLock);
@@ -499,7 +598,9 @@
     KeSetPriorityThread(InitThread, 0);
     /* If there's no thread scheduled, put this CPU in the Idle summary */
+    KiAcquirePrcbLock(Prcb);
     if (!Prcb->NextThread) KiIdleSummary |= 1 << Number;
+    KiReleasePrcbLock(Prcb);
     /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
     KfRaiseIrql(HIGH_LEVEL);
@@ -683,11 +784,6 @@
     /* Set the right wait IRQL */
     KeGetCurrentThread()->WaitIrql = DISPATCH_LEVEL;
-    /* Set idle thread as running on UP builds */
-#ifndef CONFIG_SMP
-    KeGetCurrentThread()->State = Running;
-#endif
-
     /* Jump into the idle loop */
     KiIdleLoop();
 }
Modified: trunk/reactos/ntoskrnl/ke/i386/patpge.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/patpge.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/patpge.c (original)
+++ trunk/reactos/ntoskrnl/ke/i386/patpge.c Thu Jan 18 09:23:14 2007
@@ -59,5 +59,5 @@
 KiInitializePAT(VOID)
 {
     /* FIXME: Support this */
-    DPRINT1("Your machine supports PAT but ReactOS doesn't yet.\n");
+    DPRINT1("Advanced Memory features detected but not yet taken advantage
of.\n");
 }
Modified: trunk/reactos/ntoskrnl/ke/krnlinit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/krnlinit.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/krnlinit.c (original)
+++ trunk/reactos/ntoskrnl/ke/krnlinit.c Thu Jan 18 09:23:14 2007
@@ -94,7 +94,7 @@
     InitializeListHead(&KiStackInSwapListHead);
     /* Initialize the mutex for generic DPC calls */
-    KeInitializeMutex(&KiGenericCallDpcMutex, 0);
+    ExInitializeFastMutex(&KiGenericCallDpcMutex);
     /* Initialize the syscall table */
     KeServiceDescriptorTable[0].Base = MainSSDT;
@@ -183,7 +183,7 @@
     Prcb->QueueIndex = 1;
     Prcb->ReadySummary = 0;
     Prcb->DeferredReadyListHead.Next = NULL;
-    for (i = 0; i < 32; i++)
+    for (i = 0; i < MAXIMUM_PRIORITY; i++)
     {
         /* Initialize the ready list */
         InitializeListHead(&Prcb->DispatcherReadyListHead[i]);
@@ -246,9 +246,13 @@
     {
         /* Initialize the lock and setup the Queued Spinlock */
         KeInitializeSpinLock(&KiTimerTableLock[i]);
-        Prcb->LockQueue[i].Next = NULL;
-        Prcb->LockQueue[i].Lock = &KiTimerTableLock[i];
-    }
+        Prcb->LockQueue[LockQueueTimerTableLock + i].Next = NULL;
+        Prcb->LockQueue[LockQueueTimerTableLock + i].Lock =
+            &KiTimerTableLock[i];
+    }
+
+    /* Initialize the PRCB lock */
+    KeInitializeSpinLock(&Prcb->PrcbLock);
     /* Check if this is the boot CPU */
     if (!Number)