xref: /reactos/ntoskrnl/ke/amd64/krnlinit.c (revision d5b576b2)
1 /*
2  * PROJECT:         ReactOS Kernel
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * FILE:            ntoskrnl/ke/amd64/krnlinit.c
5  * PURPOSE:         Portable part of kernel initialization
6  * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer@reactos.org)
7  *                  Alex Ionescu (alex.ionescu@reactos.org)
8  */
9 
10 /* INCLUDES ******************************************************************/
11 
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15 
16 extern ULONG_PTR MainSSDT[];
17 extern UCHAR MainSSPT[];
18 
19 extern BOOLEAN RtlpUse16ByteSLists;
20 
21 /* FUNCTIONS *****************************************************************/
22 
23 VOID
24 NTAPI
25 INIT_FUNCTION
26 KiInitializeKernel(IN PKPROCESS InitProcess,
27                    IN PKTHREAD InitThread,
28                    IN PVOID IdleStack,
29                    IN PKPRCB Prcb,
30                    IN PLOADER_PARAMETER_BLOCK LoaderBlock);
31 
32 
33 VOID
34 NTAPI
35 KiInitializeHandBuiltThread(
36     IN PKTHREAD Thread,
37     IN PKPROCESS Process,
38     IN PVOID Stack)
39 {
40     PKPRCB Prcb = KeGetCurrentPrcb();
41 
42     /* Setup the Thread */
43     KeInitializeThread(Process, Thread, NULL, NULL, NULL, NULL, NULL, Stack);
44 
45     Thread->NextProcessor = Prcb->Number;
46     Thread->Priority = HIGH_PRIORITY;
47     Thread->State = Running;
48     Thread->Affinity = (ULONG_PTR)1 << Prcb->Number;
49     Thread->WaitIrql = DISPATCH_LEVEL;
50     Process->ActiveProcessors |= (ULONG_PTR)1 << Prcb->Number;
51 
52 }
53 
54 VOID
55 NTAPI
56 INIT_FUNCTION
57 KiSystemStartupBootStack(VOID)
58 {
59     PLOADER_PARAMETER_BLOCK LoaderBlock = KeLoaderBlock; // hack
60     PKPRCB Prcb = KeGetCurrentPrcb();
61     PKTHREAD Thread = (PKTHREAD)KeLoaderBlock->Thread;
62     PKPROCESS Process = Thread->ApcState.Process;
63     PVOID KernelStack = (PVOID)KeLoaderBlock->KernelStack;
64 
65     /* Initialize the Power Management Support for this PRCB */
66     PoInitializePrcb(Prcb);
67 
68     /* Save CPU state */
69     KiSaveProcessorControlState(&Prcb->ProcessorState);
70 
71     /* Get cache line information for this CPU */
72     KiGetCacheInformation();
73 
74     /* Initialize spinlocks and DPC data */
75     KiInitSpinLocks(Prcb, Prcb->Number);
76 
77     /* Set up the thread-related fields in the PRCB */
78     Prcb->CurrentThread = Thread;
79     Prcb->NextThread = NULL;
80     Prcb->IdleThread = Thread;
81 
82     /* Initialize PRCB pool lookaside pointers */
83     ExInitPoolLookasidePointers();
84 
85     /* Lower to APC_LEVEL */
86     KeLowerIrql(APC_LEVEL);
87 
88     /* Check if this is the boot cpu */
89     if (Prcb->Number == 0)
90     {
91         /* Initialize the kernel */
92         KiInitializeKernel(Process, Thread, KernelStack, Prcb, LoaderBlock);
93     }
94     else
95     {
96         /* Initialize the startup thread */
97         KiInitializeHandBuiltThread(Thread, Process, KernelStack);
98 
99         /* Initialize cpu with HAL */
100         if (!HalInitSystem(0, LoaderBlock))
101         {
102             /* Initialization failed */
103             KeBugCheck(HAL_INITIALIZATION_FAILED);
104         }
105     }
106 
107     /* Raise to Dispatch */
108     KfRaiseIrql(DISPATCH_LEVEL);
109 
110     /* Set the Idle Priority to 0. This will jump into Phase 1 */
111     KeSetPriorityThread(Thread, 0);
112 
113     /* If there's no thread scheduled, put this CPU in the Idle summary */
114     KiAcquirePrcbLock(Prcb);
115     if (!Prcb->NextThread) KiIdleSummary |= (ULONG_PTR)1 << Prcb->Number;
116     KiReleasePrcbLock(Prcb);
117 
118     /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
119     KfRaiseIrql(HIGH_LEVEL);
120     LoaderBlock->Prcb = 0;
121 
122     /* Set the priority of this thread to 0 */
123     Thread = KeGetCurrentThread();
124     Thread->Priority = 0;
125 
126     /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */
127     _enable();
128     KeLowerIrql(DISPATCH_LEVEL);
129 
130     /* Set the right wait IRQL */
131     Thread->WaitIrql = DISPATCH_LEVEL;
132 
133     /* Jump into the idle loop */
134     KiIdleLoop();
135 }
136 
137 VOID
138 NTAPI
139 INIT_FUNCTION
140 KiInitializeKernel(IN PKPROCESS InitProcess,
141                    IN PKTHREAD InitThread,
142                    IN PVOID IdleStack,
143                    IN PKPRCB Prcb,
144                    IN PLOADER_PARAMETER_BLOCK LoaderBlock)
145 {
146     ULONG_PTR PageDirectory[2];
147     PVOID DpcStack;
148     ULONG i;
149 
150     /* Set Node Data */
151     KeNodeBlock[0] = &KiNode0;
152     Prcb->ParentNode = KeNodeBlock[0];
153     KeNodeBlock[0]->ProcessorMask = Prcb->SetMember;
154 
155     /* Set boot-level flags */
156     KeFeatureBits = Prcb->FeatureBits;
157 
158     /* Initialize 8/16 bit SList support */
159     RtlpUse16ByteSLists = (KeFeatureBits & KF_CMPXCHG16B) ? TRUE : FALSE;
160 
161     /* Set the current MP Master KPRCB to the Boot PRCB */
162     Prcb->MultiThreadSetMaster = Prcb;
163 
164     /* Initialize Bugcheck Callback data */
165     InitializeListHead(&KeBugcheckCallbackListHead);
166     InitializeListHead(&KeBugcheckReasonCallbackListHead);
167     KeInitializeSpinLock(&BugCheckCallbackLock);
168 
169     /* Initialize the Timer Expiration DPC */
170     KeInitializeDpc(&KiTimerExpireDpc, KiTimerExpiration, NULL);
171     KeSetTargetProcessorDpc(&KiTimerExpireDpc, 0);
172 
173     /* Initialize Profiling data */
174     KeInitializeSpinLock(&KiProfileLock);
175     InitializeListHead(&KiProfileListHead);
176     InitializeListHead(&KiProfileSourceListHead);
177 
178     /* Loop the timer table */
179     for (i = 0; i < TIMER_TABLE_SIZE; i++)
180     {
181         /* Initialize the list and entries */
182         InitializeListHead(&KiTimerTableListHead[i].Entry);
183         KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF;
184         KiTimerTableListHead[i].Time.LowPart = 0;
185     }
186 
187     /* Initialize the Swap event and all swap lists */
188     KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE);
189     InitializeListHead(&KiProcessInSwapListHead);
190     InitializeListHead(&KiProcessOutSwapListHead);
191     InitializeListHead(&KiStackInSwapListHead);
192 
193     /* Initialize the mutex for generic DPC calls */
194     ExInitializeFastMutex(&KiGenericCallDpcMutex);
195 
196     /* Initialize the syscall table */
197     KeServiceDescriptorTable[0].Base = MainSSDT;
198     KeServiceDescriptorTable[0].Count = NULL;
199     KeServiceDescriptorTable[0].Limit = KiServiceLimit;
200     KeServiceDescriptorTable[1].Limit = 0;
201     KeServiceDescriptorTable[0].Number = MainSSPT;
202 
203     /* Copy the the current table into the shadow table for win32k */
204     RtlCopyMemory(KeServiceDescriptorTableShadow,
205                   KeServiceDescriptorTable,
206                   sizeof(KeServiceDescriptorTable));
207 
208     /* Initialize the Idle Process and the Process Listhead */
209     InitializeListHead(&KiProcessListHead);
210     PageDirectory[0] = 0;
211     PageDirectory[1] = 0;
212     KeInitializeProcess(InitProcess,
213                         0,
214                         0xFFFFFFFF,
215                         PageDirectory,
216                         FALSE);
217     InitProcess->QuantumReset = MAXCHAR;
218 
219     /* Initialize the startup thread */
220     KiInitializeHandBuiltThread(InitThread, InitProcess, IdleStack);
221 
222     /* Initialize the Kernel Executive */
223     ExpInitializeExecutive(0, LoaderBlock);
224 
225     /* Calculate the time reciprocal */
226     KiTimeIncrementReciprocal =
227         KiComputeReciprocal(KeMaximumIncrement,
228                             &KiTimeIncrementShiftCount);
229 
230     /* Update DPC Values in case they got updated by the executive */
231     Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
232     Prcb->MinimumDpcRate = KiMinimumDpcRate;
233     Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
234 
235     /* Allocate the DPC Stack */
236     DpcStack = MmCreateKernelStack(FALSE, 0);
237     if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0);
238     Prcb->DpcStack = DpcStack;
239 }
240 
241