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