From 89b75ad8b79d78e02ae4638922d2f469038dfa23 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Thu, 15 Sep 2011 19:32:13 +0000 Subject: [PATCH] [NTOSKRNL/AMD64] - Add portable kernel initialization code for amd64 only. - Modify amd64 init code accordingly svn path=/trunk/; revision=53714 --- reactos/ntoskrnl/CMakeLists.txt | 1 + reactos/ntoskrnl/ke/amd64/boot.S | 36 +-- reactos/ntoskrnl/ke/amd64/cpu.c | 35 --- reactos/ntoskrnl/ke/amd64/kiinit.c | 342 +++++++++++---------------- reactos/ntoskrnl/ke/amd64/krnlinit.c | 235 ++++++++++++++++++ 5 files changed, 385 insertions(+), 264 deletions(-) create mode 100644 reactos/ntoskrnl/ke/amd64/krnlinit.c diff --git a/reactos/ntoskrnl/CMakeLists.txt b/reactos/ntoskrnl/CMakeLists.txt index ac85693f36c..df4b19f9792 100644 --- a/reactos/ntoskrnl/CMakeLists.txt +++ b/reactos/ntoskrnl/CMakeLists.txt @@ -312,6 +312,7 @@ elseif(ARCH MATCHES amd64) ke/amd64/interrupt.c ke/amd64/irql.c ke/amd64/kiinit.c + ke/amd64/krnlinit.c ke/amd64/spinlock.c ke/amd64/stubs.c ke/amd64/thrdini.c diff --git a/reactos/ntoskrnl/ke/amd64/boot.S b/reactos/ntoskrnl/ke/amd64/boot.S index 03da69ede75..5be8adc21dc 100644 --- a/reactos/ntoskrnl/ke/amd64/boot.S +++ b/reactos/ntoskrnl/ke/amd64/boot.S @@ -10,7 +10,7 @@ #include #include -EXTERN KiInitializeKernelAndGotoIdleLoop:PROC +EXTERN KiSystemStartupBootStack:PROC /* GLOBALS *******************************************************************/ @@ -21,42 +21,22 @@ EXTERN KiInitializeKernelAndGotoIdleLoop:PROC /** * VOID - * KiSetupStackAndInitializeKernel( - * IN PKPROCESS InitProcess, - * IN PKTHREAD InitThread, - * IN PVOID IdleStack, - * IN PKPRCB Prcb, - * IN CCHAR Number, - * IN PLOADER_PARAMETER_BLOCK LoaderBlock) + * KiSwitchToBootStack( + * IN ULONG_PTR InitialStack) */ -PUBLIC KiSetupStackAndInitializeKernel -.PROC KiSetupStackAndInitializeKernel - - /* Save current stack */ - mov rsi, rsp +PUBLIC KiSwitchToBootStack +.PROC KiSwitchToBootStack /* Setup the new stack */ mov ax, HEX(18) mov ss, ax - mov rsp, r8 + mov rsp, rcx sub rsp, HEX(300) // FIXME - - /* Copy stack parameters to the new stack */ - sub rsp, HEX(38) .ENDPROLOG - mov rdi, rsp - movsq - movsq - movsq - movsq - movsq - movsq - movsq + jmp KiSystemStartupBootStack - jmp KiInitializeKernelAndGotoIdleLoop - -.ENDP KiSetupStackAndInitializeKernel +.ENDP KiSwitchToBootStack END diff --git a/reactos/ntoskrnl/ke/amd64/cpu.c b/reactos/ntoskrnl/ke/amd64/cpu.c index cb8299e70b2..2551b5eed4b 100644 --- a/reactos/ntoskrnl/ke/amd64/cpu.c +++ b/reactos/ntoskrnl/ke/amd64/cpu.c @@ -369,41 +369,6 @@ KiGetCacheInformation(VOID) } } -VOID -FASTCALL -KiInitializeTss(IN PKTSS64 Tss, - IN UINT64 Stack) -{ - PKGDTENTRY64 TssEntry; - - /* Get pointer to the GDT entry */ - TssEntry = KiGetGdtEntry(KeGetPcr()->GdtBase, KGDT64_SYS_TSS); - - /* Initialize the GDT entry */ - KiInitGdtEntry(TssEntry, (ULONG64)Tss, sizeof(KTSS64), AMD64_TSS, 0); - - /* Zero out the TSS */ - RtlZeroMemory(Tss, sizeof(KTSS64)); - - /* FIXME: I/O Map? */ - Tss->IoMapBase = 0x68; - - /* Setup ring 0 stack pointer */ - Tss->Rsp0 = Stack; - - /* Setup a stack for Double Fault Traps */ - Tss->Ist[1] = (ULONG64)KiDoubleFaultStack; - - /* Setup a stack for CheckAbort Traps */ - Tss->Ist[2] = (ULONG64)KiDoubleFaultStack; - - /* Setup a stack for NMI Traps */ - Tss->Ist[3] = (ULONG64)KiDoubleFaultStack; - - /* Load the task register */ - __ltr(KGDT64_SYS_TSS); -} - VOID NTAPI KeFlushCurrentTb(VOID) diff --git a/reactos/ntoskrnl/ke/amd64/kiinit.c b/reactos/ntoskrnl/ke/amd64/kiinit.c index d2704638f50..f065ac8c27b 100644 --- a/reactos/ntoskrnl/ke/amd64/kiinit.c +++ b/reactos/ntoskrnl/ke/amd64/kiinit.c @@ -70,6 +70,15 @@ KiInitMachineDependent(VOID) DPRINT1("PAT support detected but not yet taken advantage of!\n"); } + /* 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); +// } } @@ -110,7 +119,7 @@ KiInitializePcr(IN PKIPCR Pcr, /* Set the Processor Number and current Processor Mask */ Pcr->Prcb.Number = (UCHAR)ProcessorNumber; - Pcr->Prcb.SetMember = 1 << ProcessorNumber; + Pcr->Prcb.SetMember = 1ULL << ProcessorNumber; /* Get GDT and IDT descriptors */ __sgdt(&GdtDescriptor.Limit); @@ -147,14 +156,20 @@ KiInitializePcr(IN PKIPCR Pcr, Pcr->Irql = PASSIVE_LEVEL; KeSetCurrentIrql(PASSIVE_LEVEL); + /* Set GS base */ + __writemsr(X86_MSR_GSBASE, (ULONG64)Pcr); + __writemsr(X86_MSR_KERNEL_GSBASE, (ULONG64)Pcr); } VOID NTAPI -KiInitializeCpuFeatures(ULONG Cpu) +KiInitializeCpu(PKPRCB Prcb) { ULONG FeatureBits; + /* Detect and set the CPU Type */ + KiSetProcessorType(); + /* Get the processor features for this CPU */ FeatureBits = KiGetFeatureBits(); @@ -172,7 +187,7 @@ KiInitializeCpuFeatures(ULONG Cpu) FeatureBits |= KF_NX_ENABLED; /* Save feature bits */ - KeGetCurrentPrcb()->FeatureBits = FeatureBits; + Prcb->FeatureBits = FeatureBits; /* Enable fx save restore support */ __writecr4(__readcr4() | CR4_FXSR); @@ -188,170 +203,139 @@ KiInitializeCpuFeatures(ULONG Cpu) /* Disable x87 fpu exceptions */ __writecr0(__readcr0() & ~CR0_NE); - + + /* LDT is unused */ + __lldt(0); +} + +VOID +FASTCALL +KiInitializeTss(IN PKTSS64 Tss, + IN UINT64 Stack) +{ + PKGDTENTRY64 TssEntry; + + /* Get pointer to the GDT entry */ + TssEntry = KiGetGdtEntry(KeGetPcr()->GdtBase, KGDT64_SYS_TSS); + + /* Initialize the GDT entry */ + KiInitGdtEntry(TssEntry, (ULONG64)Tss, sizeof(KTSS64), AMD64_TSS, 0); + + /* Zero out the TSS */ + RtlZeroMemory(Tss, sizeof(KTSS64)); + + /* FIXME: I/O Map? */ + Tss->IoMapBase = 0x68; + + /* Setup ring 0 stack pointer */ + Tss->Rsp0 = Stack; + + /* Setup a stack for Double Fault Traps */ + Tss->Ist[1] = (ULONG64)KiDoubleFaultStack; + + /* Setup a stack for CheckAbort Traps */ + Tss->Ist[2] = (ULONG64)KiDoubleFaultStack; + + /* Setup a stack for NMI Traps */ + Tss->Ist[3] = (ULONG64)KiDoubleFaultStack; + + /* Load the task register */ + __ltr(KGDT64_SYS_TSS); } VOID NTAPI -KiInitializeKernel(IN PKPROCESS InitProcess, - IN PKTHREAD InitThread, - IN PVOID IdleStack, - IN PKPRCB Prcb, - IN CCHAR Number, - IN PLOADER_PARAMETER_BLOCK LoaderBlock) +INIT_FUNCTION +KiInitializeKernelMachineDependent( + IN PKPRCB Prcb, + IN PLOADER_PARAMETER_BLOCK LoaderBlock) { - ULONG PageDirectory[2]; - PVOID DpcStack; - - /* Detect and set the CPU Type */ - KiSetProcessorType(); - - /* Initialize the Power Management Support for this PRCB */ -// PoInitializePrcb(Prcb); - - /* Save CPU state */ - KiSaveProcessorControlState(&Prcb->ProcessorState); - - /* 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 == 0) - { - /* Set Node Data */ - KeNodeBlock[0] = &KiNode0; - Prcb->ParentNode = KeNodeBlock[0]; - KeNodeBlock[0]->ProcessorMask = Prcb->SetMember; - - /* Set boot-level flags */ - KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64; - KeProcessorLevel = (USHORT)Prcb->CpuType; - if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep; - - /* Set the current MP Master KPRCB to the Boot PRCB */ - Prcb->MultiThreadSetMaster = Prcb; - - /* Lower to APC_LEVEL */ - KeLowerIrql(APC_LEVEL); - - /* Initialize some spinlocks */ - KeInitializeSpinLock(&KiFreezeExecutionLock); - - /* Initialize portable parts of the OS */ - KiInitSystem(); - - /* Initialize the Idle Process and the Process Listhead */ - InitializeListHead(&KiProcessListHead); - PageDirectory[0] = 0; - PageDirectory[1] = 0; - KeInitializeProcess(InitProcess, - 0, - 0xFFFFFFFF, - PageDirectory, - FALSE); - InitProcess->QuantumReset = MAXCHAR; - } - else - { - /* FIXME */ - DPRINT1("SMP Boot support not yet present\n"); - } - - /* HACK for MmUpdatePageDir */ - ((PETHREAD)InitThread)->ThreadsProcess = (PEPROCESS)InitProcess; - - /* Setup the Idle Thread */ - KeInitializeThread(InitProcess, - InitThread, - NULL, - NULL, - NULL, - NULL, - NULL, - IdleStack); - - InitThread->NextProcessor = Number; - InitThread->Priority = HIGH_PRIORITY; - InitThread->State = Running; - InitThread->Affinity = 1 << Number; - InitThread->WaitIrql = DISPATCH_LEVEL; - InitProcess->ActiveProcessors = 1 << Number; + /* Set boot-level flags */ + KeI386CpuType = Prcb->CpuType; + KeI386CpuStep = Prcb->CpuStep; + KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64; + KeProcessorLevel = (USHORT)Prcb->CpuType; + if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep; /* Set basic CPU Features that user mode can read */ SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = - (KeFeatureBits & KF_MMX) ? TRUE: FALSE; - SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = - (KeFeatureBits & KF_CMPXCHG8B) ? TRUE: FALSE; + (Prcb->FeatureBits & KF_MMX) ? TRUE: FALSE; + SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE; SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = - ((KeFeatureBits & KF_FXSR) && (KeFeatureBits & KF_XMMI)) ? TRUE: FALSE; + ((Prcb->FeatureBits & KF_FXSR) && (Prcb->FeatureBits & KF_XMMI)) ? TRUE: FALSE; SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = - ((KeFeatureBits & KF_FXSR) && (KeFeatureBits & KF_XMMI64)) ? TRUE: FALSE; + ((Prcb->FeatureBits & KF_FXSR) && (Prcb->FeatureBits & KF_XMMI64)) ? TRUE: FALSE; SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = - (KeFeatureBits & KF_3DNOW) ? TRUE: FALSE; - SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = - (KeFeatureBits & KF_RDTSC) ? TRUE: FALSE; + (Prcb->FeatureBits & KF_3DNOW) ? TRUE: FALSE; + SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE; - /* Set up the thread-related fields in the PRCB */ - Prcb->CurrentThread = InitThread; - Prcb->NextThread = NULL; - Prcb->IdleThread = InitThread; + /* Set the default NX policy (opt-in) */ + SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTIN; - /* Initialize the Kernel Executive */ - ExpInitializeExecutive(Number, LoaderBlock); - - /* Only do this on the boot CPU */ - if (Number == 0) + /* Check if NPX is always on */ + if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSON")) { - /* 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, 0); - 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); -// } + /* Set it always on */ + SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSON; + Prcb->FeatureBits |= KF_NX_ENABLED; + } + else if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTOUT")) + { + /* Set it in opt-out mode */ + SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTOUT; + Prcb->FeatureBits |= KF_NX_ENABLED; + } + else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTIN")) || + (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE"))) + { + /* Set the feature bits */ + Prcb->FeatureBits |= KF_NX_ENABLED; + } + else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSOFF")) || + (strstr(KeLoaderBlock->LoadOptions, "EXECUTE"))) + { + /* Set disabled mode */ + SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSOFF; + Prcb->FeatureBits |= KF_NX_DISABLED; } - /* Raise to Dispatch */ - KfRaiseIrql(DISPATCH_LEVEL); +} - /* Set the Idle Priority to 0. This will jump into Phase 1 */ - KeSetPriorityThread(InitThread, 0); +static LDR_DATA_TABLE_ENTRY LdrCoreEntries[3]; - /* If there's no thread scheduled, put this CPU in the Idle summary */ - KiAcquirePrcbLock(Prcb); - if (!Prcb->NextThread) KiIdleSummary |= 1 << Number; - KiReleasePrcbLock(Prcb); +void +KiInitModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + PLDR_DATA_TABLE_ENTRY LdrEntry; + PLIST_ENTRY Entry; + ULONG i; - /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */ - KfRaiseIrql(HIGH_LEVEL); - LoaderBlock->Prcb = 0; + /* Initialize the list head */ + InitializeListHead(&PsLoadedModuleList); + + /* Loop the first 3 entries */ + for (Entry = LoaderBlock->LoadOrderListHead.Flink, i = 0; + Entry != &LoaderBlock->LoadOrderListHead && i < 3; + Entry = Entry->Flink, i++) + { + /* Get the data table entry */ + LdrEntry = CONTAINING_RECORD(Entry, + LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks); + + /* Copy the entry */ + LdrCoreEntries[i] = *LdrEntry; + + /* Insert the copy into the list */ + InsertTailList(&PsLoadedModuleList, &LdrCoreEntries[i].InLoadOrderLinks); + } } VOID NTAPI KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { - ULONG Cpu; + CCHAR Cpu; PKTHREAD InitialThread; ULONG64 InitialStack; PKIPCR Pcr; @@ -367,11 +351,12 @@ KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) KeLoaderBlock = LoaderBlock; /* Get the current CPU number */ - Cpu = KeNumberProcessors++; // FIXME + Cpu = (CCHAR)KeNumberProcessors++; // FIXME /* LoaderBlock initialization for Cpu 0 */ if (Cpu == 0) { + FrLdrDbgPrint("LoaderBlock->Prcb=%p\n", LoaderBlock->Prcb); /* Set the initial stack, idle thread and process */ LoaderBlock->KernelStack = (ULONG_PTR)P0BootStack; LoaderBlock->Thread = (ULONG_PTR)&KiInitialThread; @@ -385,13 +370,6 @@ KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) /* Set the PRCB for this Processor */ KiProcessorBlock[Cpu] = &Pcr->Prcb; - /* Set GS base */ - __writemsr(X86_MSR_GSBASE, (ULONG64)Pcr); - __writemsr(X86_MSR_KERNEL_GSBASE, (ULONG64)Pcr); - - /* LDT is unused */ - __lldt(0); - /* Align stack to 16 bytes */ LoaderBlock->KernelStack &= ~(16 - 1); @@ -399,9 +377,6 @@ KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) InitialStack = LoaderBlock->KernelStack; // Checkme InitialThread = (PKTHREAD)LoaderBlock->Thread; - /* Clean the APC List Head */ - InitializeListHead(&InitialThread->ApcState.ApcListHead[KernelMode]); - /* Set us as the current process */ InitialThread->ApcState.Process = (PVOID)LoaderBlock->Process; @@ -409,34 +384,34 @@ KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) KiInitializePcr(Pcr, Cpu, InitialThread, (PVOID)KiDoubleFaultStack); /* Initialize the CPU features */ - KiInitializeCpuFeatures(Cpu); + KiInitializeCpu(&Pcr->Prcb); /* Initial setup for the boot CPU */ if (Cpu == 0) { + /* Initialize the module list (ntos, hal, kdcom) */ + KiInitModuleList(LoaderBlock); + /* Setup the TSS descriptors and entries */ KiInitializeTss(Pcr->TssBase, InitialStack); /* Setup the IDT */ KeInitExceptions(); - /* HACK: misuse this function to pass a function pointer to kdcom */ - KdDebuggerInitialize1((PVOID)FrLdrDbgPrint); - - /* Initialize debugging system */ + /* Initialize debugging system */ KdInitSystem(0, KeLoaderBlock); /* Check for break-in */ if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); /* Hack! Wait for the debugger! */ -#ifdef _WINKD_ +#ifdef _WINKD_x while (!KdPollBreakIn()); DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); #endif } - DPRINT("Pcr = %p, Gdt = %p, Idt = %p, Tss = %p\n", + DPRINT1("Pcr = %p, Gdt = %p, Idt = %p, Tss = %p\n", Pcr, Pcr->GdtBase, Pcr->IdtBase, Pcr->TssBase); /* Acquire lock */ @@ -444,13 +419,13 @@ KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { /* Loop until lock is free */ while ((*(volatile KSPIN_LOCK*)&KiFreezeExecutionLock) & 1); - } + } /* Initialize the Processor with HAL */ HalInitializeProcessor(Cpu, KeLoaderBlock); /* Set processor as active */ - KeActiveProcessors |= 1 << Cpu; + KeActiveProcessors |= 1ULL << Cpu; /* Release lock */ InterlockedAnd64((PLONG64)&KiFreezeExecutionLock, 0); @@ -458,45 +433,10 @@ KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) /* Raise to HIGH_LEVEL */ KfRaiseIrql(HIGH_LEVEL); + /* Machine specific kernel initialization */ + if (Cpu == 0) KiInitializeKernelMachineDependent(&Pcr->Prcb, LoaderBlock); + /* Switch to new kernel stack and start kernel bootstrapping */ - KiSetupStackAndInitializeKernel(&KiInitialProcess.Pcb, - InitialThread, - (PVOID)InitialStack, - &Pcr->Prcb, - (CCHAR)Cpu, - KeLoaderBlock); + KiSwitchToBootStack(InitialStack & ~3); } - -VOID -NTAPI -KiInitializeKernelAndGotoIdleLoop(IN PKPROCESS InitProcess, - IN PKTHREAD InitThread, - IN PVOID IdleStack, - IN PKPRCB Prcb, - IN CCHAR Number, - IN PLOADER_PARAMETER_BLOCK LoaderBlock) -{ -// DbgBreakPointWithStatus(0); - - /* Initialize kernel */ - KiInitializeKernel(InitProcess, - InitThread, - IdleStack, - Prcb, - Number, - KeLoaderBlock); - - /* Set the priority of this thread to 0 */ - InitThread->Priority = 0; - - /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */ - _enable(); - KeLowerIrql(DISPATCH_LEVEL); - - /* Set the right wait IRQL */ - InitThread->WaitIrql = DISPATCH_LEVEL; - - /* Jump into the idle loop */ - KiIdleLoop(); -} diff --git a/reactos/ntoskrnl/ke/amd64/krnlinit.c b/reactos/ntoskrnl/ke/amd64/krnlinit.c new file mode 100644 index 00000000000..79468717e4c --- /dev/null +++ b/reactos/ntoskrnl/ke/amd64/krnlinit.c @@ -0,0 +1,235 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/ke/krnlinit.c + * PURPOSE: Portable part of kernel initialization + * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) + * Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include + +extern ULONG_PTR MainSSDT[]; +extern UCHAR MainSSPT[]; + +/* FUNCTIONS *****************************************************************/ + +VOID +NTAPI +INIT_FUNCTION +KiInitializeKernel(IN PKPROCESS InitProcess, + IN PKTHREAD InitThread, + IN PVOID IdleStack, + IN PKPRCB Prcb, + IN PLOADER_PARAMETER_BLOCK LoaderBlock); + + +VOID +NTAPI +KiInitalizeHandBuiltThread( + IN PKTHREAD Thread, + IN PKPROCESS Process, + IN PVOID Stack) +{ + PKPRCB Prcb = KeGetCurrentPrcb(); + + /* Setup the Thread */ + KeInitializeThread(Process, Thread, NULL, NULL, NULL, NULL, NULL, Stack); + + Thread->NextProcessor = Prcb->Number; + Thread->Priority = HIGH_PRIORITY; + Thread->State = Running; + Thread->Affinity = (ULONG_PTR)1 << Prcb->Number; + Thread->WaitIrql = DISPATCH_LEVEL; + Process->ActiveProcessors |= (ULONG_PTR)1 << Prcb->Number; + +} + +VOID +NTAPI +INIT_FUNCTION +KiSystemStartupBootStack(VOID) +{ + PLOADER_PARAMETER_BLOCK LoaderBlock = KeLoaderBlock; // hack + PKPRCB Prcb = KeGetCurrentPrcb(); + PKTHREAD Thread = (PKTHREAD)KeLoaderBlock->Thread; + PKPROCESS Process = Thread->ApcState.Process; + PVOID KernelStack = (PVOID)KeLoaderBlock->KernelStack; + + /* Initialize the Power Management Support for this PRCB */ + PoInitializePrcb(Prcb); + + /* Save CPU state */ + KiSaveProcessorControlState(&Prcb->ProcessorState); + + /* Get cache line information for this CPU */ + KiGetCacheInformation(); + + /* Initialize spinlocks and DPC data */ + KiInitSpinLocks(Prcb, Prcb->Number); + + /* Set up the thread-related fields in the PRCB */ + Prcb->CurrentThread = Thread; + Prcb->NextThread = NULL; + Prcb->IdleThread = Thread; + + /* Initialize PRCB pool lookaside pointers */ + ExInitPoolLookasidePointers(); + + /* Check if this is the boot cpu */ + if (Prcb->Number == 0) + { + /* Initialize the kernel */ + KiInitializeKernel(Process, Thread, KernelStack, Prcb, LoaderBlock); + } + else + { + /* Initialize the startup thread */ + KiInitalizeHandBuiltThread(Thread, Process, KernelStack); + + /* Initialize cpu with HAL */ + if (!HalInitSystem(0, LoaderBlock)) + { + /* Initialization failed */ + KeBugCheck(HAL_INITIALIZATION_FAILED); + } + } + + /* Raise to Dispatch */ + KfRaiseIrql(DISPATCH_LEVEL); + + /* Set the Idle Priority to 0. This will jump into Phase 1 */ + KeSetPriorityThread(Thread, 0); + + /* If there's no thread scheduled, put this CPU in the Idle summary */ + KiAcquirePrcbLock(Prcb); + if (!Prcb->NextThread) KiIdleSummary |= (ULONG_PTR)1 << Prcb->Number; + KiReleasePrcbLock(Prcb); + + /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */ + KfRaiseIrql(HIGH_LEVEL); + LoaderBlock->Prcb = 0; + + /* Set the priority of this thread to 0 */ + Thread = KeGetCurrentThread(); + Thread->Priority = 0; + + /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */ + _enable(); + KeLowerIrql(DISPATCH_LEVEL); + + /* Set the right wait IRQL */ + Thread->WaitIrql = DISPATCH_LEVEL; + + /* Jump into the idle loop */ + KiIdleLoop(); +} + +VOID +NTAPI +INIT_FUNCTION +KiInitializeKernel(IN PKPROCESS InitProcess, + IN PKTHREAD InitThread, + IN PVOID IdleStack, + IN PKPRCB Prcb, + IN PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + ULONG PageDirectory[2]; + PVOID DpcStack; + ULONG i; + + /* Set Node Data */ + KeNodeBlock[0] = &KiNode0; + Prcb->ParentNode = KeNodeBlock[0]; + KeNodeBlock[0]->ProcessorMask = Prcb->SetMember; + + /* Set boot-level flags */ + KeFeatureBits = Prcb->FeatureBits; + + /* Set the current MP Master KPRCB to the Boot PRCB */ + Prcb->MultiThreadSetMaster = Prcb; + + /* Lower to APC_LEVEL */ + KeLowerIrql(APC_LEVEL); + + /* Initialize Bugcheck Callback data */ + InitializeListHead(&KeBugcheckCallbackListHead); + InitializeListHead(&KeBugcheckReasonCallbackListHead); + KeInitializeSpinLock(&BugCheckCallbackLock); + + /* Initialize the Timer Expiration DPC */ + KeInitializeDpc(&KiTimerExpireDpc, KiTimerExpiration, NULL); + KeSetTargetProcessorDpc(&KiTimerExpireDpc, 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 the Swap event and all swap lists */ + KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE); + InitializeListHead(&KiProcessInSwapListHead); + InitializeListHead(&KiProcessOutSwapListHead); + InitializeListHead(&KiStackInSwapListHead); + + /* Initialize the mutex for generic DPC calls */ + ExInitializeFastMutex(&KiGenericCallDpcMutex); + + /* Initialize the syscall table */ + KeServiceDescriptorTable[0].Base = MainSSDT; + KeServiceDescriptorTable[0].Count = NULL; + KeServiceDescriptorTable[0].Limit = KiServiceLimit; + KeServiceDescriptorTable[1].Limit = 0; + KeServiceDescriptorTable[0].Number = MainSSPT; + + /* Copy the the current table into the shadow table for win32k */ + RtlCopyMemory(KeServiceDescriptorTableShadow, + KeServiceDescriptorTable, + sizeof(KeServiceDescriptorTable)); + + /* Initialize the Idle Process and the Process Listhead */ + InitializeListHead(&KiProcessListHead); + PageDirectory[0] = 0; + PageDirectory[1] = 0; + KeInitializeProcess(InitProcess, + 0, + 0xFFFFFFFF, + PageDirectory, + FALSE); + InitProcess->QuantumReset = MAXCHAR; + + /* Initialize the startup thread */ + KiInitalizeHandBuiltThread(InitThread, InitProcess, IdleStack); + + /* Initialize the Kernel Executive */ + ExpInitializeExecutive(0, LoaderBlock); + + /* 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, 0); + if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0); + Prcb->DpcStack = DpcStack; +} +