xref: /reactos/ntoskrnl/ke/amd64/kiinit.c (revision 0c2cdcae)
1 /*
2  * PROJECT:         ReactOS Kernel
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * FILE:            ntoskrnl/ke/amd64/kiinit.c
5  * PURPOSE:         Kernel Initialization for x86 CPUs
6  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
7  *                  Timo Kreuzer (timo.kreuzer@reactos.org)
8  */
9 
10 /* INCLUDES *****************************************************************/
11 
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15 
16 #define REQUIRED_FEATURE_BITS (KF_RDTSC|KF_CR4|KF_CMPXCHG8B|KF_XMMI|KF_XMMI64| \
17                                KF_LARGE_PAGE|KF_FAST_SYSCALL|KF_GLOBAL_PAGE| \
18                                KF_CMOV|KF_PAT|KF_MMX|KF_FXSR|KF_NX_BIT|KF_MTRR)
19 
20 /* GLOBALS *******************************************************************/
21 
22 /* Function pointer for early debug prints */
23 ULONG (*FrLdrDbgPrint)(const char *Format, ...);
24 
25 /* Spinlocks used only on X86 */
26 KSPIN_LOCK KiFreezeExecutionLock;
27 
28 
29 KIPCR KiInitialPcr;
30 
31 /* Boot and double-fault/NMI/DPC stack */
32 UCHAR DECLSPEC_ALIGN(16) KiP0BootStackData[KERNEL_STACK_SIZE] = {0};
33 UCHAR DECLSPEC_ALIGN(16) KiP0DoubleFaultStackData[KERNEL_STACK_SIZE] = {0};
34 PVOID KiP0BootStack = &KiP0BootStackData[KERNEL_STACK_SIZE];
35 PVOID KiP0DoubleFaultStack = &KiP0DoubleFaultStackData[KERNEL_STACK_SIZE];
36 
37 ULONGLONG BootCycles, BootCyclesEnd;
38 
39 void KiInitializeSegments();
40 void KiSystemCallEntry64();
41 void KiSystemCallEntry32();
42 
43 /* FUNCTIONS *****************************************************************/
44 
45 CODE_SEG("INIT")
46 VOID
47 NTAPI
48 KiInitMachineDependent(VOID)
49 {
50     /* Check for large page support */
51     if (KeFeatureBits & KF_LARGE_PAGE)
52     {
53         /* FIXME: Support this */
54         DPRINT("Large Page support detected but not yet taken advantage of!\n");
55     }
56 
57     /* Check for global page support */
58     if (KeFeatureBits & KF_GLOBAL_PAGE)
59     {
60         /* FIXME: Support this */
61         DPRINT("Global Page support detected but not yet taken advantage of!\n");
62     }
63 
64     /* Check if we have MTRR */
65     if (KeFeatureBits & KF_MTRR)
66     {
67         /* FIXME: Support this */
68         DPRINT("MTRR support detected but not yet taken advantage of!\n");
69     }
70 
71     /* Check for PAT and/or MTRR support */
72     if (KeFeatureBits & KF_PAT)
73     {
74         /* FIXME: Support this */
75         DPRINT("PAT support detected but not yet taken advantage of!\n");
76     }
77 
78 //        /* Allocate the IOPM save area */
79 //        Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool,
80 //                                                  IOPM_SIZE,
81 //                                                  '  eK');
82 //        if (!Ki386IopmSaveArea)
83 //        {
84 //            /* Bugcheck. We need this for V86/VDM support. */
85 //            KeBugCheckEx(NO_PAGES_AVAILABLE, 2, IOPM_SIZE, 0, 0);
86 //        }
87 
88 }
89 
90 static
91 VOID
92 KiInitializePcr(
93     _Out_ PKIPCR Pcr,
94     _In_ ULONG ProcessorNumber,
95     _In_ PKGDTENTRY64 GdtBase,
96     _In_ PKIDTENTRY64 IdtBase,
97     _In_ PKTSS64 TssBase,
98     _In_ PKTHREAD IdleThread,
99     _In_ PVOID DpcStack)
100 {
101     /* Zero out the PCR */
102     RtlZeroMemory(Pcr, sizeof(KIPCR));
103 
104     /* Set pointers to ourselves */
105     Pcr->Self = (PKPCR)Pcr;
106     Pcr->CurrentPrcb = &Pcr->Prcb;
107 
108     /* Set the PCR Version */
109     Pcr->MajorVersion = PCR_MAJOR_VERSION;
110     Pcr->MinorVersion = PCR_MINOR_VERSION;
111 
112     /* Set the PRCB Version */
113     Pcr->Prcb.MajorVersion = PRCB_MAJOR_VERSION;
114     Pcr->Prcb.MinorVersion = PRCB_MINOR_VERSION;
115 
116     /* Set the Build Type */
117     Pcr->Prcb.BuildType = 0;
118 #ifndef CONFIG_SMP
119     Pcr->Prcb.BuildType |= PRCB_BUILD_UNIPROCESSOR;
120 #endif
121 #if DBG
122     Pcr->Prcb.BuildType |= PRCB_BUILD_DEBUG;
123 #endif
124 
125     /* Set the Processor Number and current Processor Mask */
126     Pcr->Prcb.Number = (UCHAR)ProcessorNumber;
127     Pcr->Prcb.SetMember = 1ULL << ProcessorNumber;
128 
129     /* Set GDT and IDT base */
130     Pcr->GdtBase = GdtBase;
131     Pcr->IdtBase = IdtBase;
132 
133     /* Set TssBase */
134     Pcr->TssBase = TssBase;
135 
136     Pcr->Prcb.RspBase = Pcr->TssBase->Rsp0; // FIXME
137 
138     /* Set DPC Stack */
139     Pcr->Prcb.DpcStack = DpcStack;
140 
141     /* Setup the processor set */
142     Pcr->Prcb.MultiThreadProcessorSet = Pcr->Prcb.SetMember;
143 
144     /* Clear DR6/7 to cleanup bootloader debugging */
145     Pcr->Prcb.ProcessorState.SpecialRegisters.KernelDr6 = 0;
146     Pcr->Prcb.ProcessorState.SpecialRegisters.KernelDr7 = 0;
147 
148     /* Initialize MXCSR (all exceptions masked) */
149     Pcr->Prcb.MxCsr = INITIAL_MXCSR;
150 
151     /* Set the Current Thread */
152     Pcr->Prcb.CurrentThread = IdleThread;
153 
154     /* Start us out at PASSIVE_LEVEL */
155     Pcr->Irql = PASSIVE_LEVEL;
156 }
157 
158 VOID
159 NTAPI
160 KiInitializeCpu(PKIPCR Pcr)
161 {
162     ULONG64 Pat;
163     ULONG64 FeatureBits;
164 
165     /* Initialize gs */
166     KiInitializeSegments();
167 
168     /* Set GS base */
169     __writemsr(MSR_GS_BASE, (ULONG64)Pcr);
170     __writemsr(MSR_GS_SWAP, (ULONG64)Pcr);
171 
172     /* Detect and set the CPU Type */
173     KiSetProcessorType();
174 
175     /* Get the processor features for this CPU */
176     FeatureBits = KiGetFeatureBits();
177 
178     /* Check if we support all needed features */
179     if ((FeatureBits & REQUIRED_FEATURE_BITS) != REQUIRED_FEATURE_BITS)
180     {
181         /* If not, bugcheck system */
182         FrLdrDbgPrint("CPU doesn't have needed features! Has: 0x%x, required: 0x%x\n",
183                 FeatureBits, REQUIRED_FEATURE_BITS);
184         KeBugCheck(0);
185     }
186 
187     /* Set DEP to always on */
188     SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSON;
189     FeatureBits |= KF_NX_ENABLED;
190 
191     /* Save feature bits */
192     Pcr->Prcb.FeatureBits = (ULONG)FeatureBits;
193     Pcr->Prcb.FeatureBitsHigh = FeatureBits >> 32;
194 
195     /* Enable fx save restore support */
196     __writecr4(__readcr4() | CR4_FXSR);
197 
198     /* Enable XMMI exceptions */
199     __writecr4(__readcr4() | CR4_XMMEXCPT);
200 
201     /* Enable Write-Protection */
202     __writecr0(__readcr0() | CR0_WP);
203 
204     /* Disable fpu monitoring */
205     __writecr0(__readcr0() & ~CR0_MP);
206 
207     /* Disable x87 fpu exceptions */
208     __writecr0(__readcr0() & ~CR0_NE);
209 
210     /* LDT is unused */
211     __lldt(0);
212 
213     /* Set the systemcall entry points */
214     __writemsr(MSR_LSTAR, (ULONG64)KiSystemCallEntry64);
215     __writemsr(MSR_CSTAR, (ULONG64)KiSystemCallEntry32);
216 
217     __writemsr(MSR_STAR, ((ULONG64)KGDT64_R0_CODE << 32) |
218                          ((ULONG64)(KGDT64_R3_CMCODE|RPL_MASK) << 48));
219 
220     /* Set the flags to be cleared when doing a syscall */
221     __writemsr(MSR_SYSCALL_MASK, EFLAGS_IF_MASK | EFLAGS_TF | EFLAGS_DF | EFLAGS_NESTED_TASK);
222 
223     /* Enable syscall instruction and no-execute support */
224     __writemsr(MSR_EFER, __readmsr(MSR_EFER) | MSR_SCE | MSR_NXE);
225 
226     /* Initialize the PAT */
227     Pat = (PAT_WB << 0)  | (PAT_WC << 8) | (PAT_UCM << 16) | (PAT_UC << 24) |
228           (PAT_WB << 32) | (PAT_WC << 40) | (PAT_UCM << 48) | (PAT_UC << 56);
229     __writemsr(MSR_PAT, Pat);
230 
231     /* Initialize MXCSR */
232     _mm_setcsr(INITIAL_MXCSR);
233 
234     KeSetCurrentIrql(PASSIVE_LEVEL);
235 }
236 
237 static
238 VOID
239 KiInitializeTss(
240     _In_ PKIPCR Pcr,
241     _Out_ PKTSS64 Tss,
242     _In_ PVOID InitialStack,
243     _In_ PVOID DoubleFaultStack,
244     _In_ PVOID NmiStack)
245 {
246     PKGDTENTRY64 TssEntry;
247 
248     /* Get pointer to the GDT entry */
249     TssEntry = KiGetGdtEntry(Pcr->GdtBase, KGDT64_SYS_TSS);
250 
251     /* Initialize the GDT entry */
252     KiInitGdtEntry(TssEntry, (ULONG64)Tss, sizeof(KTSS64), AMD64_TSS, 0);
253 
254     /* Zero out the TSS */
255     RtlZeroMemory(Tss, sizeof(KTSS64));
256 
257     /* FIXME: I/O Map? */
258     Tss->IoMapBase = 0x68;
259 
260     /* Setup ring 0 stack pointer */
261     Tss->Rsp0 = (ULONG64)InitialStack;
262 
263     /* Setup a stack for Double Fault Traps */
264     Tss->Ist[1] = (ULONG64)DoubleFaultStack;
265 
266     /* Setup a stack for CheckAbort Traps */
267     Tss->Ist[2] = (ULONG64)DoubleFaultStack;
268 
269     /* Setup a stack for NMI Traps */
270     Tss->Ist[3] = (ULONG64)NmiStack;
271 }
272 
273 CODE_SEG("INIT")
274 VOID
275 KiInitializeProcessorBootStructures(
276     _In_ ULONG ProcessorNumber,
277     _Out_ PKIPCR Pcr,
278     _In_ PKGDTENTRY64 GdtBase,
279     _In_ PKIDTENTRY64 IdtBase,
280     _In_ PKTSS64 TssBase,
281     _In_ PKTHREAD IdleThread,
282     _In_ PVOID KernelStack,
283     _In_ PVOID DpcStack,
284     _In_ PVOID DoubleFaultStack,
285     _In_ PVOID NmiStack)
286 {
287     /* Initialize the PCR */
288     KiInitializePcr(Pcr,
289                     ProcessorNumber,
290                     GdtBase,
291                     IdtBase,
292                     TssBase,
293                     IdleThread,
294                     DpcStack);
295 
296 
297     /* Setup the TSS descriptor and entries */
298     KiInitializeTss(Pcr,
299                     TssBase,
300                     KernelStack,
301                     DoubleFaultStack,
302                     NmiStack);
303 }
304 
305 CODE_SEG("INIT")
306 static
307 VOID
308 KiInitializeP0BootStructures(
309     _Inout_ PLOADER_PARAMETER_BLOCK LoaderBlock)
310 {
311     KDESCRIPTOR GdtDescriptor = {{0},0,0}, IdtDescriptor = {{0},0,0};
312     PKGDTENTRY64 TssEntry;
313     PKTSS64 TssBase;
314 
315     /* Set the initial stack, idle thread and process for processor 0 */
316     LoaderBlock->KernelStack = (ULONG_PTR)KiP0BootStack;
317     LoaderBlock->Thread = (ULONG_PTR)&KiInitialThread;
318     LoaderBlock->Process = (ULONG_PTR)&KiInitialProcess.Pcb;
319     LoaderBlock->Prcb = (ULONG_PTR)&KiInitialPcr.Prcb;
320 
321     /* Get GDT and IDT descriptors */
322     __sgdt(&GdtDescriptor.Limit);
323     __sidt(&IdtDescriptor.Limit);
324 
325     /* Get the boot TSS from the GDT */
326     TssEntry = KiGetGdtEntry(GdtDescriptor.Base, KGDT64_SYS_TSS);
327     TssBase = KiGetGdtDescriptorBase(TssEntry);
328 
329     /* Initialize PCR and TSS */
330     KiInitializeProcessorBootStructures(0,
331                                         &KiInitialPcr,
332                                         GdtDescriptor.Base,
333                                         IdtDescriptor.Base,
334                                         TssBase,
335                                         &KiInitialThread.Tcb,
336                                         KiP0BootStack,
337                                         KiP0DoubleFaultStack,
338                                         KiP0DoubleFaultStack,
339                                         KiP0DoubleFaultStack);
340 }
341 
342 CODE_SEG("INIT")
343 VOID
344 NTAPI
345 KiInitializeKernelMachineDependent(
346     IN PKPRCB Prcb,
347     IN PLOADER_PARAMETER_BLOCK LoaderBlock)
348 {
349     ULONG64 FeatureBits;
350 
351     /* Set boot-level flags */
352     KeI386CpuType = Prcb->CpuType;
353     KeI386CpuStep = Prcb->CpuStep;
354     KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64;
355     KeProcessorLevel = (USHORT)Prcb->CpuType;
356     if (Prcb->CpuID)
357         KeProcessorRevision = Prcb->CpuStep;
358 
359     FeatureBits = Prcb->FeatureBits | (ULONG64)Prcb->FeatureBitsHigh << 32;
360 
361     /* Set basic CPU Features that user mode can read */
362     SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = FALSE;
363     SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = FALSE;
364     SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
365     SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] =
366         (FeatureBits & KF_MMX) ? TRUE : FALSE;
367     SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] =
368         ((FeatureBits & KF_FXSR) && (FeatureBits & KF_XMMI)) ? TRUE : FALSE;
369     SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] =
370         (FeatureBits & KF_3DNOW) ? TRUE : FALSE;
371     SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
372     SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] = TRUE; // ???
373     SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] =
374         ((FeatureBits & KF_FXSR) && (FeatureBits & KF_XMMI64)) ? TRUE : FALSE;
375     SharedUserData->ProcessorFeatures[PF_SSE_DAZ_MODE_AVAILABLE] = FALSE; // ???
376     SharedUserData->ProcessorFeatures[PF_NX_ENABLED] = TRUE;
377     SharedUserData->ProcessorFeatures[PF_SSE3_INSTRUCTIONS_AVAILABLE] =
378         (FeatureBits & KF_SSE3) ? TRUE : FALSE;
379     SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE128] =
380         (FeatureBits & KF_CMPXCHG16B) ? TRUE : FALSE;
381     SharedUserData->ProcessorFeatures[PF_COMPARE64_EXCHANGE128] = FALSE; // ???
382     SharedUserData->ProcessorFeatures[PF_CHANNELS_ENABLED] = FALSE; // ???
383     SharedUserData->ProcessorFeatures[PF_XSAVE_ENABLED] = FALSE; // FIXME
384     SharedUserData->ProcessorFeatures[PF_SECOND_LEVEL_ADDRESS_TRANSLATION] =
385         (FeatureBits & KF_SLAT) ? TRUE : FALSE;
386     SharedUserData->ProcessorFeatures[PF_VIRT_FIRMWARE_ENABLED] =
387         (FeatureBits & KF_VIRT_FIRMWARE_ENABLED) ? TRUE : FALSE;
388     SharedUserData->ProcessorFeatures[PF_RDWRFSGSBASE_AVAILABLE] =
389         (FeatureBits & KF_RDWRFSGSBASE) ? TRUE : FALSE;
390     SharedUserData->ProcessorFeatures[PF_FASTFAIL_AVAILABLE] = TRUE;
391     SharedUserData->ProcessorFeatures[PF_RDRAND_INSTRUCTION_AVAILABLE] =
392         (FeatureBits & KF_RDRAND) ? TRUE : FALSE;
393     SharedUserData->ProcessorFeatures[PF_RDTSCP_INSTRUCTION_AVAILABLE] =
394         (FeatureBits & KF_RDTSCP) ? TRUE : FALSE;
395     SharedUserData->ProcessorFeatures[PF_RDPID_INSTRUCTION_AVAILABLE] = FALSE; // ???
396     SharedUserData->ProcessorFeatures[PF_SSSE3_INSTRUCTIONS_AVAILABLE] =
397         (FeatureBits & KF_SSSE3) ? TRUE : FALSE;
398     SharedUserData->ProcessorFeatures[PF_SSE4_1_INSTRUCTIONS_AVAILABLE] =
399         (FeatureBits & KF_SSE4_1) ? TRUE : FALSE;
400     SharedUserData->ProcessorFeatures[PF_SSE4_2_INSTRUCTIONS_AVAILABLE] =
401         (FeatureBits & KF_SSE4_2) ? TRUE : FALSE;
402     SharedUserData->ProcessorFeatures[PF_AVX_INSTRUCTIONS_AVAILABLE] = FALSE; // FIXME
403     SharedUserData->ProcessorFeatures[PF_AVX2_INSTRUCTIONS_AVAILABLE] = FALSE; // FIXME
404     SharedUserData->ProcessorFeatures[PF_AVX512F_INSTRUCTIONS_AVAILABLE] = FALSE; // FIXME
405 
406     /* Set the default NX policy (opt-in) */
407     SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTIN;
408 
409     /* Check if NPX is always on */
410     if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSON"))
411     {
412         /* Set it always on */
413         SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSON;
414         Prcb->FeatureBits |= KF_NX_ENABLED;
415     }
416     else if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTOUT"))
417     {
418         /* Set it in opt-out mode */
419         SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTOUT;
420         Prcb->FeatureBits |= KF_NX_ENABLED;
421     }
422     else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTIN")) ||
423              (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE")))
424     {
425         /* Set the feature bits */
426         Prcb->FeatureBits |= KF_NX_ENABLED;
427     }
428     else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSOFF")) ||
429              (strstr(KeLoaderBlock->LoadOptions, "EXECUTE")))
430     {
431         /* Set disabled mode */
432         SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSOFF;
433         Prcb->FeatureBits |= KF_NX_DISABLED;
434     }
435 
436 #if DBG
437     /* Print applied kernel features/policies and boot CPU features */
438     KiReportCpuFeatures(Prcb);
439 #endif
440 }
441 
442 static LDR_DATA_TABLE_ENTRY LdrCoreEntries[3];
443 
444 void
445 KiInitModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
446 {
447     PLDR_DATA_TABLE_ENTRY LdrEntry;
448     PLIST_ENTRY Entry;
449     ULONG i;
450 
451     /* Initialize the list head */
452     InitializeListHead(&PsLoadedModuleList);
453 
454     /* Loop the first 3 entries */
455     for (Entry = LoaderBlock->LoadOrderListHead.Flink, i = 0;
456          Entry != &LoaderBlock->LoadOrderListHead && i < 3;
457          Entry = Entry->Flink, i++)
458     {
459         /* Get the data table entry */
460         LdrEntry = CONTAINING_RECORD(Entry,
461                                      LDR_DATA_TABLE_ENTRY,
462                                      InLoadOrderLinks);
463 
464         /* Copy the entry */
465         LdrCoreEntries[i] = *LdrEntry;
466 
467         /* Insert the copy into the list */
468         InsertTailList(&PsLoadedModuleList, &LdrCoreEntries[i].InLoadOrderLinks);
469     }
470 }
471 
472 CODE_SEG("INIT")
473 DECLSPEC_NORETURN
474 VOID
475 NTAPI
476 KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
477 {
478     CCHAR Cpu;
479     PKTHREAD InitialThread;
480     ULONG64 InitialStack;
481     PKIPCR Pcr;
482 
483     /* Boot cycles timestamp */
484     BootCycles = __rdtsc();
485 
486     /* HACK */
487     FrLdrDbgPrint = LoaderBlock->u.I386.CommonDataArea;
488     //FrLdrDbgPrint("Hello from KiSystemStartup!!!\n");
489 
490     /* Get the current CPU number */
491     Cpu = KeNumberProcessors++; // FIXME
492 
493     /* LoaderBlock initialization for Cpu 0 */
494     if (Cpu == 0)
495     {
496         /* Save the loader block */
497         KeLoaderBlock = LoaderBlock;
498 
499         /* Prepare LoaderBlock, PCR, TSS with the P0 boot data */
500         KiInitializeP0BootStructures(LoaderBlock);
501     }
502 
503     /* Get Pcr from loader block */
504     Pcr = CONTAINING_RECORD(LoaderBlock->Prcb, KIPCR, Prcb);
505 
506     /* Set the PRCB for this Processor */
507     KiProcessorBlock[Cpu] = &Pcr->Prcb;
508 
509     /* Align stack to 16 bytes */
510     LoaderBlock->KernelStack &= ~(16 - 1);
511 
512     /* Save the initial thread and stack */
513     InitialStack = LoaderBlock->KernelStack; // Checkme
514     InitialThread = (PKTHREAD)LoaderBlock->Thread;
515 
516     /* Set us as the current process */
517     InitialThread->ApcState.Process = (PVOID)LoaderBlock->Process;
518 
519     /* Initialize the CPU features */
520     KiInitializeCpu(Pcr);
521 
522     /* Initial setup for the boot CPU */
523     if (Cpu == 0)
524     {
525         /* Initialize the module list (ntos, hal, kdcom) */
526         KiInitModuleList(LoaderBlock);
527 
528         /* Setup the IDT */
529         KeInitExceptions();
530 
531          /* Initialize debugging system */
532         KdInitSystem(0, KeLoaderBlock);
533 
534         /* Check for break-in */
535         if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
536     }
537 
538     DPRINT1("Pcr = %p, Gdt = %p, Idt = %p, Tss = %p\n",
539            Pcr, Pcr->GdtBase, Pcr->IdtBase, Pcr->TssBase);
540 
541     /* Acquire lock */
542     while (InterlockedBitTestAndSet64((PLONG64)&KiFreezeExecutionLock, 0))
543     {
544         /* Loop until lock is free */
545         while ((*(volatile KSPIN_LOCK*)&KiFreezeExecutionLock) & 1);
546     }
547 
548     /* Initialize the Processor with HAL */
549     HalInitializeProcessor(Cpu, KeLoaderBlock);
550 
551     /* Set processor as active */
552     KeActiveProcessors |= 1ULL << Cpu;
553 
554     /* Release lock */
555     InterlockedAnd64((PLONG64)&KiFreezeExecutionLock, 0);
556 
557     /* Raise to HIGH_LEVEL */
558     KfRaiseIrql(HIGH_LEVEL);
559 
560     /* Machine specific kernel initialization */
561     if (Cpu == 0) KiInitializeKernelMachineDependent(&Pcr->Prcb, LoaderBlock);
562 
563     /* Switch to new kernel stack and start kernel bootstrapping */
564     KiSwitchToBootStack(InitialStack & ~3);
565 }
566 
567