Author: ion Date: Fri Sep 1 07:05:30 2006 New Revision: 23852
URL: http://svn.reactos.org/svn/reactos?rev=23852&view=rev Log: - Multiple changes to low-level Kernel initalization sequence to bring it a bit closer to Windows. - Main difference is new CPU detection algorithms for ID, cache, etc, as well as using KF_ Kernel Feature bits instead of x86 CPU features (For portability). - Also many many other cleanups and re-sequencing.
Added: trunk/reactos/ntoskrnl/ke/i386/cpu.c Removed: trunk/reactos/ntoskrnl/ke/i386/cpu.S Modified: trunk/reactos/include/ddk/winddk.h trunk/reactos/include/ndk/ketypes.h trunk/reactos/ntoskrnl/KrnlFun.c trunk/reactos/ntoskrnl/include/internal/i386/ke.h trunk/reactos/ntoskrnl/include/internal/ke.h trunk/reactos/ntoskrnl/include/internal/po.h trunk/reactos/ntoskrnl/ke/dpc.c trunk/reactos/ntoskrnl/ke/i386/kernel.c trunk/reactos/ntoskrnl/ke/i386/main_asm.S trunk/reactos/ntoskrnl/ke/main.c trunk/reactos/ntoskrnl/ntoskrnl.rbuild trunk/reactos/ntoskrnl/po/power.c trunk/reactos/ntoskrnl/vdm/vdmmain.c
Modified: trunk/reactos/include/ddk/winddk.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ddk/winddk.h?rev=23... ============================================================================== --- trunk/reactos/include/ddk/winddk.h (original) +++ trunk/reactos/include/ddk/winddk.h Fri Sep 1 07:05:30 2006 @@ -1046,26 +1046,27 @@ #define LOCK_QUEUE_TIMER_LOCK_SHIFT 4 #define LOCK_QUEUE_TIMER_TABLE_LOCKS (1 << (8 - LOCK_QUEUE_TIMER_LOCK_SHIFT))
-typedef enum _KSPIN_LOCK_QUEUE_NUMBER { - LockQueueDispatcherLock, - LockQueueContextSwapLock, - LockQueuePfnLock, - LockQueueSystemSpaceLock, - LockQueueVacbLock, - LockQueueMasterLock, - LockQueueNonPagedPoolLock, - LockQueueIoCancelLock, - LockQueueWorkQueueLock, - LockQueueIoVpbLock, - LockQueueIoDatabaseLock, - LockQueueIoCompletionLock, - LockQueueNtfsStructLock, - LockQueueAfdWorkQueueLock, - LockQueueBcbLock, - LockQueueMmNonPagedPoolLock, - LockQueueUnusedSpare16, - LockQueueTimerTableLock, - LockQueueMaximumLock = LockQueueTimerTableLock + LOCK_QUEUE_TIMER_TABLE_LOCKS +typedef enum _KSPIN_LOCK_QUEUE_NUMBER +{ + LockQueueDispatcherLock, + LockQueueExpansionLock, + LockQueuePfnLock, + LockQueueSystemSpaceLock, + LockQueueVacbLock, + LockQueueMasterLock, + LockQueueNonPagedPoolLock, + LockQueueIoCancelLock, + LockQueueWorkQueueLock, + LockQueueIoVpbLock, + LockQueueIoDatabaseLock, + LockQueueIoCompletionLock, + LockQueueNtfsStructLock, + LockQueueAfdWorkQueueLock, + LockQueueBcbLock, + LockQueueMmNonPagedPoolLock, + LockQueueUnusedSpare16, + LockQueueTimerTableLock, + LockQueueMaximumLock = LockQueueTimerTableLock + LOCK_QUEUE_TIMER_TABLE_LOCKS } KSPIN_LOCK_QUEUE_NUMBER, *PKSPIN_LOCK_QUEUE_NUMBER;
typedef struct _KSPIN_LOCK_QUEUE {
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 Fri Sep 1 07:05:30 2006 @@ -62,7 +62,22 @@ // // Kernel Feature Bits // +#define KF_V86_VIS 0x00000001 #define KF_RDTSC 0x00000002 +#define KF_CR4 0x00000004 +#define KF_CMOV 0x00000008 +#define KF_GLOBAL_PAGE 0x00000010 +#define KF_LARGE_PAGE 0x00000020 +#define KF_MTRR 0x00000040 +#define KF_CMPXCHG8B 0x00000080 +#define KF_MMX 0x00000100 +#define KF_WORKING_PTE 0x00000200 +#define KF_PAT 0x00000400 +#define KF_FXSR 0x00000800 +#define KF_FAST_SYSCALL 0x00001000 +#define KF_XMMI 0x00002000 +#define KF_3DNOW 0x00004000 +#define KF_AMDK6MTRR 0x00008000
// // KPCR Access for non-IA64 builds
Modified: trunk/reactos/ntoskrnl/KrnlFun.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/KrnlFun.c?rev=2385... ============================================================================== --- trunk/reactos/ntoskrnl/KrnlFun.c (original) +++ trunk/reactos/ntoskrnl/KrnlFun.c Fri Sep 1 07:05:30 2006 @@ -25,11 +25,18 @@ // - Use Object Type Mutex/Lock. // // Ke: -// - Get rid of KiRosPrintAddress and use KiDumpParameterImages instead. -// - Sanitize some context fields during conversions. -// - Implement stack fault and segment fault handlers. -// - Add DR macro/save and VM macro/save. -// - Implement KiCallbackReturn, KiGetTickCount, KiRaiseAssertion. +// +// - FIXES: +// * Get rid of KiRosPrintAddress and use KiDumpParameterImages instead. +// * Sanitize some context fields during conversions. +// * Implement stack fault and segment fault handlers. +// * Add DR macro/save and VM macro/save. +// * Make boot process more NT-like. +// - FEATURES: +// * Use Queued Spinlocks for scheduling and dispatching. +// * New optimized table-based tick-hashed timer implementation. +// * New Thread Scheduler based on XP. +// * Implement KiCallbackReturn, KiGetTickCount, KiRaiseAssertion. // // Ex: // - Use pushlocks for handle implementation.
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/i386/ke.h (original) +++ trunk/reactos/ntoskrnl/include/internal/i386/ke.h Fri Sep 1 07:05:30 2006 @@ -26,21 +26,6 @@ #define X86_CR4_OSFXSR 0x00000200 /* enable FXSAVE/FXRSTOR instructions */ #define X86_CR4_OSXMMEXCPT 0x00000400 /* enable #XF exception */
-#define X86_FEATURE_VME 0x00000002 /* Virtual 8086 Extensions are present */ -#define X86_FEATURE_TSC 0x00000010 /* time stamp counters are present */ -#define X86_FEATURE_PAE 0x00000040 /* physical address extension is present */ -#define X86_FEATURE_CX8 0x00000100 /* CMPXCHG8B instruction present */ -#define X86_FEATURE_SYSCALL 0x00000800 /* SYSCALL/SYSRET support present */ -#define X86_FEATURE_PGE 0x00002000 /* Page Global Enable */ -#define X86_FEATURE_MMX 0x00800000 /* MMX extension present */ -#define X86_FEATURE_FXSR 0x01000000 /* FXSAVE/FXRSTOR instructions present */ -#define X86_FEATURE_SSE 0x02000000 /* SSE extension present */ -#define X86_FEATURE_SSE2 0x04000000 /* SSE2 extension present */ -#define X86_FEATURE_HT 0x10000000 /* Hyper-Threading present */ - -#define X86_EXT_FEATURE_SSE3 0x00000001 /* SSE3 extension present */ -#define X86_EXT_FEATURE_3DNOW 0x40000000 /* 3DNOW! extension present */ - #define DR7_ACTIVE 0x00000055 /* If any of these bits are set, a Dr is active */
#define FRAME_EDITED 0xFFF8 @@ -64,6 +49,29 @@ Ki386InitializeLdt(VOID); VOID Ki386SetProcessorFeatures(VOID); + +VOID +NTAPI +KiSetCR0Bits(VOID); + +VOID +NTAPI +KiGetCacheInformation(VOID); + +BOOLEAN +NTAPI +KiIsNpxPresent( + VOID +); + +VOID +NTAPI +KiSetProcessorType(VOID); + +ULONG +NTAPI +KiGetFeatureBits(VOID); + ULONG KeAllocateGdtSelector(ULONG Desc[2]); VOID KeFreeGdtSelector(ULONG Entry); VOID
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 Fri Sep 1 07:05:30 2006 @@ -70,6 +70,12 @@ extern ULONG KeI386NpxPresent; extern ULONG KeI386XMMIPresent; extern ULONG KeI386FxsrPresent; +extern ULONG KeI386CpuType; +extern ULONG KeI386CpuStep; +extern ULONG KeProcessorArchitecture; +extern ULONG KeProcessorLevel; +extern ULONG KeProcessorRevision; +extern ULONG KeFeatureBits; extern PKNODE KeNodeBlock[1]; extern UCHAR KeNumberNodes; extern UCHAR KeProcessNodeSeed; @@ -84,6 +90,10 @@ extern BOOLEAN KeI386VirtualIntExtensions; extern KIDTENTRY KiIdt[]; extern FAST_MUTEX KernelAddressSpaceLock; +extern ULONG KiMaximumDpcQueueDepth; +extern ULONG KiMinimumDpcRate; +extern ULONG KiAdjustDpcThreshold; +extern ULONG KiIdealDpcRate;
/* MACROS *************************************************************************/
@@ -585,10 +595,6 @@
VOID NTAPI -KeInitDpc(struct _KPRCB* Prcb); - -VOID -NTAPI KeInitDispatcher(VOID);
VOID @@ -606,8 +612,7 @@ VOID NTAPI KeInit1( - PCHAR CommandLine, - PULONG LastKernelAddress + VOID );
VOID @@ -689,7 +694,7 @@ );
VOID -STDCALL +NTAPI KeFlushCurrentTb(VOID);
VOID
Modified: trunk/reactos/ntoskrnl/include/internal/po.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/p... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/po.h (original) +++ trunk/reactos/ntoskrnl/include/internal/po.h Fri Sep 1 07:05:30 2006 @@ -12,10 +12,20 @@
NTSTATUS NTAPI -PopSetSystemPowerState(SYSTEM_POWER_STATE PowerState); +PopSetSystemPowerState( + SYSTEM_POWER_STATE PowerState +);
VOID NTAPI -PopCleanupPowerState(IN PPOWER_STATE PowerState); +PopCleanupPowerState( + IN PPOWER_STATE PowerState +); + +VOID +NTAPI +PoInitializePrcb( + IN PKPRCB Prcb +);
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_PO_H */
Modified: trunk/reactos/ntoskrnl/ke/dpc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/dpc.c?rev=23852... ============================================================================== --- trunk/reactos/ntoskrnl/ke/dpc.c (original) +++ trunk/reactos/ntoskrnl/ke/dpc.c Fri Sep 1 07:05:30 2006 @@ -35,28 +35,6 @@ #define MAX_QUANTUM 0x7F
/* FUNCTIONS ****************************************************************/ - -/* - * FUNCTION: Initialize DPC handling - */ -VOID -INIT_FUNCTION -NTAPI -KeInitDpc(PKPRCB Prcb) -{ - InitializeListHead(&Prcb->DpcData[0].DpcListHead); -#if 0 - /* - * FIXME: - * Prcb->DpcEvent is a NULL pointer. - */ - KeInitializeEvent(Prcb->DpcEvent, 0, 0); -#endif - KeInitializeSpinLock(&Prcb->DpcData[0].DpcLock); - Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth; - Prcb->MinimumDpcRate = KiMinimumDpcRate; - Prcb->DpcData[0].DpcQueueDepth = 0; -}
/* * @implemented
Removed: trunk/reactos/ntoskrnl/ke/i386/cpu.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/cpu.S?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/cpu.S (original) +++ trunk/reactos/ntoskrnl/ke/i386/cpu.S (removed) @@ -1,39 +1,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Kernel - * FILE: ntoskrnl/ke/i386/cpu.S - * PURPOSE: Handles CPU-centric operations: TLB Flushes, Breakpoints, FPU - * PROGRAMMERS: Alex Ionescu - */ - -/* INCLUDES ******************************************************************/ - -#include <asm.h> -.intel_syntax noprefix - -/* FUNCTIONS ****************************************************************/ - -.globl _KeFlushCurrentTb@0 -.func KeFlushCurrentTb@0 -_KeFlushCurrentTb@0: - - /* Check for global page support */ - test byte ptr [_Ke386GlobalPagesEnabled], 0xff - jz .L1 - - /* Modifying the PSE, PGE or PAE Flag in CR4 causes the TLB to be flushed */ - mov eax, cr4 - and eax, ~CR4_PGE - mov cr4, eax - or eax, CR4_PGE - mov cr4, eax - ret - -.L1: - /* the old way ... */ - mov eax, cr3 - mov cr3, eax - ret -.endfunc - -
Added: 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 (added) +++ trunk/reactos/ntoskrnl/ke/i386/cpu.c Fri Sep 1 07:05:30 2006 @@ -1,0 +1,561 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/ke/i386/cpu.c + * PURPOSE: Routines for CPU-level support + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *****************************************************************/ + +#include <ntoskrnl.h> +#define NDEBUG +#include <debug.h> + +/* FIXME: Local EFLAGS defines not used anywhere else */ +#define EFLAGS_IOPL 0x3000 +#define EFLAGS_NF 0x4000 +#define EFLAGS_RF 0x10000 +#define EFLAGS_ID 0x200000 + +/* GLOBALS *******************************************************************/ + +ULONG KeI386CpuType; +ULONG KeI386CpuStep; +ULONG KeProcessorArchitecture; +ULONG KeProcessorLevel; +ULONG KeProcessorRevision; +ULONG KeFeatureBits; +ULONG KiFastSystemCallDisable = 1; +ULONG KeI386NpxPresent = 0; +ULONG MxcsrFeatureMask = 0; +ULONG KeI386XMMIPresent = 0; +ULONG KeI386FxsrPresent = 0; +ULONG Ke386Pae = FALSE; +ULONG Ke386GlobalPagesEnabled = FALSE; +ULONG Ke386NoExecute = FALSE; +BOOLEAN KiI386PentiumLockErrataPresent; + +CHAR CmpIntelID[] = "GenuineIntel"; +CHAR CmpAmdID[] = "AuthenticAMD"; +CHAR CmpCyrixID[] = "CyrixInstead"; +CHAR CmpTransmetaID[] = "GenuineTMx86"; +CHAR CmpCentaurID[] = "CentaurHauls"; +CHAR CmpRiseID[] = "RiseRiseRise"; + +/* SUPPORT ROUTINES FOR MSVC COMPATIBILITY ***********************************/ + +VOID +NTAPI +CPUID(IN ULONG CpuInfo[4], + IN ULONG InfoType) +{ + Ki386Cpuid(InfoType, &CpuInfo[0], &CpuInfo[1], &CpuInfo[2], &CpuInfo[3]); +} + +VOID +WRMSR(IN ULONG Register, + IN LONGLONG Value) +{ + LARGE_INTEGER LargeVal; + LargeVal.QuadPart = Value; + Ke386Wrmsr(Register, LargeVal.HighPart, LargeVal.LowPart); +} + +LONGLONG +RDMSR(IN ULONG Register) +{ + LARGE_INTEGER LargeVal; + Ke386Rdmsr(Register, LargeVal.HighPart, LargeVal.LowPart); + return LargeVal.QuadPart; +} + +/* FUNCTIONS *****************************************************************/ + +VOID +NTAPI +KiSetProcessorType(VOID) +{ + ULONG EFlags, NewEFlags; + ULONG Reg[4]; + ULONG Stepping, Type; + + /* Start by assuming no CPUID data */ + KeGetCurrentPrcb()->CpuID = 0; + + /* Save EFlags */ + Ke386SaveFlags(EFlags); + + /* XOR out the ID bit and update EFlags */ + NewEFlags = EFlags ^ EFLAGS_ID; + Ke386RestoreFlags(NewEFlags); + + /* Get them back and see if they were modified */ + Ke386SaveFlags(NewEFlags); + if (NewEFlags != EFlags) + { + /* The modification worked, so CPUID exists. Set the ID Bit again. */ + EFlags |= EFLAGS_ID; + Ke386RestoreFlags(EFlags); + + /* Peform CPUID 0 to see if CPUID 1 is supported */ + CPUID(Reg, 0); + if (Reg[0] > 0) + { + /* Do CPUID 1 now */ + CPUID(Reg, 1); + + /* + * Get the Stepping and Type. The stepping contains both the + * Model and the Step, while the Type contains the returned Type. + * We ignore the family. + * + * For the stepping, we convert this: zzzzzzxy into this: x0y + */ + Stepping = Reg[0] & 0xF0; + Stepping <<= 4; + Stepping += (Reg[0] & 0xFF); + Stepping &= 0xF0F; + Type = Reg[0] & 0xF00; + Type >>= 8; + + /* Save them in the PRCB */ + KeGetCurrentPrcb()->CpuID = TRUE; + KeGetCurrentPrcb()->CpuType = (UCHAR)Type; + KeGetCurrentPrcb()->CpuStep = (USHORT)Stepping; + } + else + { + DPRINT1("CPUID Support lacking\n"); + } + } + else + { + DPRINT1("CPUID Support lacking\n"); + } + + /* Restore EFLAGS */ + Ke386RestoreFlags(EFlags); +} + +ULONG +NTAPI +KiGetCpuVendor(VOID) +{ + PKPRCB Prcb = KeGetCurrentPrcb(); + ULONG Vendor[5]; + + /* Assume no Vendor ID and fail if no CPUID Support. */ + Prcb->VendorString[0] = 0; + if (!Prcb->CpuID) return 0; + + /* Get the Vendor ID and null-terminate it */ + CPUID(Vendor, 0); + Vendor[4] = 0; + + /* Re-arrange vendor string */ + Vendor[5] = Vendor[2]; + Vendor[2] = Vendor[3]; + Vendor[3] = Vendor[5]; + + /* Copy it to the PRCB and null-terminate it again */ + RtlCopyMemory(Prcb->VendorString, + &Vendor[1], + sizeof(Prcb->VendorString) - sizeof(CHAR)); + Prcb->VendorString[sizeof(Prcb->VendorString) - sizeof(CHAR)] = ANSI_NULL; + + /* Now check the CPU Type */ + if (!strcmp(Prcb->VendorString, CmpIntelID)) + { + return CPU_INTEL; + } + else if (!strcmp(Prcb->VendorString, CmpAmdID)) + { + return CPU_AMD; + } + else if (!strcmp(Prcb->VendorString, CmpCyrixID)) + { + DPRINT1("Cyrix CPUs not fully supported\n"); + return 0; + } + else if (!strcmp(Prcb->VendorString, CmpTransmetaID)) + { + DPRINT1("Transmeta CPUs not fully supported\n"); + return 0; + } + else if (!strcmp(Prcb->VendorString, CmpCentaurID)) + { + DPRINT1("VIA CPUs not fully supported\n"); + return 0; + } + else if (!strcmp(Prcb->VendorString, CmpRiseID)) + { + DPRINT1("Rise CPUs not fully supported\n"); + return 0; + } + + /* Invalid CPU */ + return 0; +} + +ULONG +NTAPI +KiGetFeatureBits(VOID) +{ + PKPRCB Prcb = KeGetCurrentPrcb(); + ULONG Vendor; + ULONG FeatureBits = KF_WORKING_PTE; + ULONG Reg[4]; + BOOLEAN ExtendedCPUID = TRUE; + ULONG CpuFeatures = 0; + + /* Get the Vendor ID */ + Vendor = KiGetCpuVendor(); + + /* Make sure we got a valid vendor ID at least. */ + if (!Vendor) return FeatureBits; + + /* Get the CPUID Info. Features are in Reg[3]. */ + CPUID(Reg, 1); + + /* Check for AMD CPU */ + if (Vendor == CPU_AMD) + { + /* Check if this is a K5 or higher. */ + if ((Reg[0] & 0x0F00) >= 0x0500) + { + /* Check if this is a K5 specifically. */ + if ((Reg[0] & 0x0F00) == 0x0500) + { + /* Get the Model Number */ + switch (Reg[0] & 0x00F0) + { + /* Check if this is the Model 1 */ + case 0x0010: + + /* Check if this is Step 0 or 1. They don't support PGE */ + if ((Reg[0] & 0x000F) > 0x03) break; + + case 0x0000: + + /* Model 0 doesn't support PGE at all. */ + Reg[3] &= ~0x2000; + break; + + case 0x0080: + + /* K6-2, Step 8 and over have support for MTRR. */ + if ((Reg[0] & 0x000F) >= 0x8) FeatureBits |= KF_AMDK6MTRR; + break; + + case 0x0090: + + /* As does the K6-3 */ + FeatureBits |= KF_AMDK6MTRR; + break; + + default: + break; + } + } + } + else + { + /* Familes below 5 don't support PGE, PSE or CMOV at all */ + Reg[3] &= ~(0x08 | 0x2000 | 0x8000); + + /* They also don't support advanced CPUID functions. */ + ExtendedCPUID = FALSE; + } + + /* Set the current features */ + CpuFeatures = Reg[3]; + } + + /* Now check if this is Intel */ + if (Vendor == CPU_INTEL) + { + /* Check if it's a P6 */ + if (Prcb->CpuType == 6) + { + /* Perform the special sequence to get the MicroCode Signature */ + WRMSR(0x8B, 0); + CPUID(Reg, 1); + Prcb->UpdateSignature.QuadPart = RDMSR(0x8B); + } + else if (Prcb->CpuType == 5) + { + /* On P5, enable workaround for the LOCK errata. */ + KiI386PentiumLockErrataPresent = TRUE; + } + + /* Check for broken P6 with bad SMP PTE implementation */ + if (((Reg[0] & 0x0FF0) == 0x0610 && (Reg[0] & 0x000F) <= 0x9) || + ((Reg[0] & 0x0FF0) == 0x0630 && (Reg[0] & 0x000F) <= 0x4)) + { + /* Remove support for correct PTE support. */ + FeatureBits &= ~KF_WORKING_PTE; + } + + /* Set the current features */ + CpuFeatures = Reg[3]; + } + + /* Convert all CPUID Feature bits into our format */ + if (CpuFeatures & 0x00000002) FeatureBits |= KF_V86_VIS | KF_CR4; + if (CpuFeatures & 0x00000008) FeatureBits |= KF_LARGE_PAGE | KF_CR4; + if (CpuFeatures & 0x00000010) FeatureBits |= KF_RDTSC; + if (CpuFeatures & 0x00000100) FeatureBits |= KF_CMPXCHG8B; + if (CpuFeatures & 0x00000800) FeatureBits |= KF_FAST_SYSCALL; + if (CpuFeatures & 0x00001000) FeatureBits |= KF_MTRR; + if (CpuFeatures & 0x00002000) FeatureBits |= KF_GLOBAL_PAGE | KF_CR4; + if (CpuFeatures & 0x00008000) FeatureBits |= KF_CMOV; + if (CpuFeatures & 0x00010000) FeatureBits |= KF_PAT; + if (CpuFeatures & 0x00800000) FeatureBits |= KF_MMX; + if (CpuFeatures & 0x01000000) FeatureBits |= KF_FXSR; + if (CpuFeatures & 0x02000000) FeatureBits |= KF_XMMI; + + /* Check if CPUID 0x80000000 is supported */ + if (ExtendedCPUID) + { + /* Do the call */ + CPUID(Reg, 0x80000000); + if ((Reg[0] & 0xffffff00) == 0x80000000) + { + /* Check if CPUID 0x80000001 is supported */ + if (Reg[0] >= 0x80000001) + { + /* Check which extended features are available. */ + CPUID(Reg, 0x80000001); + + /* Now handle each features for each CPU Vendor */ + switch (Vendor) + { + case CPU_AMD: + if (Reg[3] & 0x80000000) FeatureBits |= KF_3DNOW; + break; + } + } + } + } + + /* Return the Feature Bits */ + return FeatureBits; +} + +VOID +NTAPI +KiGetCacheInformation(VOID) +{ + PKIPCR Pcr = (PKIPCR)KeGetPcr(); + ULONG Vendor; + ULONG Data[4]; + ULONG CacheRequests = 0, i; + ULONG CurrentRegister; + UCHAR RegisterByte; + BOOLEAN FirstPass = TRUE; + + /* Set default L2 size */ + Pcr->SecondLevelCacheSize = 0; + + /* Get the Vendor ID and make sure we support CPUID */ + Vendor = KiGetCpuVendor(); + if (!Vendor) return; + + /* Check the Vendor ID */ + switch (Vendor) + { + /* Handle Intel case */ + case CPU_INTEL: + + /*Check if we support CPUID 2 */ + CPUID(Data, 0); + if (Data[0] >= 2) + { + /* We need to loop for the number of times CPUID will tell us to */ + do + { + /* Do the CPUID call */ + CPUID(Data, 2); + + /* Check if it was the first call */ + if (FirstPass) + { + /* + * The number of times to loop is the first byte. Read + * it and then destroy it so we don't get confused. + */ + CacheRequests = Data[0] & 0xFF; + Data[0] &= 0xFFFFFF00; + + /* Don't go over this again */ + FirstPass = FALSE; + } + + /* Loop all 4 registers */ + for (i = 0; i < 4; i++) + { + /* Get the current register */ + CurrentRegister = Data[i]; + + /* + * If the upper bit is set, then this register should + * be skipped. + */ + if (CurrentRegister & 0x80000000) continue; + + /* Keep looping for every byte inside this register */ + while (CurrentRegister) + { + /* Read a byte, skip a byte. */ + RegisterByte = (UCHAR)(CurrentRegister & 0xFF); + CurrentRegister >>= 8; + if (!RegisterByte) continue; + + /* + * Valid values are from 0x40 (0 bytes) to 0x49 + * (32MB), or from 0x80 to 0x89 (same size but + * 8-way associative. + */ + if (((RegisterByte > 0x40) && + (RegisterByte <= 0x49)) || + ((RegisterByte > 0x80) && + (RegisterByte <= 0x89))) + { + /* Mask out only the first nibble */ + RegisterByte &= 0x0F; + + /* Set the L2 Cache Size */ + Pcr->SecondLevelCacheSize = 0x10000 << + RegisterByte; + } + } + } + } while (--CacheRequests); + } + break; + + case CPU_AMD: + + /* FIXME */ + DPRINT1("Not handling AMD caches yet\n"); + break; + } +} + +VOID +NTAPI +KiSetCR0Bits(VOID) +{ + ULONG Cr0; + + /* Save current CR0 */ + Cr0 = Ke386GetCr0(); + + /* If this is a 486, enable Write-Protection */ + if (KeGetCurrentPrcb()->CpuType > 3) Cr0 |= CR0_WP; + + /* Set new Cr0 */ + Ke386SetCr0(Cr0); +} + +VOID INIT_FUNCTION +Ki386SetProcessorFeatures(VOID) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyName = + RTL_CONSTANT_STRING(L"\Registry\Machine\System\CurrentControlSet\Control\Session Manager\Kernel"); + UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"FastSystemCallDisable"); + HANDLE KeyHandle; + ULONG ResultLength; + struct + { + KEY_VALUE_PARTIAL_INFORMATION Info; + UCHAR Buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, + Data[0]) + sizeof(ULONG)]; + } ValueData; + NTSTATUS Status; + ULONG FastSystemCallDisable = 0; + + SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = FALSE; + SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = FALSE; + SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = + (KeFeatureBits & KF_CMPXCHG8B) ? TRUE : FALSE; + SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = + (KeFeatureBits & KF_MMX) ? TRUE : FALSE; + SharedUserData->ProcessorFeatures[PF_PPC_MOVEMEM_64BIT_OK] = FALSE; + SharedUserData->ProcessorFeatures[PF_ALPHA_BYTE_INSTRUCTIONS] = FALSE; + SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = + (KeFeatureBits & KF_XMMI) ? TRUE : FALSE; + SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = + (KeFeatureBits & KF_RDTSC) ? TRUE : FALSE; + + /* Does the CPU Support Fast System Call? */ + if (KeFeatureBits & KF_FAST_SYSCALL) { + + /* FIXME: Check for Family == 6, Model < 3 and Stepping < 3 and disable */ + + /* Make sure it's not disabled in registry */ + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenKey(&KeyHandle, + KEY_QUERY_VALUE, + &ObjectAttributes); + + if (NT_SUCCESS(Status)) { + + /* Read the Value then Close the Key */ + Status = ZwQueryValueKey(KeyHandle, + &ValueName, + KeyValuePartialInformation, + &ValueData, + sizeof(ValueData), + &ResultLength); + if (NT_SUCCESS(Status)) + { + if (ResultLength == sizeof(ValueData) && + ValueData.Info.Type == REG_DWORD) + { + FastSystemCallDisable = *(PULONG)ValueData.Info.Data != 0; + } + + ZwClose(KeyHandle); + } + } + + } else { + + /* Disable SYSENTER/SYSEXIT, because the CPU doesn't support it */ + FastSystemCallDisable = 1; + + } + + if (FastSystemCallDisable) { + /* Use INT2E */ + const unsigned char Entry[7] = {0x8D, 0x54, 0x24, 0x08, /* lea 0x8(%esp),%edx */ + 0xCD, 0x2E, /* int 0x2e */ + 0xC3}; /* ret */ + memcpy(&SharedUserData->SystemCall, Entry, sizeof(Entry)); + } else { + /* Use SYSENTER */ + const unsigned char Entry[5] = {0x8B, 0xD4, /* movl %esp,%edx */ + 0x0F, 0x34, /* sysenter */ + 0xC3}; /* ret */ + memcpy(&SharedUserData->SystemCall, Entry, sizeof(Entry)); + /* Enable SYSENTER/SYSEXIT */ + KiFastSystemCallDisable = 0; + } +} + + +VOID +NTAPI +KeFlushCurrentTb(VOID) +{ + /* Flush the TLB by resetting CR3 */ + _Ke386SetCr(3, _Ke386GetCr(3)); +} +
Modified: trunk/reactos/ntoskrnl/ke/i386/kernel.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/kernel.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/kernel.c (original) +++ trunk/reactos/ntoskrnl/ke/i386/kernel.c Fri Sep 1 07:05:30 2006 @@ -21,54 +21,214 @@ UCHAR KeNumberNodes = 1; UCHAR KeProcessNodeSeed; ULONG KiPcrInitDone = 0; -static ULONG PcrsAllocated = 0; -static ULONG Ke386CpuidFlags2, Ke386CpuidExFlags, Ke386CpuidExMisc; -ULONG Ke386CacheAlignment; -CHAR Ke386CpuidModel[49] = {0,}; -ULONG Ke386L1CacheSize; -BOOLEAN Ke386NoExecute = FALSE; -BOOLEAN Ke386Pae = FALSE; -BOOLEAN Ke386GlobalPagesEnabled = FALSE; -ULONG KiFastSystemCallDisable = 1; -ULONG KeI386NpxPresent = 0; -ULONG MxcsrFeatureMask = 0; -ULONG KeI386XMMIPresent = 0; -ULONG KeI386FxsrPresent = 0; -extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS]; -extern ULONG IdleProcessorMask; -extern KIDTENTRY KiIdt[256]; -static VOID INIT_FUNCTION Ki386GetCpuId(VOID); +extern ULONG Ke386GlobalPagesEnabled; + +/* System-defined Spinlocks */ +KSPIN_LOCK KiDispatcherLock; +KSPIN_LOCK MmPfnLock; +KSPIN_LOCK MmSystemSpaceLock; +KSPIN_LOCK CcBcbSpinLock; +KSPIN_LOCK CcMasterSpinLock; +KSPIN_LOCK CcVacbSpinLock; +KSPIN_LOCK CcWorkQueueSpinLock; +KSPIN_LOCK NonPagedPoolLock; +KSPIN_LOCK MmNonPagedPoolLock; +KSPIN_LOCK IopCancelSpinLock; +KSPIN_LOCK IopVpbSpinLock; +KSPIN_LOCK IopDatabaseLock; +KSPIN_LOCK IopCompletionLock; +KSPIN_LOCK NtfsStructLock; +KSPIN_LOCK AfdWorkQueueSpinLock; +KSPIN_LOCK KiTimerTableLock[16]; +KSPIN_LOCK KiReverseStallIpiLock;
#if defined (ALLOC_PRAGMA) -#pragma alloc_text(INIT, Ki386GetCpuId) #pragma alloc_text(INIT, KeInit1) #pragma alloc_text(INIT, KeInit2) -#pragma alloc_text(INIT, Ki386SetProcessorFeatures) #endif
-BOOLEAN +/* FUNCTIONS *****************************************************************/ + +VOID NTAPI -KiIsNpxPresent( - VOID -); - -/* FUNCTIONS *****************************************************************/ +KiInitSpinLocks(IN PKPRCB Prcb, + IN CCHAR Number) +{ + ULONG i; + + /* Initialize Dispatcher Fields */ + Prcb->QueueIndex = 1; + Prcb->ReadySummary = 0; + Prcb->DeferredReadyListHead.Next = NULL; + for (i = 0; i < 32; i++) + { + /* Initialize the ready list */ + InitializeListHead(&Prcb->DispatcherReadyListHead[i]); + } + + /* Initialize DPC Fields */ + InitializeListHead(&Prcb->DpcData[0].DpcListHead); + KeInitializeSpinLock(&Prcb->DpcData[0].DpcLock); + Prcb->DpcData[0].DpcQueueDepth = 0; + Prcb->DpcData[0].DpcCount = 0; + Prcb->DpcRoutineActive = FALSE; + Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth; + Prcb->MinimumDpcRate = KiMinimumDpcRate; + Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; + KeInitializeDpc(&Prcb->CallDpc, NULL, NULL); + //KeSetTargetProcessorDpc(&Prcb->CallDpc, Number); + KeSetImportanceDpc(&Prcb->CallDpc, HighImportance); + + /* Initialize the Wait List Head */ + InitializeListHead(&Prcb->WaitListHead); + + /* Initialize Queued Spinlocks */ + Prcb->LockQueue[LockQueueDispatcherLock].Next = NULL; + Prcb->LockQueue[LockQueueDispatcherLock].Lock = &KiDispatcherLock; + Prcb->LockQueue[LockQueueExpansionLock].Next = NULL; + Prcb->LockQueue[LockQueueExpansionLock].Lock = NULL; + Prcb->LockQueue[LockQueuePfnLock].Next = NULL; + Prcb->LockQueue[LockQueuePfnLock].Lock = &MmPfnLock; + Prcb->LockQueue[LockQueueSystemSpaceLock].Next = NULL; + Prcb->LockQueue[LockQueueSystemSpaceLock].Lock = &MmSystemSpaceLock; + Prcb->LockQueue[LockQueueBcbLock].Next = NULL; + Prcb->LockQueue[LockQueueBcbLock].Lock = &CcBcbSpinLock; + Prcb->LockQueue[LockQueueMasterLock].Next = NULL; + Prcb->LockQueue[LockQueueMasterLock].Lock = &CcMasterSpinLock; + Prcb->LockQueue[LockQueueVacbLock].Next = NULL; + Prcb->LockQueue[LockQueueVacbLock].Lock = &CcVacbSpinLock; + Prcb->LockQueue[LockQueueWorkQueueLock].Next = NULL; + Prcb->LockQueue[LockQueueWorkQueueLock].Lock = &CcWorkQueueSpinLock; + Prcb->LockQueue[LockQueueNonPagedPoolLock].Next = NULL; + Prcb->LockQueue[LockQueueNonPagedPoolLock].Lock = &NonPagedPoolLock; + Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Next = NULL; + Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Lock = &MmNonPagedPoolLock; + Prcb->LockQueue[LockQueueIoCancelLock].Next = NULL; + Prcb->LockQueue[LockQueueIoCancelLock].Lock = &IopCancelSpinLock; + Prcb->LockQueue[LockQueueIoVpbLock].Next = NULL; + Prcb->LockQueue[LockQueueIoVpbLock].Lock = &IopVpbSpinLock; + Prcb->LockQueue[LockQueueIoDatabaseLock].Next = NULL; + Prcb->LockQueue[LockQueueIoDatabaseLock].Lock = &IopDatabaseLock; + Prcb->LockQueue[LockQueueIoCompletionLock].Next = NULL; + Prcb->LockQueue[LockQueueIoCompletionLock].Lock = &IopCompletionLock; + Prcb->LockQueue[LockQueueNtfsStructLock].Next = NULL; + Prcb->LockQueue[LockQueueNtfsStructLock].Lock = &NtfsStructLock; + Prcb->LockQueue[LockQueueAfdWorkQueueLock].Next = NULL; + Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock; + Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL; + Prcb->LockQueue[LockQueueUnusedSpare16].Lock = NULL; + for (i = LockQueueTimerTableLock; i < LockQueueMaximumLock; i++) + { + KeInitializeSpinLock(&KiTimerTableLock[i - 16]); + Prcb->LockQueue[i].Next = NULL; + Prcb->LockQueue[i].Lock = &KiTimerTableLock[i - 16]; + } + + /* Check if this is the boot CPU */ + if (!Number) + { + /* Initialize the lock themselves */ + KeInitializeSpinLock(&KiDispatcherLock); + KeInitializeSpinLock(&KiReverseStallIpiLock); + KeInitializeSpinLock(&MmPfnLock); + KeInitializeSpinLock(&MmSystemSpaceLock); + KeInitializeSpinLock(&CcBcbSpinLock); + KeInitializeSpinLock(&CcMasterSpinLock); + KeInitializeSpinLock(&CcVacbSpinLock); + KeInitializeSpinLock(&CcWorkQueueSpinLock); + KeInitializeSpinLock(&IopCancelSpinLock); + KeInitializeSpinLock(&IopCompletionLock); + KeInitializeSpinLock(&IopDatabaseLock); + KeInitializeSpinLock(&IopVpbSpinLock); + KeInitializeSpinLock(&NonPagedPoolLock); + KeInitializeSpinLock(&MmNonPagedPoolLock); + KeInitializeSpinLock(&NtfsStructLock); + KeInitializeSpinLock(&AfdWorkQueueSpinLock); + } +}
VOID -INIT_FUNCTION NTAPI -KiCheckFPU(VOID) +KeInit1(VOID) { - PKPRCB Prcb = KeGetCurrentPrcb(); - - /* Check for a math co-processor (NPX) */ - KeI386NpxPresent = KiIsNpxPresent(); - - /* Check for and enable MMX/SSE support if possible */ - KeI386FxsrPresent = Prcb->FeatureBits & X86_FEATURE_FXSR ? TRUE : FALSE; - - /* Check for SSE (2 and 3 should have this set too) */ - KeI386XMMIPresent = Prcb->FeatureBits & X86_FEATURE_SSE ? TRUE : FALSE; + PKIPCR KPCR; + PKPRCB Prcb; + BOOLEAN NpxPresent; + ULONG FeatureBits; + extern USHORT KiBootGdt[]; + extern KTSS KiBootTss; + + /* Initialize the PCR */ + KPCR = (PKIPCR)KPCR_BASE; + Prcb = &KPCR->PrcbData; + memset(KPCR, 0, PAGE_SIZE); + KPCR->Self = (PKPCR)KPCR; + KPCR->Prcb = &KPCR->PrcbData; + KPCR->Irql = SYNCH_LEVEL; + KPCR->NtTib.Self = &KPCR->NtTib; + KPCR->NtTib.ExceptionList = (PVOID)-1; + KPCR->GDT = KiBootGdt; + KPCR->IDT = KiIdt; + KPCR->TSS = &KiBootTss; + KPCR->Number = 0; + KPCR->SetMember = 1 << 0; + KeActiveProcessors = 1 << 0; + KPCR->PrcbData.SetMember = 1 << 0; + KiPcrInitDone = 1; + + /* + * Low-level GDT, TSS and LDT Setup, most of which Freeldr should have done + * instead, and we should only add some extra information. This would be + * required for future NTLDR compatibility. + */ + KiInitializeGdt(NULL); + Ki386BootInitializeTSS(); + Ki386InitializeLdt(); + KeInitExceptions(); + KeInitInterrupts(); + + /* Detect and set the CPU Type */ + KiSetProcessorType(); + + /* Set CR0 features based on detected CPU */ + KiSetCR0Bits(); + + /* Check if an FPU is present */ + NpxPresent = KiIsNpxPresent(); + + /* Initialize the Power Management Support for this PRCB */ + PoInitializePrcb(Prcb); + + /* Bugcheck if this is a 386 CPU */ + if (Prcb->CpuType == 3) KeBugCheckEx(0x5D, 0x386, 0, 0, 0); + + /* Get the processor features for the CPU */ + FeatureBits = KiGetFeatureBits(); + + /* Save feature bits */ + Prcb->FeatureBits = FeatureBits; + + /* Get cache line information for this CPU */ + KiGetCacheInformation(); + + /* Initialize spinlocks and DPC data */ + KiInitSpinLocks(Prcb, 0); + + /* Set Node Data */ + KeNodeBlock[0] = &KiNode0; + Prcb->ParentNode = KeNodeBlock[0]; + KeNodeBlock[0]->ProcessorMask = Prcb->SetMember; + + /* Set boot-level flags */ + KeI386NpxPresent = NpxPresent; + KeI386CpuType = Prcb->CpuType; + KeI386CpuStep = Prcb->CpuStep; + KeProcessorArchitecture = 0; + KeProcessorLevel = (USHORT)Prcb->CpuType; + if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep; + KeFeatureBits = FeatureBits; + KeI386FxsrPresent = (KeFeatureBits & KF_FXSR) ? TRUE : FALSE; + KeI386XMMIPresent = (KeFeatureBits & KF_XMMI) ? TRUE : FALSE;
/* Check if Fxsr was found */ if (KeI386FxsrPresent) @@ -85,167 +245,8 @@ /* FIXME: Implement and enable XMM Page Zeroing for Mm */ } } -} - -static VOID INIT_FUNCTION -Ki386GetCpuId(VOID) -{ - ULONG OrigFlags, Flags, FinalFlags; - ULONG MaxCpuidLevel; - ULONG Dummy, Eax, Ecx, Edx; - PKIPCR Pcr = (PKIPCR)KeGetCurrentKPCR(); - - Ke386CpuidFlags2 = Ke386CpuidExFlags = 0; - Ke386CacheAlignment = 32; - - /* Try to toggle the id bit in eflags. */ - Ke386SaveFlags(OrigFlags); - Flags = OrigFlags ^ X86_EFLAGS_ID; - Ke386RestoreFlags(Flags); - Ke386SaveFlags(FinalFlags); - - Pcr->PrcbData.LogicalProcessorsPerPhysicalProcessor = 1; - Pcr->PrcbData.InitialApicId = 0xff; - - if ((OrigFlags & X86_EFLAGS_ID) == (FinalFlags & X86_EFLAGS_ID)) - { - /* No cpuid supported. */ - Pcr->PrcbData.CpuID = FALSE; - Pcr->PrcbData.CpuType = 3; - return; - } - Pcr->PrcbData.CpuID = TRUE; - - /* Get the vendor name and the maximum cpuid level supported. */ - Ki386Cpuid(0, &MaxCpuidLevel, (PULONG)&Pcr->PrcbData.VendorString[0], (PULONG)&Pcr->PrcbData.VendorString[8], (PULONG)&Pcr->PrcbData.VendorString[4]); - if (MaxCpuidLevel > 0) - { - /* Get the feature flags. */ - Ki386Cpuid(1, &Eax, &Ke386CpuidExMisc, &Ke386CpuidFlags2, &Pcr->PrcbData.FeatureBits); - - DPRINT ("Model: %x\n", (Eax & 0xf00) == 0xf00 ? ((Eax >> 4) & 0xf) | ((Eax >> 12) & 0xf0) : (Eax >> 4) & 0xf); - DPRINT ("Family: %x\n", (Eax & 0xf00) == 0xf00 ? ((Eax >> 8) & 0xf) + ((Eax >> 20) & 0xff) : (Eax >> 8) & 0xf); - - /* Get the cache alignment, if it is available */ - if (Pcr->PrcbData.FeatureBits & (1<<19)) - { - Ke386CacheAlignment = ((Ke386CpuidExMisc >> 8) & 0xff) * 8; - } - Pcr->PrcbData.CpuType = (Eax >> 8) & 0xf; - Pcr->PrcbData.CpuStep = (Eax & 0xf) | ((Eax << 4) & 0xf00); - - Pcr->PrcbData.InitialApicId = (Ke386CpuidExMisc >> 24) & 0xff; - - /* detect Hyper-Threading on Pentium 4 CPUs or later */ - if ((Pcr->PrcbData.CpuType == 0xf || (Eax & 0x0f00000)) && - !strncmp(Pcr->PrcbData.VendorString, "GenuineIntel", 12) && - Pcr->PrcbData.FeatureBits & X86_FEATURE_HT) - { - Pcr->PrcbData.LogicalProcessorsPerPhysicalProcessor = (Ke386CpuidExMisc >> 16) & 0xff; - } - } - else - { - Pcr->PrcbData.CpuType = 4; - } - - /* Get the maximum extended cpuid level supported. */ - Ki386Cpuid(0x80000000, &MaxCpuidLevel, &Dummy, &Dummy, &Dummy); - if (MaxCpuidLevel > 0) - { - /* Get the extended feature flags. */ - Ki386Cpuid(0x80000001, &Dummy, &Dummy, &Dummy, &Ke386CpuidExFlags); - } - - /* Get the model name. */ - if (MaxCpuidLevel >= 0x80000004) - { - PULONG v = (PULONG)Ke386CpuidModel; - Ki386Cpuid(0x80000002, v, v + 1, v + 2, v + 3); - Ki386Cpuid(0x80000003, v + 4, v + 5, v + 6, v + 7); - Ki386Cpuid(0x80000004, v + 8, v + 9, v + 10, v + 11); - } - - /* Get the L1 cache size */ - if (MaxCpuidLevel >= 0x80000005) - { - Ki386Cpuid(0x80000005, &Dummy, &Dummy, &Ecx, &Edx); - Ke386L1CacheSize = (Ecx >> 24)+(Edx >> 24); - if ((Ecx & 0xff) > 0) - { - Ke386CacheAlignment = Ecx & 0xff; - } - } - - /* Get the L2 cache size */ - if (MaxCpuidLevel >= 0x80000006) - { - Ki386Cpuid(0x80000006, &Dummy, &Dummy, &Ecx, &Dummy); - Pcr->SecondLevelCacheSize = Ecx >> 16; - } -} - -VOID -INIT_FUNCTION -NTAPI -KeInit1(PCHAR CommandLine, PULONG LastKernelAddress) -{ - PKIPCR KPCR; - BOOLEAN Pae = FALSE; - BOOLEAN NoExecute = FALSE; - PCHAR p1, p2; - extern USHORT KiBootGdt[]; - extern KTSS KiBootTss; - - /* - * Initialize the initial PCR region. We can't allocate a page - * with MmAllocPage() here because MmInit1() has not yet been - * called, so we use a predefined page in low memory - */ - - KPCR = (PKIPCR)KPCR_BASE; - memset(KPCR, 0, PAGE_SIZE); - KPCR->Self = (PKPCR)KPCR; - KPCR->Prcb = &KPCR->PrcbData; - KPCR->Irql = SYNCH_LEVEL; - KPCR->NtTib.Self = &KPCR->NtTib; - KPCR->GDT = KiBootGdt; - KPCR->IDT = KiIdt; - KPCR->TSS = &KiBootTss; - KPCR->Number = 0; - KPCR->SetMember = 1 << 0; - KeActiveProcessors = 1 << 0; - KPCR->PrcbData.SetMember = 1 << 0; - KiPcrInitDone = 1; - PcrsAllocated++; - - KiInitializeGdt (NULL); - Ki386BootInitializeTSS(); - Ki386InitializeLdt(); - - /* Get processor information. */ - Ki386GetCpuId(); - - /* Check FPU/MMX/SSE support. */ - KiCheckFPU(); - - /* Mark the end of the exception handler list */ - KPCR->NtTib.ExceptionList = (PVOID)-1; - - KeInitDpc(KPCR->Prcb); - InitializeListHead(&KPCR->PrcbData.WaitListHead); - - KeInitExceptions (); - KeInitInterrupts (); - - KeActiveProcessors |= 1 << 0; - - /* Set Node Data */ - KeNodeBlock[0] = &KiNode0; - KPCR->PrcbData.ParentNode = KeNodeBlock[0]; - KeNodeBlock[0]->ProcessorMask = KPCR->PrcbData.SetMember; - - if (KPCR->PrcbData.FeatureBits & X86_FEATURE_PGE) + + if (KeFeatureBits & KF_GLOBAL_PAGE) { ULONG Flags; /* Enable global pages */ @@ -256,32 +257,7 @@ Ke386RestoreFlags(Flags); }
- /* Search for pae and noexecute */ - p1 = (PCHAR)KeLoaderBlock.CommandLine; - while(*p1 && (p2 = strchr(p1, '/'))) - { - p2++; - if (!_strnicmp(p2, "PAE", 3)) - { - if (p2[3] == ' ' || p2[3] == 0) - { - p2 += 3; - Pae = TRUE; - } - } - else if (!_strnicmp(p2, "NOEXECUTE", 9)) - { - if (p2[9] == ' ' || p2[9] == '=' || p2[9] == 0) - { - p2 += 9; - NoExecute = TRUE; - } - } - p1 = p2; - } - - Ke386Pae = Ke386GetCr4() & X86_CR4_PAE ? TRUE : FALSE; - if (KPCR->PrcbData.FeatureBits & X86_FEATURE_SYSCALL) + if (KeFeatureBits & KF_FAST_SYSCALL) { extern void KiFastCallEntry(void);
@@ -294,7 +270,7 @@ }
/* Does the CPU Support 'prefetchnta' (SSE) */ - if(KPCR->PrcbData.FeatureBits & X86_FEATURE_SSE) + if(KeFeatureBits & KF_XMMI) { ULONG Protect;
@@ -312,164 +288,40 @@ KeInit2(VOID) { ULONG Protect; - PKIPCR Pcr = (PKIPCR)KeGetCurrentKPCR(); + PKIPCR Pcr = (PKIPCR)KeGetPcr(); + PKPRCB Prcb = Pcr->Prcb;
KiInitializeBugCheck(); KeInitializeDispatcher(); KiInitializeSystemClock();
- if (Pcr->PrcbData.FeatureBits & X86_FEATURE_PAE) - { - DPRINT("CPU supports PAE mode\n"); - if (Ke386Pae) - { - DPRINT("CPU runs in PAE mode\n"); - if (Ke386NoExecute) - { - DPRINT("NoExecute is enabled\n"); - } - } - else - { - DPRINT("CPU doesn't run in PAE mode\n"); - } - } - if ((Pcr->PrcbData.FeatureBits & (X86_FEATURE_FXSR | X86_FEATURE_MMX | X86_FEATURE_SSE | X86_FEATURE_SSE2)) || - (Ke386CpuidFlags2 & X86_EXT_FEATURE_SSE3)) - { - DPRINT("CPU supports" "%s%s%s%s%s" ".\n", - ((Pcr->PrcbData.FeatureBits & X86_FEATURE_FXSR) ? " FXSR" : ""), - ((Pcr->PrcbData.FeatureBits & X86_FEATURE_MMX) ? " MMX" : ""), - ((Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE) ? " SSE" : ""), - ((Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE2) ? " SSE2" : ""), - ((Ke386CpuidFlags2 & X86_EXT_FEATURE_SSE3) ? " SSE3" : "")); - } - if (Ke386GetCr4() & X86_CR4_OSFXSR) - { - DPRINT("SSE enabled.\n"); - } - if (Ke386GetCr4() & X86_CR4_OSXMMEXCPT) - { - DPRINT("Unmasked SIMD exceptions enabled.\n"); - } - if (Pcr->PrcbData.VendorString[0]) - { - DPRINT("CPU Vendor: %s\n", Pcr->PrcbData.VendorString); - } - if (Ke386CpuidModel[0]) - { - DPRINT("CPU Model: %s\n", Ke386CpuidModel); - } - - DPRINT("Ke386CacheAlignment: %d\n", Ke386CacheAlignment); - if (Ke386L1CacheSize) - { - - DPRINT("Ke386L1CacheSize: %dkB\n", Ke386L1CacheSize); - } - if (Pcr->SecondLevelCacheSize) - { - DPRINT("Ke386L2CacheSize: %dkB\n", Pcr->SecondLevelCacheSize); - } + DPRINT1("CPU Detection Complete.\n" + "CPUID: %lx\n" + "Step : %lx\n" + "Type : %lx\n" + "ID : %s\n" + "FPU : %lx\n" + "XMMI : %lx\n" + "Fxsr : %lx\n" + "Feat : %lx\n" + "Ftrs : %lx\n" + "Cache: %lx\n" + "CR0 : %lx\n" + "CR4 : %lx\n", + Prcb->CpuID, + Prcb->CpuStep, + Prcb->CpuType, + Prcb->VendorString, + KeI386NpxPresent, + KeI386XMMIPresent, + KeI386FxsrPresent, + Prcb->FeatureBits, + KeFeatureBits, + Pcr->SecondLevelCacheSize, + Ke386GetCr0(), + Ke386GetCr4());
/* Set IDT to writable */ Protect = MmGetPageProtect(NULL, (PVOID)KiIdt); MmSetPageProtect(NULL, (PVOID)KiIdt, Protect | PAGE_IS_WRITABLE); } - -VOID INIT_FUNCTION -Ki386SetProcessorFeatures(VOID) -{ - PKIPCR Pcr = (PKIPCR)KeGetCurrentKPCR(); - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING KeyName = - RTL_CONSTANT_STRING(L"\Registry\Machine\System\CurrentControlSet\Control\Session Manager\Kernel"); - UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"FastSystemCallDisable"); - HANDLE KeyHandle; - ULONG ResultLength; - struct - { - KEY_VALUE_PARTIAL_INFORMATION Info; - UCHAR Buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, - Data[0]) + sizeof(ULONG)]; - } ValueData; - NTSTATUS Status; - ULONG FastSystemCallDisable = 0; - - SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = FALSE; - SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = FALSE; - SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = - (Pcr->PrcbData.FeatureBits & X86_FEATURE_CX8) ? TRUE : FALSE; - SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = - (Pcr->PrcbData.FeatureBits & X86_FEATURE_MMX) ? TRUE : FALSE; - SharedUserData->ProcessorFeatures[PF_PPC_MOVEMEM_64BIT_OK] = FALSE; - SharedUserData->ProcessorFeatures[PF_ALPHA_BYTE_INSTRUCTIONS] = FALSE; - SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = - (Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE) ? TRUE : FALSE; - SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = - (Ke386CpuidExFlags & X86_EXT_FEATURE_3DNOW) ? TRUE : FALSE; - SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = - (Pcr->PrcbData.FeatureBits & X86_FEATURE_TSC) ? TRUE : FALSE; - SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] = Ke386Pae; - SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = - (Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE2) ? TRUE : FALSE; - - /* Does the CPU Support Fast System Call? */ - if (Pcr->PrcbData.FeatureBits & X86_FEATURE_SYSCALL) { - - /* FIXME: Check for Family == 6, Model < 3 and Stepping < 3 and disable */ - - /* Make sure it's not disabled in registry */ - InitializeObjectAttributes(&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - Status = ZwOpenKey(&KeyHandle, - KEY_QUERY_VALUE, - &ObjectAttributes); - - if (NT_SUCCESS(Status)) { - - /* Read the Value then Close the Key */ - Status = ZwQueryValueKey(KeyHandle, - &ValueName, - KeyValuePartialInformation, - &ValueData, - sizeof(ValueData), - &ResultLength); - if (NT_SUCCESS(Status)) - { - if (ResultLength == sizeof(ValueData) && - ValueData.Info.Type == REG_DWORD) - { - FastSystemCallDisable = *(PULONG)ValueData.Info.Data != 0; - } - - ZwClose(KeyHandle); - } - } - - } else { - - /* Disable SYSENTER/SYSEXIT, because the CPU doesn't support it */ - FastSystemCallDisable = 1; - - } - - if (FastSystemCallDisable) { - /* Use INT2E */ - const unsigned char Entry[7] = {0x8D, 0x54, 0x24, 0x08, /* lea 0x8(%esp),%edx */ - 0xCD, 0x2E, /* int 0x2e */ - 0xC3}; /* ret */ - memcpy(&SharedUserData->SystemCall, Entry, sizeof(Entry)); - } else { - /* Use SYSENTER */ - const unsigned char Entry[5] = {0x8B, 0xD4, /* movl %esp,%edx */ - 0x0F, 0x34, /* sysenter */ - 0xC3}; /* ret */ - memcpy(&SharedUserData->SystemCall, Entry, sizeof(Entry)); - /* Enable SYSENTER/SYSEXIT */ - KiFastSystemCallDisable = 0; - } -}
Modified: trunk/reactos/ntoskrnl/ke/i386/main_asm.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/main_asm.S... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/main_asm.S (original) +++ trunk/reactos/ntoskrnl/ke/i386/main_asm.S Fri Sep 1 07:05:30 2006 @@ -74,6 +74,4 @@
/* Call the main kernel initialization */ pushl %edx - pushl %ecx - call __main - + call _KiRosPrepareForSystemStartup@4
Modified: trunk/reactos/ntoskrnl/ke/main.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/main.c?rev=2385... ============================================================================== --- trunk/reactos/ntoskrnl/ke/main.c (original) +++ trunk/reactos/ntoskrnl/ke/main.c Fri Sep 1 07:05:30 2006 @@ -90,6 +90,12 @@ { DPRINT("KiSystemStartup(%d)\n", BootProcessor);
+ /* Initialize the Debugger */ + KdInitSystem (0, &KeLoaderBlock); + + /* Initialize HAL */ + HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock); + /* Initialize the Processor with HAL */ HalInitializeProcessor(KeNumberProcessors, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
@@ -124,18 +130,9 @@ for(;;); }
-/* - * FUNCTION: Called by the boot loader to start the kernel - * ARGUMENTS: - * LoaderBlock = Pointer to boot parameters initialized by the boot - * loader - * NOTE: The boot parameters are stored in low memory which will become - * invalid after the memory managment is initialized so we make a local copy. - */ VOID -INIT_FUNCTION -_main(ULONG MultiBootMagic, - PROS_LOADER_PARAMETER_BLOCK _LoaderBlock) +NTAPI +KiRosPrepareForSystemStartup(PROS_LOADER_PARAMETER_BLOCK LoaderBlock) { ULONG i; ULONG size; @@ -147,18 +144,52 @@ CHAR* s;
/* Copy the Loader Block Data locally since Low-Memory will be wiped */ - memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(ROS_LOADER_PARAMETER_BLOCK)); + memcpy(&KeLoaderBlock, LoaderBlock, sizeof(ROS_LOADER_PARAMETER_BLOCK)); memcpy(&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr, sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount); KeLoaderBlock.ModsCount++; KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
+ /* Check for BIOS memory map */ + KeMemoryMapRangeCount = 0; + if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO) + { + /* We have a memory map from the nice BIOS */ + size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG))); + i = 0; + + /* Map it until we run out of size */ + while (i < KeLoaderBlock.MmapLength) + { + /* Copy into the Kernel Memory Map */ + memcpy (&KeMemoryMap[KeMemoryMapRangeCount], + (PVOID)(KeLoaderBlock.MmapAddr + i), + sizeof(ADDRESS_RANGE)); + + /* Increase Memory Map Count */ + KeMemoryMapRangeCount++; + + /* Increase Size */ + i += size; + } + + /* Save data */ + KeLoaderBlock.MmapLength = KeMemoryMapRangeCount * sizeof(ADDRESS_RANGE); + KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap; + } + else + { + /* Nothing from BIOS */ + KeLoaderBlock.MmapLength = 0; + KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap; + } + /* Save the Base Address */ MmSystemRangeStart = (PVOID)KeLoaderBlock.KernelBase;
/* Set the Command Line */ - strcpy(KeLoaderCommandLine, (PCHAR)_LoaderBlock->CommandLine); + strcpy(KeLoaderCommandLine, (PCHAR)LoaderBlock->CommandLine); KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
/* Write the first Module (the Kernel) */ @@ -174,15 +205,15 @@ KeLoaderModules[0].ModEnd = KeLoaderModules[0].ModStart + PAGE_ROUND_UP((ULONG)OptHead->SizeOfImage);
/* Create a block for each module */ - for (i = 1; i < KeLoaderBlock.ModsCount; i++) { - + for (i = 1; i < KeLoaderBlock.ModsCount; i++) + { /* Check if we have to copy the path or not */ - if ((s = strrchr((PCHAR)KeLoaderModules[i].String, '/')) != 0) { - + if ((s = strrchr((PCHAR)KeLoaderModules[i].String, '/')) != 0) + { strcpy(KeLoaderModuleStrings[i], s + 1); - - } else { - + } + else + { strcpy(KeLoaderModuleStrings[i], (PCHAR)KeLoaderModules[i].String); }
@@ -204,9 +235,6 @@
/* Choose last module address as the final kernel address */ LastKernelAddress = PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd); - - /* Low level architecture specific initialization */ - KeInit1((PCHAR)KeLoaderBlock.CommandLine, &LastKernelAddress);
/* Select the HAL Base */ HalBase = KeLoaderModules[1].ModStart; @@ -238,6 +266,9 @@ /* Increase the last kernel address with the size of HAL */ LastKernelAddress += PAGE_ROUND_UP(DriverSize);
+ /* FIXME: We need to do this in KiSystemStartup! */ + KeInit1(); + /* Load the Kernel with the PE Loader */ LdrSafePEProcessModule((PVOID)KERNEL_BASE, (PVOID)KERNEL_BASE, @@ -248,45 +279,6 @@ FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - KERNEL_BASE + 0x200000; LastKrnlPhysAddr = LastKernelAddress - KERNEL_BASE + 0x200000;
- KeMemoryMapRangeCount = 0; - if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO) { - - /* We have a memory map from the nice BIOS */ - size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG))); - i = 0; - - /* Map it until we run out of size */ - while (i < KeLoaderBlock.MmapLength) { - - /* Copy into the Kernel Memory Map */ - memcpy (&KeMemoryMap[KeMemoryMapRangeCount], - (PVOID)(KeLoaderBlock.MmapAddr + i), - sizeof(ADDRESS_RANGE)); - - /* Increase Memory Map Count */ - KeMemoryMapRangeCount++; - - /* Increase Size */ - i += size; - } - - /* Save data */ - KeLoaderBlock.MmapLength = KeMemoryMapRangeCount * sizeof(ADDRESS_RANGE); - KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap; - - } else { - - /* Nothing from BIOS */ - KeLoaderBlock.MmapLength = 0; - KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap; - } - - /* Initialize the Debugger */ - KdInitSystem (0, &KeLoaderBlock); - - /* Initialize HAL */ - HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock); - /* Do general System Startup */ KiSystemStartup(1); }
Modified: trunk/reactos/ntoskrnl/ntoskrnl.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl.rbuild?re... ============================================================================== --- trunk/reactos/ntoskrnl/ntoskrnl.rbuild (original) +++ trunk/reactos/ntoskrnl/ntoskrnl.rbuild Fri Sep 1 07:05:30 2006 @@ -27,7 +27,7 @@ <if property="ARCH" value="i386"> <directory name="i386"> <file first="true">main_asm.S</file> - <file>cpu.S</file> + <file>cpu.c</file> <file>ctxswitch.S</file> <file>clock.S</file> <file>exp.c</file>
Modified: trunk/reactos/ntoskrnl/po/power.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/po/power.c?rev=238... ============================================================================== --- trunk/reactos/ntoskrnl/po/power.c (original) +++ trunk/reactos/ntoskrnl/po/power.c Fri Sep 1 07:05:30 2006 @@ -320,6 +320,48 @@ } }
+VOID +NTAPI +PopPerfIdle(PPROCESSOR_POWER_STATE PowerState) +{ + DPRINT1("PerfIdle function: %p\n", PowerState); +} + +VOID +NTAPI +PopPerfIdleDpc(IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +{ + /* Call the Perf Idle function */ + PopPerfIdle(&((PKPRCB)DeferredContext)->PowerState); +} + +VOID +FASTCALL +PopIdle0(IN PKPRCB Prcb) +{ + DPRINT1("Idle function: %p\n", Prcb); +} + +VOID +NTAPI +PoInitializePrcb(IN PKPRCB Prcb) +{ + /* Initialize the Power State */ + RtlZeroMemory(&Prcb->PowerState, sizeof(Prcb->PowerState)); + Prcb->PowerState.Idle0KernelTimeLimit = 0xFFFFFFFF; + Prcb->PowerState.CurrentThrottle = 100; + Prcb->PowerState.CurrentThrottleIndex = 0; + Prcb->PowerState.IdleFunction = PopIdle0; + + /* Initialize the Perf DPC and Timer */ + KeInitializeDpc(&Prcb->PowerState.PerfDpc, PopPerfIdleDpc, Prcb); + //KeSetTargetProcessorDpc(&Prcb->PowerState.PerfDpc, Prcb->Number); + KeInitializeTimerEx(&Prcb->PowerState.PerfTimer, SynchronizationTimer); +} + /* * @unimplemented */
Modified: trunk/reactos/ntoskrnl/vdm/vdmmain.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/vdm/vdmmain.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/vdm/vdmmain.c (original) +++ trunk/reactos/ntoskrnl/vdm/vdmmain.c Fri Sep 1 07:05:30 2006 @@ -76,7 +76,7 @@ if (!NT_SUCCESS(Status)) { /* Not present, so check if the CPU supports VME */ - if (KeGetPcr()->Prcb->FeatureBits & X86_FEATURE_VME) + if (KeGetPcr()->Prcb->FeatureBits & KF_V86_VIS) { /* Enable them. FIXME: Use IPI */ Ki386VdmEnablePentiumExtentions();