diff --git a/reactos/ntoskrnl/KrnlFun.c b/reactos/ntoskrnl/KrnlFun.c index 419ffd816cc..ccfa08ac410 100644 --- a/reactos/ntoskrnl/KrnlFun.c +++ b/reactos/ntoskrnl/KrnlFun.c @@ -27,11 +27,10 @@ // Ke: // // - FIXES: +// * Implement invalid opcode handler (fixes some apps from crashing). // * 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. diff --git a/reactos/ntoskrnl/ex/init.c b/reactos/ntoskrnl/ex/init.c index cab32e4329f..56935d2a479 100644 --- a/reactos/ntoskrnl/ex/init.c +++ b/reactos/ntoskrnl/ex/init.c @@ -15,6 +15,17 @@ /* DATA **********************************************************************/ +#define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF)) + +/* NT Version Info */ +ULONG NtMajorVersion = 5; +ULONG NtMinorVersion = 0; +ULONG NtOSCSDVersion = BUILD_OSCSDVERSION(4, 0); +ULONG NtBuildNumber = KERNEL_VERSION_BUILD; +ULONG NtGlobalFlag = 0; + +ULONG InitSafeBootMode = 0; /* KB83764 */ + extern ULONG MmCoreDumpType; extern CHAR KiTimerSystemAuditing; extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS]; diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index a1c1e6e9c0c..f184b4e0101 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -82,9 +82,13 @@ extern ULONG KeProcessorArchitecture; extern ULONG KeProcessorLevel; extern ULONG KeProcessorRevision; extern ULONG KeFeatureBits; +extern ULONG Ke386GlobalPagesEnabled; +extern KNODE KiNode0; extern PKNODE KeNodeBlock[1]; extern UCHAR KeNumberNodes; extern UCHAR KeProcessNodeSeed; +extern ETHREAD KiInitialThread; +extern EPROCESS KiInitialProcess; extern ULONG KiInterruptTemplate[KINTERRUPT_DISPATCH_CODES]; extern PULONG KiInterruptTemplateObject; extern PULONG KiInterruptTemplateDispatch; @@ -801,6 +805,26 @@ KiFlushNPXState( IN FLOATING_SAVE_AREA *SaveArea ); +VOID +NTAPI +KiInitSpinLocks( + IN PKPRCB Prcb, + IN CCHAR Number +); + +LARGE_INTEGER +NTAPI +KiComputeReciprocal( + IN LONG Divisor, + OUT PUCHAR Shift +); + +VOID +NTAPI +KiInitSystem( + VOID +); + #include "ke_x.h" #endif /* __NTOSKRNL_INCLUDE_INTERNAL_KE_H */ diff --git a/reactos/ntoskrnl/ke/main.c b/reactos/ntoskrnl/ke/freeldr.c similarity index 79% rename from reactos/ntoskrnl/ke/main.c rename to reactos/ntoskrnl/ke/freeldr.c index de99ddaa1fc..a2a2159f529 100644 --- a/reactos/ntoskrnl/ke/main.c +++ b/reactos/ntoskrnl/ke/freeldr.c @@ -1,76 +1,41 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/main.c - * PURPOSE: Initalizes the kernel - * - * PROGRAMMERS: Alex Ionescu (cleaned up code, moved Executiv stuff to ex/init.c) - * David Welch (welch@cwcom.net) + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/ke/freeldr.c + * PURPOSE: FreeLDR Bootstrap Support + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ /* INCLUDES *****************************************************************/ #include #define NDEBUG -#include +#include /* GLOBALS *******************************************************************/ -#define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF)) - - -ULONG NtMajorVersion = 5; -ULONG NtMinorVersion = 0; -ULONG NtOSCSDVersion = BUILD_OSCSDVERSION(4, 0); -ULONG NtBuildNumber = KERNEL_VERSION_BUILD; -ULONG NtGlobalFlag = 0; -CHAR KeNumberProcessors; -KAFFINITY KeActiveProcessors = 1; -ROS_LOADER_PARAMETER_BLOCK KeLoaderBlock; -ULONG KeDcacheFlushCount = 0; -ULONG KeIcacheFlushCount = 0; -ULONG KiDmaIoCoherency = 0; /* RISC Architectures only */ -ULONG InitSafeBootMode = 0; /* KB83764 */ - +/* FreeLDR Module Data */ LOADER_MODULE KeLoaderModules[64]; static CHAR KeLoaderModuleStrings[64][256]; -static CHAR KeLoaderCommandLine[256]; +PLOADER_MODULE CachedModules[MaximumCachedModuleType]; + +/* FreeLDR Memory Data */ ADDRESS_RANGE KeMemoryMap[64]; ULONG KeMemoryMapRangeCount; ULONG_PTR FirstKrnlPhysAddr; ULONG_PTR LastKrnlPhysAddr; ULONG_PTR LastKernelAddress; -PVOID KeUserApcDispatcher = NULL; -PVOID KeUserCallbackDispatcher = NULL; -PVOID KeUserExceptionDispatcher = NULL; -PVOID KeRaiseUserExceptionDispatcher = NULL; - -ULONG KeLargestCacheLine = 0x40; /* FIXME: Arch-specific */ - -/* Cached modules from the loader block */ -PLOADER_MODULE CachedModules[MaximumCachedModuleType]; +/* FreeLDR Loader Data */ +ROS_LOADER_PARAMETER_BLOCK KeLoaderBlock; +static CHAR KeLoaderCommandLine[256]; +/* FreeLDR PE Hack Data */ extern unsigned int _image_base__; ULONG_PTR KERNEL_BASE = (ULONG_PTR)&_image_base__; - -#if defined (ALLOC_PRAGMA) -#pragma alloc_text(INIT, _main) -#endif - extern LDR_DATA_TABLE_ENTRY HalModuleObject; -/* FUNCTIONS ****************************************************************/ - -/* - * @implemented - */ -ULONG -STDCALL -KeGetRecommendedSharedDataAlignment(VOID) -{ - return KeLargestCacheLine; -} +/* FUNCTIONS *****************************************************************/ VOID NTAPI @@ -121,7 +86,8 @@ KiRosPrepareForSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock) } /* Save data */ - KeLoaderBlock.MmapLength = KeMemoryMapRangeCount * sizeof(ADDRESS_RANGE); + KeLoaderBlock.MmapLength = KeMemoryMapRangeCount * + sizeof(ADDRESS_RANGE); KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap; } else @@ -148,7 +114,8 @@ KiRosPrepareForSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock) OptHead = &NtHeader->OptionalHeader; /* Set Kernel Ending */ - KeLoaderModules[0].ModEnd = KeLoaderModules[0].ModStart + PAGE_ROUND_UP((ULONG)OptHead->SizeOfImage); + 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++) @@ -180,7 +147,8 @@ KiRosPrepareForSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock) } /* Choose last module address as the final kernel address */ - LastKernelAddress = PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd); + LastKernelAddress = PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock. + ModsCount - 1].ModEnd); /* Select the HAL Base */ HalBase = KeLoaderModules[1].ModStart; @@ -207,7 +175,9 @@ KiRosPrepareForSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock) // // This dirty hack fixes it, and should make symbol lookup work too. // - HalModuleObject.SizeOfImage = RtlImageNtHeader((PVOID)HalModuleObject.DllBase)->OptionalHeader.SizeOfImage; + HalModuleObject.SizeOfImage = RtlImageNtHeader((PVOID)HalModuleObject. + DllBase)-> + OptionalHeader.SizeOfImage; /* Increase the last kernel address with the size of HAL */ LastKernelAddress += PAGE_ROUND_UP(DriverSize); diff --git a/reactos/ntoskrnl/ke/i386/main_asm.S b/reactos/ntoskrnl/ke/i386/boot.S similarity index 95% rename from reactos/ntoskrnl/ke/i386/main_asm.S rename to reactos/ntoskrnl/ke/i386/boot.S index 3a64b052999..000a5d9bc40 100644 --- a/reactos/ntoskrnl/ke/i386/main_asm.S +++ b/reactos/ntoskrnl/ke/i386/boot.S @@ -1,5 +1,5 @@ /* - * FILE: ntoskrnl/ke/i386/main_asm.S + * FILE: ntoskrnl/ke/i386/boot.S * COPYRIGHT: See COPYING in the top level directory * PURPOSE: Kernel Bootstrap Code * PROGRAMMER: Alex Ionescu (alex@relsoft.net) diff --git a/reactos/ntoskrnl/ke/i386/cpu.c b/reactos/ntoskrnl/ke/i386/cpu.c index 7f275dfd792..e4462832c9e 100644 --- a/reactos/ntoskrnl/ke/i386/cpu.c +++ b/reactos/ntoskrnl/ke/i386/cpu.c @@ -65,6 +65,12 @@ ULONG Ke386Pae = FALSE; ULONG Ke386GlobalPagesEnabled = FALSE; ULONG Ke386NoExecute = FALSE; BOOLEAN KiI386PentiumLockErrataPresent; +ULONG KeLargestCacheLine = 0x40; +ULONG KeDcacheFlushCount = 0; +ULONG KeIcacheFlushCount = 0; +ULONG KiDmaIoCoherency = 0; +CHAR KeNumberProcessors; +KAFFINITY KeActiveProcessors = 1; /* CPU Signatures */ CHAR CmpIntelID[] = "GenuineIntel"; @@ -769,3 +775,12 @@ KeFlushCurrentTb(VOID) _Ke386SetCr(3, _Ke386GetCr(3)); } +/* + * @implemented + */ +ULONG +STDCALL +KeGetRecommendedSharedDataAlignment(VOID) +{ + return KeLargestCacheLine; +} diff --git a/reactos/ntoskrnl/ke/i386/kiinit.c b/reactos/ntoskrnl/ke/i386/kiinit.c new file mode 100644 index 00000000000..fc7d9f54772 --- /dev/null +++ b/reactos/ntoskrnl/ke/i386/kiinit.c @@ -0,0 +1,306 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/ke/i386/kiinit.c + * PURPOSE: Kernel Initialization for x86 CPUs + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +/* Spinlocks used only on X86 */ +KSPIN_LOCK KiFreezeExecutionLock; +KSPIN_LOCK Ki486CompatibilityLock; + +/* FUNCTIONS *****************************************************************/ + +VOID +NTAPI +KiInitializePcr(IN ULONG ProcessorNumber, + IN PKIPCR Pcr, + IN PKIDTENTRY Idt, + IN PKGDTENTRY Gdt, + IN PKTSS Tss, + IN PKTHREAD IdleThread, + IN PVOID DpcStack) +{ + /* Setup the TIB */ + Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END; + Pcr->NtTib.StackBase = 0; + Pcr->NtTib.StackLimit = 0; + Pcr->NtTib.Self = 0; + + /* Set the Current Thread */ + //Pcr->PrcbData.CurrentThread = IdleThread; + + /* Set pointers to ourselves */ + Pcr->Self = (PKPCR)Pcr; + Pcr->Prcb = &Pcr->PrcbData; + + /* Set the PCR Version */ + Pcr->MajorVersion = PCR_MAJOR_VERSION; + Pcr->MinorVersion = PCR_MINOR_VERSION; + + /* Set the PCRB Version */ + Pcr->PrcbData.MajorVersion = 1; + Pcr->PrcbData.MinorVersion = 1; + + /* Set the Build Type */ + Pcr->PrcbData.BuildType = 0; + + /* Set the Processor Number and current Processor Mask */ + Pcr->PrcbData.Number = (UCHAR)ProcessorNumber; + Pcr->PrcbData.SetMember = 1 << ProcessorNumber; + + /* Set the PRCB for this Processor */ + KiProcessorBlock[ProcessorNumber] = Pcr->Prcb; + + /* Start us out at PASSIVE_LEVEL */ + Pcr->Irql = PASSIVE_LEVEL; + + /* Set the GDI, IDT, TSS and DPC Stack */ + Pcr->GDT = (PVOID)Gdt; + Pcr->IDT = Idt; + Pcr->TSS = Tss; + Pcr->PrcbData.DpcStack = DpcStack; +} + +VOID +NTAPI +KiInitializeKernel(IN PKPROCESS InitProcess, + IN PKTHREAD InitThread, + IN PVOID IdleStack, + IN PKPRCB Prcb, + IN CCHAR Number, + IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock) +{ + BOOLEAN NpxPresent; + ULONG FeatureBits; + LARGE_INTEGER PageDirectory; + PVOID DpcStack; + + /* 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, Number); + + /* Check if this is the Boot CPU */ + if (!Number) + { + /* 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; + + /* Set the current MP Master KPRCB to the Boot PRCB */ + Prcb->MultiThreadSetMaster = Prcb; + + /* Initialize some spinlocks */ + KeInitializeSpinLock(&KiFreezeExecutionLock); + KeInitializeSpinLock(&Ki486CompatibilityLock); + + /* Initialize portable parts of the OS */ + KiInitSystem(); + + /* Initialize the Idle Process and the Process Listhead */ + InitializeListHead(&KiProcessListHead); + PageDirectory.QuadPart = 0; + KeInitializeProcess(InitProcess, + 0, + 0xFFFFFFFF, + PageDirectory); + InitProcess->QuantumReset = MAXCHAR; + } + else + { + /* FIXME */ + DPRINT1("SMP Boot support not yet present\n"); + } + +#if 0 + /* Setup the Idle Thread */ + KeInitializeThread(InitProcess, + InitThread, + NULL, + NULL, + NULL, + NULL, + NULL, + IdleStack); +#endif + InitThread->NextProcessor = Number; + InitThread->Priority = HIGH_PRIORITY; + InitThread->State = Running; + InitThread->Affinity = 1 << Number; + InitThread->WaitIrql = DISPATCH_LEVEL; + InitProcess->ActiveProcessors = 1 << Number; + + /* Set up the thread-related fields in the PRCB */ + //Prcb->CurrentThread = InitThread; + Prcb->NextThread = NULL; + //Prcb->IdleThread = InitThread; + + /* Initialize the Kernel Executive */ + ExpInitializeExecutive(); + + /* Only do this on the boot CPU */ + if (!Number) + { + /* Calculate the time reciprocal */ + KiTimeIncrementReciprocal = + KiComputeReciprocal(KeMaximumIncrement, + &KiTimeIncrementShiftCount); + + /* Update DPC Values in case they got updated by the executive */ + Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth; + Prcb->MinimumDpcRate = KiMinimumDpcRate; + Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; + + /* Allocate the DPC Stack */ + DpcStack = MmCreateKernelStack(FALSE); + if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0); + Prcb->DpcStack = DpcStack; + + /* Allocate the IOPM save area. */ + Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool, + PAGE_SIZE * 2, + TAG('K', 'e', ' ', ' ')); + if (!Ki386IopmSaveArea) + { + /* Bugcheck. We need this for V86/VDM support. */ + KeBugCheckEx(NO_PAGES_AVAILABLE, 2, PAGE_SIZE * 2, 0, 0); + } + } + + /* Free Initial Memory */ + MiFreeInitMemory(); + + while (1) + { + LARGE_INTEGER Timeout; + Timeout.QuadPart = 0x7fffffffffffffffLL; + KeDelayExecutionThread(KernelMode, FALSE, &Timeout); + } + + /* Bug Check and loop forever if anything failed */ + KEBUGCHECK(0); + for(;;); +} + +VOID +NTAPI +KiSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock) +{ + ULONG Cpu; + PKIPCR Pcr = (PKIPCR)KPCR_BASE; + PKPRCB Prcb; + + /* Save the loader block and get the current CPU */ + //KeLoaderBlock = LoaderBlock; + Cpu = KeNumberProcessors; + if (!Cpu) + { + /* If this is the boot CPU, set FS and the CPU Number*/ + Ke386SetFs(KGDT_R0_PCR); + KeGetPcr()->Number = Cpu; + } + + /* Skip initial setup if this isn't the Boot CPU */ + if (Cpu) goto AppCpuInit; + + /* Setup the boot (Freeldr should've done), double fault and NMI TSS */ + Ki386InitializeTss(); + + /* Initialize the PCR */ + RtlZeroMemory(Pcr, PAGE_SIZE); + KiInitializePcr(Cpu, + Pcr, + KiIdt, + KiBootGdt, + &KiBootTss, + &KiInitialThread.Tcb, + KiDoubleFaultStack); + + /* Set us as the current process */ + KiInitialThread.Tcb.ApcState.Process = &KiInitialProcess.Pcb; + + /* Clear DR6/7 to cleanup bootloader debugging */ + Pcr->PrcbData.ProcessorState.SpecialRegisters.KernelDr6 = 0; + Pcr->PrcbData.ProcessorState.SpecialRegisters.KernelDr7 = 0; + + /* Load Ring 3 selectors for DS/ES */ + Ke386SetDs(KGDT_R3_DATA | RPL_MASK); + Ke386SetEs(KGDT_R3_DATA | RPL_MASK); + + /* Setup CPU-related fields */ +AppCpuInit: + Prcb = Pcr->Prcb; + Pcr->Number = Cpu; + Pcr->SetMember = 1 << Cpu; + Pcr->SetMemberCopy = 1 << Cpu; + Prcb->SetMember = 1 << Cpu; + + /* Initialize the Processor with HAL */ + HalInitializeProcessor(Cpu, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock); + + /* Set active processors */ + KeActiveProcessors |= Pcr->SetMember; + KeNumberProcessors++; + + /* Initialize the Debugger for the Boot CPU */ + if (!Cpu) KdInitSystem (0, &KeLoaderBlock); + + /* Check for break-in */ + if (KdPollBreakIn()) DbgBreakPointWithStatus(1); + + /* Raise to HIGH_LEVEL */ + KfRaiseIrql(HIGH_LEVEL); + + /* Call main kernel intialization */ + KiInitializeKernel(&KiInitialProcess.Pcb, + &KiInitialThread.Tcb, + P0BootStack, + Prcb, + Cpu, + LoaderBlock); +} + diff --git a/reactos/ntoskrnl/ke/i386/kernel.c b/reactos/ntoskrnl/ke/krnlinit.c similarity index 54% rename from reactos/ntoskrnl/ke/i386/kernel.c rename to reactos/ntoskrnl/ke/krnlinit.c index 5ce3cbcd50f..734d1ee54e2 100644 --- a/reactos/ntoskrnl/ke/i386/kernel.c +++ b/reactos/ntoskrnl/ke/krnlinit.c @@ -1,622 +1,330 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/i386/kernel.c - * PURPOSE: Initializes the kernel - * - * PROGRAMMERS: David Welch (welch@mcmail.com) - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include -#include - -/* GLOBALS *******************************************************************/ - -PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS]; -KNODE KiNode0; -PKNODE KeNodeBlock[1]; -UCHAR KeNumberNodes = 1; -UCHAR KeProcessNodeSeed; -ETHREAD KiInitialThread; -EPROCESS KiInitialProcess; - -extern ULONG Ke386GlobalPagesEnabled; -extern PVOID trap_stack; - -/* 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; - -KSPIN_LOCK KiFreezeExecutionLock; -KSPIN_LOCK Ki486CompatibilityLock; - -#if defined (ALLOC_PRAGMA) -#pragma alloc_text(INIT, KeInit1) -#pragma alloc_text(INIT, KeInit2) -#endif - -/* FUNCTIONS *****************************************************************/ - -VOID -NTAPI -KiInitSystem(VOID) -{ - ULONG i; - - /* Initialize Bugcheck Callback data */ - InitializeListHead(&BugcheckCallbackListHead); - InitializeListHead(&BugcheckReasonCallbackListHead); - KeInitializeSpinLock(&BugCheckCallbackLock); - - /* Initialize the Timer Expiration DPC */ - KeInitializeDpc(&KiExpireTimerDpc, KiExpireTimers, NULL); - KeSetTargetProcessorDpc(&KiExpireTimerDpc, 0); - - /* Initialize Profiling data */ - KeInitializeSpinLock(&KiProfileLock); - InitializeListHead(&KiProfileListHead); - InitializeListHead(&KiProfileSourceListHead); - - /* Loop the timer table */ - for (i = 0; i < TIMER_TABLE_SIZE; i++) - { - /* Initialize the list and entries */ - InitializeListHead(&KiTimerTableListHead[i].Entry); - KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF; - KiTimerTableListHead[i].Time.LowPart = 0; - } - - /* Initialize old-style list */ - InitializeListHead(&KiTimerListHead); - - /* Initialize the Swap event and all swap lists */ - KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE); - InitializeListHead(&KiProcessInSwapListHead); - InitializeListHead(&KiProcessOutSwapListHead); - InitializeListHead(&KiStackInSwapListHead); - - /* Initialize the mutex for generic DPC calls */ - KeInitializeMutex(&KiGenericCallDpcMutex, 0); - - /* Initialize the syscall table */ - KeServiceDescriptorTable[0].Base = MainSSDT; - KeServiceDescriptorTable[0].Count = NULL; - KeServiceDescriptorTable[0].Limit = NUMBER_OF_SYSCALLS; - KeServiceDescriptorTable[1].Limit = 0; - KeServiceDescriptorTable[0].Number = MainSSPT; - - /* Copy the the current table into the shadow table for win32k */ - RtlCopyMemory(KeServiceDescriptorTableShadow, - KeServiceDescriptorTable, - sizeof(KeServiceDescriptorTable)); -} - -LARGE_INTEGER -NTAPI -KiComputeReciprocal(IN LONG Divisor, - OUT PUCHAR Shift) -{ - LARGE_INTEGER Reciprocal = {{0}}; - LONG BitCount = 0, Remainder = 1; - - /* Start by calculating the remainder */ - while (Reciprocal.HighPart >= 0) - { - /* Increase the loop (bit) count */ - BitCount++; - - /* Calculate the current fraction */ - Reciprocal.HighPart = (Reciprocal.HighPart << 1) | - (Reciprocal.LowPart >> 31); - Reciprocal.LowPart <<= 1; - - /* Double the remainder and see if we went past the divisor */ - Remainder <<= 1; - if (Remainder >= Divisor) - { - /* Set the low-bit and calculate the new remainder */ - Remainder -= Divisor; - Reciprocal.LowPart |= 1; - } - } - - /* Check if we have a remainder */ - if (Remainder) - { - /* Check if the current fraction value is too large */ - if ((Reciprocal.LowPart == 0xFFFFFFFF) && - (Reciprocal.HighPart == 0xFFFFFFFF)) - { - /* Set the high bit and reduce the bit count */ - Reciprocal.LowPart = 0; - Reciprocal.HighPart = 0x80000000; - BitCount--; - } - else - { - /* Check if only the lowest bits got too large */ - if (Reciprocal.LowPart == 0xFFFFFFFF) - { - /* Reset them and increase the high bits instead */ - Reciprocal.LowPart = 0; - Reciprocal.HighPart++; - } - else - { - /* All is well, increase the low bits */ - Reciprocal.LowPart++; - } - } - } - - /* Now calculate the actual shift and return the reciprocal */ - *Shift = (UCHAR)BitCount - 64; - return Reciprocal; -} - -VOID -NTAPI -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[DPC_NORMAL].DpcListHead); - KeInitializeSpinLock(&Prcb->DpcData[DPC_NORMAL].DpcLock); - Prcb->DpcData[DPC_NORMAL].DpcQueueDepth = 0; - Prcb->DpcData[DPC_NORMAL].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; - - /* Loop timer locks */ - for (i = 0; i < LOCK_QUEUE_TIMER_TABLE_LOCKS; i++) - { - /* Initialize the lock and setup the Queued Spinlock */ - KeInitializeSpinLock(&KiTimerTableLock[i]); - Prcb->LockQueue[i].Next = NULL; - Prcb->LockQueue[i].Lock = &KiTimerTableLock[i]; - } - - /* 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); - KeInitializeDispatcher(); // ROS OLD DISPATCHER - } -} - -VOID -NTAPI -KiInitializePcr(IN ULONG ProcessorNumber, - IN PKIPCR Pcr, - IN PKIDTENTRY Idt, - IN PKGDTENTRY Gdt, - IN PKTSS Tss, - IN PKTHREAD IdleThread, - IN PVOID DpcStack) -{ - /* Setup the TIB */ - Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END; - Pcr->NtTib.StackBase = 0; - Pcr->NtTib.StackLimit = 0; - Pcr->NtTib.Self = 0; - - /* Set the Current Thread */ - //Pcr->PrcbData.CurrentThread = IdleThread; - - /* Set pointers to ourselves */ - Pcr->Self = (PKPCR)Pcr; - Pcr->Prcb = &Pcr->PrcbData; - - /* Set the PCR Version */ - Pcr->MajorVersion = PCR_MAJOR_VERSION; - Pcr->MinorVersion = PCR_MINOR_VERSION; - - /* Set the PCRB Version */ - Pcr->PrcbData.MajorVersion = 1; - Pcr->PrcbData.MinorVersion = 1; - - /* Set the Build Type */ - Pcr->PrcbData.BuildType = 0; - - /* Set the Processor Number and current Processor Mask */ - Pcr->PrcbData.Number = (UCHAR)ProcessorNumber; - Pcr->PrcbData.SetMember = 1 << ProcessorNumber; - - /* Set the PRCB for this Processor */ - KiProcessorBlock[ProcessorNumber] = Pcr->Prcb; - - /* Start us out at PASSIVE_LEVEL */ - Pcr->Irql = PASSIVE_LEVEL; - - /* Set the GDI, IDT, TSS and DPC Stack */ - Pcr->GDT = (PVOID)Gdt; - Pcr->IDT = Idt; - Pcr->TSS = Tss; - Pcr->PrcbData.DpcStack = DpcStack; -} - -VOID -NTAPI -KiInitializeKernel(IN PKPROCESS InitProcess, - IN PKTHREAD InitThread, - IN PVOID IdleStack, - IN PKPRCB Prcb, - IN CCHAR Number, - IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock) -{ - BOOLEAN NpxPresent; - ULONG FeatureBits; - LARGE_INTEGER PageDirectory; - PVOID DpcStack; - - /* 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, Number); - - /* Check if this is the Boot CPU */ - if (!Number) - { - /* 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; - - /* Set the current MP Master KPRCB to the Boot PRCB */ - Prcb->MultiThreadSetMaster = Prcb; - - /* Initialize some spinlocks */ - KeInitializeSpinLock(&KiFreezeExecutionLock); - KeInitializeSpinLock(&Ki486CompatibilityLock); - - /* Initialize portable parts of the OS */ - KiInitSystem(); - - /* Initialize the Idle Process and the Process Listhead */ - InitializeListHead(&KiProcessListHead); - PageDirectory.QuadPart = 0; - KeInitializeProcess(InitProcess, - 0, - 0xFFFFFFFF, - PageDirectory); - InitProcess->QuantumReset = MAXCHAR; - } - else - { - /* FIXME */ - DPRINT1("SMP Boot support not yet present\n"); - } - -#if 0 - /* Setup the Idle Thread */ - KeInitializeThread(InitProcess, - InitThread, - NULL, - NULL, - NULL, - NULL, - NULL, - IdleStack); -#endif - InitThread->NextProcessor = Number; - InitThread->Priority = HIGH_PRIORITY; - InitThread->State = Running; - InitThread->Affinity = 1 << Number; - InitThread->WaitIrql = DISPATCH_LEVEL; - InitProcess->ActiveProcessors = 1 << Number; - - /* Set up the thread-related fields in the PRCB */ - //Prcb->CurrentThread = InitThread; - Prcb->NextThread = NULL; - //Prcb->IdleThread = InitThread; - - /* Initialize the Kernel Executive */ - ExpInitializeExecutive(); - - /* Only do this on the boot CPU */ - if (!Number) - { - /* Calculate the time reciprocal */ - KiTimeIncrementReciprocal = - KiComputeReciprocal(KeMaximumIncrement, - &KiTimeIncrementShiftCount); - - /* Update DPC Values in case they got updated by the executive */ - Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth; - Prcb->MinimumDpcRate = KiMinimumDpcRate; - Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; - - /* Allocate the DPC Stack */ - DpcStack = MmCreateKernelStack(FALSE); - if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0); - Prcb->DpcStack = DpcStack; - - /* Allocate the IOPM save area. */ - Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool, - PAGE_SIZE * 2, - TAG('K', 'e', ' ', ' ')); - if (!Ki386IopmSaveArea) - { - /* Bugcheck. We need this for V86/VDM support. */ - KeBugCheckEx(NO_PAGES_AVAILABLE, 2, PAGE_SIZE * 2, 0, 0); - } - } - - /* Free Initial Memory */ - MiFreeInitMemory(); - - while (1) - { - LARGE_INTEGER Timeout; - Timeout.QuadPart = 0x7fffffffffffffffLL; - KeDelayExecutionThread(KernelMode, FALSE, &Timeout); - } - - /* Bug Check and loop forever if anything failed */ - KEBUGCHECK(0); - for(;;); -} - -VOID -NTAPI -KiSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock) -{ - ULONG Cpu; - PKIPCR Pcr = (PKIPCR)KPCR_BASE; - PKPRCB Prcb; - - /* Save the loader block and get the current CPU */ - //KeLoaderBlock = LoaderBlock; - Cpu = KeNumberProcessors; - if (!Cpu) - { - /* If this is the boot CPU, set FS and the CPU Number*/ - Ke386SetFs(KGDT_R0_PCR); - KeGetPcr()->Number = Cpu; - } - - /* Skip initial setup if this isn't the Boot CPU */ - if (Cpu) goto AppCpuInit; - - /* Setup the boot (Freeldr should've done), double fault and NMI TSS */ - Ki386InitializeTss(); - - /* Initialize the PCR */ - RtlZeroMemory(Pcr, PAGE_SIZE); - KiInitializePcr(Cpu, - Pcr, - KiIdt, - KiBootGdt, - &KiBootTss, - &KiInitialThread.Tcb, - KiDoubleFaultStack); - - /* Set us as the current process */ - KiInitialThread.Tcb.ApcState.Process = &KiInitialProcess.Pcb; - - /* Clear DR6/7 to cleanup bootloader debugging */ - Pcr->PrcbData.ProcessorState.SpecialRegisters.KernelDr6 = 0; - Pcr->PrcbData.ProcessorState.SpecialRegisters.KernelDr7 = 0; - - /* Load Ring 3 selectors for DS/ES */ - Ke386SetDs(KGDT_R3_DATA | RPL_MASK); - Ke386SetEs(KGDT_R3_DATA | RPL_MASK); - - /* Setup CPU-related fields */ -AppCpuInit: - Prcb = Pcr->Prcb; - Pcr->Number = Cpu; - Pcr->SetMember = 1 << Cpu; - Pcr->SetMemberCopy = 1 << Cpu; - Prcb->SetMember = 1 << Cpu; - - /* Initialize the Processor with HAL */ - HalInitializeProcessor(Cpu, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock); - - /* Set active processors */ - KeActiveProcessors |= Pcr->SetMember; - KeNumberProcessors++; - - /* Initialize the Debugger for the Boot CPU */ - if (!Cpu) KdInitSystem (0, &KeLoaderBlock); - - /* Check for break-in */ - if (KdPollBreakIn()) DbgBreakPointWithStatus(1); - - /* Raise to HIGH_LEVEL */ - KfRaiseIrql(HIGH_LEVEL); - - /* Call main kernel intialization */ - KiInitializeKernel(&KiInitialProcess.Pcb, - &KiInitialThread.Tcb, - P0BootStack, - Prcb, - Cpu, - LoaderBlock); -} - -VOID -INIT_FUNCTION -NTAPI -KeInit2(VOID) -{ - ULONG Protect; - - /* Check if Fxsr was found */ - if (KeI386FxsrPresent) - { - /* Enable it. FIXME: Send an IPI */ - Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSFXSR); - - /* Check if XMM was found too */ - if (KeI386XMMIPresent) - { - /* Enable it: FIXME: Send an IPI. */ - Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSXMMEXCPT); - - /* FIXME: Implement and enable XMM Page Zeroing for Mm */ - } - } - - if (KeFeatureBits & KF_GLOBAL_PAGE) - { - ULONG Flags; - /* Enable global pages */ - Ke386GlobalPagesEnabled = TRUE; - Ke386SaveFlags(Flags); - Ke386DisableInterrupts(); - Ke386SetCr4(Ke386GetCr4() | X86_CR4_PGE); - Ke386RestoreFlags(Flags); - } - - if (KeFeatureBits & KF_FAST_SYSCALL) - { - extern void KiFastCallEntry(void); - - /* CS Selector of the target segment. */ - Ke386Wrmsr(0x174, KGDT_R0_CODE, 0); - /* Target ESP. */ - Ke386Wrmsr(0x175, 0, 0); - /* Target EIP. */ - Ke386Wrmsr(0x176, (ULONG_PTR)KiFastCallEntry, 0); - } - - /* Does the CPU Support 'prefetchnta' (SSE) */ - if(KeFeatureBits & KF_XMMI) - { - Protect = MmGetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal); - MmSetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal, Protect | PAGE_IS_WRITABLE); - /* Replace the ret by a nop */ - *(PCHAR)RtlPrefetchMemoryNonTemporal = 0x90; - MmSetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal, Protect); - } - - /* Set IDT to writable */ - Protect = MmGetPageProtect(NULL, (PVOID)KiIdt); - MmSetPageProtect(NULL, (PVOID)KiIdt, Protect | PAGE_IS_WRITABLE); -} +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/ke/krnlinit.c + * PURPOSE: Portable part of kernel initialization + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include +#include + +/* GLOBALS *******************************************************************/ + +/* PRCB Array */ +PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS]; + +/* NUMA Node Support */ +KNODE KiNode0; +PKNODE KeNodeBlock[1]; +UCHAR KeNumberNodes = 1; +UCHAR KeProcessNodeSeed; + +/* Initial Process and Thread */ +ETHREAD KiInitialThread; +EPROCESS KiInitialProcess; + +/* 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; + +/* FUNCTIONS *****************************************************************/ + +VOID +NTAPI +KiInitSystem(VOID) +{ + ULONG i; + + /* Initialize Bugcheck Callback data */ + InitializeListHead(&BugcheckCallbackListHead); + InitializeListHead(&BugcheckReasonCallbackListHead); + KeInitializeSpinLock(&BugCheckCallbackLock); + + /* Initialize the Timer Expiration DPC */ + KeInitializeDpc(&KiExpireTimerDpc, KiExpireTimers, NULL); + KeSetTargetProcessorDpc(&KiExpireTimerDpc, 0); + + /* Initialize Profiling data */ + KeInitializeSpinLock(&KiProfileLock); + InitializeListHead(&KiProfileListHead); + InitializeListHead(&KiProfileSourceListHead); + + /* Loop the timer table */ + for (i = 0; i < TIMER_TABLE_SIZE; i++) + { + /* Initialize the list and entries */ + InitializeListHead(&KiTimerTableListHead[i].Entry); + KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF; + KiTimerTableListHead[i].Time.LowPart = 0; + } + + /* Initialize old-style list */ + InitializeListHead(&KiTimerListHead); + + /* Initialize the Swap event and all swap lists */ + KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE); + InitializeListHead(&KiProcessInSwapListHead); + InitializeListHead(&KiProcessOutSwapListHead); + InitializeListHead(&KiStackInSwapListHead); + + /* Initialize the mutex for generic DPC calls */ + KeInitializeMutex(&KiGenericCallDpcMutex, 0); + + /* Initialize the syscall table */ + KeServiceDescriptorTable[0].Base = MainSSDT; + KeServiceDescriptorTable[0].Count = NULL; + KeServiceDescriptorTable[0].Limit = NUMBER_OF_SYSCALLS; + KeServiceDescriptorTable[1].Limit = 0; + KeServiceDescriptorTable[0].Number = MainSSPT; + + /* Copy the the current table into the shadow table for win32k */ + RtlCopyMemory(KeServiceDescriptorTableShadow, + KeServiceDescriptorTable, + sizeof(KeServiceDescriptorTable)); +} + +LARGE_INTEGER +NTAPI +KiComputeReciprocal(IN LONG Divisor, + OUT PUCHAR Shift) +{ + LARGE_INTEGER Reciprocal = {{0}}; + LONG BitCount = 0, Remainder = 1; + + /* Start by calculating the remainder */ + while (Reciprocal.HighPart >= 0) + { + /* Increase the loop (bit) count */ + BitCount++; + + /* Calculate the current fraction */ + Reciprocal.HighPart = (Reciprocal.HighPart << 1) | + (Reciprocal.LowPart >> 31); + Reciprocal.LowPart <<= 1; + + /* Double the remainder and see if we went past the divisor */ + Remainder <<= 1; + if (Remainder >= Divisor) + { + /* Set the low-bit and calculate the new remainder */ + Remainder -= Divisor; + Reciprocal.LowPart |= 1; + } + } + + /* Check if we have a remainder */ + if (Remainder) + { + /* Check if the current fraction value is too large */ + if ((Reciprocal.LowPart == 0xFFFFFFFF) && + (Reciprocal.HighPart == 0xFFFFFFFF)) + { + /* Set the high bit and reduce the bit count */ + Reciprocal.LowPart = 0; + Reciprocal.HighPart = 0x80000000; + BitCount--; + } + else + { + /* Check if only the lowest bits got too large */ + if (Reciprocal.LowPart == 0xFFFFFFFF) + { + /* Reset them and increase the high bits instead */ + Reciprocal.LowPart = 0; + Reciprocal.HighPart++; + } + else + { + /* All is well, increase the low bits */ + Reciprocal.LowPart++; + } + } + } + + /* Now calculate the actual shift and return the reciprocal */ + *Shift = (UCHAR)BitCount - 64; + return Reciprocal; +} + +VOID +NTAPI +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[DPC_NORMAL].DpcListHead); + KeInitializeSpinLock(&Prcb->DpcData[DPC_NORMAL].DpcLock); + Prcb->DpcData[DPC_NORMAL].DpcQueueDepth = 0; + Prcb->DpcData[DPC_NORMAL].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; + + /* Loop timer locks */ + for (i = 0; i < LOCK_QUEUE_TIMER_TABLE_LOCKS; i++) + { + /* Initialize the lock and setup the Queued Spinlock */ + KeInitializeSpinLock(&KiTimerTableLock[i]); + Prcb->LockQueue[i].Next = NULL; + Prcb->LockQueue[i].Lock = &KiTimerTableLock[i]; + } + + /* 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); + KeInitializeDispatcher(); // ROS OLD DISPATCHER + } +} + +/* FIXME: Rename and make portable */ +VOID +NTAPI +KeInit2(VOID) +{ + ULONG Protect; + + /* Check if Fxsr was found */ + if (KeI386FxsrPresent) + { + /* Enable it. FIXME: Send an IPI */ + Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSFXSR); + + /* Check if XMM was found too */ + if (KeI386XMMIPresent) + { + /* Enable it: FIXME: Send an IPI. */ + Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSXMMEXCPT); + + /* FIXME: Implement and enable XMM Page Zeroing for Mm */ + } + } + + if (KeFeatureBits & KF_GLOBAL_PAGE) + { + ULONG Flags; + /* Enable global pages */ + Ke386GlobalPagesEnabled = TRUE; + Ke386SaveFlags(Flags); + Ke386DisableInterrupts(); + Ke386SetCr4(Ke386GetCr4() | X86_CR4_PGE); + Ke386RestoreFlags(Flags); + } + + if (KeFeatureBits & KF_FAST_SYSCALL) + { + extern void KiFastCallEntry(void); + + /* CS Selector of the target segment. */ + Ke386Wrmsr(0x174, KGDT_R0_CODE, 0); + /* Target ESP. */ + Ke386Wrmsr(0x175, 0, 0); + /* Target EIP. */ + Ke386Wrmsr(0x176, (ULONG_PTR)KiFastCallEntry, 0); + } + + /* Does the CPU Support 'prefetchnta' (SSE) */ + if(KeFeatureBits & KF_XMMI) + { + Protect = MmGetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal); + MmSetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal, Protect | PAGE_IS_WRITABLE); + /* Replace the ret by a nop */ + *(PCHAR)RtlPrefetchMemoryNonTemporal = 0x90; + MmSetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal, Protect); + } + + /* Set IDT to writable */ + Protect = MmGetPageProtect(NULL, (PVOID)KiIdt); + MmSetPageProtect(NULL, (PVOID)KiIdt, Protect | PAGE_IS_WRITABLE); +} diff --git a/reactos/ntoskrnl/ke/process.c b/reactos/ntoskrnl/ke/process.c index 260ec804545..40683146960 100644 --- a/reactos/ntoskrnl/ke/process.c +++ b/reactos/ntoskrnl/ke/process.c @@ -7,13 +7,13 @@ * Gregor Anich */ -/* INCLUDES *****************************************************************/ +/* INCLUDES ********(*********************************************************/ #include #define NDEBUG #include -/* GLOBALS *****************************************************************/ +/* GLOBALS *******************************************************************/ LIST_ENTRY KiProcessListHead; LIST_ENTRY KiProcessInSwapListHead, KiProcessOutSwapListHead; @@ -23,6 +23,11 @@ KEVENT KiSwapEvent; KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[SSDT_MAX_ENTRIES]; KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTableShadow[SSDT_MAX_ENTRIES]; +PVOID KeUserApcDispatcher; +PVOID KeUserCallbackDispatcher; +PVOID KeUserExceptionDispatcher; +PVOID KeRaiseUserExceptionDispatcher; + /* FUNCTIONS *****************************************************************/ PKPROCESS diff --git a/reactos/ntoskrnl/mm/i386/page.c b/reactos/ntoskrnl/mm/i386/page.c index 6ee1780be5b..334155afcda 100644 --- a/reactos/ntoskrnl/mm/i386/page.c +++ b/reactos/ntoskrnl/mm/i386/page.c @@ -70,7 +70,6 @@ __inline LARGE_INTEGER PTE_TO_PAGE(ULONG npage) extern BOOLEAN Ke386Pae; extern BOOLEAN Ke386NoExecute; -extern BOOLEAN Ke386GlobalPagesEnabled; /* FUNCTIONS ***************************************************************/ diff --git a/reactos/ntoskrnl/ntoskrnl.rbuild b/reactos/ntoskrnl/ntoskrnl.rbuild index 49739cddab9..443ba8e0cb4 100644 --- a/reactos/ntoskrnl/ntoskrnl.rbuild +++ b/reactos/ntoskrnl/ntoskrnl.rbuild @@ -26,14 +26,14 @@ - main_asm.S + boot.S abios.c cpu.c ctxswitch.S clock.S exp.c - kernel.c + kiinit.c ldt.c thread.c trap.s @@ -49,12 +49,13 @@ dpc.c event.c exception.c + freeldr.c gate.c gmutex.c ipi.c kqueue.c + krnlinit.c kthread.c - main.c mutex.c process.c profile.c