[NTOSKRNL/AMD64]

- Add portable kernel initialization code for amd64 only.
- Modify amd64 init code accordingly

svn path=/trunk/; revision=53714
This commit is contained in:
Timo Kreuzer
2011-09-15 19:32:13 +00:00
parent 3e2fddbe19
commit 89b75ad8b7
5 changed files with 385 additions and 264 deletions
+1
View File
@@ -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
+8 -28
View File
@@ -10,7 +10,7 @@
#include <asm.inc>
#include <ksamd64.inc>
EXTERN KiInitializeKernelAndGotoIdleLoop:PROC
EXTERN KiSystemStartupBootStack:PROC
/* GLOBALS *******************************************************************/
@@ -21,42 +21,22 @@ EXTERN KiInitializeKernelAndGotoIdleLoop:PROC
/**
* VOID
* KiSetupStackAndInitializeKernel(
* IN PKPROCESS InitProcess, <rsp + 0x08, rcx>
* IN PKTHREAD InitThread, <rsp + 0x10, rdx>
* IN PVOID IdleStack, <rsp + 0x18, r8>
* IN PKPRCB Prcb, <rsp + 0x20, r9>
* IN CCHAR Number, <rsp + 0x28>
* IN PLOADER_PARAMETER_BLOCK LoaderBlock) <rsp + 0x30>
* KiSwitchToBootStack(
* IN ULONG_PTR InitialStack<rcx>)
*/
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
-35
View File
@@ -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)
+141 -201
View File
@@ -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();
}
+235
View File
@@ -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 ([email protected])
* Alex Ionescu ([email protected])
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
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;
}