- Remove LDT initialization, LDT shouldn't be initialized at bootup.
[reactos.git] / reactos / ntoskrnl / ke / i386 / kernel.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/i386/kernel.c
6 * PURPOSE: Initializes the kernel
7 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16 #include <internal/napi.h>
17
18 /* GLOBALS *******************************************************************/
19
20 PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS];
21 KNODE KiNode0;
22 PKNODE KeNodeBlock[1];
23 UCHAR KeNumberNodes = 1;
24 UCHAR KeProcessNodeSeed;
25 ETHREAD KiInitialThread;
26 EPROCESS KiInitialProcess;
27
28 extern ULONG Ke386GlobalPagesEnabled;
29 extern PVOID trap_stack, init_stack;
30
31 /* System-defined Spinlocks */
32 KSPIN_LOCK KiDispatcherLock;
33 KSPIN_LOCK MmPfnLock;
34 KSPIN_LOCK MmSystemSpaceLock;
35 KSPIN_LOCK CcBcbSpinLock;
36 KSPIN_LOCK CcMasterSpinLock;
37 KSPIN_LOCK CcVacbSpinLock;
38 KSPIN_LOCK CcWorkQueueSpinLock;
39 KSPIN_LOCK NonPagedPoolLock;
40 KSPIN_LOCK MmNonPagedPoolLock;
41 KSPIN_LOCK IopCancelSpinLock;
42 KSPIN_LOCK IopVpbSpinLock;
43 KSPIN_LOCK IopDatabaseLock;
44 KSPIN_LOCK IopCompletionLock;
45 KSPIN_LOCK NtfsStructLock;
46 KSPIN_LOCK AfdWorkQueueSpinLock;
47 KSPIN_LOCK KiTimerTableLock[16];
48 KSPIN_LOCK KiReverseStallIpiLock;
49
50 KSPIN_LOCK KiFreezeExecutionLock;
51 KSPIN_LOCK Ki486CompatibilityLock;
52
53 #if defined (ALLOC_PRAGMA)
54 #pragma alloc_text(INIT, KeInit1)
55 #pragma alloc_text(INIT, KeInit2)
56 #endif
57
58 /* FUNCTIONS *****************************************************************/
59
60 VOID
61 NTAPI
62 KiInitSystem(VOID)
63 {
64 ULONG i;
65
66 /* Initialize Bugcheck Callback data */
67 InitializeListHead(&BugcheckCallbackListHead);
68 InitializeListHead(&BugcheckReasonCallbackListHead);
69 KeInitializeSpinLock(&BugCheckCallbackLock);
70
71 /* Initialize the Timer Expiration DPC */
72 KeInitializeDpc(&KiExpireTimerDpc, KiExpireTimers, NULL);
73 KeSetTargetProcessorDpc(&KiExpireTimerDpc, 0);
74
75 /* Initialize Profiling data */
76 KeInitializeSpinLock(&KiProfileLock);
77 InitializeListHead(&KiProfileListHead);
78 InitializeListHead(&KiProfileSourceListHead);
79
80 /* Loop the timer table */
81 for (i = 0; i < TIMER_TABLE_SIZE; i++)
82 {
83 /* Initialize the list and entries */
84 InitializeListHead(&KiTimerTableListHead[i].Entry);
85 KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF;
86 KiTimerTableListHead[i].Time.LowPart = 0;
87 }
88
89 /* Initialize old-style list */
90 InitializeListHead(&KiTimerListHead);
91
92 /* Initialize the Swap event and all swap lists */
93 KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE);
94 InitializeListHead(&KiProcessInSwapListHead);
95 InitializeListHead(&KiProcessOutSwapListHead);
96 InitializeListHead(&KiStackInSwapListHead);
97
98 /* Initialize the mutex for generic DPC calls */
99 KeInitializeMutex(&KiGenericCallDpcMutex, 0);
100
101 /* Initialize the syscall table */
102 KeServiceDescriptorTable[0].Base = MainSSDT;
103 KeServiceDescriptorTable[0].Count = NULL;
104 KeServiceDescriptorTable[0].Limit = NUMBER_OF_SYSCALLS;
105 KeServiceDescriptorTable[1].Limit = 0;
106 KeServiceDescriptorTable[0].Number = MainSSPT;
107
108 /* Copy the the current table into the shadow table for win32k */
109 RtlCopyMemory(KeServiceDescriptorTableShadow,
110 KeServiceDescriptorTable,
111 sizeof(KeServiceDescriptorTable));
112 }
113
114 LARGE_INTEGER
115 NTAPI
116 KiComputeReciprocal(IN LONG Divisor,
117 OUT PUCHAR Shift)
118 {
119 LARGE_INTEGER Reciprocal = {{0}};
120 LONG BitCount = 0, Remainder = 1;
121
122 /* Start by calculating the remainder */
123 while (Reciprocal.HighPart >= 0)
124 {
125 /* Increase the loop (bit) count */
126 BitCount++;
127
128 /* Calculate the current fraction */
129 Reciprocal.HighPart = (Reciprocal.HighPart << 1) |
130 (Reciprocal.LowPart >> 31);
131 Reciprocal.LowPart <<= 1;
132
133 /* Double the remainder and see if we went past the divisor */
134 Remainder <<= 1;
135 if (Remainder >= Divisor)
136 {
137 /* Set the low-bit and calculate the new remainder */
138 Remainder -= Divisor;
139 Reciprocal.LowPart |= 1;
140 }
141 }
142
143 /* Check if we have a remainder */
144 if (Remainder)
145 {
146 /* Check if the current fraction value is too large */
147 if ((Reciprocal.LowPart == 0xFFFFFFFF) &&
148 (Reciprocal.HighPart == 0xFFFFFFFF))
149 {
150 /* Set the high bit and reduce the bit count */
151 Reciprocal.LowPart = 0;
152 Reciprocal.HighPart = 0x80000000;
153 BitCount--;
154 }
155 else
156 {
157 /* Check if only the lowest bits got too large */
158 if (Reciprocal.LowPart == 0xFFFFFFFF)
159 {
160 /* Reset them and increase the high bits instead */
161 Reciprocal.LowPart = 0;
162 Reciprocal.HighPart++;
163 }
164 else
165 {
166 /* All is well, increase the low bits */
167 Reciprocal.LowPart++;
168 }
169 }
170 }
171
172 /* Now calculate the actual shift and return the reciprocal */
173 *Shift = (UCHAR)BitCount - 64;
174 return Reciprocal;
175 }
176
177 VOID
178 NTAPI
179 KiInitSpinLocks(IN PKPRCB Prcb,
180 IN CCHAR Number)
181 {
182 ULONG i;
183
184 /* Initialize Dispatcher Fields */
185 Prcb->QueueIndex = 1;
186 Prcb->ReadySummary = 0;
187 Prcb->DeferredReadyListHead.Next = NULL;
188 for (i = 0; i < 32; i++)
189 {
190 /* Initialize the ready list */
191 InitializeListHead(&Prcb->DispatcherReadyListHead[i]);
192 }
193
194 /* Initialize DPC Fields */
195 InitializeListHead(&Prcb->DpcData[DPC_NORMAL].DpcListHead);
196 KeInitializeSpinLock(&Prcb->DpcData[DPC_NORMAL].DpcLock);
197 Prcb->DpcData[DPC_NORMAL].DpcQueueDepth = 0;
198 Prcb->DpcData[DPC_NORMAL].DpcCount = 0;
199 Prcb->DpcRoutineActive = FALSE;
200 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
201 Prcb->MinimumDpcRate = KiMinimumDpcRate;
202 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
203 KeInitializeDpc(&Prcb->CallDpc, NULL, NULL);
204 KeSetTargetProcessorDpc(&Prcb->CallDpc, Number);
205 KeSetImportanceDpc(&Prcb->CallDpc, HighImportance);
206
207 /* Initialize the Wait List Head */
208 InitializeListHead(&Prcb->WaitListHead);
209
210 /* Initialize Queued Spinlocks */
211 Prcb->LockQueue[LockQueueDispatcherLock].Next = NULL;
212 Prcb->LockQueue[LockQueueDispatcherLock].Lock = &KiDispatcherLock;
213 Prcb->LockQueue[LockQueueExpansionLock].Next = NULL;
214 Prcb->LockQueue[LockQueueExpansionLock].Lock = NULL;
215 Prcb->LockQueue[LockQueuePfnLock].Next = NULL;
216 Prcb->LockQueue[LockQueuePfnLock].Lock = &MmPfnLock;
217 Prcb->LockQueue[LockQueueSystemSpaceLock].Next = NULL;
218 Prcb->LockQueue[LockQueueSystemSpaceLock].Lock = &MmSystemSpaceLock;
219 Prcb->LockQueue[LockQueueBcbLock].Next = NULL;
220 Prcb->LockQueue[LockQueueBcbLock].Lock = &CcBcbSpinLock;
221 Prcb->LockQueue[LockQueueMasterLock].Next = NULL;
222 Prcb->LockQueue[LockQueueMasterLock].Lock = &CcMasterSpinLock;
223 Prcb->LockQueue[LockQueueVacbLock].Next = NULL;
224 Prcb->LockQueue[LockQueueVacbLock].Lock = &CcVacbSpinLock;
225 Prcb->LockQueue[LockQueueWorkQueueLock].Next = NULL;
226 Prcb->LockQueue[LockQueueWorkQueueLock].Lock = &CcWorkQueueSpinLock;
227 Prcb->LockQueue[LockQueueNonPagedPoolLock].Next = NULL;
228 Prcb->LockQueue[LockQueueNonPagedPoolLock].Lock = &NonPagedPoolLock;
229 Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Next = NULL;
230 Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Lock = &MmNonPagedPoolLock;
231 Prcb->LockQueue[LockQueueIoCancelLock].Next = NULL;
232 Prcb->LockQueue[LockQueueIoCancelLock].Lock = &IopCancelSpinLock;
233 Prcb->LockQueue[LockQueueIoVpbLock].Next = NULL;
234 Prcb->LockQueue[LockQueueIoVpbLock].Lock = &IopVpbSpinLock;
235 Prcb->LockQueue[LockQueueIoDatabaseLock].Next = NULL;
236 Prcb->LockQueue[LockQueueIoDatabaseLock].Lock = &IopDatabaseLock;
237 Prcb->LockQueue[LockQueueIoCompletionLock].Next = NULL;
238 Prcb->LockQueue[LockQueueIoCompletionLock].Lock = &IopCompletionLock;
239 Prcb->LockQueue[LockQueueNtfsStructLock].Next = NULL;
240 Prcb->LockQueue[LockQueueNtfsStructLock].Lock = &NtfsStructLock;
241 Prcb->LockQueue[LockQueueAfdWorkQueueLock].Next = NULL;
242 Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock;
243 Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL;
244 Prcb->LockQueue[LockQueueUnusedSpare16].Lock = NULL;
245
246 /* Loop timer locks */
247 for (i = 0; i < LOCK_QUEUE_TIMER_TABLE_LOCKS; i++)
248 {
249 /* Initialize the lock and setup the Queued Spinlock */
250 KeInitializeSpinLock(&KiTimerTableLock[i]);
251 Prcb->LockQueue[i].Next = NULL;
252 Prcb->LockQueue[i].Lock = &KiTimerTableLock[i];
253 }
254
255 /* Check if this is the boot CPU */
256 if (!Number)
257 {
258 /* Initialize the lock themselves */
259 KeInitializeSpinLock(&KiDispatcherLock);
260 KeInitializeSpinLock(&KiReverseStallIpiLock);
261 KeInitializeSpinLock(&MmPfnLock);
262 KeInitializeSpinLock(&MmSystemSpaceLock);
263 KeInitializeSpinLock(&CcBcbSpinLock);
264 KeInitializeSpinLock(&CcMasterSpinLock);
265 KeInitializeSpinLock(&CcVacbSpinLock);
266 KeInitializeSpinLock(&CcWorkQueueSpinLock);
267 KeInitializeSpinLock(&IopCancelSpinLock);
268 KeInitializeSpinLock(&IopCompletionLock);
269 KeInitializeSpinLock(&IopDatabaseLock);
270 KeInitializeSpinLock(&IopVpbSpinLock);
271 KeInitializeSpinLock(&NonPagedPoolLock);
272 KeInitializeSpinLock(&MmNonPagedPoolLock);
273 KeInitializeSpinLock(&NtfsStructLock);
274 KeInitializeSpinLock(&AfdWorkQueueSpinLock);
275 KeInitializeDispatcher(); // ROS OLD DISPATCHER
276 }
277 }
278
279 VOID
280 NTAPI
281 KiInitializePcr(IN ULONG ProcessorNumber,
282 IN PKIPCR Pcr,
283 IN PKIDTENTRY Idt,
284 IN PKGDTENTRY Gdt,
285 IN PKTSS Tss,
286 IN PKTHREAD IdleThread,
287 IN PVOID DpcStack)
288 {
289 /* Setup the TIB */
290 Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
291 Pcr->NtTib.StackBase = 0;
292 Pcr->NtTib.StackLimit = 0;
293 Pcr->NtTib.Self = 0;
294
295 /* Set the Current Thread */
296 //Pcr->PrcbData.CurrentThread = IdleThread;
297
298 /* Set pointers to ourselves */
299 Pcr->Self = (PKPCR)Pcr;
300 Pcr->Prcb = &Pcr->PrcbData;
301
302 /* Set the PCR Version */
303 Pcr->MajorVersion = PCR_MAJOR_VERSION;
304 Pcr->MinorVersion = PCR_MINOR_VERSION;
305
306 /* Set the PCRB Version */
307 Pcr->PrcbData.MajorVersion = 1;
308 Pcr->PrcbData.MinorVersion = 1;
309
310 /* Set the Build Type */
311 Pcr->PrcbData.BuildType = 0;
312
313 /* Set the Processor Number and current Processor Mask */
314 Pcr->PrcbData.Number = (UCHAR)ProcessorNumber;
315 Pcr->PrcbData.SetMember = 1 << ProcessorNumber;
316
317 /* Set the PRCB for this Processor */
318 KiProcessorBlock[ProcessorNumber] = Pcr->Prcb;
319
320 /* Start us out at PASSIVE_LEVEL */
321 Pcr->Irql = PASSIVE_LEVEL;
322
323 /* Set the GDI, IDT, TSS and DPC Stack */
324 Pcr->GDT = (PVOID)Gdt;
325 Pcr->IDT = Idt;
326 Pcr->TSS = Tss;
327 Pcr->PrcbData.DpcStack = DpcStack;
328 }
329
330 VOID
331 NTAPI
332 KiInitializeKernel(IN PKPROCESS InitProcess,
333 IN PKTHREAD InitThread,
334 IN PVOID IdleStack,
335 IN PKPRCB Prcb,
336 IN CCHAR Number,
337 IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
338 {
339 BOOLEAN NpxPresent;
340 ULONG FeatureBits;
341 LARGE_INTEGER PageDirectory;
342 PVOID DpcStack;
343
344 /* Detect and set the CPU Type */
345 KiSetProcessorType();
346
347 /* Set CR0 features based on detected CPU */
348 KiSetCR0Bits();
349
350 /* Check if an FPU is present */
351 NpxPresent = KiIsNpxPresent();
352
353 /* Initialize the Power Management Support for this PRCB */
354 PoInitializePrcb(Prcb);
355
356 /* Bugcheck if this is a 386 CPU */
357 if (Prcb->CpuType == 3) KeBugCheckEx(0x5D, 0x386, 0, 0, 0);
358
359 /* Get the processor features for the CPU */
360 FeatureBits = KiGetFeatureBits();
361
362 /* Save feature bits */
363 Prcb->FeatureBits = FeatureBits;
364
365 /* Get cache line information for this CPU */
366 KiGetCacheInformation();
367
368 /* Initialize spinlocks and DPC data */
369 KiInitSpinLocks(Prcb, Number);
370
371 /* Check if this is the Boot CPU */
372 if (!Number)
373 {
374 /* Set Node Data */
375 KeNodeBlock[0] = &KiNode0;
376 Prcb->ParentNode = KeNodeBlock[0];
377 KeNodeBlock[0]->ProcessorMask = Prcb->SetMember;
378
379 /* Set boot-level flags */
380 KeI386NpxPresent = NpxPresent;
381 KeI386CpuType = Prcb->CpuType;
382 KeI386CpuStep = Prcb->CpuStep;
383 KeProcessorArchitecture = 0;
384 KeProcessorLevel = (USHORT)Prcb->CpuType;
385 if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep;
386 KeFeatureBits = FeatureBits;
387 KeI386FxsrPresent = (KeFeatureBits & KF_FXSR) ? TRUE : FALSE;
388 KeI386XMMIPresent = (KeFeatureBits & KF_XMMI) ? TRUE : FALSE;
389
390 /* Set the current MP Master KPRCB to the Boot PRCB */
391 Prcb->MultiThreadSetMaster = Prcb;
392
393 /* Initialize some spinlocks */
394 KeInitializeSpinLock(&KiFreezeExecutionLock);
395 KeInitializeSpinLock(&Ki486CompatibilityLock);
396
397 /* Initialize portable parts of the OS */
398 KiInitSystem();
399
400 /* Initialize the Idle Process and the Process Listhead */
401 InitializeListHead(&KiProcessListHead);
402 PageDirectory.QuadPart = 0;
403 KeInitializeProcess(InitProcess,
404 0,
405 0xFFFFFFFF,
406 PageDirectory);
407 InitProcess->QuantumReset = MAXCHAR;
408 }
409 else
410 {
411 /* FIXME */
412 DPRINT1("SMP Boot support not yet present\n");
413 }
414
415 #if 0
416 /* Setup the Idle Thread */
417 KeInitializeThread(InitProcess,
418 InitThread,
419 NULL,
420 NULL,
421 NULL,
422 NULL,
423 NULL,
424 IdleStack);
425 #endif
426 InitThread->NextProcessor = Number;
427 InitThread->Priority = HIGH_PRIORITY;
428 InitThread->State = Running;
429 InitThread->Affinity = 1 << Number;
430 InitThread->WaitIrql = DISPATCH_LEVEL;
431 InitProcess->ActiveProcessors = 1 << Number;
432
433 /* Set up the thread-related fields in the PRCB */
434 //Prcb->CurrentThread = InitThread;
435 Prcb->NextThread = NULL;
436 //Prcb->IdleThread = InitThread;
437
438 /* Initialize the Debugger */
439 KdInitSystem (0, &KeLoaderBlock);
440
441 /* Initialize the Kernel Executive */
442 ExpInitializeExecutive();
443
444 /* Only do this on the boot CPU */
445 if (!Number)
446 {
447 /* Calculate the time reciprocal */
448 KiTimeIncrementReciprocal =
449 KiComputeReciprocal(KeMaximumIncrement,
450 &KiTimeIncrementShiftCount);
451
452 /* Update DPC Values in case they got updated by the executive */
453 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
454 Prcb->MinimumDpcRate = KiMinimumDpcRate;
455 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
456
457 /* Allocate the DPC Stack */
458 DpcStack = MmCreateKernelStack(FALSE);
459 if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0);
460 Prcb->DpcStack = DpcStack;
461
462 /* Allocate the IOPM save area. */
463 Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool,
464 PAGE_SIZE * 2,
465 TAG('K', 'e', ' ', ' '));
466 if (!Ki386IopmSaveArea)
467 {
468 /* Bugcheck. We need this for V86/VDM support. */
469 KeBugCheckEx(NO_PAGES_AVAILABLE, 2, PAGE_SIZE * 2, 0, 0);
470 }
471 }
472
473 /* Free Initial Memory */
474 MiFreeInitMemory();
475
476 while (1)
477 {
478 LARGE_INTEGER Timeout;
479 Timeout.QuadPart = 0x7fffffffffffffffLL;
480 KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
481 }
482
483 /* Bug Check and loop forever if anything failed */
484 KEBUGCHECK(0);
485 for(;;);
486 }
487
488 VOID
489 NTAPI
490 KiSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
491 {
492 /* Currently hacked for CPU 0 only */
493 ULONG Cpu = 0;
494 PKIPCR Pcr = (PKIPCR)KPCR_BASE;
495 PKPRCB Prcb;
496
497 /* Initialize the PCR */
498 RtlZeroMemory(Pcr, PAGE_SIZE);
499 KiInitializePcr(Cpu,
500 Pcr,
501 KiIdt,
502 KiBootGdt,
503 &KiBootTss,
504 &KiInitialThread.Tcb,
505 trap_stack);
506 Prcb = Pcr->Prcb;
507
508 /* Set us as the current process */
509 KiInitialThread.Tcb.ApcState.Process = &KiInitialProcess.Pcb;
510
511 /* Clear DR6/7 to cleanup bootloader debugging */
512 Pcr->PrcbData.ProcessorState.SpecialRegisters.KernelDr6 = 0;
513 Pcr->PrcbData.ProcessorState.SpecialRegisters.KernelDr7 = 0;
514
515 /* Setup the boot (Freeldr should've done), double fault and NMI TSS */
516 Ki386InitializeTss();
517
518 /* Setup CPU-related fields */
519 Pcr->Number = Cpu;
520 Pcr->SetMember = 1 << Cpu;
521 Pcr->SetMemberCopy = 1 << Cpu;
522 Prcb->SetMember = 1 << Cpu;
523
524 /* Initialize the Processor with HAL */
525 HalInitializeProcessor(Cpu, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
526
527 /* Set active processors */
528 KeActiveProcessors |= Pcr->SetMember;
529 KeNumberProcessors++;
530
531 /* Raise to HIGH_LEVEL */
532 KfRaiseIrql(HIGH_LEVEL);
533
534 /* Call main kernel intialization */
535 KiInitializeKernel(&KiInitialProcess.Pcb,
536 &KiInitialThread.Tcb,
537 init_stack,
538 Prcb,
539 Cpu,
540 LoaderBlock);
541 }
542
543 VOID
544 INIT_FUNCTION
545 NTAPI
546 KeInit2(VOID)
547 {
548 ULONG Protect;
549
550 /* Check if Fxsr was found */
551 if (KeI386FxsrPresent)
552 {
553 /* Enable it. FIXME: Send an IPI */
554 Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSFXSR);
555
556 /* Check if XMM was found too */
557 if (KeI386XMMIPresent)
558 {
559 /* Enable it: FIXME: Send an IPI. */
560 Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSXMMEXCPT);
561
562 /* FIXME: Implement and enable XMM Page Zeroing for Mm */
563 }
564 }
565
566 if (KeFeatureBits & KF_GLOBAL_PAGE)
567 {
568 ULONG Flags;
569 /* Enable global pages */
570 Ke386GlobalPagesEnabled = TRUE;
571 Ke386SaveFlags(Flags);
572 Ke386DisableInterrupts();
573 Ke386SetCr4(Ke386GetCr4() | X86_CR4_PGE);
574 Ke386RestoreFlags(Flags);
575 }
576
577 if (KeFeatureBits & KF_FAST_SYSCALL)
578 {
579 extern void KiFastCallEntry(void);
580
581 /* CS Selector of the target segment. */
582 Ke386Wrmsr(0x174, KGDT_R0_CODE, 0);
583 /* Target ESP. */
584 Ke386Wrmsr(0x175, 0, 0);
585 /* Target EIP. */
586 Ke386Wrmsr(0x176, (ULONG_PTR)KiFastCallEntry, 0);
587 }
588
589 /* Does the CPU Support 'prefetchnta' (SSE) */
590 if(KeFeatureBits & KF_XMMI)
591 {
592 Protect = MmGetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal);
593 MmSetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal, Protect | PAGE_IS_WRITABLE);
594 /* Replace the ret by a nop */
595 *(PCHAR)RtlPrefetchMemoryNonTemporal = 0x90;
596 MmSetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal, Protect);
597 }
598
599 /* Set IDT to writable */
600 Protect = MmGetPageProtect(NULL, (PVOID)KiIdt);
601 MmSetPageProtect(NULL, (PVOID)KiIdt, Protect | PAGE_IS_WRITABLE);
602 }